mirror of
https://github.com/Orasund/elm-ui-widgets.git
synced 2024-11-22 13:14:10 +03:00
Added unstable homepage
This commit is contained in:
parent
b73a19d3ce
commit
27dff31fb9
17994
docs/unstable/index.html
Normal file
17994
docs/unstable/index.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,8 @@ import Browser
|
||||
import Element exposing (Color, Element)
|
||||
import Element.Background as Background
|
||||
import Element.Input as Input
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
import Framework
|
||||
import Framework.Button as Button
|
||||
import Framework.Card as Card
|
||||
@ -19,22 +21,32 @@ import Html.Attributes as Attributes
|
||||
import Set exposing (Set)
|
||||
import Time
|
||||
import Widget
|
||||
import Widget.Button as Button exposing (ButtonStyle)
|
||||
import Widget.FilterSelect as FilterSelect
|
||||
import Widget.FilterMultiSelect as FilterMultiSelect
|
||||
import Widget.ScrollingNav as ScrollingNav
|
||||
import Widget.Snackbar as Snackbar
|
||||
import Widget.ValidatedInput as ValidatedInput
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ filterSelect : FilterSelect.Model
|
||||
, filterMultiSelect : FilterMultiSelect.Model
|
||||
, validatedInput : ValidatedInput.Model () ( String, String )
|
||||
}
|
||||
|
||||
|
||||
type Msg
|
||||
= FilterSelectSpecific FilterSelect.Msg
|
||||
| FilterMultiSelectSpecific FilterMultiSelect.Msg
|
||||
| ValidatedInputSpecific ValidatedInput.Msg
|
||||
|
||||
chipButton : ButtonStyle msg
|
||||
chipButton =
|
||||
{ container = Tag.simple
|
||||
, disabled = []
|
||||
, label = Grid.simple
|
||||
, active = Color.primary
|
||||
}
|
||||
|
||||
init : Model
|
||||
init =
|
||||
@ -56,6 +68,24 @@ init =
|
||||
]
|
||||
|> Set.fromList
|
||||
|> FilterSelect.init
|
||||
, filterMultiSelect =
|
||||
[ "Apple"
|
||||
, "Kiwi"
|
||||
, "Strawberry"
|
||||
, "Pineapple"
|
||||
, "Mango"
|
||||
, "Grapes"
|
||||
, "Watermelon"
|
||||
, "Orange"
|
||||
, "Lemon"
|
||||
, "Blueberry"
|
||||
, "Grapefruit"
|
||||
, "Coconut"
|
||||
, "Cherry"
|
||||
, "Banana"
|
||||
]
|
||||
|> Set.fromList
|
||||
|> FilterMultiSelect.init
|
||||
, validatedInput =
|
||||
ValidatedInput.init
|
||||
{ value = ( "John", "Doe" )
|
||||
@ -83,6 +113,13 @@ update msg model =
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
FilterMultiSelectSpecific m ->
|
||||
( { model
|
||||
| filterMultiSelect = model.filterMultiSelect |> FilterMultiSelect.update m
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ValidatedInputSpecific m ->
|
||||
( { model
|
||||
| validatedInput = model.validatedInput |> ValidatedInput.update m
|
||||
@ -129,6 +166,55 @@ filterSelect model =
|
||||
]
|
||||
)
|
||||
|
||||
filterMultiSelect : FilterMultiSelect.Model -> (String,Element Msg)
|
||||
filterMultiSelect model =
|
||||
( "Filter Multi Select"
|
||||
, [ FilterMultiSelect.viewInput model
|
||||
{ msgMapper = FilterMultiSelectSpecific
|
||||
, placeholder =
|
||||
Just <|
|
||||
Input.placeholder [] <|
|
||||
Element.text <|
|
||||
"Fruit"
|
||||
, label = "Fruit"
|
||||
, toChip = \string ->
|
||||
{ text = string
|
||||
, onPress = Just <| FilterMultiSelectSpecific <| FilterMultiSelect.ToggleSelected <| string
|
||||
, icon = Element.none
|
||||
}
|
||||
}
|
||||
|> Widget.textInput
|
||||
{ chip = chipButton
|
||||
, chipsRow =
|
||||
[ Element.width <| Element.shrink
|
||||
, Element.spacing <| 4 ]
|
||||
, containerRow =
|
||||
Button.simple
|
||||
++ Color.light
|
||||
++ [ Border.color <| Element.rgb255 186 189 182
|
||||
, Font.alignLeft
|
||||
, Element.padding 8
|
||||
, Element.height <| Element.px <|42
|
||||
]
|
||||
++ Grid.simple
|
||||
, input =
|
||||
Color.light
|
||||
++ [Element.padding 0]
|
||||
}
|
||||
|
||||
, model
|
||||
|> FilterMultiSelect.viewOptions
|
||||
|> List.map
|
||||
(\string ->
|
||||
Input.button (Button.simple ++ Tag.simple)
|
||||
{ onPress = Just <| FilterMultiSelectSpecific <| FilterMultiSelect.ToggleSelected <| string
|
||||
, label = Element.text string
|
||||
}
|
||||
)
|
||||
|> Element.wrappedRow [ Element.spacing 10 ]
|
||||
]
|
||||
|> Element.column Grid.simple
|
||||
)
|
||||
|
||||
validatedInput : ValidatedInput.Model () ( String, String ) -> (String,Element Msg)
|
||||
validatedInput model =
|
||||
@ -162,6 +248,7 @@ view msgMapper model =
|
||||
, description = "Components have a Model, an Update- and sometimes even a Subscription-function. It takes some time to set them up correctly."
|
||||
, items =
|
||||
[ filterSelect model.filterSelect
|
||||
, filterMultiSelect model.filterMultiSelect
|
||||
, validatedInput model.validatedInput
|
||||
]
|
||||
|> List.map (Tuple.mapSecond (Element.map msgMapper) )
|
||||
|
@ -127,7 +127,8 @@ style =
|
||||
Card.simple
|
||||
++ Color.dark
|
||||
++ Grid.simple
|
||||
++ [ Element.paddingXY 8 6]
|
||||
++ [ Element.paddingXY 8 6
|
||||
, Element.height <| Element.px <|54]
|
||||
, button =
|
||||
{ label = Grid.simple
|
||||
, container = Button.simple ++ Color.dark
|
||||
@ -137,6 +138,23 @@ style =
|
||||
, text = [Element.paddingXY 8 0]
|
||||
}
|
||||
, layout = Framework.responsiveLayout
|
||||
{--\a w ->
|
||||
Html.div []
|
||||
[ Html.node "meta"
|
||||
[ Attributes.attribute "name" "viewport"
|
||||
, Attributes.attribute "content" "width=device-width, initial-scale=1.0"
|
||||
]
|
||||
[]
|
||||
, Element.layoutWith
|
||||
{options = (Element.focusStyle
|
||||
{ borderColor = Nothing
|
||||
, backgroundColor = Nothing
|
||||
, shadow = Nothing
|
||||
}
|
||||
|> List.singleton)
|
||||
}
|
||||
(Framework.layoutAttributes ++ a) <| w
|
||||
]--}
|
||||
, header =
|
||||
Framework.container
|
||||
++ Color.dark
|
||||
|
@ -21,6 +21,7 @@ import Widget.Button as Button exposing (ButtonStyle)
|
||||
import Layout exposing (Part(..))
|
||||
import Icons
|
||||
import Widget
|
||||
import Element.Font as Font
|
||||
|
||||
buttonStyle : ButtonStyle msg
|
||||
buttonStyle =
|
||||
@ -38,13 +39,23 @@ tabButtonStyle=
|
||||
, active = Color.primary
|
||||
}
|
||||
|
||||
chipButton : ButtonStyle msg
|
||||
chipButton =
|
||||
{ container = Tag.simple
|
||||
, disabled = []
|
||||
, label = Grid.simple
|
||||
, active = Color.primary
|
||||
}
|
||||
|
||||
type alias Model =
|
||||
{ selected : Maybe Int
|
||||
, multiSelected : Set Int
|
||||
, chipTextInput : Set String
|
||||
, isCollapsed : Bool
|
||||
, carousel : Int
|
||||
, tab : Maybe Int
|
||||
, button : Bool
|
||||
, textInput : String
|
||||
}
|
||||
|
||||
|
||||
@ -52,19 +63,24 @@ type Msg
|
||||
= ChangedSelected Int
|
||||
| ChangedMultiSelected Int
|
||||
| ToggleCollapsable Bool
|
||||
| ToggleTextInputChip String
|
||||
| ChangedTab Int
|
||||
| SetCarousel Int
|
||||
| ToggleButton Bool
|
||||
| SetTextInput String
|
||||
| Idle
|
||||
|
||||
|
||||
init : Model
|
||||
init =
|
||||
{ selected = Nothing
|
||||
, multiSelected = Set.empty
|
||||
, chipTextInput = Set.empty
|
||||
, isCollapsed = False
|
||||
, carousel = 0
|
||||
, tab = Just 1
|
||||
, button = True
|
||||
, textInput = ""
|
||||
}
|
||||
|
||||
|
||||
@ -98,6 +114,18 @@ update msg model =
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
ToggleTextInputChip string ->
|
||||
( { model
|
||||
| chipTextInput =
|
||||
model.chipTextInput |>
|
||||
if model.chipTextInput |> Set.member string then
|
||||
Set.remove string
|
||||
else
|
||||
Set.insert string
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
SetCarousel int ->
|
||||
( if (int < 0) || (int > 3) then
|
||||
@ -115,6 +143,12 @@ update msg model =
|
||||
|
||||
ToggleButton bool ->
|
||||
( { model | button = bool }, Cmd.none )
|
||||
|
||||
SetTextInput string ->
|
||||
( {model | textInput = string },Cmd.none)
|
||||
|
||||
Idle ->
|
||||
( model, Cmd.none)
|
||||
|
||||
|
||||
select : Model -> (String,Element Msg)
|
||||
@ -187,29 +221,35 @@ multiSelect model =
|
||||
collapsable : Model -> (String,Element Msg)
|
||||
collapsable model =
|
||||
( "Collapsable"
|
||||
, Widget.collapsable
|
||||
{ onToggle = ToggleCollapsable
|
||||
, { onToggle = ToggleCollapsable
|
||||
, isCollapsed = model.isCollapsed
|
||||
, label =
|
||||
Element.row Grid.compact
|
||||
Element.row (Grid.simple ++ [Element.width<| Element.fill])
|
||||
[ Element.html <|
|
||||
if model.isCollapsed then
|
||||
Heroicons.cheveronRight [ Attributes.width 20 ]
|
||||
|
||||
else
|
||||
Heroicons.cheveronDown [ Attributes.width 20 ]
|
||||
, Element.el Heading.h4 <| Element.text <| "Title"
|
||||
, Element.text <| "Title"
|
||||
]
|
||||
, content = Element.text <| "Hello World"
|
||||
}
|
||||
|>Widget.collapsable
|
||||
{ containerColumn = Card.simple ++ Grid.simple
|
||||
++ [ Element.padding 8 ]
|
||||
, button = []
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
tab : Model -> (String,Element Msg)
|
||||
tab model =
|
||||
( "Tab"
|
||||
, Widget.tab
|
||||
{ tabButton = tabButtonStyle
|
||||
, tabRow = Grid.simple
|
||||
{ button = tabButtonStyle
|
||||
, optionRow = Grid.simple
|
||||
, containerColumn = Grid.compact
|
||||
}
|
||||
{ selected = model.tab
|
||||
, options = [ 1, 2, 3 ]
|
||||
@ -315,6 +355,64 @@ iconButton model =
|
||||
] |> Element.column Grid.simple
|
||||
)
|
||||
|
||||
textInput : Model -> (String,Element Msg)
|
||||
textInput model =
|
||||
( "Chip Text Input"
|
||||
, [ { chips =
|
||||
model.chipTextInput
|
||||
|> Set.toList
|
||||
|> List.map (\string ->
|
||||
{ icon = Element.none
|
||||
, text = string
|
||||
, onPress =
|
||||
string
|
||||
|> ToggleTextInputChip
|
||||
|> Just
|
||||
}
|
||||
)
|
||||
, text = model.textInput
|
||||
, placeholder = Nothing
|
||||
, label = "Chips"
|
||||
, onChange = SetTextInput
|
||||
}
|
||||
|> Widget.textInput
|
||||
{ chip = chipButton
|
||||
, chipsRow =
|
||||
[ Element.width <| Element.shrink
|
||||
, Element.spacing <| 4 ]
|
||||
, containerRow =
|
||||
Button.simple
|
||||
++ Color.light
|
||||
++ [ Border.color <| Element.rgb255 186 189 182
|
||||
, Font.alignLeft
|
||||
, Element.padding 8
|
||||
, Element.height <| Element.px <|42
|
||||
]
|
||||
++ Grid.simple
|
||||
, input =
|
||||
Color.light
|
||||
++ [Element.padding 0]
|
||||
}
|
||||
, model.chipTextInput
|
||||
|> Set.diff
|
||||
(["A","B","C"]
|
||||
|> Set.fromList
|
||||
)
|
||||
|> Set.toList
|
||||
|> List.map
|
||||
(\string ->
|
||||
Input.button (Button.simple ++ Tag.simple)
|
||||
{ onPress =
|
||||
string
|
||||
|> ToggleTextInputChip
|
||||
|> Just
|
||||
, label = Element.text string
|
||||
}
|
||||
)
|
||||
|> Element.wrappedRow [ Element.spacing 10 ]
|
||||
] |> Element.column Grid.simple
|
||||
)
|
||||
|
||||
view :
|
||||
{ msgMapper : Msg -> msg
|
||||
, showDialog : msg
|
||||
@ -336,5 +434,6 @@ view { msgMapper, showDialog, changedSheet } model =
|
||||
, carousel model |> Tuple.mapSecond (Element.map msgMapper)
|
||||
, tab model |> Tuple.mapSecond (Element.map msgMapper)
|
||||
, dialog showDialog model
|
||||
, textInput model |> Tuple.mapSecond (Element.map msgMapper)
|
||||
]
|
||||
}
|
||||
|
@ -1,24 +1,19 @@
|
||||
module Widget exposing
|
||||
( select, multiSelect, collapsable, carousel, modal, tab, dialog
|
||||
, Dialog, MultiSelect, Select, selectButton
|
||||
, Dialog, Select, selectButton, textInput
|
||||
)
|
||||
|
||||
{-| This module contains functions for displaying data.
|
||||
|
||||
@docs select, multiSelect, collapsable, carousel, modal, tab, dialog
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
|
||||
@docs dialog
|
||||
|
||||
-}
|
||||
|
||||
import Array exposing (Array)
|
||||
import Element exposing (Attribute, Element)
|
||||
import Element.Background as Background
|
||||
import Element.Events as Events
|
||||
import Element.Input as Input
|
||||
import Element.Input as Input exposing (Placeholder)
|
||||
import Set exposing (Set)
|
||||
import Widget.Button as Button exposing (Button, ButtonStyle, TextButton)
|
||||
|
||||
@ -34,17 +29,6 @@ type alias Select msg =
|
||||
}
|
||||
|
||||
|
||||
type alias MultiSelect msg =
|
||||
{ selected : Set Int
|
||||
, options :
|
||||
List
|
||||
{ text : String
|
||||
, icon : Element Never
|
||||
}
|
||||
, onSelect : Int -> Maybe msg
|
||||
}
|
||||
|
||||
|
||||
type alias Dialog msg =
|
||||
{ title : Maybe String
|
||||
, body : Element msg
|
||||
@ -95,7 +79,14 @@ select { selected, options, onSelect } =
|
||||
{-| Selects multible options. This can be used for checkboxes.
|
||||
-}
|
||||
multiSelect :
|
||||
MultiSelect msg
|
||||
{ selected : Set Int
|
||||
, options :
|
||||
List
|
||||
{ text : String
|
||||
, icon : Element Never
|
||||
}
|
||||
, onSelect : Int -> Maybe msg
|
||||
}
|
||||
-> List ( Bool, Button msg )
|
||||
multiSelect { selected, options, onSelect } =
|
||||
options
|
||||
@ -110,18 +101,51 @@ multiSelect { selected, options, onSelect } =
|
||||
)
|
||||
|
||||
|
||||
{-| -}
|
||||
textInput :
|
||||
{ chip : ButtonStyle msg
|
||||
, containerRow : List (Attribute msg)
|
||||
, chipsRow : List (Attribute msg)
|
||||
, input : List (Attribute msg)
|
||||
}
|
||||
->
|
||||
{ chips : List (Button msg)
|
||||
, text : String
|
||||
, placeholder : Maybe (Placeholder msg)
|
||||
, label : String
|
||||
, onChange : String -> msg
|
||||
}
|
||||
-> Element msg
|
||||
textInput style { chips, placeholder, label, text, onChange } =
|
||||
Element.row style.containerRow
|
||||
[ chips
|
||||
|> List.map (Button.view style.chip)
|
||||
|> Element.row style.chipsRow
|
||||
, Input.text style.input
|
||||
{ onChange = onChange
|
||||
, text = text
|
||||
, placeholder = placeholder
|
||||
, label = Input.labelHidden label
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
{-| Some collapsable content.
|
||||
-}
|
||||
collapsable :
|
||||
{ onToggle : Bool -> msg
|
||||
, isCollapsed : Bool
|
||||
, label : Element msg
|
||||
, content : Element msg
|
||||
{ containerColumn : List (Attribute msg)
|
||||
, button : List (Attribute msg)
|
||||
}
|
||||
->
|
||||
{ onToggle : Bool -> msg
|
||||
, isCollapsed : Bool
|
||||
, label : Element msg
|
||||
, content : Element msg
|
||||
}
|
||||
-> Element msg
|
||||
collapsable { onToggle, isCollapsed, label, content } =
|
||||
Element.column [] <|
|
||||
[ Input.button []
|
||||
collapsable style { onToggle, isCollapsed, label, content } =
|
||||
Element.column style.containerColumn <|
|
||||
[ Input.button style.button
|
||||
{ onPress = Just <| onToggle <| not isCollapsed
|
||||
, label = label
|
||||
}
|
||||
@ -137,9 +161,9 @@ collapsable { onToggle, isCollapsed, label, content } =
|
||||
{-| Displayes a list of contents in a tab
|
||||
-}
|
||||
tab :
|
||||
{ style
|
||||
| tabButton : ButtonStyle msg
|
||||
, tabRow : List (Attribute msg)
|
||||
{ button : ButtonStyle msg
|
||||
, optionRow : List (Attribute msg)
|
||||
, containerColumn : List (Attribute msg)
|
||||
}
|
||||
-> Select msg
|
||||
-> (Maybe Int -> Element msg)
|
||||
@ -147,12 +171,12 @@ tab :
|
||||
tab style options content =
|
||||
[ options
|
||||
|> select
|
||||
|> List.map (selectButton style.tabButton)
|
||||
|> Element.row style.tabRow
|
||||
|> List.map (selectButton style.button)
|
||||
|> Element.row style.optionRow
|
||||
, options.selected
|
||||
|> content
|
||||
]
|
||||
|> Element.column []
|
||||
|> Element.column style.containerColumn
|
||||
|
||||
|
||||
dialog :
|
||||
|
108
src/Widget/FilterMultiSelect.elm
Normal file
108
src/Widget/FilterMultiSelect.elm
Normal file
@ -0,0 +1,108 @@
|
||||
module Widget.FilterMultiSelect exposing (Model, Msg(..), init, update, viewInput, viewOptions)
|
||||
|
||||
{-|
|
||||
|
||||
@docs Model, Msg, init, update, viewInput, viewOptions
|
||||
|
||||
-}
|
||||
|
||||
import Element.Input exposing (Placeholder)
|
||||
import Set exposing (Set)
|
||||
import Widget.Button exposing (Button)
|
||||
|
||||
|
||||
{-| The Model containing the raw value, the selected value and all the possible options.
|
||||
-}
|
||||
type alias Model =
|
||||
{ raw : String
|
||||
, selected : Set String
|
||||
, options : Set String
|
||||
}
|
||||
|
||||
|
||||
{-| The Msg is exposed by design. You can unselect by sending `Selected Nothing`.
|
||||
-}
|
||||
type Msg
|
||||
= ChangedRaw String
|
||||
| ToggleSelected String
|
||||
|
||||
|
||||
{-| The initial state contains the set of possible options.
|
||||
-}
|
||||
init : Set String -> Model
|
||||
init options =
|
||||
{ raw = ""
|
||||
, selected = Set.empty
|
||||
, options = options
|
||||
}
|
||||
|
||||
|
||||
{-| Updates the Model
|
||||
-}
|
||||
update : Msg -> Model -> Model
|
||||
update msg model =
|
||||
case msg of
|
||||
ChangedRaw string ->
|
||||
{ model
|
||||
| raw = string
|
||||
}
|
||||
|
||||
ToggleSelected string ->
|
||||
if model.selected |> Set.member string then
|
||||
{ model
|
||||
| selected = model.selected |> Set.remove string
|
||||
}
|
||||
|
||||
else
|
||||
{ model
|
||||
| selected = model.selected |> Set.insert string
|
||||
, raw = ""
|
||||
}
|
||||
|
||||
|
||||
{-| A wrapper around Input.text.
|
||||
-}
|
||||
viewInput :
|
||||
Model
|
||||
->
|
||||
{ msgMapper : Msg -> msg
|
||||
, placeholder : Maybe (Placeholder msg)
|
||||
, label : String
|
||||
, toChip : String -> Button msg
|
||||
}
|
||||
->
|
||||
{ chips : List (Button msg)
|
||||
, text : String
|
||||
, placeholder : Maybe (Placeholder msg)
|
||||
, label : String
|
||||
, onChange : String -> msg
|
||||
}
|
||||
viewInput model { msgMapper, placeholder, label, toChip } =
|
||||
{ chips =
|
||||
model.selected
|
||||
|> Set.toList
|
||||
|> List.map toChip
|
||||
, text = model.raw
|
||||
, placeholder = placeholder
|
||||
, label = label
|
||||
, onChange = ChangedRaw >> msgMapper
|
||||
}
|
||||
|
||||
|
||||
{-| Returns a List of all options that matches the filter.
|
||||
-}
|
||||
viewOptions : Model -> List String
|
||||
viewOptions { raw, options, selected } =
|
||||
if raw == "" then
|
||||
[]
|
||||
|
||||
else
|
||||
options
|
||||
|> Set.filter (String.toUpper >> String.contains (raw |> String.toUpper))
|
||||
|> Set.filter
|
||||
(\string ->
|
||||
selected
|
||||
|> Set.member string
|
||||
|> not
|
||||
)
|
||||
|> Set.toList
|
@ -20,7 +20,6 @@ module Widget.Snackbar exposing
|
||||
|
||||
import Element exposing (Attribute, Element)
|
||||
import Queue exposing (Queue)
|
||||
import Widget
|
||||
import Widget.Button as Button exposing (ButtonStyle, TextButton)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user