Merge branch 'minor'

This commit is contained in:
Lucas Payr 2020-08-13 19:21:21 +02:00
commit 6dbe10ab25
13 changed files with 429 additions and 21 deletions

File diff suppressed because one or more lines are too long

View File

@ -8,6 +8,7 @@ import Example.ExpansionPanel as ExpansionPanel
import Example.List as List
import Example.Modal as Modal
import Example.MultiSelect as MultiSelect
import Example.ProgressIndicator as ProgressIndicator
import Example.Select as Select
import Example.SortTable as SortTable
import Example.Tab as Tab
@ -27,6 +28,7 @@ type Example
| DialogExample
| TextInputExample
| ListExample
| ProgressIndicatorExample
asList : List Example
@ -41,6 +43,7 @@ asList =
, DialogExample
, TextInputExample
, ListExample
, ProgressIndicatorExample
]
|> List.sortBy toString
@ -78,6 +81,9 @@ toString example =
ListExample ->
"List"
ProgressIndicatorExample ->
"Progress Indicator"
fromString : String -> Maybe Example
fromString string =
@ -112,6 +118,9 @@ fromString string =
"List" ->
Just ListExample
"Progress Indicator" ->
Just ProgressIndicatorExample
_ ->
Nothing
@ -149,6 +158,9 @@ get example =
ListExample ->
.list
ProgressIndicatorExample ->
.progressIndicator
toTests : Example -> msg -> Style msg -> List ( String, Element msg )
toTests example =
@ -183,6 +195,9 @@ toTests example =
ListExample ->
Test.list
ProgressIndicatorExample ->
Test.progressIndicator
type Msg
= Button Button.Msg
@ -195,6 +210,7 @@ type Msg
| Dialog Dialog.Msg
| TextInput TextInput.Msg
| List List.Msg
| ProgressIndicator ProgressIndicator.Msg
type alias Model =
@ -208,6 +224,7 @@ type alias Model =
, dialog : Dialog.Model
, textInput : TextInput.Model
, list : List.Model
, progressIndicator : ProgressIndicator.Model
}
@ -231,6 +248,7 @@ type alias UpgradeCollection =
, dialog : UpgradeRecord Dialog.Model Dialog.Msg
, textInput : UpgradeRecord TextInput.Model TextInput.Msg
, list : UpgradeRecord List.Model List.Msg
, progressIndicator : UpgradeRecord ProgressIndicator.Model ProgressIndicator.Msg
}
@ -245,6 +263,7 @@ type alias ExampleView msg =
, dialog : Element msg
, textInput : Element msg
, list : Element msg
, progressIndicator : Element msg
}
@ -280,6 +299,9 @@ init =
( listModel, listMsg ) =
List.init
( progressIndicatorModel, progressIndicatorMsg ) =
ProgressIndicator.init
in
( { button = buttonModel
, select = selectModel
@ -291,6 +313,7 @@ init =
, dialog = dialogModel
, textInput = textInputModel
, list = listModel
, progressIndicator = progressIndicatorModel
}
, [ Cmd.map Button buttonMsg
, Cmd.map Select selectMsg
@ -302,6 +325,7 @@ init =
, Cmd.map Dialog dialogMsg
, Cmd.map TextInput textInputMsg
, Cmd.map List listMsg
, Cmd.map ProgressIndicator progressIndicatorMsg
]
|> Cmd.batch
)
@ -379,6 +403,13 @@ upgradeRecord =
, updateFun = List.update
, subscriptionsFun = List.subscriptions
}
, progressIndicator =
{ from = .progressIndicator
, to = \model a -> { model | progressIndicator = a }
, msgMapper = ProgressIndicator
, updateFun = ProgressIndicator.update
, subscriptionsFun = ProgressIndicator.subscriptions
}
}
@ -414,6 +445,9 @@ update msg model =
List m ->
updateField .list m
ProgressIndicator m ->
updateField .progressIndicator m
)
model
@ -434,6 +468,7 @@ subscriptions model =
, upgradeRecord.dialog |> subFun
, upgradeRecord.textInput |> subFun
, upgradeRecord.list |> subFun
, upgradeRecord.progressIndicator |> subFun
]
|> Sub.batch
@ -464,6 +499,8 @@ view msgMapper style model =
TextInput.view (TextInput >> msgMapper) style (.textInput model)
, list =
List.view (List >> msgMapper) style (.list model)
, progressIndicator =
ProgressIndicator.view (ProgressIndicator >> msgMapper) style (.progressIndicator model)
}

View File

@ -7,6 +7,7 @@ import Widget.Style
, DialogStyle
, ExpansionPanelStyle
, LayoutStyle
, ProgressIndicatorStyle
, RowStyle
, SortTableStyle
, TabStyle
@ -28,5 +29,6 @@ type alias Style msg =
, cardColumn : ColumnStyle msg
, sortTable : SortTableStyle msg
, selectButton : ButtonStyle msg
, progressIndicator : ProgressIndicatorStyle msg
, layout : LayoutStyle msg
}

View File

@ -20,6 +20,7 @@ import Widget.Style
, DialogStyle
, ExpansionPanelStyle
, LayoutStyle
, ProgressIndicatorStyle
, RowStyle
, SnackbarStyle
, SortTableStyle
@ -283,6 +284,19 @@ sortTable =
}
progressIndicatorStyle : ProgressIndicatorStyle msg
progressIndicatorStyle =
{ containerFunction =
\maybeProgress ->
case maybeProgress of
Nothing ->
Element.text "Indeterminate progress indicator"
Just progress ->
Element.text ("Determinate progress indicator, " ++ String.fromFloat progress ++ "completeness")
}
layout : LayoutStyle msg
layout =
{ container = []
@ -335,5 +349,6 @@ style =
, expansionPanel = expansionPanelStyle
, dialog = dialog
, selectButton = buttonStyle
, progressIndicator = progressIndicatorStyle
, layout = layout
}

View File

@ -52,5 +52,6 @@ style palette =
, chipButton = Material.chip palette
, expansionPanel = Material.expansionPanel palette
, dialog = Material.alertDialog palette
, progressIndicator = Material.progressIndicator palette
, layout = Material.layout palette
}

View File

@ -23,5 +23,6 @@ style =
, expansionPanel = Template.expansionPanel "expansionPanel"
, selectButton = Template.button "selectButton"
, dialog = Template.dialog "dialog"
, progressIndicator = Template.progressIndicator "progressIndicator"
, layout = Template.layout "layout"
}

View File

@ -0,0 +1,65 @@
module Example.ProgressIndicator exposing (Model, Msg, init, subscriptions, update, view)
import Browser
import Element exposing (Element)
import Widget
import Widget.Style exposing (ProgressIndicatorStyle)
import Widget.Style.Material as Material
type alias Style style msg =
{ style
| progressIndicator : ProgressIndicatorStyle msg
}
materialStyle : Style {} msg
materialStyle =
{ progressIndicator = Material.progressIndicator Material.defaultPalette
}
type Model
= MaybeProgress (Maybe Float)
type Msg
= ChangedProgress (Maybe Float)
init : ( Model, Cmd Msg )
init =
( MaybeProgress Nothing
, Cmd.none
)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg _ =
case msg of
ChangedProgress maybeFloat ->
( MaybeProgress maybeFloat
, Cmd.none
)
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
{-| You can remove the msgMapper. But by doing so, make sure to also change `msg` to `Msg` in the line below.
-}
view : (Msg -> msg) -> Style style msg -> Model -> Element msg
view msgMapper style (MaybeProgress maybeProgress) =
Widget.circularProgressIndicator style.progressIndicator maybeProgress
main : Program () Model Msg
main =
Browser.element
{ init = always init
, view = view identity materialStyle >> Element.layout []
, update = update
, subscriptions = subscriptions
}

View File

@ -1,4 +1,4 @@
module View.Test exposing (button, dialog, expansionPanel, list, modal, multiSelect, select, sortTable, tab, textInput)
module View.Test exposing (button, dialog, expansionPanel, list, modal, multiSelect, progressIndicator, select, sortTable, tab, textInput)
import Data.Style exposing (Style)
import Element exposing (Element)
@ -511,3 +511,22 @@ list _ style =
|> Widget.column style.cardColumn
)
]
progressIndicator : msg -> Style msg -> List ( String, Element msg )
progressIndicator _ style =
let
determinateIndicators =
[ 0, 0.25, 0.50, 0.75, 1 ]
|> List.map
(\completeness ->
( "Completeness " ++ String.fromFloat completeness
, Widget.circularProgressIndicator style.progressIndicator (Just completeness)
)
)
in
[ ( "Indeterminate Progress Indicator"
, Widget.circularProgressIndicator style.progressIndicator Nothing
)
]
++ determinateIndicators

View File

@ -0,0 +1,12 @@
module Internal.ProgressIndicator exposing (circularProgressIndicator)
import Element exposing (Element)
import Widget.Style exposing (ProgressIndicatorStyle)
circularProgressIndicator :
ProgressIndicatorStyle msg
-> Maybe Float
-> Element msg
circularProgressIndicator style maybeProgress =
style.containerFunction maybeProgress

View File

@ -2,12 +2,14 @@ module Widget exposing
( Button, TextButton, iconButton, textButton, button
, Select, selectButton, select
, MultiSelect, multiSelect
, Dialog, modal, dialog
, ExpansionPanel, expansionPanel
, DialogV2, modal, dialog
, ExpansionPanelV2, expansionPanel
, row, column, buttonRow, buttonColumn
, SortTable, Column, sortTable, floatColumn, intColumn, stringColumn, unsortableColumn
, TextInput, textInput
, Tab, tab
, Dialog, ExpansionPanel
, ProgressIndicator, circularProgressIndicator
)
{-| This module contains different stateless view functions. No wiring required.
@ -65,7 +67,7 @@ You can create you own widgets by sticking widgets types together.
[Open in Ellie](https://ellie-app.com/9p5Rdz625TZa1)
@docs Dialog, modal, dialog
@docs DialogV2, modal, dialog
# Expansion Panel
@ -74,7 +76,7 @@ You can create you own widgets by sticking widgets types together.
[Open in Ellie](https://ellie-app.com/9p5Rv5jfVdFa1)
@docs ExpansionPanel, expansionPanel
@docs ExpansionPanelV2, expansionPanel
# List
@ -112,6 +114,16 @@ You can create you own widgets by sticking widgets types together.
@docs Tab, tab
# DEPRECATED
@docs Dialog, ExpansionPanel
# Progress Indicator
@docs ProgressIndicator, circularProgressIndicator
-}
import Element exposing (Attribute, Element, Length)
@ -120,12 +132,13 @@ import Internal.Button as Button
import Internal.Dialog as Dialog
import Internal.ExpansionPanel as ExpansionPanel
import Internal.List as List
import Internal.ProgressIndicator as ProgressIndicator
import Internal.Select as Select
import Internal.SortTable as SortTable
import Internal.Tab as Tab
import Internal.TextInput as TextInput
import Set exposing (Set)
import Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, RowStyle, SortTableStyle, TabStyle, TextInputStyle)
import Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, ProgressIndicatorStyle, RowStyle, SortTableStyle, TabStyle, TextInputStyle)
@ -162,7 +175,12 @@ iconButton :
}
-> Element msg
iconButton =
Button.iconButton
let
fun : ButtonStyle msg -> Button msg -> Element msg
fun =
Button.iconButton
in
fun
{-| A button with just text and not icon.
@ -176,7 +194,12 @@ textButton :
}
-> Element msg
textButton style { text, onPress } =
Button.textButton style
let
fun : ButtonStyle msg -> TextButton msg -> Element msg
fun =
Button.textButton
in
fun style
{ text = text
, onPress = onPress
}
@ -193,7 +216,12 @@ button :
}
-> Element msg
button =
Button.button
let
fun : ButtonStyle msg -> Button msg -> Element msg
fun =
Button.button
in
fun
@ -272,7 +300,10 @@ multiSelect =
----------------------------------------------------------}
{-| Dialog widget type
{-| DEPRECATED
Use `DialogV2` instead
-}
type alias Dialog msg =
{ title : Maybe String
@ -282,6 +313,16 @@ type alias Dialog msg =
}
{-| Dialog widget type
-}
type alias DialogV2 msg =
{ title : Maybe String
, text : String
, accept : Maybe (TextButton msg)
, dismiss : Maybe (TextButton msg)
}
{-| A modal.
Technical Remark:
@ -306,7 +347,12 @@ dialog :
}
-> List (Attribute msg)
dialog =
Dialog.dialog
let
fun : DialogStyle msg -> DialogV2 msg -> List (Attribute msg)
fun =
Dialog.dialog
in
fun
@ -315,7 +361,10 @@ dialog =
----------------------------------------------------------}
{-| Expansion Panel widget type
{-| DEPRECATED
Use `ExpansionPanelV2` instead
-}
type alias ExpansionPanel msg =
{ onToggle : Bool -> msg
@ -328,6 +377,17 @@ type alias ExpansionPanel msg =
}
{-| Expansion Panel widget type
-}
type alias ExpansionPanelV2 msg =
{ onToggle : Bool -> msg
, icon : Element Never
, text : String
, content : Element msg
, isExpanded : Bool
}
{-| An expansion Panel
-}
expansionPanel :
@ -341,7 +401,12 @@ expansionPanel :
}
-> Element msg
expansionPanel =
ExpansionPanel.expansionPanel
let
fun : ExpansionPanelStyle msg -> ExpansionPanelV2 msg -> Element msg
fun =
ExpansionPanel.expansionPanel
in
fun
@ -374,7 +439,12 @@ textInput :
}
-> Element msg
textInput =
TextInput.textInput
let
fun : TextInputStyle msg -> TextInput msg -> Element msg
fun =
TextInput.textInput
in
fun
@ -515,7 +585,12 @@ sortTable :
}
-> Element msg
sortTable =
SortTable.sortTable
let
fun : SortTableStyle msg -> SortTable a msg -> Element msg
fun =
SortTable.sortTable
in
fun
@ -542,4 +617,35 @@ tab :
}
-> Element msg
tab =
Tab.tab
let
fun : TabStyle msg -> Tab msg -> Element msg
fun =
Tab.tab
in
fun
{----------------------------------------------------------
- PROGRESS INDICATOR
----------------------------------------------------------}
{-| Progress Indicator widget type
If `maybeProgress` is set to `Nothing`, an indeterminate progress indicator (e.g. spinner) will display.
If `maybeProgress` is set to `Just Float` (where the `Float` is proportion of completeness between 0 and 1 inclusive), a determinate progress indicator will visualize the progress.
-}
type alias ProgressIndicator =
Maybe Float
{-| Displays a circular progress indicator
-}
circularProgressIndicator :
ProgressIndicatorStyle msg
-> Maybe Float
-> Element msg
circularProgressIndicator =
ProgressIndicator.circularProgressIndicator

View File

@ -1,8 +1,8 @@
module Widget.Style exposing (ButtonStyle,ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle)
module Widget.Style exposing (ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle, ProgressIndicatorStyle)
{-| This module contains style types for every widget.
@docs ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle
@docs ButtonStyle, ColumnStyle, DialogStyle, ExpansionPanelStyle, LayoutStyle, RowStyle, SnackbarStyle, SortTableStyle, TabStyle, TextInputStyle, ProgressIndicatorStyle
-}
@ -132,3 +132,9 @@ type alias LayoutStyle msg =
, search : List (Attribute msg)
, searchFill : List (Attribute msg)
}
{-| -}
type alias ProgressIndicatorStyle msg =
{ containerFunction : Maybe Float -> Element msg
}

View File

@ -7,6 +7,7 @@ module Widget.Style.Material exposing
, alertDialog
, expansionPanel
, row, column
, progressIndicator
, snackbar
, tab, tabButton
, layout
@ -42,6 +43,7 @@ You can use the theme by copying the following code:
, cardColumn : ColumnStyle msg
, sortTable : SortTableStyle msg
, selectButton : ButtonStyle msg
, progressIndicator : ProgressIndicatorStyle msg
, layout : LayoutStyle msg
}
@ -69,6 +71,7 @@ You can use the theme by copying the following code:
, chipButton = Material.chip palette
, expansionPanel = Material.expansionPanel palette
, dialog = Material.alertDialog palette
, progressIndicator = Material.progressIndicator palette
, layout = Material.layout palette
}
@ -123,6 +126,11 @@ The [List widget](https://material.io/components/lists) is a very complex widget
@docs row, column
# Progress Indicator
@docs progressIndicator
# Snackbar
@docs snackbar
@ -156,6 +164,7 @@ import Widget.Style
, DialogStyle
, ExpansionPanelStyle
, LayoutStyle
, ProgressIndicatorStyle
, RowStyle
, SnackbarStyle
, TabStyle
@ -1201,6 +1210,124 @@ expansionPanel palette =
{-------------------------------------------------------------------------------
-- P R O G R E S S I N D I C A T O R
-------------------------------------------------------------------------------}
indeterminateCircularIcon : Color.Color -> List (Attribute msg) -> Element msg
indeterminateCircularIcon color attribs =
-- Based on example at https://codepen.io/FezVrasta/pen/oXrgdR
Svg.svg
[ Svg.Attributes.height "48px"
, Svg.Attributes.width "48px"
, Svg.Attributes.viewBox "0 0 66 66"
, Svg.Attributes.xmlSpace "http://www.w3.org/2000/svg"
]
[ Svg.g []
[ Svg.animateTransform
[ Svg.Attributes.attributeName "transform"
, Svg.Attributes.type_ "rotate"
, Svg.Attributes.values "0 33 33;270 33 33"
, Svg.Attributes.begin "0s"
, Svg.Attributes.dur "1.4s"
, Svg.Attributes.fill "freeze"
, Svg.Attributes.repeatCount "indefinite"
]
[]
, Svg.circle
[ Svg.Attributes.fill "none"
, Svg.Attributes.stroke (Color.toCssString color)
, Svg.Attributes.strokeWidth "5"
, Svg.Attributes.strokeLinecap "square"
, Svg.Attributes.cx "33"
, Svg.Attributes.cy "33"
, Svg.Attributes.r "30"
, Svg.Attributes.strokeDasharray "187"
, Svg.Attributes.strokeDashoffset "610"
]
[ Svg.animateTransform
[ Svg.Attributes.attributeName "transform"
, Svg.Attributes.type_ "rotate"
, Svg.Attributes.values "0 33 33;135 33 33;450 33 33"
, Svg.Attributes.begin "0s"
, Svg.Attributes.dur "1.4s"
, Svg.Attributes.fill "freeze"
, Svg.Attributes.repeatCount "indefinite"
]
[]
, Svg.animate
[ Svg.Attributes.attributeName "stroke-dashoffset"
, Svg.Attributes.values "187;46.75;187"
, Svg.Attributes.begin "0s"
, Svg.Attributes.dur "1.4s"
, Svg.Attributes.fill "freeze"
, Svg.Attributes.repeatCount "indefinite"
]
[]
]
]
]
|> Element.html
|> Element.el attribs
determinateCircularIcon : Color.Color -> List (Attribute msg) -> Float -> Element msg
determinateCircularIcon color attribs progress =
-- With help from https://css-tricks.com/building-progress-ring-quickly/
let
strokeDashoffset =
let
clampedProgress =
clamp 0 1 progress
in
-- 188 is circumference of circle in pixels
188
- (188 * clampedProgress)
|> round
in
Svg.svg
[ Svg.Attributes.height "48px"
, Svg.Attributes.width "48px"
, Svg.Attributes.viewBox "0 0 66 66"
, Svg.Attributes.xmlSpace "http://www.w3.org/2000/svg"
]
[ Svg.g []
[ Svg.circle
[ Svg.Attributes.fill "none"
, Svg.Attributes.stroke (Color.toCssString color)
, Svg.Attributes.strokeWidth "5"
, Svg.Attributes.strokeLinecap "butt"
, Svg.Attributes.cx "33"
, Svg.Attributes.cy "33"
, Svg.Attributes.r "30"
, Svg.Attributes.strokeDasharray "188 188"
, Svg.Attributes.strokeDashoffset (String.fromInt strokeDashoffset)
, Svg.Attributes.transform "rotate(-90 33 33)"
]
[]
]
]
|> Element.html
|> Element.el attribs
{-| A circular progress indicator
-}
progressIndicator : Palette -> ProgressIndicatorStyle msg
progressIndicator palette =
{ containerFunction =
\maybeProgress ->
case maybeProgress of
Nothing ->
indeterminateCircularIcon palette.primary []
Just progress ->
determinateCircularIcon palette.primary [] progress
}
{-------------------------------------------------------------------------------
-- S N A C K B A R
-------------------------------------------------------------------------------}

View File

@ -1,6 +1,6 @@
module Widget.Style.Template exposing
( box, decoration, icon
, button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput
, button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput, progressIndicator
)
{-| ![Example using the Template style](https://orasund.github.io/elm-ui-widgets/assets/template-style.png)
@ -54,7 +54,7 @@ style =
# Mockups
@docs button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput
@docs button, column, dialog, expansionPanel, layout, row, snackbar, sortTable, tab, textInput, progressIndicator
-}
@ -69,6 +69,7 @@ import Widget.Style
, DialogStyle
, ExpansionPanelStyle
, LayoutStyle
, ProgressIndicatorStyle
, RowStyle
, SnackbarStyle
, SortTableStyle
@ -339,6 +340,22 @@ sortTable string =
}
{-|
```
progressIndicator : String -> ProgressIndicatorStyle msg
progressIndicator string =
{ icon = (\_ -> icon <| string ++ ":icon")
}
```
-}
progressIndicator : String -> ProgressIndicatorStyle msg
progressIndicator string =
{ containerFunction = \_ -> icon <| string ++ ":icon"
}
{-|
```