Last active
August 29, 2015 14:27
-
-
Save TheSeamau5/5a38cbe5ce085705ba34 to your computer and use it in GitHub Desktop.
UI Components
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Signal exposing (Address) | |
import Html exposing (Html) | |
import Task exposing (Task) | |
import Time exposing (Time) | |
import Window | |
type Never = Never Never | |
type alias Init options state effect = options -> (state, Maybe effect) | |
type alias Update action state effect = action -> state -> (state, Maybe effect) | |
type alias View action state view = Address action -> state -> view | |
type alias Loopback action effect = Address action -> effect -> Task Never () | |
type UIAction action | |
= Tick Time | |
| Resize (Int, Int) | |
| Action action | |
type alias Component options action state effect view = | |
{ init : Init options state effect | |
, update : Update action state effect | |
, view : View action state view | |
} | |
stateless | |
: { init : state | |
, view : state -> view | |
} | |
-> Component Never Never state Never view | |
stateless {init, view} = | |
{ init = (\_ -> (init, Nothing)) | |
, update = (\_ s -> (s, Nothing)) | |
, view = always view | |
} | |
type alias Runner options action state effect view | |
= options | |
-> Component options action state effect view | |
-> Output action state effect view | |
type alias Output action state effect view = | |
{ states : Signal state | |
, actions : Signal (Maybe action) | |
, effects : Signal (Maybe effect) | |
, tasks : Signal (Task Never ()) | |
, views : Signal view | |
} | |
runUI | |
: Loopback action effect | |
-> Runner options (UIAction action) state effect view | |
runUI loopback options component = | |
let | |
mailbox = | |
Signal.mailbox Nothing | |
uiaddress = | |
Signal.forwardTo mailbox.address Just | |
address = | |
Signal.forwardTo uiaddress Action | |
compStartMailbox = | |
Signal.mailbox () | |
appStartTask = | |
Signal.send compStartMailbox.address () | |
resizes = | |
Signal.map Resize Window.dimensions | |
actions = | |
Signal.sampleOn compStartMailbox.signal resizes | |
|> Signal.merge resizes | |
|> Signal.merge (Signal.map Tick (Time.every 60)) -- Replace by AnimationFrame.frame | |
|> Signal.map Just | |
|> Signal.merge mailbox.signal | |
update maybeAction (state, effect) = | |
case maybeAction of | |
Nothing -> | |
(state, effect) | |
Just action -> | |
component.update action state | |
view state = | |
component.view address state | |
transactions = | |
Signal.foldp update (component.init options) actions | |
states = | |
Signal.map fst transactions | |
effects = | |
Signal.map snd transactions | |
runEffect maybeEffect = | |
case maybeEffect of | |
Nothing -> | |
Task.succeed () | |
Just effect -> | |
loopback address effect | |
tasks = | |
effects | |
|> Signal.map runEffect | |
|> Signal.merge appStartTask | |
views = | |
Signal.map view states | |
in | |
{ states = states | |
, actions = actions | |
, effects = effects | |
, tasks = tasks | |
, views = views | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment