mirror of
https://github.com/ryan-haskell/elm-spa.git
synced 2024-11-29 09:31:20 +03:00
im really happy with this thing 😭
This commit is contained in:
parent
2c9d529f84
commit
fb0e01a083
4
examples/docs/.gitignore
vendored
Normal file
4
examples/docs/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
elm-stuff
|
||||||
|
dist
|
24
examples/docs/README.md
Normal file
24
examples/docs/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# your elm-spa
|
||||||
|
> learn more at [https://elm-spa.dev](https://elm-spa.dev)
|
||||||
|
|
||||||
|
### local development
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## folder structure
|
||||||
|
|
||||||
|
```elm
|
||||||
|
README.md -- this file you're reading 👀
|
||||||
|
elm.json -- has project dependencies
|
||||||
|
src/
|
||||||
|
Main.elm -- the entrypoint to the app
|
||||||
|
Global.elm -- share state across pages
|
||||||
|
Transitions.elm -- smoothly animate between pages
|
||||||
|
Ports.elm -- communicate with JS
|
||||||
|
Pages/ -- where all your pages go
|
||||||
|
Layouts/ -- reusable views around pages
|
||||||
|
Components/ -- views shared across the site
|
||||||
|
Utils/ -- a place for helper functions
|
||||||
|
```
|
31
examples/docs/elm.json
Normal file
31
examples/docs/elm.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"type": "application",
|
||||||
|
"source-directories": [
|
||||||
|
"src",
|
||||||
|
"elm-stuff/.elm-spa"
|
||||||
|
],
|
||||||
|
"elm-version": "0.19.1",
|
||||||
|
"dependencies": {
|
||||||
|
"direct": {
|
||||||
|
"elm/core": "1.0.2",
|
||||||
|
"elm/html": "1.0.0",
|
||||||
|
"elm/json": "1.1.3",
|
||||||
|
"elm/url": "1.0.0",
|
||||||
|
"elm-explorations/markdown": "1.0.0",
|
||||||
|
"mdgriffith/elm-ui": "1.1.5",
|
||||||
|
"ryannhg/elm-spa": "2.0.0"
|
||||||
|
},
|
||||||
|
"indirect": {
|
||||||
|
"elm/browser": "1.0.2",
|
||||||
|
"elm/time": "1.0.0",
|
||||||
|
"elm/virtual-dom": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test-dependencies": {
|
||||||
|
"direct": {},
|
||||||
|
"indirect": {}
|
||||||
|
},
|
||||||
|
"elm-spa": {
|
||||||
|
"ui": "Element"
|
||||||
|
}
|
||||||
|
}
|
1457
examples/docs/package-lock.json
generated
Normal file
1457
examples/docs/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
examples/docs/package.json
Normal file
24
examples/docs/package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "my-elm-spa-project",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "learn more at https://elm-spa.dev",
|
||||||
|
"scripts": {
|
||||||
|
"start": "npm install && npm run dev",
|
||||||
|
"dev": "npm run elm:spa:build && npm run elm:spa:watch & npm run elm:live",
|
||||||
|
"build": "npm run elm:spa:build && npm run elm:compile",
|
||||||
|
"elm:compile": "elm make src/Main.elm --output=public/dist/elm.compiled.js --optimize",
|
||||||
|
"elm:live": "elm-live src/Main.elm --dir=public --start-page=index.html --open --pushstate --port=1234 -- --output=public/dist/elm.compiled.js --debug",
|
||||||
|
"elm:spa:build": "elm-spa build .",
|
||||||
|
"elm:spa:watch": "SHELL=/bin/bash chokidar 'src/Pages' -c 'npm run elm:spa:build'"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"chokidar-cli": "2.1.0",
|
||||||
|
"elm": "0.19.1-3",
|
||||||
|
"elm-live": "4.0.1",
|
||||||
|
"elm-spa": "2.0.4"
|
||||||
|
}
|
||||||
|
}
|
BIN
examples/docs/public/favicon.png
Normal file
BIN
examples/docs/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
25
examples/docs/public/index.html
Normal file
25
examples/docs/public/index.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||||
|
<title>our-elm-spa</title>
|
||||||
|
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||||
|
<link rel="stylesheet" href="/styles.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/styles/atom-one-light.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/elm.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/languages/html.min.js"></script>
|
||||||
|
<script src="/dist/elm.compiled.js"></script>
|
||||||
|
<script src="/ports.js"></script>
|
||||||
|
<script>
|
||||||
|
window.hljs.initHighlightingOnLoad()
|
||||||
|
window.addEventListener('load', _ => {
|
||||||
|
window.ports.init(Elm.Main.init())
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
17
examples/docs/public/ports.js
Normal file
17
examples/docs/public/ports.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// On load, listen to Elm!
|
||||||
|
window.addEventListener('load', _ => {
|
||||||
|
window.ports = {
|
||||||
|
init: (app) =>
|
||||||
|
app.ports.outgoing.subscribe(({ action, data }) =>
|
||||||
|
actions[action]
|
||||||
|
? actions[action](data)
|
||||||
|
: console.warn(`I didn't recognize action "${action}".`)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// maps actions to functions!
|
||||||
|
const actions = {
|
||||||
|
'LOG': (message) =>
|
||||||
|
console.log(`From Elm:`, message)
|
||||||
|
}
|
49
examples/docs/public/styles.css
Normal file
49
examples/docs/public/styles.css
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* you can include CSS here */
|
||||||
|
html, body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > * {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown > *:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h3 {
|
||||||
|
margin-top: 1.5em;
|
||||||
|
line-height: 1.1;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown h4 {
|
||||||
|
line-height: 1.2;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown p, ul, ol {
|
||||||
|
line-height: 1.4;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown pre {
|
||||||
|
border: solid 1px #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 0 calc(4px - 1em);
|
||||||
|
margin-top: 1em;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown a {
|
||||||
|
color: rgb(200, 75, 85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown iframe {
|
||||||
|
width: 100%;
|
||||||
|
margin: 2em -1em;
|
||||||
|
background: #eee;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
53
examples/docs/src/Components/Hero.elm
Normal file
53
examples/docs/src/Components/Hero.elm
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
module Components.Hero exposing (Options, view)
|
||||||
|
|
||||||
|
import Element exposing (..)
|
||||||
|
import Element.Background as Background
|
||||||
|
import Element.Border as Border
|
||||||
|
import Element.Font as Font
|
||||||
|
import Element.Region as Region
|
||||||
|
import Ui exposing (colors, styles)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Options =
|
||||||
|
{ title : String
|
||||||
|
, subtitle : String
|
||||||
|
, links :
|
||||||
|
List
|
||||||
|
{ label : String
|
||||||
|
, url : String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
view : Options -> Element msg
|
||||||
|
view options =
|
||||||
|
column
|
||||||
|
[ paddingEach
|
||||||
|
{ top = 128
|
||||||
|
, left = 0
|
||||||
|
, right = 0
|
||||||
|
, bottom = 32
|
||||||
|
}
|
||||||
|
, centerX
|
||||||
|
, spacing 24
|
||||||
|
]
|
||||||
|
[ column [ spacing 14, centerX ]
|
||||||
|
[ el
|
||||||
|
[ Font.size 56
|
||||||
|
, Font.bold
|
||||||
|
, centerX
|
||||||
|
, Region.heading 1
|
||||||
|
]
|
||||||
|
(text options.title)
|
||||||
|
, el [ centerX, alpha 0.5, Region.heading 2 ] (text options.subtitle)
|
||||||
|
]
|
||||||
|
, wrappedRow [ spacing 12, centerX ] <|
|
||||||
|
List.map
|
||||||
|
(\{ label, url } ->
|
||||||
|
link styles.button
|
||||||
|
{ label = text label
|
||||||
|
, url = url
|
||||||
|
}
|
||||||
|
)
|
||||||
|
options.links
|
||||||
|
]
|
40
examples/docs/src/Components/Navbar.elm
Normal file
40
examples/docs/src/Components/Navbar.elm
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
module Components.Navbar exposing (view)
|
||||||
|
|
||||||
|
import Element exposing (..)
|
||||||
|
import Element.Font as Font
|
||||||
|
import Generated.Routes as Routes exposing (Route, routes)
|
||||||
|
import Ui exposing (colors, styles)
|
||||||
|
|
||||||
|
|
||||||
|
view : Route -> Element msg
|
||||||
|
view currentRoute =
|
||||||
|
row
|
||||||
|
[ spacing 24
|
||||||
|
, centerX
|
||||||
|
, width fill
|
||||||
|
]
|
||||||
|
[ row [ Font.color colors.coral, spacing 16 ]
|
||||||
|
[ el [ Font.semiBold, Font.size 20 ]
|
||||||
|
(viewLink currentRoute ( "elm-spa", routes.top ))
|
||||||
|
, viewLink currentRoute ( "docs", routes.docs )
|
||||||
|
, viewLink currentRoute ( "guide", routes.guide )
|
||||||
|
]
|
||||||
|
, el [ alignRight ] <|
|
||||||
|
link styles.button
|
||||||
|
{ label = text "get started"
|
||||||
|
, url = "/guide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewLink : Route -> ( String, Route ) -> Element msg
|
||||||
|
viewLink currentRoute ( label, route ) =
|
||||||
|
if currentRoute == route then
|
||||||
|
el styles.link.disabled
|
||||||
|
(text label)
|
||||||
|
|
||||||
|
else
|
||||||
|
link styles.link.enabled
|
||||||
|
{ label = text label
|
||||||
|
, url = Routes.toPath route
|
||||||
|
}
|
2
examples/docs/src/Components/README.md
Normal file
2
examples/docs/src/Components/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# src/Components
|
||||||
|
> views shared across the site
|
49
examples/docs/src/Global.elm
Normal file
49
examples/docs/src/Global.elm
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
module Global exposing
|
||||||
|
( Flags
|
||||||
|
, Model
|
||||||
|
, Msg(..)
|
||||||
|
, init
|
||||||
|
, subscriptions
|
||||||
|
, update
|
||||||
|
)
|
||||||
|
|
||||||
|
import Generated.Routes as Routes exposing (Route)
|
||||||
|
import Ports
|
||||||
|
|
||||||
|
|
||||||
|
type alias Flags =
|
||||||
|
()
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= Msg
|
||||||
|
|
||||||
|
|
||||||
|
type alias Commands msg =
|
||||||
|
{ navigate : Route -> Cmd msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init : Commands msg -> Flags -> ( Model, Cmd Msg, Cmd msg )
|
||||||
|
init _ _ =
|
||||||
|
( {}
|
||||||
|
, Cmd.none
|
||||||
|
, Ports.log "Hello!"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
update : Commands msg -> Msg -> Model -> ( Model, Cmd Msg, Cmd msg )
|
||||||
|
update _ _ model =
|
||||||
|
( model
|
||||||
|
, Cmd.none
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
subscriptions : Model -> Sub Msg
|
||||||
|
subscriptions _ =
|
||||||
|
Sub.none
|
49
examples/docs/src/Layout.elm
Normal file
49
examples/docs/src/Layout.elm
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
module Layout exposing (view)
|
||||||
|
|
||||||
|
import Components.Navbar as Navbar
|
||||||
|
import Element exposing (..)
|
||||||
|
import Element.Font as Font
|
||||||
|
import Element.Region as Region
|
||||||
|
import Utils.Spa as Spa
|
||||||
|
|
||||||
|
|
||||||
|
view : Spa.LayoutContext msg -> Element msg
|
||||||
|
view { page, route } =
|
||||||
|
column
|
||||||
|
[ height fill
|
||||||
|
, width (fill |> maximum 512)
|
||||||
|
, centerX
|
||||||
|
, Font.size 16
|
||||||
|
, Font.family
|
||||||
|
[ Font.external
|
||||||
|
{ name = "IBM Plex Sans"
|
||||||
|
, url = "https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,400i,600,600i"
|
||||||
|
}
|
||||||
|
, Font.sansSerif
|
||||||
|
]
|
||||||
|
, paddingEach
|
||||||
|
{ top = 32
|
||||||
|
, left = 16
|
||||||
|
, right = 16
|
||||||
|
, bottom = 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
[ el [ Region.navigation, width fill ] (Navbar.view route)
|
||||||
|
, el [ Region.mainContent, width fill, height fill ] page
|
||||||
|
, el [ Region.footer, width fill ] viewFooter
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
viewFooter : Element msg
|
||||||
|
viewFooter =
|
||||||
|
row
|
||||||
|
[ width fill
|
||||||
|
, paddingEach { top = 96, left = 0, right = 0, bottom = 48 }
|
||||||
|
, alpha 0.5
|
||||||
|
]
|
||||||
|
[ text "this site was built with elm-spa!"
|
||||||
|
, newTabLink [ alignRight, Font.underline ]
|
||||||
|
{ label = text "github"
|
||||||
|
, url = "https://github.com/ryannhg/elm-spa"
|
||||||
|
}
|
||||||
|
]
|
2
examples/docs/src/Layouts/README.md
Normal file
2
examples/docs/src/Layouts/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# src/Layouts
|
||||||
|
> where all your pages go
|
26
examples/docs/src/Main.elm
Normal file
26
examples/docs/src/Main.elm
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module Main exposing (main)
|
||||||
|
|
||||||
|
import Generated.Pages as Pages
|
||||||
|
import Generated.Routes as Routes exposing (routes)
|
||||||
|
import Global
|
||||||
|
import Spa
|
||||||
|
import Transitions
|
||||||
|
|
||||||
|
|
||||||
|
main : Spa.Program Global.Flags Global.Model Global.Msg Pages.Model Pages.Msg
|
||||||
|
main =
|
||||||
|
Spa.create
|
||||||
|
{ ui = Spa.usingElmUi
|
||||||
|
, transitions = Transitions.transitions
|
||||||
|
, routing =
|
||||||
|
{ routes = Routes.parsers
|
||||||
|
, toPath = Routes.toPath
|
||||||
|
, notFound = routes.notFound
|
||||||
|
}
|
||||||
|
, global =
|
||||||
|
{ init = Global.init
|
||||||
|
, update = Global.update
|
||||||
|
, subscriptions = Global.subscriptions
|
||||||
|
}
|
||||||
|
, page = Pages.page
|
||||||
|
}
|
49
examples/docs/src/Pages/Docs.elm
Normal file
49
examples/docs/src/Pages/Docs.elm
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
module Pages.Docs exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Components.Hero as Hero
|
||||||
|
import Element exposing (..)
|
||||||
|
import Generated.Params as Params
|
||||||
|
import Spa.Page
|
||||||
|
import Ui
|
||||||
|
import Utils.Spa exposing (Page)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
()
|
||||||
|
|
||||||
|
|
||||||
|
type alias Msg =
|
||||||
|
Never
|
||||||
|
|
||||||
|
|
||||||
|
page : Page Params.Docs Model Msg model msg appMsg
|
||||||
|
page =
|
||||||
|
Spa.Page.static
|
||||||
|
{ title = always "docs | elm-spa"
|
||||||
|
, view = always view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Element Msg
|
||||||
|
view =
|
||||||
|
Ui.sections
|
||||||
|
[ Hero.view
|
||||||
|
{ title = "docs"
|
||||||
|
, subtitle = "\"it's not done until the docs are great!\""
|
||||||
|
, links = []
|
||||||
|
}
|
||||||
|
, Ui.markdown """
|
||||||
|
### table of contents
|
||||||
|
|
||||||
|
1. [installation & setup](#installation)
|
||||||
|
1. project structure
|
||||||
|
1. adding pages
|
||||||
|
1. changing layouts
|
||||||
|
1. components and reusable ui
|
||||||
|
|
||||||
|
"""
|
||||||
|
]
|
50
examples/docs/src/Pages/Guide.elm
Normal file
50
examples/docs/src/Pages/Guide.elm
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
module Pages.Guide exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Components.Hero as Hero
|
||||||
|
import Element exposing (..)
|
||||||
|
import Generated.Params as Params
|
||||||
|
import Spa.Page
|
||||||
|
import Ui
|
||||||
|
import Utils.Spa exposing (Page)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
()
|
||||||
|
|
||||||
|
|
||||||
|
type alias Msg =
|
||||||
|
Never
|
||||||
|
|
||||||
|
|
||||||
|
page : Page Params.Guide Model Msg model msg appMsg
|
||||||
|
page =
|
||||||
|
Spa.Page.static
|
||||||
|
{ title = always "guide | elm-spa"
|
||||||
|
, view = always view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Element Msg
|
||||||
|
view =
|
||||||
|
Ui.sections
|
||||||
|
[ Hero.view
|
||||||
|
{ title = "guide"
|
||||||
|
, subtitle = "let's build something together!"
|
||||||
|
, links = []
|
||||||
|
}
|
||||||
|
, Ui.markdown """
|
||||||
|
### what can i build with elm-spa?
|
||||||
|
|
||||||
|
__This entire site!__ And in this guide we'll build it together, from scratch.
|
||||||
|
(Step-by-step, with short videos)
|
||||||
|
|
||||||
|
<iframe title="elm-spa: welcome to the guide!" width="560" height="315" src="https://www.youtube.com/embed/OMDMawvANNs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||||
|
|
||||||
|
|
||||||
|
Are you officially hyped? Let's [get you setup](/guide/setup)!
|
||||||
|
"""
|
||||||
|
]
|
42
examples/docs/src/Pages/NotFound.elm
Normal file
42
examples/docs/src/Pages/NotFound.elm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
module Pages.NotFound exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Components.Hero as Hero
|
||||||
|
import Element exposing (..)
|
||||||
|
import Element.Font as Font
|
||||||
|
import Generated.Params as Params
|
||||||
|
import Generated.Routes as Routes exposing (routes)
|
||||||
|
import Spa.Page
|
||||||
|
import Utils.Spa exposing (Page)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
()
|
||||||
|
|
||||||
|
|
||||||
|
type alias Msg =
|
||||||
|
Never
|
||||||
|
|
||||||
|
|
||||||
|
page : Page Params.NotFound Model Msg model msg appMsg
|
||||||
|
page =
|
||||||
|
Spa.Page.static
|
||||||
|
{ title = always "not found | elm-spa"
|
||||||
|
, view = always view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Element Msg
|
||||||
|
view =
|
||||||
|
Hero.view
|
||||||
|
{ title = "page not found?"
|
||||||
|
, subtitle = "it's not you, it's me."
|
||||||
|
, links =
|
||||||
|
[ { label = "but this link works!"
|
||||||
|
, url = "/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3
examples/docs/src/Pages/README.md
Normal file
3
examples/docs/src/Pages/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# src/Pages
|
||||||
|
> where all your pages go
|
||||||
|
|
50
examples/docs/src/Pages/Top.elm
Normal file
50
examples/docs/src/Pages/Top.elm
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
module Pages.Top exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Components.Hero as Hero
|
||||||
|
import Element exposing (..)
|
||||||
|
import Generated.Params as Params
|
||||||
|
import Spa.Page
|
||||||
|
import Ui
|
||||||
|
import Utils.Spa exposing (Page)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
()
|
||||||
|
|
||||||
|
|
||||||
|
type alias Msg =
|
||||||
|
Never
|
||||||
|
|
||||||
|
|
||||||
|
page : Page Params.Top Model Msg model msg appMsg
|
||||||
|
page =
|
||||||
|
Spa.Page.static
|
||||||
|
{ title = always "elm-spa"
|
||||||
|
, view = always view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Element Msg
|
||||||
|
view =
|
||||||
|
Ui.sections
|
||||||
|
[ Hero.view
|
||||||
|
{ title = "elm-spa"
|
||||||
|
, subtitle = "a framework for building single page apps"
|
||||||
|
, links = [ { label = "get started", url = "/guide" } ]
|
||||||
|
}
|
||||||
|
, Ui.markdown """
|
||||||
|
### does elm _need_ a framework?
|
||||||
|
|
||||||
|
__nope, not really–__ it's kinda got one built in! so building something like React, VueJS, or Angular wouldn't really make sense.
|
||||||
|
|
||||||
|
#### ...but even frameworks need frameworks!
|
||||||
|
|
||||||
|
that's why projects like VueJS also have awesome tools like NuxtJS that bring together the best tools in the ecosystem (and a set of shared best practices!)
|
||||||
|
|
||||||
|
welcome to __elm-spa__, a framework for Elm!
|
||||||
|
"""
|
||||||
|
]
|
14
examples/docs/src/Ports.elm
Normal file
14
examples/docs/src/Ports.elm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
port module Ports exposing (log)
|
||||||
|
|
||||||
|
import Json.Encode as Json
|
||||||
|
|
||||||
|
|
||||||
|
port outgoing : { action : String, data : Json.Value } -> Cmd msg
|
||||||
|
|
||||||
|
|
||||||
|
log : String -> Cmd msg
|
||||||
|
log message =
|
||||||
|
outgoing
|
||||||
|
{ action = "LOG"
|
||||||
|
, data = Json.string message
|
||||||
|
}
|
12
examples/docs/src/Transitions.elm
Normal file
12
examples/docs/src/Transitions.elm
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
module Transitions exposing (transitions)
|
||||||
|
|
||||||
|
import Spa.Transition as Transition
|
||||||
|
import Utils.Spa as Spa
|
||||||
|
|
||||||
|
|
||||||
|
transitions : Spa.Transitions msg
|
||||||
|
transitions =
|
||||||
|
{ layout = Transition.none
|
||||||
|
, page = Transition.fadeElmUi 300
|
||||||
|
, pages = []
|
||||||
|
}
|
100
examples/docs/src/Ui.elm
Normal file
100
examples/docs/src/Ui.elm
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
module Ui exposing
|
||||||
|
( colors
|
||||||
|
, markdown
|
||||||
|
, sections
|
||||||
|
, styles
|
||||||
|
, transition
|
||||||
|
)
|
||||||
|
|
||||||
|
import Element exposing (..)
|
||||||
|
import Element.Background as Background
|
||||||
|
import Element.Border as Border
|
||||||
|
import Element.Font as Font
|
||||||
|
import Html.Attributes as Attr
|
||||||
|
import Markdown
|
||||||
|
|
||||||
|
|
||||||
|
colors : { coral : Color, white : Color }
|
||||||
|
colors =
|
||||||
|
{ coral = rgb255 200 75 85
|
||||||
|
, white = rgb255 255 255 255
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
styles :
|
||||||
|
{ button : List (Attribute msg)
|
||||||
|
, link :
|
||||||
|
{ enabled : List (Attribute msg)
|
||||||
|
, disabled : List (Attribute msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
styles =
|
||||||
|
{ link =
|
||||||
|
{ enabled =
|
||||||
|
[ Font.underline
|
||||||
|
, transition
|
||||||
|
{ duration = 200
|
||||||
|
, props = [ "opacity" ]
|
||||||
|
}
|
||||||
|
, mouseOver [ alpha 0.5 ]
|
||||||
|
]
|
||||||
|
, disabled =
|
||||||
|
[ alpha 0.5
|
||||||
|
]
|
||||||
|
}
|
||||||
|
, button =
|
||||||
|
[ centerX
|
||||||
|
, Font.size 14
|
||||||
|
, Font.semiBold
|
||||||
|
, Border.solid
|
||||||
|
, Border.width 2
|
||||||
|
, Border.rounded 4
|
||||||
|
, paddingXY 24 8
|
||||||
|
, Font.color colors.coral
|
||||||
|
, Border.color colors.coral
|
||||||
|
, Background.color colors.white
|
||||||
|
, pointer
|
||||||
|
, transition
|
||||||
|
{ duration = 200
|
||||||
|
, props = [ "background", "color" ]
|
||||||
|
}
|
||||||
|
, mouseOver
|
||||||
|
[ Background.color colors.coral
|
||||||
|
, Font.color colors.white
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sections : List (Element msg) -> Element msg
|
||||||
|
sections =
|
||||||
|
column [ spacing 32, width fill ]
|
||||||
|
|
||||||
|
|
||||||
|
markdown : String -> Element msg
|
||||||
|
markdown =
|
||||||
|
let
|
||||||
|
options =
|
||||||
|
Markdown.defaultOptions
|
||||||
|
|> (\o -> { o | sanitize = False })
|
||||||
|
in
|
||||||
|
Markdown.toHtmlWith options [ Attr.class "markdown" ]
|
||||||
|
>> Element.html
|
||||||
|
>> List.singleton
|
||||||
|
>> paragraph []
|
||||||
|
|
||||||
|
|
||||||
|
transition : { props : List String, duration : Int } -> Attribute msg
|
||||||
|
transition options =
|
||||||
|
options.props
|
||||||
|
|> List.map
|
||||||
|
(\prop ->
|
||||||
|
String.join " "
|
||||||
|
[ prop
|
||||||
|
, String.fromInt options.duration ++ "ms"
|
||||||
|
, "ease-in-out"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> String.join ", "
|
||||||
|
|> Attr.style "transition"
|
||||||
|
|> Element.htmlAttribute
|
2
examples/docs/src/Utils/README.md
Normal file
2
examples/docs/src/Utils/README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# src/Utils
|
||||||
|
> a place for helper functions
|
72
examples/docs/src/Utils/Spa.elm
Normal file
72
examples/docs/src/Utils/Spa.elm
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
module Utils.Spa exposing
|
||||||
|
( Bundle
|
||||||
|
, Init
|
||||||
|
, LayoutContext
|
||||||
|
, Page
|
||||||
|
, PageContext
|
||||||
|
, Recipe
|
||||||
|
, Transitions
|
||||||
|
, Update
|
||||||
|
, layout
|
||||||
|
, recipe
|
||||||
|
)
|
||||||
|
|
||||||
|
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 =
|
||||||
|
Spa.Types.Page Route params model msg (Element msg) layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Recipe params model msg layoutModel layoutMsg appMsg =
|
||||||
|
Spa.Types.Recipe Route params model msg layoutModel layoutMsg (Element layoutMsg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Init model msg =
|
||||||
|
Spa.Types.Init Route model msg Global.Model Global.Msg
|
||||||
|
|
||||||
|
|
||||||
|
type alias Update model msg =
|
||||||
|
Spa.Types.Update Route model msg Global.Model Global.Msg
|
||||||
|
|
||||||
|
|
||||||
|
type alias Bundle msg appMsg =
|
||||||
|
Spa.Types.Bundle Route msg (Element msg) Global.Model Global.Msg appMsg (Element appMsg)
|
||||||
|
|
||||||
|
|
||||||
|
type alias LayoutContext msg =
|
||||||
|
Spa.Types.LayoutContext Route msg (Element msg) Global.Model Global.Msg
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
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
|
||||||
|
recipe =
|
||||||
|
Spa.Page.recipe Element.map
|
||||||
|
|
||||||
|
|
||||||
|
type alias Transitions msg =
|
||||||
|
Spa.Types.Transitions (Element msg)
|
Loading…
Reference in New Issue
Block a user