mirror of
https://github.com/ryannhg/elm-spa.git
synced 2024-11-22 09:44:55 +03:00
write docs for new api
This commit is contained in:
parent
89e3b99966
commit
d54a2711b1
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
.DS_Store
|
||||
./dist
|
||||
elm-stuff
|
||||
./node_modules
|
||||
node_modules
|
4
elm.json
4
elm.json
@ -7,7 +7,9 @@
|
||||
"exposed-modules": [
|
||||
"Spa",
|
||||
"Spa.Page",
|
||||
"Spa.Types"
|
||||
"Spa.Types",
|
||||
"Spa.Transition",
|
||||
"Spa.Path"
|
||||
],
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Components.Button exposing (view)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Components.Hero exposing (Action(..), view)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Element.Input as Input
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Components.Section exposing (view)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Html.Attributes as Attr
|
||||
import Markdown
|
||||
|
@ -1,7 +1,7 @@
|
||||
module Layout exposing (view)
|
||||
|
||||
import Components.Button
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Element.Background as Background
|
||||
import Element.Border as Border
|
||||
@ -48,7 +48,7 @@ viewNavbar user_ =
|
||||
, Font.color Styles.colors.coral
|
||||
, Styles.transition
|
||||
{ property = "opacity"
|
||||
, speed = 150
|
||||
, duration = 150
|
||||
}
|
||||
, mouseOver [ alpha 0.6 ]
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Layouts.Docs exposing (view)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Element.Font as Font
|
||||
import Generated.Routes as Routes exposing (Route, routes)
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Layouts.Guide exposing (view)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Utils.Spa as Spa
|
||||
|
||||
|
@ -2,7 +2,7 @@ module Pages.SignIn exposing (Model, Msg, page)
|
||||
|
||||
import Spa.Page
|
||||
import Components.Button
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Element.Border as Border
|
||||
import Element.Font as Font
|
||||
|
@ -3,7 +3,7 @@ module Pages.Top exposing (Model, Msg, page)
|
||||
import Spa.Page
|
||||
import Components.Hero
|
||||
import Components.Section
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Generated.Params as Params
|
||||
import Html.Attributes as Attr
|
||||
|
@ -1,29 +1,17 @@
|
||||
module Transitions exposing (transitions)
|
||||
|
||||
import Components.Styles as Styles
|
||||
import Utils.Styles as Styles
|
||||
import Element exposing (..)
|
||||
import Generated.Docs.Pages
|
||||
import Layout
|
||||
import Layouts.Docs
|
||||
import Layouts.Guide
|
||||
import Spa.Path exposing (Path)
|
||||
import Generated.Docs.Pages as Docs
|
||||
import Spa.Transition as Transition exposing (Transition)
|
||||
|
||||
|
||||
transitions :
|
||||
{ layout : Transition (Element msg)
|
||||
, page : Transition (Element msg)
|
||||
, pages :
|
||||
List
|
||||
{ path : Path
|
||||
, transition : Transition (Element msg)
|
||||
}
|
||||
}
|
||||
transitions : Transition.Transitions (Element msg)
|
||||
transitions =
|
||||
{ layout = Transition.fadeUi 300
|
||||
, page = Transition.fadeUi 300
|
||||
, pages =
|
||||
[ { path = Generated.Docs.Pages.path
|
||||
[ { path = Docs.path
|
||||
, transition = batmanNewspaper 600
|
||||
}
|
||||
]
|
||||
@ -35,9 +23,9 @@ transitions =
|
||||
|
||||
|
||||
batmanNewspaper : Int -> Transition (Element msg)
|
||||
batmanNewspaper speed =
|
||||
batmanNewspaper duration =
|
||||
Transition.custom
|
||||
{ speed = speed
|
||||
{ duration = duration
|
||||
, invisible =
|
||||
\page ->
|
||||
el
|
||||
@ -47,7 +35,7 @@ batmanNewspaper speed =
|
||||
, scale 0
|
||||
, Styles.transition
|
||||
{ property = "all"
|
||||
, speed = speed
|
||||
, duration = duration
|
||||
}
|
||||
]
|
||||
page
|
||||
@ -58,7 +46,7 @@ batmanNewspaper speed =
|
||||
, width fill
|
||||
, Styles.transition
|
||||
{ property = "all"
|
||||
, speed = speed
|
||||
, duration = duration
|
||||
}
|
||||
]
|
||||
page
|
||||
|
@ -10,11 +10,11 @@ module Utils.Spa exposing
|
||||
, recipe
|
||||
)
|
||||
|
||||
import Spa.Page
|
||||
import Spa.Types
|
||||
import Element exposing (Element)
|
||||
import Generated.Routes as Routes exposing (Route)
|
||||
import Global
|
||||
import Spa.Page
|
||||
import Spa.Types
|
||||
|
||||
|
||||
type alias Page params model msg layoutModel layoutMsg appMsg =
|
||||
@ -37,14 +37,6 @@ type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle Route msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias Layout params model msg appMsg =
|
||||
Spa.Types.Layout Route params model msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias Upgrade params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Upgrade Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
type alias LayoutContext msg =
|
||||
Spa.Types.LayoutContext Route msg (Element msg) Global.Model Global.Msg
|
||||
|
||||
@ -53,6 +45,10 @@ type alias PageContext =
|
||||
Spa.Types.PageContext Route Global.Model
|
||||
|
||||
|
||||
type alias Layout params model msg appMsg =
|
||||
Spa.Types.Layout Route params model msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
layout :
|
||||
Layout params model msg appMsg
|
||||
-> Page params model msg layoutModel layoutMsg appMsg
|
||||
@ -60,6 +56,10 @@ layout =
|
||||
Spa.Page.layout Element.map
|
||||
|
||||
|
||||
type alias Upgrade params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Upgrade Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
recipe :
|
||||
Upgrade params model msg layoutModel layoutMsg appMsg
|
||||
-> Recipe params model msg layoutModel layoutMsg appMsg
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Components.Styles exposing
|
||||
module Utils.Styles exposing
|
||||
( button
|
||||
, colors
|
||||
, fonts
|
||||
@ -39,7 +39,7 @@ link =
|
||||
, Font.color colors.coral
|
||||
, transition
|
||||
{ property = "opacity"
|
||||
, speed = 150
|
||||
, duration = 150
|
||||
}
|
||||
, mouseOver
|
||||
[ alpha 0.6
|
||||
@ -59,7 +59,7 @@ button =
|
||||
, pointer
|
||||
, transition
|
||||
{ property = "all"
|
||||
, speed = 150
|
||||
, duration = 150
|
||||
}
|
||||
, mouseOver
|
||||
[ Font.color colors.white
|
||||
@ -88,14 +88,14 @@ h3 =
|
||||
|
||||
transition :
|
||||
{ property : String
|
||||
, speed : Int
|
||||
, duration : Int
|
||||
}
|
||||
-> Attribute msg
|
||||
transition { property, speed } =
|
||||
transition { property, duration } =
|
||||
Element.htmlAttribute
|
||||
(Attr.style
|
||||
"transition"
|
||||
(property ++ " " ++ String.fromInt speed ++ "ms ease-in-out")
|
||||
(property ++ " " ++ String.fromInt duration ++ "ms ease-in-out")
|
||||
)
|
||||
|
||||
|
2893
package-lock.json
generated
2893
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,22 @@
|
||||
{
|
||||
"name": "elm-spa",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "a package for building single-page applications!",
|
||||
"main": "cli/src/index.js",
|
||||
"bin": "./cli/src/index.js",
|
||||
"scripts": {
|
||||
"start": "npm link && npm run dev",
|
||||
"build": "(cd cli && npm run build)",
|
||||
"dev": "npm run build && npm run example",
|
||||
"docs": "elm-doc-preview",
|
||||
"example": "npm run examples:complex",
|
||||
"examples:intro": "(cd examples/intro && npm install && npm run dev)",
|
||||
"examples:complex": "(cd examples/complex && npm install && npm run dev)"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"devDependencies": {
|
||||
"elm": "0.19.1-3",
|
||||
"elm-doc-preview": "3.0.4"
|
||||
},
|
||||
"keywords": []
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
module Internals.Transition exposing
|
||||
( Transition
|
||||
, speed, view
|
||||
, duration, view
|
||||
, optOut, none, fadeHtml, fadeUi
|
||||
, Visibility
|
||||
, visible, invisible
|
||||
@ -10,7 +10,7 @@ module Internals.Transition exposing
|
||||
{-|
|
||||
|
||||
@docs Transition
|
||||
@docs speed, view, chooseFrom
|
||||
@docs duration, view, chooseFrom
|
||||
@docs optOut, none, fadeHtml, fadeUi
|
||||
|
||||
@docs Visibility
|
||||
@ -46,7 +46,7 @@ type Transition ui_msg
|
||||
|
||||
|
||||
type alias Options ui_msg =
|
||||
{ speed : Int
|
||||
{ duration : Int
|
||||
, invisible : View ui_msg
|
||||
, visible : View ui_msg
|
||||
}
|
||||
@ -57,8 +57,8 @@ type alias View ui_msg =
|
||||
-> ui_msg
|
||||
|
||||
|
||||
speed : Transition ui_msg -> Int
|
||||
speed transition =
|
||||
duration : Transition ui_msg -> Int
|
||||
duration transition =
|
||||
case transition of
|
||||
OptOut ->
|
||||
0
|
||||
@ -67,7 +67,7 @@ speed transition =
|
||||
0
|
||||
|
||||
Transition t ->
|
||||
t.speed
|
||||
t.duration
|
||||
|
||||
|
||||
view :
|
||||
@ -107,7 +107,7 @@ none =
|
||||
|
||||
|
||||
fadeHtml : Int -> Transition (Html msg)
|
||||
fadeHtml speed_ =
|
||||
fadeHtml duration_ =
|
||||
let
|
||||
withOpacity : Int -> View (Html msg)
|
||||
withOpacity opacity page =
|
||||
@ -116,21 +116,21 @@ fadeHtml speed_ =
|
||||
, Attr.style "transition" <|
|
||||
String.concat
|
||||
[ "opacity "
|
||||
, String.fromInt speed_
|
||||
, String.fromInt duration_
|
||||
, "ms ease-in-out"
|
||||
]
|
||||
]
|
||||
[ page ]
|
||||
in
|
||||
Transition <|
|
||||
{ speed = speed_
|
||||
{ duration = duration_
|
||||
, invisible = withOpacity 0
|
||||
, visible = withOpacity 1
|
||||
}
|
||||
|
||||
|
||||
fadeUi : Int -> Transition (Element msg)
|
||||
fadeUi speed_ =
|
||||
fadeUi duration_ =
|
||||
let
|
||||
withOpacity : Float -> View (Element msg)
|
||||
withOpacity opacity page =
|
||||
@ -142,21 +142,21 @@ fadeUi speed_ =
|
||||
Attr.style "transition" <|
|
||||
String.concat
|
||||
[ "opacity "
|
||||
, String.fromInt speed_
|
||||
, String.fromInt duration_
|
||||
, "ms ease-in-out"
|
||||
]
|
||||
]
|
||||
page
|
||||
in
|
||||
Transition <|
|
||||
{ speed = speed_
|
||||
{ duration = duration_
|
||||
, invisible = withOpacity 0
|
||||
, visible = withOpacity 1
|
||||
}
|
||||
|
||||
|
||||
custom :
|
||||
{ speed : Int
|
||||
{ duration : Int
|
||||
, invisible : View ui_msg
|
||||
, visible : View ui_msg
|
||||
}
|
||||
|
28
src/Spa.elm
28
src/Spa.elm
@ -1,7 +1,6 @@
|
||||
module Spa exposing
|
||||
( Program, create
|
||||
, usingHtml
|
||||
, queryParameters
|
||||
)
|
||||
|
||||
{-|
|
||||
@ -14,17 +13,21 @@ as the entrypoint to your app.
|
||||
|
||||
import Global
|
||||
import Pages
|
||||
import Routes
|
||||
import Routes exposing (routes)
|
||||
import Spa
|
||||
import Transitions
|
||||
import Utils.Spa
|
||||
|
||||
main : Utils.Spa.Program Pages.Model Pages.Msg
|
||||
main =
|
||||
Spa.create
|
||||
{ ui = Spa.usingHtml
|
||||
, routing =
|
||||
{ routes = Routes.parsers
|
||||
, toPath = Routes.toPath
|
||||
, notFound = Routes.routes.notFound
|
||||
, notFound = routes.notFound
|
||||
}
|
||||
, transitions = Transitions.transitions
|
||||
, global =
|
||||
{ init = Global.init
|
||||
, update = Global.update
|
||||
@ -38,7 +41,7 @@ as the entrypoint to your app.
|
||||
|
||||
# using elm-ui?
|
||||
|
||||
If you're a big fan of [mdgriffith/elm-ui](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/) (or not-so-big-fan of CSS),
|
||||
If you're a big fan of [mdgriffith/elm-ui](https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/) (or a "not-so-big-fan of CSS"),
|
||||
this package supports using `Element msg` instead of `Html msg` for your pages and components.
|
||||
|
||||
Providing `Spa.create` with these `ui` options will do the trick!
|
||||
@ -80,7 +83,7 @@ type alias Program flags globalModel globalMsg layoutModel layoutMsg =
|
||||
Platform.Program flags (Model flags globalModel layoutModel) (Msg globalMsg layoutMsg)
|
||||
|
||||
|
||||
{-| Pass this in when calling `Spa.create`
|
||||
{-| If you're just using `elm/html`, you can pass this into `Spa.create`
|
||||
|
||||
main =
|
||||
Spa.create
|
||||
@ -104,10 +107,11 @@ usingHtml =
|
||||
|
||||
{-| Creates a new `Program` given some one-time configuration:
|
||||
|
||||
- `ui` - How do we convert the view to `Html msg`?
|
||||
- `ui` - How do we convert our views into `Html msg`?
|
||||
- `routing` - What are the app's routes?
|
||||
- `global` - How do we manage shared state between pages?
|
||||
- `page` - What pages do we have available?
|
||||
- `transitions` - How should we transition between routes?
|
||||
- `global` - How do we share state between pages?
|
||||
- `page` - What page should we render?
|
||||
|
||||
-}
|
||||
create :
|
||||
@ -286,7 +290,7 @@ init config flags url key =
|
||||
[ Cmd.map Page pageCmd
|
||||
, Cmd.map Global pageGlobalCmd
|
||||
, Cmd.map Global globalCmd
|
||||
, Utils.delay (Transition.speed config.routing.transition) FadeInLayout
|
||||
, Utils.delay (Transition.duration config.routing.transition) FadeInLayout
|
||||
, cmd
|
||||
]
|
||||
)
|
||||
@ -383,7 +387,7 @@ update config msg model =
|
||||
|
||||
ChangedUrl url ->
|
||||
let
|
||||
( path, speed ) =
|
||||
( path, duration ) =
|
||||
chooseFrom
|
||||
{ transitions = config.routing.transitions
|
||||
, from = model.url
|
||||
@ -391,7 +395,7 @@ update config msg model =
|
||||
}
|
||||
|> Just
|
||||
|> Maybe.withDefault (List.head config.routing.transitions)
|
||||
|> Maybe.map (\item -> ( item.path, Transition.speed item.transition ))
|
||||
|> Maybe.map (\item -> ( item.path, Transition.duration item.transition ))
|
||||
|> Maybe.withDefault ( [], 0 )
|
||||
in
|
||||
( { model
|
||||
@ -404,7 +408,7 @@ update config msg model =
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Utils.delay
|
||||
speed
|
||||
duration
|
||||
(FadeInPage url)
|
||||
]
|
||||
)
|
||||
|
@ -8,26 +8,34 @@ module Spa.Page exposing
|
||||
, keep
|
||||
)
|
||||
|
||||
{-| Each page can be as simple or complex as you need:
|
||||
|
||||
1. [Static](#static) - a page without state
|
||||
|
||||
2. [Sandbox](#sandbox) - a page without side-effects
|
||||
|
||||
3. [Element](#element) - a page _with_ side-effects
|
||||
|
||||
4. [Component](#component) - a page that can change the global state
|
||||
{-|
|
||||
|
||||
|
||||
## what's that `always` for?
|
||||
## Pick the simplest page for the job!
|
||||
|
||||
You may notice the examples below use `always`. This is to **opt-out** each
|
||||
function from reading the global model.
|
||||
1. [`static`](#static) - a page without state
|
||||
|
||||
If you need access to `Global.Model` in your `title`, `init`, `update`, `view`, or
|
||||
`subscriptions` functions, just remove the always.
|
||||
2. [`sandbox`](#sandbox) - a page without side-effects
|
||||
|
||||
**It is recommended to include this to keep your pages as simple as possible!**
|
||||
3. [`element`](#element) - a page _with_ side-effects
|
||||
|
||||
4. [`component`](#component) - a page that can change the global state
|
||||
|
||||
|
||||
### **heads up:** `always` incoming!
|
||||
|
||||
You may notice the examples below use the function `always`.
|
||||
|
||||
Page.static
|
||||
{ title = always "Hello"
|
||||
, view = always view
|
||||
}
|
||||
|
||||
This is to **opt-out** each function from accessing data like [`PageContext`](./Spa-Types#PageContext)
|
||||
|
||||
If you decide you need access to the `Route`, query parameters, or `Global.Model`:
|
||||
Remove the `always` from `title`, `init`, `update`, `view`, or
|
||||
`subscriptions` functions.
|
||||
|
||||
|
||||
# static
|
||||
@ -50,13 +58,12 @@ If you need access to `Global.Model` in your `title`, `init`, `update`, `view`,
|
||||
@docs component, send
|
||||
|
||||
|
||||
# composing pages together
|
||||
# manually composing pages?
|
||||
|
||||
The rest of this module contains types and functions that
|
||||
can be generated with the [cli companion tool](https://github.com/ryannhg/elm-spa/tree/master/cli)
|
||||
are automatically generated with the [CLI companion tool](https://github.com/ryannhg/elm-spa/tree/master/cli)!
|
||||
|
||||
If you're typing this stuff manually, you might need to know what
|
||||
these are for!
|
||||
If you'd rather type this stuff manually, these docs are for you!
|
||||
|
||||
|
||||
## layout
|
||||
@ -69,12 +76,23 @@ these are for!
|
||||
@docs recipe
|
||||
|
||||
|
||||
## what's a "bundle"?
|
||||
## wait... what's a "bundle"?
|
||||
|
||||
We can "bundle" the `view` and `subscriptions` functions together,
|
||||
because they both only need the current `model`.
|
||||
We can "bundle" the `title`,`view`, and `subscriptions` functions together,
|
||||
because they only need access to the current `model`.
|
||||
|
||||
So _instead_ of typing out these:
|
||||
So _instead_ of typing out all this:
|
||||
|
||||
title bigModel =
|
||||
case bigModel of
|
||||
FooModel model ->
|
||||
foo.title model
|
||||
|
||||
BarModel model ->
|
||||
bar.title model
|
||||
|
||||
BazModel model ->
|
||||
baz.title model
|
||||
|
||||
view bigModel =
|
||||
case bigModel of
|
||||
@ -98,7 +116,7 @@ So _instead_ of typing out these:
|
||||
BazModel model ->
|
||||
baz.subscriptions model
|
||||
|
||||
You only need **one** case expression: (woohoo, less boilerplate!)
|
||||
You only create **one** case expression: (woohoo, less typing!)
|
||||
|
||||
bundle bigModel =
|
||||
case bigModel of
|
||||
@ -133,9 +151,9 @@ type alias Page route pageParams pageModel pageMsg ui_pageMsg layoutModel layout
|
||||
|
||||
|
||||
{-| Implementing the `init`, `update` and `bundle` functions is much easier
|
||||
when you turn a `Page` type into `Recipe`.
|
||||
when you turn a `Page` type into a `Recipe`.
|
||||
|
||||
A `Recipe` contains a record waiting for page specific data.
|
||||
A `Recipe` is just an Elm record waiting for its page specific data.
|
||||
|
||||
- `init`: just needs a `route`
|
||||
|
||||
@ -172,8 +190,8 @@ recipe =
|
||||
Internals.Page.upgrade
|
||||
|
||||
|
||||
{-| In the event that our `case` expression in `update` receives a `msg` that doesn't
|
||||
match up with it's `model`, we use `keep` to leave the page as-is.
|
||||
{-| If the `update` function receives a `msg` that doesn't
|
||||
match up its `model`, we use `keep` to leave the page as-is.
|
||||
|
||||
update : Msg -> Model -> Spa.Update Model Msg
|
||||
update bigMsg bigModel =
|
||||
@ -427,8 +445,8 @@ element page =
|
||||
, init = always init
|
||||
, update = always update
|
||||
, subscriptions = always subscriptions
|
||||
-- no always, so `view` gets `Global.Model`
|
||||
, view = view
|
||||
, view = view -- no always used here, so view
|
||||
-- has access to `PageContext`
|
||||
}
|
||||
|
||||
title : String
|
||||
@ -447,11 +465,14 @@ element page =
|
||||
subscriptions model =
|
||||
-- ...
|
||||
|
||||
view : Global.Model -> Model -> Html Msg
|
||||
view global model =
|
||||
view : Spa.PageContext -> Model -> Html Msg
|
||||
view { global } model =
|
||||
case global.user of
|
||||
SignedIn _ -> viewSignOutForm
|
||||
SignedOut -> viewSignInForm
|
||||
SignedIn user ->
|
||||
viewSignOutForm user model
|
||||
|
||||
SignedOut ->
|
||||
viewSignInForm model
|
||||
|
||||
-}
|
||||
component :
|
||||
@ -492,7 +513,7 @@ component page =
|
||||
)
|
||||
|
||||
|
||||
{-| Useful for sending `Global.Msg` from a component.
|
||||
{-| A utility for sending `Global.Msg` commands from your `Page.component`
|
||||
|
||||
init : Params.SignIn -> ( Model, Cmd Msg, Cmd Global.Msg )
|
||||
init params =
|
||||
|
@ -1,21 +1,73 @@
|
||||
module Spa.Path exposing
|
||||
( Path
|
||||
, dynamic
|
||||
, static
|
||||
, static, dynamic
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
|
||||
## specify transitions for different routes!
|
||||
|
||||
If you're using the [CLI companion tool](https://github.com/ryannhg/elm-spa/tree/master/cli),
|
||||
these are **automatically generated**.
|
||||
|
||||
If you're doing things by hand, this documentation might be helpful!
|
||||
|
||||
@docs Path
|
||||
|
||||
@docs static, dynamic
|
||||
|
||||
-}
|
||||
|
||||
import Internals.Path as Internals
|
||||
|
||||
|
||||
{-| a `List` of path segments that you use with `Spa.Transition`
|
||||
|
||||
transitions : Spa.Transitions (Element msg)
|
||||
transitions =
|
||||
{ layout = Transition.none
|
||||
, page = Transition.none
|
||||
, pages =
|
||||
[ -- applies fade to all pages under `/guide/*`
|
||||
{ path = [ static "guide" ]
|
||||
, transition = Transition.fadeUi 300
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
-}
|
||||
type alias Path =
|
||||
Internals.Path
|
||||
|
||||
|
||||
{-| A static segment of a path.
|
||||
|
||||
[ static "docs" ]
|
||||
-- /docs
|
||||
|
||||
[ static "docs", static "intro" ]
|
||||
-- /docs/intro
|
||||
|
||||
-}
|
||||
static : String -> Internals.Piece
|
||||
static =
|
||||
Internals.static
|
||||
|
||||
|
||||
{-| A dynamic segment of a path.
|
||||
|
||||
[ static "docs", dynamic ]
|
||||
-- /docs/welcome
|
||||
-- /docs/hello
|
||||
-- /docs/hooray
|
||||
|
||||
[ static "docs", dynamic, static "intro" ]
|
||||
-- /docs/welcome/intro
|
||||
-- /docs/hello/intro
|
||||
-- /docs/hooray/intro
|
||||
|
||||
-}
|
||||
dynamic : Internals.Piece
|
||||
dynamic =
|
||||
Internals.dynamic
|
||||
|
@ -1,20 +1,50 @@
|
||||
module Spa.Transition exposing
|
||||
( Transition
|
||||
, none, fadeHtml, fadeUi, custom
|
||||
, none, fadeHtml, fadeUi
|
||||
, custom
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
|
||||
## Create transitions from page to page!
|
||||
|
||||
A huge benefit to doing client-side rendering is the ability to
|
||||
seamlessly navigate from one page to another!
|
||||
|
||||
This package is designed to make creating page transitions a breeze!
|
||||
|
||||
@docs Transition
|
||||
@docs none, fadeHtml, fadeUi, custom
|
||||
|
||||
|
||||
# use one of these transitions
|
||||
|
||||
@docs none, fadeHtml, fadeUi
|
||||
|
||||
|
||||
# ot roll your own
|
||||
|
||||
@docs custom
|
||||
|
||||
-}
|
||||
|
||||
import Element exposing (Element)
|
||||
import Html exposing (Html)
|
||||
import Internals.Path exposing (Path)
|
||||
import Internals.Transition
|
||||
|
||||
|
||||
{-| Describes how to move from one page to another.
|
||||
|
||||
transition : Transition (Html msg)
|
||||
transition =
|
||||
Transition.none
|
||||
|
||||
anotherTransition : Transition (Element msg)
|
||||
anotherTransition =
|
||||
Transition.fadeUi 300
|
||||
|
||||
-}
|
||||
type alias Transition ui_msg =
|
||||
Internals.Transition.Transition ui_msg
|
||||
|
||||
@ -23,23 +53,110 @@ type alias Transition ui_msg =
|
||||
-- TRANSITIONS
|
||||
|
||||
|
||||
{-| Don't transition from one page to another
|
||||
|
||||
transitions : Transitions (Html msg)
|
||||
transitions =
|
||||
{ layout = Transition.none -- page loads instantly
|
||||
, page = Transition.fadeHtml 300
|
||||
, pages = []
|
||||
}
|
||||
|
||||
-}
|
||||
none : Transition ui_msg
|
||||
none =
|
||||
Internals.Transition.none
|
||||
|
||||
|
||||
{-| Fade one page out and another one in. (For use with `elm/html`)
|
||||
|
||||
Animation duration is represented in **milliseconds**
|
||||
|
||||
transitions : Spa.Types.Transitions (Html msg)
|
||||
transitions =
|
||||
{ layout = Transition.none
|
||||
, page = Transition.fadeHtml 300 -- 300 milliseconds
|
||||
, pages = []
|
||||
}
|
||||
|
||||
-}
|
||||
fadeHtml : Int -> Transition (Html msg)
|
||||
fadeHtml =
|
||||
Internals.Transition.fadeHtml
|
||||
|
||||
|
||||
{-| Fade one page out and another one in. (For use with `mdgriffith/elm-ui`)
|
||||
|
||||
Animation duration is represented in **milliseconds**
|
||||
|
||||
transitions : Spa.Types.Transitions (Element msg)
|
||||
transitions =
|
||||
{ layout = Transition.none
|
||||
, page = Transition.fadeUi 300 -- 300 milliseconds
|
||||
, pages = []
|
||||
}
|
||||
|
||||
-}
|
||||
fadeUi : Int -> Transition (Element msg)
|
||||
fadeUi =
|
||||
Internals.Transition.fadeUi
|
||||
|
||||
|
||||
{-| Create your own custom transition!
|
||||
|
||||
Just provide three things:
|
||||
|
||||
- How long (in milliseconds) the transition lasts.
|
||||
|
||||
- What the page looks like when invisible.
|
||||
|
||||
- What the page looks like when **visible**.
|
||||
|
||||
```
|
||||
batmanNewspaper : Int -> Transition (Element msg)
|
||||
batmanNewspaper duration =
|
||||
Transition.custom
|
||||
{ duration = duration
|
||||
, invisible =
|
||||
\page ->
|
||||
el
|
||||
[ alpha 0
|
||||
, width fill
|
||||
, rotate (4 * pi)
|
||||
, scale 0
|
||||
, Styles.transition
|
||||
{ property = "all"
|
||||
, duration = duration
|
||||
}
|
||||
]
|
||||
page
|
||||
, visible =
|
||||
\page ->
|
||||
el
|
||||
[ alpha 1
|
||||
, width fill
|
||||
, Styles.transition
|
||||
{ property = "all"
|
||||
, duration = duration
|
||||
}
|
||||
]
|
||||
page
|
||||
}
|
||||
|
||||
--
|
||||
-- using it later on
|
||||
--
|
||||
transitions : Spa.Types.Transitions (Element msg)
|
||||
transitions =
|
||||
{ layout = batmanNewspaper 500 -- 🦇
|
||||
, page = Transition.none
|
||||
, pages = []
|
||||
}
|
||||
```
|
||||
|
||||
-}
|
||||
custom :
|
||||
{ speed : Int
|
||||
{ duration : Int
|
||||
, invisible : View ui_msg
|
||||
, visible : View ui_msg
|
||||
}
|
||||
|
@ -5,24 +5,25 @@ module Spa.Types exposing
|
||||
, Update
|
||||
, Bundle
|
||||
, Layout, Upgrade
|
||||
, Transitions
|
||||
, LayoutContext, PageContext
|
||||
)
|
||||
|
||||
{-|
|
||||
|
||||
|
||||
## types so spooky, they got their own module! 👻
|
||||
## types so spooky, they got their own module!
|
||||
|
||||
This module is all about exposing the types that `ryannhg/elm-app` uses
|
||||
under the hood.
|
||||
|
||||
At a glance, there are a **lot of generic types**.
|
||||
You might notice that there are a **lot of generic types**.
|
||||
|
||||
In practice, we can handle this with a single
|
||||
In practice, we can avoid the messy types with a single
|
||||
[`Utils/Spa.elm`](https://github.com/ryannhg/elm-spa/blob/master/example/src/Utils/Spa.elm) file that
|
||||
makes your types easier to understand!
|
||||
|
||||
`elm-spa init` generates that file for you, but I've added examples below if you're
|
||||
`elm-spa init` will generate that file for you, but I've added examples below if you're
|
||||
doing things by hand.
|
||||
|
||||
|
||||
@ -55,9 +56,22 @@ doing things by hand.
|
||||
|
||||
@docs Layout, Upgrade
|
||||
|
||||
|
||||
# transitions
|
||||
|
||||
@docs Transitions
|
||||
|
||||
|
||||
# context
|
||||
|
||||
@docs LayoutContext, PageContext
|
||||
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import Internals.Page as Page
|
||||
import Internals.Path exposing (Path)
|
||||
import Internals.Transition exposing (Transition)
|
||||
|
||||
|
||||
{-|
|
||||
@ -73,7 +87,7 @@ import Internals.Page as Page
|
||||
import Element exposing (Element)
|
||||
|
||||
type alias Page params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Page params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
Spa.Types.Page Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
-- if using elm/html
|
||||
|
||||
@ -81,7 +95,7 @@ import Internals.Page as Page
|
||||
import Html exposing (Html)
|
||||
|
||||
type alias Page params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Page params model msg (Html msg) layoutModel layoutMsg (Html layoutMsg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
Spa.Types.Page Route params model msg (Html msg) layoutModel layoutMsg (Html layoutMsg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
|
||||
|
||||
## using your alias
|
||||
@ -112,7 +126,7 @@ type alias Page route params pageModel pageMsg ui_pageMsg layoutModel layoutMsg
|
||||
import Element exposing (Element)
|
||||
|
||||
type alias Recipe params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Recipe params model msg layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
Spa.Types.Recipe Route params model msg layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
-- if using elm/html
|
||||
|
||||
@ -120,7 +134,7 @@ type alias Page route params pageModel pageMsg ui_pageMsg layoutModel layoutMsg
|
||||
import Html exposing (Html)
|
||||
|
||||
type alias Recipe params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Recipe params model msg layoutModel layoutMsg (Html layoutMsg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
Spa.Types.Recipe Route params model msg layoutModel layoutMsg (Html layoutMsg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
|
||||
|
||||
## using your alias
|
||||
@ -148,7 +162,7 @@ type alias Recipe route params pageModel pageMsg layoutModel layoutMsg ui_layout
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
type alias Init model msg =
|
||||
Spa.Types.Init model msg Global.Model Global.Msg
|
||||
Spa.Types.Init Route model msg Global.Model Global.Msg
|
||||
|
||||
|
||||
## using your alias
|
||||
@ -175,7 +189,7 @@ type alias Init route layoutModel layoutMsg globalModel globalMsg =
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
type alias Update model msg =
|
||||
Spa.Types.Update model msg Global.Model Global.Msg
|
||||
Spa.Types.Update Route model msg Global.Model Global.Msg
|
||||
|
||||
|
||||
## using your alias
|
||||
@ -207,7 +221,7 @@ type alias Update route layoutModel layoutMsg globalModel globalMsg =
|
||||
import Element exposing (Element)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
Spa.Types.Bundle Route msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
-- if using elm/html
|
||||
|
||||
@ -215,7 +229,7 @@ type alias Update route layoutModel layoutMsg globalModel globalMsg =
|
||||
import Html exposing (Html)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Html msg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
Spa.Types.Bundle Route msg (Html msg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
|
||||
|
||||
## using your alias
|
||||
@ -246,44 +260,135 @@ type alias Bundle route layoutMsg ui_layoutMsg globalModel globalMsg msg ui_msg
|
||||
import Spa.Types
|
||||
import Element exposing (Element)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
type alias Layout params model msg appMsg =
|
||||
Spa.Types.Layout Route params model msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
|
||||
-- if using elm/html
|
||||
|
||||
import Spa.Types
|
||||
import Html exposing (Html)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Html msg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
type alias Layout params model msg appMsg =
|
||||
Spa.Types.Layout Route params model msg (Html msg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
|
||||
|
||||
## using your alias
|
||||
|
||||
**`.elm-spa/Generated/Pages.elm`**
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
import Utils.Spa as Spa
|
||||
|
||||
bundle : Model -> Spa.Bundle Msg msg
|
||||
bundle model_ =
|
||||
case model_ of
|
||||
-- ...
|
||||
layout :
|
||||
Layout params model msg appMsg
|
||||
-> Page params model msg layoutModel layoutMsg appMsg
|
||||
layout =
|
||||
Spa.Page.layout Element.map
|
||||
|
||||
-}
|
||||
type alias Layout route pageParams pageModel pageMsg ui_pageMsg globalModel globalMsg msg ui_msg =
|
||||
Page.Layout route pageParams pageModel pageMsg ui_pageMsg globalModel globalMsg msg ui_msg
|
||||
|
||||
|
||||
{-| TODO: PageContext docs
|
||||
{-| Describes how to transition between layouts and pages.
|
||||
|
||||
transitions : Transitions (Html msg)
|
||||
transitions =
|
||||
{ layout = Transition.none -- page loads instantly
|
||||
, page = Transition.fadeHtml 300
|
||||
, pages = []
|
||||
}
|
||||
|
||||
-}
|
||||
type alias Transitions ui_msg =
|
||||
{ layout : Transition ui_msg
|
||||
, page : Transition ui_msg
|
||||
, pages :
|
||||
List
|
||||
{ path : Path
|
||||
, transition : Transition ui_msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{-| This is what your `src/Pages/*.elm` files can access!
|
||||
|
||||
|
||||
## creating your alias
|
||||
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
type alias PageContext =
|
||||
Spa.Types.PageContext Route Global.Model
|
||||
|
||||
|
||||
## using your alias
|
||||
|
||||
**`src/Pages/Top.elm`**
|
||||
|
||||
import Utils.Spa as Spa
|
||||
|
||||
page =
|
||||
Page.static
|
||||
{ title = always "Homepage"
|
||||
, view = view -- leaving off always here!
|
||||
}
|
||||
|
||||
view : PageContext -> Html Msg
|
||||
view context =
|
||||
case context.global.user of
|
||||
SignedIn user ->
|
||||
viewUser user
|
||||
|
||||
SignedOut ->
|
||||
text "Who dis?"
|
||||
|
||||
-}
|
||||
type alias PageContext route globalModel =
|
||||
Page.PageContext route globalModel
|
||||
{ global : globalModel
|
||||
, route : route
|
||||
, queryParameters : Dict String String
|
||||
}
|
||||
|
||||
|
||||
{-| TODO: LayoutContext docs
|
||||
{-| This is what your `src/Layouts/*.elm` files can access!
|
||||
|
||||
|
||||
## creating your alias
|
||||
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
type alias LayoutContext msg =
|
||||
Spa.Types.LayoutContext Route msg (Element msg) Global.Model Global.Msg
|
||||
|
||||
|
||||
## using your alias
|
||||
|
||||
**`src/Layout.elm`**
|
||||
|
||||
import Utils.Spa as Spa
|
||||
|
||||
view : Spa.LayoutContext msg -> Html msg
|
||||
view { page, fromGlobalMsg, global } =
|
||||
div [ class "app" ]
|
||||
[ Html.map fromGlobalMsg (viewNavbar global)
|
||||
, page
|
||||
, viewFooter
|
||||
]
|
||||
|
||||
viewNavbar : Global.Model -> Html Global.Msg
|
||||
viewNavbar =
|
||||
-- ...
|
||||
|
||||
viewFooter : Html msg
|
||||
viewFooter =
|
||||
-- ...
|
||||
|
||||
-}
|
||||
type alias LayoutContext route msg ui_msg globalModel globalMsg =
|
||||
Page.LayoutContext route msg ui_msg globalModel globalMsg
|
||||
{ page : ui_msg
|
||||
, route : route
|
||||
, global : globalModel
|
||||
, fromGlobalMsg : globalMsg -> msg
|
||||
}
|
||||
|
||||
|
||||
{-|
|
||||
@ -298,28 +403,27 @@ type alias LayoutContext route msg ui_msg globalModel globalMsg =
|
||||
import Spa.Types
|
||||
import Element exposing (Element)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
type alias Upgrade params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Upgrade Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||
|
||||
-- if using elm/html
|
||||
|
||||
import Spa.Types
|
||||
import Html exposing (Html)
|
||||
|
||||
type alias Bundle msg appMsg =
|
||||
Spa.Types.Bundle msg (Html msg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
type alias Upgrade params model msg layoutModel layoutMsg appMsg =
|
||||
Spa.Types.Upgrade Route params model msg (Html msg) layoutModel layoutMsg (Html layoutMsg) Global.Model Global.Msg appMsg (Html appMsg)
|
||||
|
||||
|
||||
## using your alias
|
||||
|
||||
**`.elm-spa/Generated/Pages.elm`**
|
||||
**`src/Utils/Spa.elm`**
|
||||
|
||||
import Utils.Spa as Spa
|
||||
|
||||
bundle : Model -> Spa.Bundle Msg msg
|
||||
bundle model_ =
|
||||
case model_ of
|
||||
-- ...
|
||||
recipe :
|
||||
Upgrade params model msg layoutModel layoutMsg appMsg
|
||||
-> Recipe params model msg layoutModel layoutMsg appMsg
|
||||
recipe =
|
||||
Spa.Page.recipe Element.map
|
||||
|
||||
-}
|
||||
type alias Upgrade route pageParams pageModel pageMsg ui_pageMsg layoutModel layoutMsg ui_layoutMsg globalModel globalMsg msg ui_msg =
|
||||
|
Loading…
Reference in New Issue
Block a user