explorer: refactor the tooling

This commit is contained in:
Christophe de Vienne 2021-05-24 00:12:06 +02:00
parent c24a664d1a
commit 168d2df830
3 changed files with 214 additions and 232 deletions

View File

@ -4,8 +4,8 @@ import Element exposing (Element)
import Element.Background as Background
import Material.Icons as MaterialIcons exposing (offline_bolt)
import Material.Icons.Types exposing (Coloring(..))
import Story
import Tooling
import UIExplorer.Story as Story
import UIExplorer.Tile as Tile
import UiExplorer
import Widget
import Widget.Customize as Customize
@ -16,28 +16,22 @@ import Widget.Material.Typography as Typography
page =
Tooling.firstBloc (intro |> Tooling.withBlocTitle "Button")
|> Tooling.nextBlocList book
|> Tooling.nextBloc demo
|> Tooling.page
Tile.first (intro |> Tile.withTitle "Button")
|> Tile.nextGroup book
|> Tile.next demo
|> Tile.page
intro =
Tooling.markdown []
Tile.markdown []
""" A simple button """
book =
Story.book (Just "States")
(Story.initStaticBlocs
|> Story.addBloc Tooling.LeftColumnBloc
[ Background.color <| MaterialColor.fromColor MaterialColor.gray ]
Nothing
viewButton
|> Story.addBloc Tooling.FullWidthBloc
[]
(Just "source code")
viewButtonSource
(Story.initStaticTiles
|> Story.addTile viewButton
|> Story.addTile viewButtonSource
)
|> Story.addStory
(Story.optionListStory "Palette"
@ -78,43 +72,53 @@ book =
viewButton palette text icon onPress size _ _ =
Widget.button
(containedButton palette
|> Customize.elementButton
[ Element.height <| Element.px size
, Element.centerX
, Element.centerY
]
)
{ text = text
, icon = icon
, onPress = onPress
}
{ title = Nothing
, position = Tile.LeftColumnTile
, attributes = [ Background.color <| MaterialColor.fromColor MaterialColor.gray ]
, body =
Widget.button
(containedButton palette
|> Customize.elementButton
[ Element.height <| Element.px size
, Element.centerX
, Element.centerY
]
)
{ text = text
, icon = icon
, onPress = onPress
}
}
viewButtonSource palette text icon onPress size _ _ =
Tooling.sourceCode <|
"""Widget.button
{ title = Just "source code"
, position = Tile.FullWidthTile
, attributes = []
, body =
Tile.sourceCode <|
"""Widget.button
(Material.containedButton palette
|> Customize.elementButton [ Element.height <| Element.px """
++ String.fromInt size
++ """ ]
++ String.fromInt size
++ """ ]
)
{ text =\""""
++ text
++ """"
++ text
++ """"
, icon = MaterialIcons.done |> Icon.elmMaterialIcons Widget.Material.Types.Color
, onPress = """
++ (case onPress of
Nothing ->
"Nothing"
++ (case onPress of
Nothing ->
"Nothing"
Just () ->
"Just ()"
)
++ """
Just () ->
"Just ()"
)
++ """
}
"""
}
type alias Model =
@ -129,13 +133,12 @@ type Msg
--|> Story.addBloc (Just "Interactive example") view
--|> Story.addTile (Just "Interactive example") view
demo =
{ init = always init
, update = update
, title = Just "Interactive Demo"
, view = view
, subscriptions = subscriptions
}
@ -192,7 +195,8 @@ view _ model =
, cardColumn = Material.cardColumn palette
}
in
{ position = Tooling.FullWidthBloc
{ title = Just "Interactive Demo"
, position = Tile.FullWidthTile
, attributes = []
, body =
[ model

View File

@ -1,10 +1,10 @@
module Story exposing (..)
module UIExplorer.Story exposing (..)
import Dict exposing (Dict)
import Element exposing (Attribute, Element)
import Element.Input as Input exposing (Label, Option, labelAbove, option, radio)
import SelectList exposing (SelectList)
import Tooling
import UIExplorer.Tile as Tile
import UiExplorer exposing (PageSize)
@ -74,20 +74,18 @@ boolStory label ( ifTrue, ifFalse ) default =
}
type alias BlocList view model msg flags =
type alias Group view model msg flags =
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, titles : List (Maybe String)
, views : List ( Tooling.BlocPosition, List (Attribute msg), view )
, views : List view
, subscriptions : model -> Sub msg
}
type alias BlocListBuilder view model msg flags a =
type alias GroupBuilder view model msg flags a =
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, titles : List (Maybe String)
, views : a -> List ( Tooling.BlocPosition, List (Attribute msg), view )
, views : a -> List view
, subscriptions : model -> Sub msg
}
@ -96,24 +94,23 @@ type alias BookBuilder view model msg flags a =
{ title : Maybe String
, stories : List StoryInfo
, storiesToValue : List String -> a
, bloclist : BlocListBuilder view model msg flags a
, tilelist : GroupBuilder view model msg flags a
}
book :
Maybe String
-> BlocList view model msg flags
-> Group view model msg flags
-> BookBuilder view model msg flags ()
book title bloclist =
book title tilelist =
{ title = title
, stories = []
, storiesToValue = always ()
, bloclist =
{ init = bloclist.init
, update = bloclist.update
, titles = bloclist.titles
, subscriptions = bloclist.subscriptions
, views = always bloclist.views
, tilelist =
{ init = tilelist.init
, update = tilelist.update
, subscriptions = tilelist.subscriptions
, views = always tilelist.views
}
}
@ -133,56 +130,53 @@ addStory { info, toValue } builder =
{ title = builder.title
, stories = info :: builder.stories
, storiesToValue = storiesToValue
, bloclist = addStoryToBlocList builder.bloclist
, tilelist = addStoryToGroup builder.tilelist
}
addStoryToBlocList : BlocListBuilder (a -> view) model msg flags previous -> BlocListBuilder view model msg flags ( a, previous )
addStoryToBlocList builder =
addStoryToGroup : GroupBuilder (a -> view) model msg flags previous -> GroupBuilder view model msg flags ( a, previous )
addStoryToGroup builder =
{ init = builder.init
, update = builder.update
, titles = builder.titles
, subscriptions = builder.subscriptions
, views =
\( a, previous ) ->
builder.views previous
|> List.map (\( position, attrs, view ) -> ( position, attrs, view a ))
|> List.map
(\view ->
view a
)
}
initBlocs :
initTiles :
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, subscriptions : model -> Sub msg
}
-> BlocList view model msg flags
initBlocs { init, update, subscriptions } =
-> Group view model msg flags
initTiles { init, update, subscriptions } =
{ init = init
, titles = []
, update = update
, views = []
, subscriptions = subscriptions
}
addBloc :
Tooling.BlocPosition
-> List (Attribute msg)
-> Maybe String
-> view
-> BlocList view model msg flags
-> BlocList view model msg flags
addBloc position attributes title view bloclist =
{ bloclist
| titles = List.append bloclist.titles [ title ]
, views = List.append bloclist.views [ ( position, attributes, view ) ]
addTile :
view
-> Group view model msg flags
-> Group view model msg flags
addTile view tilelist =
{ tilelist
| views =
List.append tilelist.views [ view ]
}
initStaticBlocs : BlocList view () () ()
initStaticBlocs =
initStaticTiles : Group view () () ()
initStaticTiles =
{ init = always ( (), Cmd.none )
, titles = []
, update = \_ _ -> ( (), Cmd.none )
, views = []
, subscriptions = always Sub.none
@ -372,8 +366,8 @@ storyView model =
}
storyBloc : Maybe String -> List StoryInfo -> (List String -> a) -> Tooling.BlocList StorySelectorModel StorySelectorMsg flags
storyBloc title stories storiesToValue =
storyTile : Maybe String -> List StoryInfo -> (List String -> a) -> Tile.Group StorySelectorModel StorySelectorMsg flags
storyTile title stories storiesToValue =
{ init =
\_ ->
( stories
@ -386,11 +380,11 @@ storyBloc title stories storiesToValue =
case msg of
StorySelect story value ->
( selectStory story value model, Cmd.none )
, titles = [ title ]
, subscriptions = always Sub.none
, views =
\_ model ->
[ { position = Tooling.NewRightColumnBloc
[ { title = title
, position = Tile.NewRightColumnTile
, attributes = []
, body =
model
@ -402,30 +396,25 @@ storyBloc title stories storiesToValue =
build :
BookBuilder (PageSize -> model -> Element msg) model msg flags a
-> Tooling.BlocList ( StorySelectorModel, model ) (Tooling.BlocMsg StorySelectorMsg msg) flags
BookBuilder (PageSize -> model -> Tile.View msg) model msg flags a
-> Tile.Group ( StorySelectorModel, model ) (Tile.TileMsg StorySelectorMsg msg) flags
build builder =
storyBloc builder.title builder.stories builder.storiesToValue
|> Tooling.linkBlocList
{ init = builder.bloclist.init
storyTile builder.title builder.stories builder.storiesToValue
|> Tile.linkGroup
{ init = builder.tilelist.init
, update =
\msg ( selectorModel, model ) ->
builder.bloclist.update msg model
, titles = builder.bloclist.titles
, subscriptions = Tuple.second >> builder.bloclist.subscriptions
builder.tilelist.update msg model
, subscriptions = Tuple.second >> builder.tilelist.subscriptions
, views =
\pagesize ( selectorModel, model ) ->
List.map
(\( position, attrs, view ) ->
{ position = position
, attributes = attrs
, body = view pagesize model
}
)
(selectorModel
|> selectedStories
|> List.reverse
|> builder.storiesToValue
|> builder.bloclist.views
)
selectorModel
|> selectedStories
|> List.reverse
|> builder.storiesToValue
|> builder.tilelist.views
|> List.map
(\view ->
view pagesize model
)
}

View File

@ -1,4 +1,4 @@
module Tooling exposing (..)
module UIExplorer.Tile exposing (..)
import Dict exposing (Dict)
import Element exposing (Attribute, Element)
@ -13,68 +13,67 @@ import Widget.Material.Color as MaterialColor
import Widget.Material.Typography as Typography
type BlocPosition
= FullWidthBloc
| RightColumnBloc
| NewRightColumnBloc
| LeftColumnBloc
| NewLeftColumnBloc
type Position
= FullWidthTile
| RightColumnTile
| NewRightColumnTile
| LeftColumnTile
| NewLeftColumnTile
type alias BlocView msg =
{ body : Element msg
, position : BlocPosition
type alias View msg =
{ title : Maybe String
, position : Position
, attributes : List (Attribute msg)
, body : Element msg
}
mapBlocView : (a -> b) -> BlocView a -> BlocView b
mapBlocView map view =
{ body = Element.map map view.body
mapView : (a -> b) -> View a -> View b
mapView map view =
{ title = view.title
, position = view.position
, attributes = List.map (Element.mapAttribute map) view.attributes
, body = Element.map map view.body
}
mapBlocViewList : (a -> b) -> List (BlocView a) -> List (BlocView b)
mapBlocViewList map =
List.map (mapBlocView map)
mapViewList : (a -> b) -> List (View a) -> List (View b)
mapViewList map =
List.map (mapView map)
type alias Bloc model msg flags =
type alias Tile model msg flags =
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, title : Maybe String
, view : PageSize -> model -> BlocView msg
, view : PageSize -> model -> View msg
, subscriptions : model -> Sub msg
}
type alias BlocList model msg flags =
type alias Group model msg flags =
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, titles : List (Maybe String)
, views : PageSize -> model -> List (BlocView msg)
, views : PageSize -> model -> List (View msg)
, subscriptions : model -> Sub msg
}
type alias LinkedBlockList sharedModel model msg flags =
type alias LinkedGroup sharedModel model msg flags =
{ init : flags -> ( model, Cmd msg )
, update : msg -> ( sharedModel, model ) -> ( model, Cmd msg )
, titles : List (Maybe String)
, views : PageSize -> ( sharedModel, model ) -> List (BlocView msg)
, views : PageSize -> ( sharedModel, model ) -> List (View msg)
, subscriptions : ( sharedModel, model ) -> Sub msg
}
linkBlocList :
LinkedBlockList sharedModel model msg flags
-> BlocList sharedModel upMsg flags
-> BlocList ( sharedModel, model ) (BlocMsg upMsg msg) flags
linkBlocList linked parent =
linkGroup :
LinkedGroup sharedModel model msg flags
-> Group sharedModel upMsg flags
-> Group ( sharedModel, model ) (TileMsg upMsg msg) flags
linkGroup linked parent =
let
init_ : flags -> ( ( sharedModel, model ), Cmd (BlocMsg upMsg msg) )
init_ : flags -> ( ( sharedModel, model ), Cmd (TileMsg upMsg msg) )
init_ flags =
let
( parentModel, parentCmd ) =
@ -101,9 +100,6 @@ linkBlocList linked parent =
in
( ( sharedModel, newModel ), Cmd.map Current cmd )
titles_ =
List.append parent.titles linked.titles
subscriptions_ ( sharedModel, model ) =
Sub.batch
[ Sub.map Current (linked.subscriptions ( sharedModel, model ))
@ -112,85 +108,75 @@ linkBlocList linked parent =
views_ pageSize ( sharedModel, model ) =
List.append
(parent.views pageSize sharedModel |> mapBlocViewList Previous)
(linked.views pageSize ( sharedModel, model ) |> mapBlocViewList Current)
(parent.views pageSize sharedModel |> mapViewList Previous)
(linked.views pageSize ( sharedModel, model ) |> mapViewList Current)
in
{ init = init_
, update = update_
, titles = titles_
, views = views_
, subscriptions = subscriptions_
}
-- addLinkedBlocList :
-- LinkedBlockList sharedModel model msg flags
-- -> BlocList ( sharedModel, previousModel ) upMsg flags
-- -> BlocList ( sharedModel, ( model, previousModel ) ) (BlocMsg upMsg msg) flags
blocListSingleton : Bloc model msg flags -> BlocList model msg flags
blocListSingleton bloc =
{ init = bloc.init
, update = bloc.update
, titles = List.singleton bloc.title
groupSingleton : Tile model msg flags -> Group model msg flags
groupSingleton tile =
{ init = tile.init
, update = tile.update
, views =
\pagesize model ->
List.singleton <| bloc.view pagesize model
, subscriptions = bloc.subscriptions
List.singleton <| tile.view pagesize model
, subscriptions = tile.subscriptions
}
type alias BlocMeta =
{ title : Maybe String }
{-| -}
type BlocBuilder model msg flags
= BlocBuilder
type Builder model msg flags
= Builder
{ init : flags -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, views : PageSize -> model -> List (BlocView msg)
, views : PageSize -> model -> List (View msg)
, subscriptions : model -> Sub msg
, meta : List BlocMeta
}
type BlocMsg previous current
type TileMsg previous current
= Previous previous
| Current current
firstBloc : Bloc model msg flags -> BlocBuilder ( (), model ) (BlocMsg () msg) flags
firstBloc config =
BlocBuilder
firstGroup : Group model msg flags -> Builder ( (), model ) (TileMsg () msg) flags
firstGroup config =
Builder
{ init = always ( (), Cmd.none )
, update = \_ m -> ( m, Cmd.none )
, views =
\_ _ ->
[]
, subscriptions = always Sub.none
, meta = []
}
|> nextBloc config
|> nextGroup config
nextBloc :
Bloc model msg flags
-> BlocBuilder modelPrevious msgPrevious flags
-> BlocBuilder ( modelPrevious, model ) (BlocMsg msgPrevious msg) flags
nextBloc =
blocListSingleton >> nextBlocList
first : Tile model msg flags -> Builder ( (), model ) (TileMsg () msg) flags
first =
groupSingleton >> firstGroup
nextBlocList :
BlocList model msg flags
-> BlocBuilder modelPrevious msgPrevious flags
-> BlocBuilder ( modelPrevious, model ) (BlocMsg msgPrevious msg) flags
nextBlocList config (BlocBuilder previous) =
next :
Tile model msg flags
-> Builder modelPrevious msgPrevious flags
-> Builder ( modelPrevious, model ) (TileMsg msgPrevious msg) flags
next =
groupSingleton >> nextGroup
nextGroup :
Group model msg flags
-> Builder modelPrevious msgPrevious flags
-> Builder ( modelPrevious, model ) (TileMsg msgPrevious msg) flags
nextGroup config (Builder previous) =
let
init_ : flags -> ( ( modelPrevious, model ), Cmd (BlocMsg msgPrevious msg) )
init_ : flags -> ( ( modelPrevious, model ), Cmd (TileMsg msgPrevious msg) )
init_ flags =
let
( previousModel, previousCmds ) =
@ -202,9 +188,9 @@ nextBlocList config (BlocBuilder previous) =
( ( previousModel, model ), Cmd.batch [ Cmd.map Previous previousCmds, Cmd.map Current cmds ] )
update_ :
BlocMsg msgPrevious msg
TileMsg msgPrevious msg
-> ( modelPrevious, model )
-> ( ( modelPrevious, model ), Cmd (BlocMsg msgPrevious msg) )
-> ( ( modelPrevious, model ), Cmd (TileMsg msgPrevious msg) )
update_ msg ( previousModel, model ) =
case msg of
Previous previousMsg ->
@ -221,11 +207,11 @@ nextBlocList config (BlocBuilder previous) =
in
( ( previousModel, newModel ), Cmd.map Current cmds )
views_ : PageSize -> ( modelPrevious, model ) -> List (BlocView (BlocMsg msgPrevious msg))
views_ : PageSize -> ( modelPrevious, model ) -> List (View (TileMsg msgPrevious msg))
views_ windowSize ( previousModel, model ) =
List.append
(previous.views windowSize previousModel |> mapBlocViewList Previous)
(config.views windowSize model |> mapBlocViewList Current)
(previous.views windowSize previousModel |> mapViewList Previous)
(config.views windowSize model |> mapViewList Current)
subscriptions_ ( previousModel, model ) =
Sub.batch
@ -233,63 +219,59 @@ nextBlocList config (BlocBuilder previous) =
, Sub.map Previous (previous.subscriptions previousModel)
]
in
BlocBuilder
Builder
{ init = init_
, update = update_
, views = views_
, subscriptions = subscriptions_
, meta =
List.append
previous.meta
(List.map (\title -> { title = title }) config.titles)
}
type LayoutRow msg
= OneColumn (List ( BlocMeta, BlocView msg ))
| TwoColumn (List ( BlocMeta, BlocView msg )) (List ( BlocMeta, BlocView msg ))
= OneColumn (List (View msg))
| TwoColumn (List (View msg)) (List (View msg))
type alias Layout msg =
List (LayoutRow msg)
layoutAddBloc : ( BlocMeta, BlocView msg ) -> Layout msg -> Layout msg
layoutAddBloc ( meta, view ) layout =
layoutAddTile : View msg -> Layout msg -> Layout msg
layoutAddTile view layout =
case view.position of
FullWidthBloc ->
FullWidthTile ->
case layout of
(OneColumn items) :: tail ->
OneColumn (( meta, view ) :: items) :: tail
OneColumn (view :: items) :: tail
_ ->
OneColumn [ ( meta, view ) ] :: layout
OneColumn [ view ] :: layout
LeftColumnBloc ->
LeftColumnTile ->
case layout of
(TwoColumn left right) :: tail ->
TwoColumn (( meta, view ) :: left) right :: tail
TwoColumn (view :: left) right :: tail
_ ->
TwoColumn [ ( meta, view ) ] [] :: layout
TwoColumn [ view ] [] :: layout
NewLeftColumnBloc ->
TwoColumn [ ( meta, view ) ] [] :: layout
NewLeftColumnTile ->
TwoColumn [ view ] [] :: layout
RightColumnBloc ->
RightColumnTile ->
case layout of
(TwoColumn left right) :: tail ->
TwoColumn left (( meta, view ) :: right) :: tail
TwoColumn left (view :: right) :: tail
_ ->
TwoColumn [] [ ( meta, view ) ] :: layout
TwoColumn [] [ view ] :: layout
NewRightColumnBloc ->
TwoColumn [] [ ( meta, view ) ] :: layout
NewRightColumnTile ->
TwoColumn [] [ view ] :: layout
layoutBlocView : List (Attribute msg) -> ( BlocMeta, BlocView msg ) -> Element msg
layoutBlocView attributes ( meta, view ) =
layoutView : List (Attribute msg) -> View msg -> Element msg
layoutView attributes view =
Widget.column
(Material.cardColumn Material.defaultPalette
|> Customize.elementColumn attributes
@ -297,7 +279,7 @@ layoutBlocView attributes ( meta, view ) =
)
<|
List.filterMap identity
[ meta.title
[ view.title
|> Maybe.map Element.text
|> Maybe.map (Element.el Typography.h3)
, Just view.body
@ -310,7 +292,7 @@ layoutRowView row =
OneColumn items ->
items
|> List.reverse
|> List.map (layoutBlocView [])
|> List.map (layoutView [])
TwoColumn left right ->
Element.row
@ -323,7 +305,7 @@ layoutRowView row =
]
<|
List.map
(layoutBlocView
(layoutView
[ Element.height Element.fill ]
)
<|
@ -334,7 +316,7 @@ layoutRowView row =
]
<|
List.map
(layoutBlocView
(layoutView
[ Element.height Element.fill ]
)
<|
@ -343,15 +325,14 @@ layoutRowView row =
|> List.singleton
page : BlocBuilder model msg flags -> Page model msg flags
page (BlocBuilder config) =
page : Builder model msg flags -> Page model msg flags
page (Builder config) =
{ init = config.init
, update = config.update
, view =
\pagesize model ->
config.views pagesize model
|> List.map2 Tuple.pair config.meta
|> List.foldl layoutAddBloc []
|> List.foldl layoutAddTile []
|> List.reverse
|> List.concatMap layoutRowView
|> Element.column
@ -366,7 +347,7 @@ page (BlocBuilder config) =
{-| render a markdown text into a simple panel
-}
markdown : List (Attribute ()) -> String -> Bloc () () ()
markdown : List (Attribute ()) -> String -> Tile () () ()
markdown attributes text =
static attributes
(\_ _ ->
@ -375,24 +356,32 @@ markdown attributes text =
)
static : List (Attribute msg) -> (PageSize -> flags -> Element msg) -> Bloc flags msg flags
static attributes blocView =
static : List (Attribute msg) -> (PageSize -> flags -> Element msg) -> Tile flags msg flags
static attributes tileView =
{ init = \flags -> ( flags, Cmd.none )
, title = Nothing
, update = \_ m -> ( m, Cmd.none )
, view =
\pagesize flags ->
{ body = blocView pagesize flags
, position = FullWidthBloc
{ title = Nothing
, body = tileView pagesize flags
, position = FullWidthTile
, attributes = attributes
}
, subscriptions = \_ -> Sub.none
}
withBlocTitle : String -> Bloc model msg flags -> Bloc model msg flags
withBlocTitle title bloc =
{ bloc | title = Just title }
withTitle : String -> Tile model msg flags -> Tile model msg flags
withTitle title tile =
let
settitle t v =
{ v | title = Just t }
in
{ tile
| view =
\pagesize flags ->
tile.view pagesize flags |> settitle title
}
canvas : Element msg -> Element msg