mirror of
https://github.com/correl/elm-mdl.git
synced 2024-12-24 11:50:50 +00:00
Functional component model.
This commit is contained in:
parent
dfda38d0c1
commit
1fdcc78ba7
6 changed files with 249 additions and 192 deletions
|
@ -15,7 +15,7 @@ import Material.Button as Button
|
|||
type alias Model =
|
||||
{ count : Int
|
||||
, mdl : Material.Model Action
|
||||
-- Boilerplate: Model store for any and all MDL components you need.
|
||||
-- Boilerplate: mdl is the Model store for any and all MDL components you need.
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@ model : Model
|
|||
model =
|
||||
{ count = 0
|
||||
, mdl = Material.model
|
||||
-- Always use this initial MDL component model store.
|
||||
-- Boilerplate: Always use this initial MDL model store.
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,7 +36,6 @@ type Action
|
|||
| Reset
|
||||
| MDL (Material.Action Action)
|
||||
-- Boilerplate: Action for MDL actions (ripple animations etc.).
|
||||
-- It should always look like this.
|
||||
|
||||
|
||||
update : Action -> Model -> (Model, Effects.Effects Action)
|
||||
|
@ -83,8 +82,7 @@ button. The arguments are:
|
|||
-}
|
||||
increase : Button.Instance Mdl Action
|
||||
increase =
|
||||
Button.instance 0 MDL
|
||||
Button.flat (Button.model True)
|
||||
Button.instance 0 MDL Button.flat (Button.model True)
|
||||
[ Button.fwdClick Increase ]
|
||||
|
||||
|
||||
|
@ -93,8 +91,7 @@ click event to our Reset action.
|
|||
-}
|
||||
reset : Button.Instance Mdl Action
|
||||
reset =
|
||||
Button.instance 1 MDL
|
||||
Button.flat (Button.model False)
|
||||
Button.instance 1 MDL Button.flat (Button.model False)
|
||||
[ Button.fwdClick Reset ]
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,8 @@ import Demo.Page as Page
|
|||
-- MODEL
|
||||
|
||||
|
||||
type alias Mdl = Material.Model Action
|
||||
type alias Mdl =
|
||||
Material.Model Action
|
||||
|
||||
|
||||
type alias Model =
|
||||
|
@ -48,22 +49,8 @@ type Action
|
|||
| MDL (Material.Action Action)
|
||||
|
||||
|
||||
snackbar : Int -> Snackbar.Contents Action
|
||||
snackbar k =
|
||||
Snackbar.snackbar
|
||||
("Snackbar message #" ++ toString k)
|
||||
"UNDO"
|
||||
(Undo k)
|
||||
|
||||
|
||||
toast : Int -> Snackbar.Contents Action
|
||||
toast k =
|
||||
Snackbar.toast
|
||||
<| "Toast message #" ++ toString k
|
||||
|
||||
|
||||
add : (Int -> Snackbar.Contents Action) -> Model -> (Model, Effects Action)
|
||||
add f model =
|
||||
add : Model -> (Int -> Snackbar.Contents Action) -> (Model, Effects Action)
|
||||
add model f =
|
||||
let
|
||||
(mdl', fx) =
|
||||
Snackbar.add (f model.count) snackbarComponent model.mdl
|
||||
|
@ -81,10 +68,12 @@ update : Action -> Model -> (Model, Effects Action)
|
|||
update action model =
|
||||
case action of
|
||||
AddSnackbar ->
|
||||
add snackbar model
|
||||
add model
|
||||
<| \k -> Snackbar.snackbar ("Snackbar message #" ++ toString k) "UNDO" (Undo k)
|
||||
|
||||
AddToast ->
|
||||
add toast model
|
||||
add model
|
||||
<| \k -> Snackbar.toast <| "Toast message #" ++ toString k
|
||||
|
||||
Undo k ->
|
||||
({ model
|
||||
|
@ -96,18 +85,19 @@ update action model =
|
|||
Material.update MDL action' model.mdl
|
||||
|> map1st (\m -> { model | mdl = m })
|
||||
|
||||
|
||||
-- VIEW
|
||||
|
||||
|
||||
addSnackbar : Button.Instance Mdl Action
|
||||
addSnackbar =
|
||||
addSnackbarButton : Button.Instance Mdl Action
|
||||
addSnackbarButton =
|
||||
Button.instance 0 MDL
|
||||
Button.raised (Button.model True)
|
||||
[ Button.fwdClick AddSnackbar ]
|
||||
|
||||
|
||||
addToast : Button.Instance Mdl Action
|
||||
addToast =
|
||||
addToastButton : Button.Instance Mdl Action
|
||||
addToastButton =
|
||||
Button.instance 1 MDL
|
||||
Button.raised (Button.model True)
|
||||
[ Button.fwdClick AddToast ]
|
||||
|
@ -115,8 +105,7 @@ addToast =
|
|||
|
||||
snackbarComponent : Snackbar.Instance Mdl Action
|
||||
snackbarComponent =
|
||||
Snackbar.instance 2 MDL Snackbar.model
|
||||
|
||||
Snackbar.instance MDL Snackbar.model
|
||||
|
||||
|
||||
clickView : Model -> Int -> Html
|
||||
|
@ -164,11 +153,11 @@ view addr model =
|
|||
-- to add css/classes to top-level element of components (div
|
||||
-- in grid, button in button, div in textfield etc.)
|
||||
[ cell [ size All 2, size Phone 2, align Top ]
|
||||
[ addToast.view addr model.mdl [] [ text "Toast" ]
|
||||
[ addToastButton.view addr model.mdl [] [ text "Toast" ]
|
||||
]
|
||||
, cell
|
||||
[ size All 2, size Phone 2, align Top ]
|
||||
[ addSnackbar.view addr model.mdl [] [ text "Snackbar" ]
|
||||
[ addSnackbarButton.view addr model.mdl [] [ text "Snackbar" ]
|
||||
]
|
||||
, cell
|
||||
[ size Desktop 7, size Tablet 3, size Phone 12, align Top ]
|
||||
|
|
|
@ -15,27 +15,28 @@ for a live demo.
|
|||
|
||||
# Component model
|
||||
|
||||
The component model of the library is simply the Elm Architecture, e.g.,
|
||||
each component has Model, Action, view, and update. A minimal example using
|
||||
this library in plain Elm Architecture can be found
|
||||
[here](https://github.com/debois/elm-mdl/blob/master/examples/Component-EA.elm).
|
||||
The component model of the library is simply the Elm Architecture (TEA), i.e.,
|
||||
each component has types `Model` and `Action`, and values `view` and `update`. A
|
||||
minimal example using this library in plain TEA can be found
|
||||
[here](https://github.com/debois/elm-mdl/blob/master/examples/Component-TEA.elm).
|
||||
|
||||
Nesting large amounts of components in the Elm Architecture is somewhat
|
||||
unwieldy because of the large amount of boilerplate one has to write. This
|
||||
library includes "component support", for getting rid of most of that
|
||||
boilerplate. A minimal example using component support is
|
||||
Using more than a few component in plain TEA is unwieldy because of the large
|
||||
amount of boilerplate one has to write. This library provides the "component
|
||||
support" for getting rid of most of that boilerplate. A minimal example using
|
||||
component support is
|
||||
[here](http://github.com/debois/elm-mdl/blob/master/examples/Component.elm).
|
||||
|
||||
It is important to note that component support lives __within__ the Elm
|
||||
architecture; it is not an alternative architecture.
|
||||
It is important to note that component support lives __within__ TEA;
|
||||
it is not an alternative architecture.
|
||||
|
||||
# Getting started
|
||||
|
||||
The easiest way to get started is to start with one of the minimal examples above.
|
||||
We recommend going with the library's component support rather than working
|
||||
directly in plain Elm Architecture.
|
||||
We recommend going with the library's
|
||||
[component support](http://github.com/debois/elm-mdl/blob/master/examples/Component.elm)
|
||||
rather than working directly in plain Elm Architecture.
|
||||
|
||||
# This module
|
||||
# Component Support
|
||||
|
||||
This module contains only convenience functions for working with nested
|
||||
components in the Elm architecture. A minimal example using this library
|
||||
|
@ -49,6 +50,7 @@ All examples in this subsection is from the
|
|||
Here is how you use component support in general. First, boilerplate.
|
||||
|
||||
1. Include `Material`:
|
||||
|
||||
`import Material`
|
||||
|
||||
2. Add a model container Material components to your model:
|
||||
|
@ -80,7 +82,6 @@ Here is how you use component support in general. First, boilerplate.
|
|||
in
|
||||
( { model | mdl = mdl' } , fx )
|
||||
|
||||
|
||||
Next, make the component instances you need. Do this in the View section of your
|
||||
source file. Let's say you need a textfield for name entry, and you'd like to
|
||||
be notifed whenever the field changes value through your own NameChanged action:
|
||||
|
@ -106,8 +107,8 @@ be notifed whenever the field changes value through your own NameChanged action:
|
|||
nameInput : Textfield.Instance Material.Model Action
|
||||
nameInput =
|
||||
Textfield.instance 2 MDL Textfield.model
|
||||
[ Textfield.fwdInput NameChanged ]
|
||||
|
||||
[ Textfield.fwdInput NameChanged
|
||||
]
|
||||
|
||||
view addr model =
|
||||
...
|
||||
|
@ -125,13 +126,13 @@ but now it's not boilerplate, its "business logic".)
|
|||
Using this module will force all elm-mdl components to be built and included in
|
||||
your application. If this is unacceptable, you can custom-build a version of this
|
||||
module that uses only the components you need. To do so, you need to re-implement
|
||||
the present module, modifying the values `model` and `Model`. The module source
|
||||
can be found
|
||||
the present module, modifying the values `model` and `Model` by commenting out the
|
||||
components you are not using. The module source can be found
|
||||
[here](https://github.com/debois/elm-mdl/blob/master/src/Material.elm).
|
||||
|
||||
You do not need to re-build the entire elm-mdl library; simply copy the
|
||||
source of this module, give it a new name, modify as itMatendicated above, then use
|
||||
your modified module rather than this one.
|
||||
source of this module, give it a new name, modify as it as indicated above,
|
||||
then use your modified module rather than this one.
|
||||
|
||||
@docs Model, model, Action, update
|
||||
-}
|
||||
|
@ -145,37 +146,39 @@ import Material.Snackbar as Snackbar
|
|||
import Material.Component as Component exposing (Indexed)
|
||||
|
||||
|
||||
{-| Model encompassing all Material components.
|
||||
{-| Model encompassing all Material components. Since some components store
|
||||
user actions in their model (notably Snackbar), the model is generic in the
|
||||
type of such "observations".
|
||||
-}
|
||||
type alias Model a =
|
||||
type alias Model obs =
|
||||
{ button : Indexed Button.Model
|
||||
, textfield : Indexed Textfield.Model
|
||||
, snackbar : Indexed (Snackbar.Model a)
|
||||
, snackbar : Maybe (Snackbar.Model obs)
|
||||
}
|
||||
|
||||
|
||||
{-| Initial model.
|
||||
-}
|
||||
model : Model a
|
||||
model : Model obs
|
||||
model =
|
||||
{ button = Dict.empty
|
||||
, textfield = Dict.empty
|
||||
, snackbar = Dict.empty
|
||||
, snackbar = Nothing
|
||||
}
|
||||
|
||||
|
||||
{-| Action encompassing actions of all Material components.
|
||||
-}
|
||||
type alias Action action =
|
||||
Component.Action (Model action) action
|
||||
type alias Action obs =
|
||||
Component.Action (Model obs) obs
|
||||
|
||||
|
||||
{-| Update function for the above Action.
|
||||
-}
|
||||
update :
|
||||
(Action action -> action)
|
||||
-> Action action
|
||||
-> Model action
|
||||
-> (Model action, Effects action)
|
||||
(Action obs -> obs)
|
||||
-> Action obs
|
||||
-> Model obs
|
||||
-> (Model obs, Effects obs)
|
||||
update =
|
||||
Component.update
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
module Material.Component
|
||||
( Embedding, Observer
|
||||
( embed, embedIndexed, Embedding, Observer
|
||||
, Indexed
|
||||
, Instance, instance
|
||||
, Instance, instance, instance1
|
||||
, update
|
||||
, Action
|
||||
) where
|
||||
|
||||
{-|
|
||||
|
||||
The Elm Architecture is conceptually very nice, but it forces us
|
||||
to write large amounts of boilerplate whenever we need to use a "component".
|
||||
We must:
|
||||
The Elm Architecture is conceptually very nice, but it forces us to write large
|
||||
amounts of boilerplate whenever we need to use a "component". We must:
|
||||
|
||||
1. Retain the state of the component in our Model
|
||||
2. Add the components actions to our Action
|
||||
|
@ -28,35 +27,41 @@ produce `instance` functions; if you are using elm-mdl (and are not interested i
|
|||
optimising for compiled program size), you should ignore this module and look
|
||||
instead at `Material`.
|
||||
|
||||
# Component types
|
||||
@docs Indexed, Embedding, Observer, Instance
|
||||
|
||||
# Embeddings
|
||||
@docs Indexed, Embedding, embed, embedIndexed
|
||||
|
||||
# Instance construction
|
||||
@docs instance
|
||||
@docs Action, Instance, Observer, instance, instance1
|
||||
|
||||
# Instance consumption
|
||||
@docs update, Action
|
||||
@docs update
|
||||
|
||||
-}
|
||||
|
||||
import Effects exposing (Effects)
|
||||
import Task
|
||||
import Dict exposing (Dict)
|
||||
|
||||
import Material.Helpers exposing (map1, map2, map1st, map2nd, Update, Update')
|
||||
|
||||
|
||||
|
||||
-- TYPES
|
||||
|
||||
|
||||
|
||||
{-| Standard EA view function type.
|
||||
-}
|
||||
type alias View model action a =
|
||||
Signal.Address action -> model -> a
|
||||
|
||||
|
||||
|
||||
-- EMBEDDING MODELS
|
||||
|
||||
|
||||
|
||||
{-| Indexed families of things.
|
||||
-}
|
||||
type alias Indexed a =
|
||||
|
@ -65,7 +70,7 @@ type alias Indexed a =
|
|||
|
||||
{-| An __embedding__ of an Elm Architecture component is a variant in which
|
||||
view and update functions know how to extract and update their model
|
||||
from a larger container model.
|
||||
from a larger master model.
|
||||
-}
|
||||
type alias Embedding model container action a =
|
||||
{ view : View container action a
|
||||
|
@ -78,6 +83,14 @@ type alias Embedding model container action a =
|
|||
{-| Embed a component. Third and fourth arguments are a getter (extract the
|
||||
local model from the container) and a setter (update local model in the
|
||||
container).
|
||||
|
||||
It is instructive to compare the types of the view and update function in
|
||||
the input and output:
|
||||
|
||||
{- Input -} {- Output -}
|
||||
View model action a View container action a
|
||||
Update model action Update container action
|
||||
|
||||
-}
|
||||
embed :
|
||||
View model action a -> -- Given a view function,
|
||||
|
@ -98,11 +111,9 @@ embed view update get set =
|
|||
}
|
||||
|
||||
|
||||
{-| We are interested in particular embeddings where components of the same type
|
||||
all have their state living inside a shared `Dict`; the individual component
|
||||
has an id used for looking up its own state. Its the responsibility of the user
|
||||
to make
|
||||
sure that ids are unique.
|
||||
{-| We are interested in particular embeddings where components of the same
|
||||
type all have their state living inside a shared `Dict`; the individual
|
||||
component has a key used to look up its own state.
|
||||
-}
|
||||
embedIndexed :
|
||||
View model action a -> -- Given a view function,
|
||||
|
@ -128,37 +139,90 @@ embedIndexed view update get set model0 id =
|
|||
-- LIFTING ACTIONS
|
||||
|
||||
|
||||
{-| Generic MDL Action.
|
||||
|
||||
{-| Similarly to how embeddings enable collecting models of different type
|
||||
in a single model container, we need to collect actions in a single "master
|
||||
action" type. Obviously, actions need to be eventually executed by running
|
||||
the corresponding update function. To avoid this master action type explicitly
|
||||
representing the Action/update pairs of elm-mdl components, we represent an
|
||||
action of an individual component as a partially applied update function; that
|
||||
is, a function `container -> container`. E.g., the `Click` action of Button is
|
||||
conceptually represented as:
|
||||
|
||||
embeddedButton : Embedding Button.Model container action ...
|
||||
embeddedButton =
|
||||
embedIndexed
|
||||
Button.view Button.update .button {\m x -> {m|button=x} Button.model 0
|
||||
|
||||
clickAction : container -> container
|
||||
clickAction = embeddedButton.update Button.click
|
||||
|
||||
When all Material components are embedded in the same `container` model, we
|
||||
then have a uniform update mechanism.
|
||||
|
||||
We lost the ability to inspect the action when we did this, though. To be
|
||||
able to react to some actions of a component, we add to our `container ->
|
||||
container` type for actions a potential __observation__ of type `obs`.
|
||||
In practice, this observation type `obs` will be the Action of the TEA
|
||||
component __hosting__ MDL components.
|
||||
|
||||
Altogether, accounting also for effects, we arrive at the following type.
|
||||
-}
|
||||
type Action model obs =
|
||||
A (model -> (model, Effects (Action model obs), Maybe obs))
|
||||
type Action container obs =
|
||||
A (container -> (container, Effects (Action container obs), Maybe obs))
|
||||
|
||||
|
||||
{-| Type of observers, i.e., functions that take an actual action of the
|
||||
underlying TEA component to an observation. E.g., Button has an Observer for
|
||||
its `Click` action.
|
||||
-}
|
||||
type alias Observer action obs =
|
||||
action -> Maybe obs
|
||||
|
||||
|
||||
{-| Generic update function for Action.
|
||||
-}
|
||||
update :
|
||||
(Action state action -> action) ->
|
||||
Update' state (Action state action) action
|
||||
(Action container obs -> obs) ->
|
||||
Update' container (Action container obs) obs
|
||||
|
||||
update fwd (A f) state =
|
||||
update fwd (A f) container =
|
||||
let
|
||||
(state', fx, obs) =
|
||||
f state
|
||||
(container', fx, obs) =
|
||||
f container
|
||||
|> map2 (Effects.map fwd)
|
||||
in
|
||||
case obs of
|
||||
Nothing ->
|
||||
(state', fx)
|
||||
(container', fx)
|
||||
|
||||
Just x ->
|
||||
(state', Effects.batch [ fx, Effects.tick (always x) ])
|
||||
(container', Effects.batch [ fx, Effects.task (Task.succeed x) ])
|
||||
|
||||
|
||||
|
||||
|
||||
-- INSTANCES
|
||||
|
||||
|
||||
{- EA update function variant where running the function
|
||||
|
||||
|
||||
|
||||
|
||||
{-| Type of component instances. A component instance contains a view,
|
||||
get/set/map for the inner model, and a forwarder lifting component
|
||||
actions to observations.
|
||||
-}
|
||||
type alias Instance model container action obs a =
|
||||
{ view : View container obs a
|
||||
, get : container -> model
|
||||
, set : model -> container -> container
|
||||
, map : (model -> model) -> container -> container
|
||||
, fwd : action -> obs
|
||||
}
|
||||
|
||||
|
||||
{- TEA update function variant where running the function
|
||||
produces not just a new model and an effect, but also an
|
||||
observation.
|
||||
-}
|
||||
|
@ -166,34 +230,13 @@ type alias Step model action obs =
|
|||
action -> model -> (model, Effects action, Maybe obs)
|
||||
|
||||
|
||||
|
||||
{-| Type of component instances. A component instance contains a view,
|
||||
and get/set/map for, well, getting, setting, and mapping the component
|
||||
model.
|
||||
-}
|
||||
type alias Instance submodel model subaction action a =
|
||||
{ view : View model action a
|
||||
, get : model -> submodel
|
||||
, set : submodel -> model -> model
|
||||
, map : (submodel -> submodel) -> model -> model
|
||||
, fwd : subaction -> action
|
||||
}
|
||||
|
||||
|
||||
{- Partially apply a step function to an action,
|
||||
producing a generic Action.
|
||||
{- Partially apply a step function to an action, producing a generic Action.
|
||||
-}
|
||||
pack : (Step model action obs) -> action -> Action model obs
|
||||
pack update action =
|
||||
A (update action >> map2 (Effects.map (pack update)))
|
||||
|
||||
|
||||
{-| Type of observers.
|
||||
-}
|
||||
type alias Observer action obs =
|
||||
action -> Maybe obs
|
||||
|
||||
|
||||
{- Convert an update function to a step function by applying a
|
||||
function that converts the action input to the update function into
|
||||
an observation.
|
||||
|
@ -216,20 +259,22 @@ pick f xs =
|
|||
x -> x
|
||||
|
||||
|
||||
connect : List (Observer subaction action) -> Observer subaction action
|
||||
{- Promote a list of Observers to a single Observer by picking, for a given
|
||||
action, the first one that succeeds.
|
||||
-}
|
||||
connect : List (Observer action obs) -> Observer action obs
|
||||
connect observers subaction =
|
||||
pick ((|>) subaction) observers
|
||||
|
||||
|
||||
|
||||
{-| Given a lifting function, a list of observers and an embedding, construct an
|
||||
Instance. Notice that the Instance forgets the type parameter `subaction`.
|
||||
Instance.
|
||||
-}
|
||||
instance' :
|
||||
(Action model action -> action) ->
|
||||
List (Observer subaction action) ->
|
||||
Embedding submodel model subaction a ->
|
||||
Instance submodel model subaction action a
|
||||
instance'
|
||||
: (Action container obs -> obs)
|
||||
-> List (Observer action obs)
|
||||
-> Embedding model container action a
|
||||
-> Instance model container action obs a
|
||||
instance' lift observers embedding =
|
||||
let
|
||||
fwd =
|
||||
|
@ -249,19 +294,28 @@ instance' lift observers embedding =
|
|||
}
|
||||
|
||||
|
||||
|
||||
{-| It is helpful to see parameter names:
|
||||
|
||||
instance view update get set id lift model0 observers =
|
||||
...
|
||||
|
||||
Convert a regular Elm Architecture component (view, update) to a component
|
||||
which knows how to access its state in a generic container model (get, set),
|
||||
and which dispatches generic Action updates, lifted to the consumers action
|
||||
type (lift). You can react to actions in custom way by providing observers
|
||||
(observers). You must also provide an initial model (model0) and an identifier
|
||||
for the instance (id). The identifier must be unique for all instances of the
|
||||
same type stored in the same model (rule of thumb: if they are in the same
|
||||
file, they need distinct ids.)
|
||||
Convert a regular Elm Architecture component (`view`, `update`) to a component
|
||||
which knows how to access its model inside a generic container model (`get`,
|
||||
`set`), and which dispatches generic `Action` updates, lifted to the consumers
|
||||
action type `obs` (`lift`). You can react to actions in custom way by providing
|
||||
observers (`observers`). You must also provide an initial model (`model0`) and an
|
||||
identifier for the instance (`id`). The identifier must be unique for all
|
||||
instances of the same type stored in the same model (overapproximating rule of
|
||||
thumb: if they are in the same file, they need distinct ids.)
|
||||
|
||||
Its instructive to compare the types of the input and output views:
|
||||
|
||||
{- Input -} {- Output -}
|
||||
View model action a View container obs a
|
||||
|
||||
That is, this function fully converts a view from its own `model` and `action`
|
||||
to the master `container` model and `observation` action.
|
||||
-}
|
||||
instance
|
||||
: View model action a
|
||||
|
@ -269,11 +323,29 @@ instance
|
|||
-> (container -> Indexed model)
|
||||
-> (Indexed model -> container -> container)
|
||||
-> Int
|
||||
-> (Action container observation -> observation)
|
||||
-> (Action container obs -> obs)
|
||||
-> model
|
||||
-> List (Observer action observation)
|
||||
-> Instance model container action observation a
|
||||
-> List (Observer action obs)
|
||||
-> Instance model container action obs a
|
||||
|
||||
instance view update get set id lift model0 observers =
|
||||
embedIndexed view update get set model0 id
|
||||
|> instance' lift observers
|
||||
|
||||
|
||||
{-| Variant of `instance` for components that are naturally singletons
|
||||
(e.g., snackbar, layout).
|
||||
-}
|
||||
instance1
|
||||
: View model action a
|
||||
-> Update model action
|
||||
-> (container -> Maybe model)
|
||||
-> (Maybe model -> container -> container)
|
||||
-> (Action container obs -> obs)
|
||||
-> model
|
||||
-> List (Observer action obs)
|
||||
-> Instance model container action obs a
|
||||
|
||||
instance1 view update get set lift model0 observers =
|
||||
embed view update (get >> Maybe.withDefault model0) (Just >> set)
|
||||
|> instance' lift observers
|
||||
|
|
|
@ -281,7 +281,7 @@ view addr model =
|
|||
{-|
|
||||
-}
|
||||
type alias State s obs =
|
||||
{ s | snackbar : Indexed (Model obs) }
|
||||
{ s | snackbar : Maybe (Model obs) }
|
||||
|
||||
|
||||
{-|
|
||||
|
@ -306,19 +306,16 @@ actionObserver action =
|
|||
Nothing
|
||||
|
||||
|
||||
|
||||
{-| Component instance.
|
||||
-}
|
||||
instance :
|
||||
Int
|
||||
-> (Component.Action (State state obs) obs -> obs)
|
||||
instance
|
||||
: (Component.Action (State state obs) obs -> obs)
|
||||
-> (Model obs)
|
||||
-> Instance (State state obs) obs
|
||||
|
||||
instance id lift model0 =
|
||||
Component.instance
|
||||
view update .snackbar (\x y -> {y | snackbar = x}) id lift model0 [ actionObserver ]
|
||||
|
||||
instance lift model0 =
|
||||
Component.instance1
|
||||
view update .snackbar (\x y -> {y | snackbar = x}) lift model0 [ actionObserver ]
|
||||
|
||||
{-|
|
||||
TODO
|
||||
|
@ -334,4 +331,3 @@ add contents inst model =
|
|||
update (Add contents) (inst.get model)
|
||||
in
|
||||
(inst.set sb model, Effects.map inst.fwd fx)
|
||||
|
||||
|
|
Loading…
Reference in a new issue