mirror of
https://gitlab.com/upRootNutrition/dotfiles.git
synced 2025-07-05 02:45:01 -05:00
feat: improved elm template
This commit is contained in:
parent
8545d7c1e8
commit
6b2a601776
22 changed files with 2139 additions and 0 deletions
7
templates/elm/frontend/.gitignore
vendored
Normal file
7
templates/elm/frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/dist
|
||||||
|
/.elm-land
|
||||||
|
/.env
|
||||||
|
/elm-stuff
|
||||||
|
/node_modules
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
16
templates/elm/frontend/README.md
Normal file
16
templates/elm/frontend/README.md
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# frontend
|
||||||
|
> Built with [Elm Land](https://elm.land) 🌈
|
||||||
|
|
||||||
|
## Local development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Requires Node.js v18+ (https://nodejs.org)
|
||||||
|
npx elm-land server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploying to production
|
||||||
|
|
||||||
|
Elm Land projects are most commonly deployed as static websites.
|
||||||
|
|
||||||
|
Please visit [the "Deployment" guide](https://elm.land/guide/deploying) to learn more
|
||||||
|
about deploying your app for free using Netlify or Vercel.
|
26
templates/elm/frontend/elm-land.json
Normal file
26
templates/elm/frontend/elm-land.json
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"elm": {
|
||||||
|
"development": { "debugger": true },
|
||||||
|
"production": { "debugger": false }
|
||||||
|
},
|
||||||
|
"env": [],
|
||||||
|
"html": {
|
||||||
|
"attributes": {
|
||||||
|
"html": { "lang": "en" },
|
||||||
|
"head": {}
|
||||||
|
},
|
||||||
|
"title": "Elm Land",
|
||||||
|
"meta": [
|
||||||
|
{ "charset": "UTF-8" },
|
||||||
|
{ "http-equiv": "X-UA-Compatible", "content": "IE=edge" },
|
||||||
|
{ "name": "viewport", "content": "width=device-width, initial-scale=1.0" }
|
||||||
|
],
|
||||||
|
"link": [],
|
||||||
|
"script": []
|
||||||
|
},
|
||||||
|
"router": {
|
||||||
|
"useHashRouting": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
templates/elm/frontend/elm.json
Normal file
53
templates/elm/frontend/elm.json
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"type": "application",
|
||||||
|
"source-directories": [
|
||||||
|
"src",
|
||||||
|
".elm-land/src"
|
||||||
|
],
|
||||||
|
"elm-version": "0.19.1",
|
||||||
|
"dependencies": {
|
||||||
|
"direct": {
|
||||||
|
"dillonkearns/elm-markdown": "7.0.1",
|
||||||
|
"elm/browser": "1.0.2",
|
||||||
|
"elm/core": "1.0.5",
|
||||||
|
"elm/html": "1.0.0",
|
||||||
|
"elm/json": "1.1.3",
|
||||||
|
"elm/svg": "1.0.1",
|
||||||
|
"elm/url": "1.0.0",
|
||||||
|
"elm-community/list-extra": "8.7.0",
|
||||||
|
"elm-community/maybe-extra": "5.3.0",
|
||||||
|
"gampleman/elm-visualization": "2.4.2",
|
||||||
|
"hecrj/html-parser": "2.4.0",
|
||||||
|
"mdgriffith/elm-ui": "1.1.8"
|
||||||
|
},
|
||||||
|
"indirect": {
|
||||||
|
"avh4/elm-color": "1.0.0",
|
||||||
|
"elm/parser": "1.1.0",
|
||||||
|
"elm/random": "1.0.0",
|
||||||
|
"elm/regex": "1.0.0",
|
||||||
|
"elm/time": "1.0.0",
|
||||||
|
"elm/virtual-dom": "1.0.3",
|
||||||
|
"elmcraft/core-extra": "2.2.0",
|
||||||
|
"folkertdev/elm-deque": "3.0.1",
|
||||||
|
"folkertdev/one-true-path-experiment": "6.0.1",
|
||||||
|
"folkertdev/svg-path-lowlevel": "4.0.1",
|
||||||
|
"gampleman/elm-rosetree": "1.1.0",
|
||||||
|
"ianmackenzie/elm-1d-parameter": "1.0.1",
|
||||||
|
"ianmackenzie/elm-float-extra": "1.1.0",
|
||||||
|
"ianmackenzie/elm-geometry": "3.11.0",
|
||||||
|
"ianmackenzie/elm-interval": "3.1.0",
|
||||||
|
"ianmackenzie/elm-triangular-mesh": "1.1.0",
|
||||||
|
"ianmackenzie/elm-units": "2.10.0",
|
||||||
|
"ianmackenzie/elm-units-interval": "3.2.0",
|
||||||
|
"ianmackenzie/elm-units-prefixed": "2.8.0",
|
||||||
|
"justinmimbs/date": "4.1.0",
|
||||||
|
"justinmimbs/time-extra": "1.2.0",
|
||||||
|
"rtfeldman/elm-hex": "1.0.0",
|
||||||
|
"ryan-haskell/date-format": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test-dependencies": {
|
||||||
|
"direct": {},
|
||||||
|
"indirect": {}
|
||||||
|
}
|
||||||
|
}
|
94
templates/elm/frontend/src/Config/Helpers/Response.elm
Executable file
94
templates/elm/frontend/src/Config/Helpers/Response.elm
Executable file
|
@ -0,0 +1,94 @@
|
||||||
|
module Config.Helpers.Response exposing
|
||||||
|
( contentContainer
|
||||||
|
, pageList
|
||||||
|
, pageListCenter
|
||||||
|
, pageListFormat
|
||||||
|
, topLevelContainer
|
||||||
|
)
|
||||||
|
|
||||||
|
import Config.Style.Colour.Helpers exposing (colourTheme)
|
||||||
|
import Element as E
|
||||||
|
exposing
|
||||||
|
( Attribute
|
||||||
|
, Device
|
||||||
|
, DeviceClass(..)
|
||||||
|
, Element
|
||||||
|
, Orientation(..)
|
||||||
|
, alignTop
|
||||||
|
, centerX
|
||||||
|
, centerY
|
||||||
|
, el
|
||||||
|
, fill
|
||||||
|
, height
|
||||||
|
, maximum
|
||||||
|
, minimum
|
||||||
|
, padding
|
||||||
|
, paddingXY
|
||||||
|
, scrollbarY
|
||||||
|
, spacing
|
||||||
|
, width
|
||||||
|
)
|
||||||
|
import Element.Background as B exposing (color)
|
||||||
|
import Html.Attributes exposing (style)
|
||||||
|
|
||||||
|
|
||||||
|
topLevelContainer : Element msg -> Element msg
|
||||||
|
topLevelContainer =
|
||||||
|
el
|
||||||
|
[ width fill
|
||||||
|
, height fill
|
||||||
|
, B.color colourTheme.backgroundLightGrey
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
pageListCenter : Device -> List (Attribute msg)
|
||||||
|
pageListCenter device =
|
||||||
|
[ centerY
|
||||||
|
]
|
||||||
|
++ pageListFormat device
|
||||||
|
|
||||||
|
|
||||||
|
pageList : Device -> List (Attribute msg)
|
||||||
|
pageList device =
|
||||||
|
[ alignTop
|
||||||
|
]
|
||||||
|
++ pageListFormat device
|
||||||
|
|
||||||
|
|
||||||
|
pageListFormat : Device -> List (Attribute msg)
|
||||||
|
pageListFormat device =
|
||||||
|
let
|
||||||
|
pageListAttr =
|
||||||
|
[ centerX
|
||||||
|
, width fill
|
||||||
|
, height fill
|
||||||
|
, scrollbarY
|
||||||
|
]
|
||||||
|
in
|
||||||
|
pageListAttr
|
||||||
|
++ (case ( device.class, device.orientation ) of
|
||||||
|
( Phone, Portrait ) ->
|
||||||
|
[ spacing 0
|
||||||
|
, paddingXY 10 30
|
||||||
|
]
|
||||||
|
|
||||||
|
( Tablet, Portrait ) ->
|
||||||
|
[ spacing 0
|
||||||
|
, paddingXY 10 30
|
||||||
|
]
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
[ spacing 20
|
||||||
|
, paddingXY 30 30
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
contentContainer : Element msg -> Element msg
|
||||||
|
contentContainer =
|
||||||
|
el
|
||||||
|
[ width (fill |> minimum 100)
|
||||||
|
, width (fill |> maximum 875)
|
||||||
|
, padding 10
|
||||||
|
, centerX
|
||||||
|
]
|
16
templates/elm/frontend/src/Config/Helpers/Viewport.elm
Executable file
16
templates/elm/frontend/src/Config/Helpers/Viewport.elm
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
module Config.Helpers.Viewport exposing
|
||||||
|
( Msg
|
||||||
|
, resetViewport
|
||||||
|
)
|
||||||
|
|
||||||
|
import Browser.Dom as Dom exposing (setViewport)
|
||||||
|
import Task exposing (attempt)
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= NoOp
|
||||||
|
|
||||||
|
|
||||||
|
resetViewport : Cmd Msg
|
||||||
|
resetViewport =
|
||||||
|
Task.attempt (\_ -> NoOp) (Dom.setViewportOf "scroll-container" 0 0)
|
118
templates/elm/frontend/src/Config/Style/Colour/Helpers.elm
Executable file
118
templates/elm/frontend/src/Config/Style/Colour/Helpers.elm
Executable file
|
@ -0,0 +1,118 @@
|
||||||
|
module Config.Style.Colour.Helpers exposing
|
||||||
|
( ThemeColor(..)
|
||||||
|
, colourTheme
|
||||||
|
, getThemeColor
|
||||||
|
, syntaxTheme
|
||||||
|
)
|
||||||
|
|
||||||
|
import Config.Style.Colour.Types
|
||||||
|
exposing
|
||||||
|
( SyntaxColors
|
||||||
|
, Theme
|
||||||
|
)
|
||||||
|
import Element as E
|
||||||
|
exposing
|
||||||
|
( Color
|
||||||
|
, rgb255
|
||||||
|
, rgba
|
||||||
|
)
|
||||||
|
import Element.Font as F exposing (color)
|
||||||
|
|
||||||
|
|
||||||
|
colourTheme : Theme
|
||||||
|
colourTheme =
|
||||||
|
{ textLightGrey = rgb255 212 212 212
|
||||||
|
, textDarkGrey = rgb255 126 126 126
|
||||||
|
, textLightOrange = rgb255 204 102 0
|
||||||
|
, textDarkOrange = rgb255 120 60 0
|
||||||
|
, textDeepDarkOrange = rgb255 60 30 0
|
||||||
|
, backgroundLightGrey = rgb255 40 40 40
|
||||||
|
, backgroundDarkGrey = rgb255 30 30 30
|
||||||
|
, backgroundDeepDarkGrey = rgb255 20 20 20
|
||||||
|
, backgroundSpreadsheet = rgb255 36 36 36
|
||||||
|
, backgroundSpreadsheetDark = rgb255 26 26 26
|
||||||
|
, shadow = rgb255 10 10 10
|
||||||
|
, barGreen = rgb255 0 102 0
|
||||||
|
, barRed = rgb255 102 0 0
|
||||||
|
, debugColour = rgb255 227 28 121
|
||||||
|
, transparent = rgba 1 1 1 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
syntaxTheme : SyntaxColors
|
||||||
|
syntaxTheme =
|
||||||
|
{ punctuation = rgb255 202 158 230
|
||||||
|
, key = rgb255 138 173 244
|
||||||
|
, string = rgb255 166 218 149
|
||||||
|
, keyword = rgb255 245 169 127
|
||||||
|
, operator = rgb255 178 185 194
|
||||||
|
, background = rgb255 36 39 58
|
||||||
|
, text = rgb255 202 211 245
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type ThemeColor
|
||||||
|
= TextLightGrey
|
||||||
|
| TextDarkGrey
|
||||||
|
| TextLightOrange
|
||||||
|
| TextDarkOrange
|
||||||
|
| TextDeepDarkOrange
|
||||||
|
| BackgroundLightGrey
|
||||||
|
| BackgroundDarkGrey
|
||||||
|
| BackgroundDeepDarkGrey
|
||||||
|
| BackgroundSpreadsheet
|
||||||
|
| BackgroundSpreadsheetDark
|
||||||
|
| Shadow
|
||||||
|
| BarGreen
|
||||||
|
| BarRed
|
||||||
|
| DebugColour
|
||||||
|
| Transparent
|
||||||
|
|
||||||
|
|
||||||
|
getThemeColor : ThemeColor -> Color
|
||||||
|
getThemeColor color =
|
||||||
|
case color of
|
||||||
|
TextLightGrey ->
|
||||||
|
colourTheme.textLightGrey
|
||||||
|
|
||||||
|
TextDarkGrey ->
|
||||||
|
colourTheme.textDarkGrey
|
||||||
|
|
||||||
|
TextLightOrange ->
|
||||||
|
colourTheme.textLightOrange
|
||||||
|
|
||||||
|
TextDarkOrange ->
|
||||||
|
colourTheme.textDarkOrange
|
||||||
|
|
||||||
|
TextDeepDarkOrange ->
|
||||||
|
colourTheme.textDeepDarkOrange
|
||||||
|
|
||||||
|
BackgroundLightGrey ->
|
||||||
|
colourTheme.backgroundLightGrey
|
||||||
|
|
||||||
|
BackgroundDarkGrey ->
|
||||||
|
colourTheme.backgroundDarkGrey
|
||||||
|
|
||||||
|
BackgroundDeepDarkGrey ->
|
||||||
|
colourTheme.backgroundDeepDarkGrey
|
||||||
|
|
||||||
|
BackgroundSpreadsheet ->
|
||||||
|
colourTheme.backgroundSpreadsheet
|
||||||
|
|
||||||
|
BackgroundSpreadsheetDark ->
|
||||||
|
colourTheme.backgroundSpreadsheetDark
|
||||||
|
|
||||||
|
Shadow ->
|
||||||
|
colourTheme.shadow
|
||||||
|
|
||||||
|
BarGreen ->
|
||||||
|
colourTheme.barGreen
|
||||||
|
|
||||||
|
BarRed ->
|
||||||
|
colourTheme.barRed
|
||||||
|
|
||||||
|
DebugColour ->
|
||||||
|
colourTheme.debugColour
|
||||||
|
|
||||||
|
Transparent ->
|
||||||
|
colourTheme.transparent
|
36
templates/elm/frontend/src/Config/Style/Colour/Types.elm
Executable file
36
templates/elm/frontend/src/Config/Style/Colour/Types.elm
Executable file
|
@ -0,0 +1,36 @@
|
||||||
|
module Config.Style.Colour.Types exposing
|
||||||
|
( SyntaxColors
|
||||||
|
, Theme
|
||||||
|
)
|
||||||
|
|
||||||
|
import Element exposing (Color)
|
||||||
|
|
||||||
|
|
||||||
|
type alias Theme =
|
||||||
|
{ textLightGrey : Color
|
||||||
|
, textDarkGrey : Color
|
||||||
|
, textLightOrange : Color
|
||||||
|
, textDarkOrange : Color
|
||||||
|
, textDeepDarkOrange : Color
|
||||||
|
, backgroundLightGrey : Color
|
||||||
|
, backgroundDarkGrey : Color
|
||||||
|
, backgroundDeepDarkGrey : Color
|
||||||
|
, backgroundSpreadsheet : Color
|
||||||
|
, backgroundSpreadsheetDark : Color
|
||||||
|
, shadow : Color
|
||||||
|
, barGreen : Color
|
||||||
|
, barRed : Color
|
||||||
|
, debugColour : Color
|
||||||
|
, transparent : Color
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias SyntaxColors =
|
||||||
|
{ punctuation : Color
|
||||||
|
, key : Color
|
||||||
|
, string : Color
|
||||||
|
, keyword : Color
|
||||||
|
, operator : Color
|
||||||
|
, background : Color
|
||||||
|
, text : Color
|
||||||
|
}
|
50
templates/elm/frontend/src/Config/Style/Fonts.elm
Executable file
50
templates/elm/frontend/src/Config/Style/Fonts.elm
Executable file
|
@ -0,0 +1,50 @@
|
||||||
|
module Config.Style.Fonts exposing
|
||||||
|
( defaultFontSize
|
||||||
|
, headerFontSizeBig
|
||||||
|
, headerFontSizeMedium
|
||||||
|
, paragraphSpacing
|
||||||
|
, smallTextFontSize
|
||||||
|
, spartanFont
|
||||||
|
)
|
||||||
|
|
||||||
|
import Element
|
||||||
|
exposing
|
||||||
|
( Attr
|
||||||
|
, Attribute
|
||||||
|
, spacing
|
||||||
|
)
|
||||||
|
import Element.Font as F
|
||||||
|
exposing
|
||||||
|
( size
|
||||||
|
, typeface
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
spartanFont : F.Font
|
||||||
|
spartanFont =
|
||||||
|
F.typeface "League Spartan"
|
||||||
|
|
||||||
|
|
||||||
|
paragraphSpacing : Attribute msg
|
||||||
|
paragraphSpacing =
|
||||||
|
spacing 0
|
||||||
|
|
||||||
|
|
||||||
|
headerFontSizeBig : Attr decorative msg
|
||||||
|
headerFontSizeBig =
|
||||||
|
F.size 23
|
||||||
|
|
||||||
|
|
||||||
|
headerFontSizeMedium : Attr decorative msg
|
||||||
|
headerFontSizeMedium =
|
||||||
|
F.size 20
|
||||||
|
|
||||||
|
|
||||||
|
defaultFontSize : Attr decorative msg
|
||||||
|
defaultFontSize =
|
||||||
|
F.size 18
|
||||||
|
|
||||||
|
|
||||||
|
smallTextFontSize : Attr decorative msg
|
||||||
|
smallTextFontSize =
|
||||||
|
F.size 16
|
24
templates/elm/frontend/src/Config/Style/Glow.elm
Executable file
24
templates/elm/frontend/src/Config/Style/Glow.elm
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
module Config.Style.Glow exposing
|
||||||
|
( glowDeepDarkGrey
|
||||||
|
, glowDeepDarkGreyNavbar
|
||||||
|
, glowDeepDarkOrange
|
||||||
|
)
|
||||||
|
|
||||||
|
import Config.Style.Colour.Helpers exposing (ThemeColor(..), colourTheme, getThemeColor)
|
||||||
|
import Element exposing (Attr)
|
||||||
|
import Element.Border as D exposing (glow)
|
||||||
|
|
||||||
|
|
||||||
|
glowDeepDarkGrey : Attr decorative msg
|
||||||
|
glowDeepDarkGrey =
|
||||||
|
D.glow (getThemeColor Shadow) 4
|
||||||
|
|
||||||
|
|
||||||
|
glowDeepDarkOrange : Attr decorative msg
|
||||||
|
glowDeepDarkOrange =
|
||||||
|
D.glow (getThemeColor TextDeepDarkOrange) 4
|
||||||
|
|
||||||
|
|
||||||
|
glowDeepDarkGreyNavbar : Attr decorative msg
|
||||||
|
glowDeepDarkGreyNavbar =
|
||||||
|
D.glow (getThemeColor Shadow) 10
|
32
templates/elm/frontend/src/Config/Style/Icons/Helpers.elm
Executable file
32
templates/elm/frontend/src/Config/Style/Icons/Helpers.elm
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
module Config.Style.Icons.Helpers exposing (buildSvg)
|
||||||
|
|
||||||
|
import Config.Style.Icons.Types as SvgTypes
|
||||||
|
exposing
|
||||||
|
( InnerPart
|
||||||
|
, OuterPart
|
||||||
|
)
|
||||||
|
import Element as E
|
||||||
|
exposing
|
||||||
|
( Element
|
||||||
|
, el
|
||||||
|
, html
|
||||||
|
)
|
||||||
|
import Svg exposing (svg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{- buildSvg consumes an inner record to construct most of an SVG, and an outer record to supply
|
||||||
|
any potentially varying TypedSvg.Core.Attribute msgs and wrap it in an Element.el so it can be
|
||||||
|
used by elm-ui. It provides a consistent interface for inserting SVGs into elm-ui code.
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
buildSvg : SvgTypes.OuterPart msg -> SvgTypes.InnerPart msg -> Element msg
|
||||||
|
buildSvg outer inner =
|
||||||
|
el
|
||||||
|
outer.elementAttributes
|
||||||
|
<|
|
||||||
|
html <|
|
||||||
|
Svg.svg
|
||||||
|
(outer.svgAttributes ++ inner.svgAttributes)
|
||||||
|
inner.svg
|
1038
templates/elm/frontend/src/Config/Style/Icons/Icons.elm
Executable file
1038
templates/elm/frontend/src/Config/Style/Icons/Icons.elm
Executable file
File diff suppressed because it is too large
Load diff
28
templates/elm/frontend/src/Config/Style/Icons/Types.elm
Executable file
28
templates/elm/frontend/src/Config/Style/Icons/Types.elm
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
module Config.Style.Icons.Types exposing
|
||||||
|
( InnerPart
|
||||||
|
, OuterPart
|
||||||
|
)
|
||||||
|
|
||||||
|
{-| The types used for SVG management.
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Element exposing (Attribute)
|
||||||
|
import Shared exposing (Model)
|
||||||
|
import Svg exposing (svg)
|
||||||
|
|
||||||
|
|
||||||
|
{-| The outer record for the SVG builder. This is explained in ../Helpers/Svg.elm.
|
||||||
|
-}
|
||||||
|
type alias OuterPart msg =
|
||||||
|
{ elementAttributes : List (Element.Attribute msg)
|
||||||
|
, sharedModel : Shared.Model
|
||||||
|
, svgAttributes : List (Svg.Attribute msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| The inner record for the SVG builder. This is explained in ../Helpers/Svg.elm.
|
||||||
|
-}
|
||||||
|
type alias InnerPart msg =
|
||||||
|
{ svgAttributes : List (Svg.Attribute msg)
|
||||||
|
, svg : List (Svg.Svg msg)
|
||||||
|
}
|
69
templates/elm/frontend/src/Config/Style/Transitions.elm
Executable file
69
templates/elm/frontend/src/Config/Style/Transitions.elm
Executable file
|
@ -0,0 +1,69 @@
|
||||||
|
module Config.Style.Transitions exposing (..)
|
||||||
|
|
||||||
|
import Config.Style.Colour.Helpers exposing (colourTheme)
|
||||||
|
import Config.Style.Glow
|
||||||
|
exposing
|
||||||
|
( glowDeepDarkGrey
|
||||||
|
, glowDeepDarkOrange
|
||||||
|
)
|
||||||
|
import Element
|
||||||
|
exposing
|
||||||
|
( Attribute
|
||||||
|
, htmlAttribute
|
||||||
|
, mouseOver
|
||||||
|
)
|
||||||
|
import Element.Background as B exposing (color)
|
||||||
|
import Element.Border as D exposing (color)
|
||||||
|
import Element.Font as F exposing (color)
|
||||||
|
import Html.Attributes as H exposing (style)
|
||||||
|
|
||||||
|
|
||||||
|
transitionStyleSlow : Attribute msg
|
||||||
|
transitionStyleSlow =
|
||||||
|
htmlAttribute <| style "transition" "all 0.4s ease-in-out"
|
||||||
|
|
||||||
|
|
||||||
|
transitionStyleMedium : Attribute msg
|
||||||
|
transitionStyleMedium =
|
||||||
|
htmlAttribute <| style "transition" "all 0.2s ease-in-out"
|
||||||
|
|
||||||
|
|
||||||
|
transitionStyleFast : Attribute msg
|
||||||
|
transitionStyleFast =
|
||||||
|
htmlAttribute <| style "transition" "all 0.1s ease-in-out"
|
||||||
|
|
||||||
|
|
||||||
|
specialNavbarTransition : Attribute msg
|
||||||
|
specialNavbarTransition =
|
||||||
|
htmlAttribute <| style "transition" "opacity .4s"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- This special transition is needed to avoid weird animation sequencing rather in Chrome-based browsers.
|
||||||
|
|
||||||
|
|
||||||
|
hoverFontLightOrange : Attribute msg
|
||||||
|
hoverFontLightOrange =
|
||||||
|
mouseOver [ F.color colourTheme.textLightOrange ]
|
||||||
|
|
||||||
|
|
||||||
|
hoverFontDarkOrange : Attribute msg
|
||||||
|
hoverFontDarkOrange =
|
||||||
|
mouseOver [ F.color colourTheme.textDarkOrange ]
|
||||||
|
|
||||||
|
|
||||||
|
hoverCircleButtonDarkOrange : Attribute msg
|
||||||
|
hoverCircleButtonDarkOrange =
|
||||||
|
mouseOver
|
||||||
|
[ D.color colourTheme.textDarkOrange
|
||||||
|
, B.color colourTheme.textDarkOrange
|
||||||
|
, glowDeepDarkOrange
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
hoverPageButtonDeepDarkOrange : Attribute msg
|
||||||
|
hoverPageButtonDeepDarkOrange =
|
||||||
|
mouseOver
|
||||||
|
[ B.color colourTheme.textDeepDarkOrange
|
||||||
|
, F.color colourTheme.textLightOrange
|
||||||
|
]
|
194
templates/elm/frontend/src/Effect.elm
Normal file
194
templates/elm/frontend/src/Effect.elm
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
module Effect exposing
|
||||||
|
( Effect
|
||||||
|
, none, batch
|
||||||
|
, sendCmd, sendMsg
|
||||||
|
, pushRoute, replaceRoute, loadExternalUrl
|
||||||
|
, map, toCmd
|
||||||
|
)
|
||||||
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
@docs Effect
|
||||||
|
@docs none, batch
|
||||||
|
@docs sendCmd, sendMsg
|
||||||
|
@docs pushRoute, replaceRoute, loadExternalUrl
|
||||||
|
|
||||||
|
@docs map, toCmd
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Browser.Navigation
|
||||||
|
import Dict exposing (Dict)
|
||||||
|
import Route exposing (Route)
|
||||||
|
import Route.Path
|
||||||
|
import Shared.Model
|
||||||
|
import Shared.Msg
|
||||||
|
import Task
|
||||||
|
import Url exposing (Url)
|
||||||
|
|
||||||
|
|
||||||
|
type Effect msg
|
||||||
|
= -- BASICS
|
||||||
|
None
|
||||||
|
| Batch (List (Effect msg))
|
||||||
|
| SendCmd (Cmd msg)
|
||||||
|
-- ROUTING
|
||||||
|
| PushUrl String
|
||||||
|
| ReplaceUrl String
|
||||||
|
| LoadExternalUrl String
|
||||||
|
-- SHARED
|
||||||
|
| SendSharedMsg Shared.Msg.Msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- BASICS
|
||||||
|
|
||||||
|
|
||||||
|
{-| Don't send any effect.
|
||||||
|
-}
|
||||||
|
none : Effect msg
|
||||||
|
none =
|
||||||
|
None
|
||||||
|
|
||||||
|
|
||||||
|
{-| Send multiple effects at once.
|
||||||
|
-}
|
||||||
|
batch : List (Effect msg) -> Effect msg
|
||||||
|
batch =
|
||||||
|
Batch
|
||||||
|
|
||||||
|
|
||||||
|
{-| Send a normal `Cmd msg` as an effect, something like `Http.get` or `Random.generate`.
|
||||||
|
-}
|
||||||
|
sendCmd : Cmd msg -> Effect msg
|
||||||
|
sendCmd =
|
||||||
|
SendCmd
|
||||||
|
|
||||||
|
|
||||||
|
{-| Send a message as an effect. Useful when emitting events from UI components.
|
||||||
|
-}
|
||||||
|
sendMsg : msg -> Effect msg
|
||||||
|
sendMsg msg =
|
||||||
|
Task.succeed msg
|
||||||
|
|> Task.perform identity
|
||||||
|
|> SendCmd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ROUTING
|
||||||
|
|
||||||
|
|
||||||
|
{-| Set the new route, and make the back button go back to the current route.
|
||||||
|
-}
|
||||||
|
pushRoute :
|
||||||
|
{ path : Route.Path.Path
|
||||||
|
, query : Dict String String
|
||||||
|
, hash : Maybe String
|
||||||
|
}
|
||||||
|
-> Effect msg
|
||||||
|
pushRoute route =
|
||||||
|
PushUrl (Route.toString route)
|
||||||
|
|
||||||
|
{-| Set given path as route (without any query params or hash), and make the back button go back to the current route.
|
||||||
|
-}
|
||||||
|
pushPath :
|
||||||
|
Route.Path.Path
|
||||||
|
-> Effect msg
|
||||||
|
pushPath path =
|
||||||
|
PushUrl (Route.toString { path = path, query = Dict.empty, hash = Nothing })
|
||||||
|
|
||||||
|
{-| Set the new route, but replace the previous one, so clicking the back
|
||||||
|
button **won't** go back to the previous route.
|
||||||
|
-}
|
||||||
|
replaceRoute :
|
||||||
|
{ path : Route.Path.Path
|
||||||
|
, query : Dict String String
|
||||||
|
, hash : Maybe String
|
||||||
|
}
|
||||||
|
-> Effect msg
|
||||||
|
replaceRoute route =
|
||||||
|
ReplaceUrl (Route.toString route)
|
||||||
|
|
||||||
|
{-| Set given path as route (without any query params or hash), but replace the previous route,
|
||||||
|
so clicking the back button **won't** go back to the previous route
|
||||||
|
-}
|
||||||
|
replacePath :
|
||||||
|
Route.Path.Path
|
||||||
|
-> Effect msg
|
||||||
|
replacePath path =
|
||||||
|
ReplaceUrl (Route.toString { path = path, query = Dict.empty, hash = Nothing })
|
||||||
|
|
||||||
|
{-| Redirect users to a new URL, somewhere external your web application.
|
||||||
|
-}
|
||||||
|
loadExternalUrl : String -> Effect msg
|
||||||
|
loadExternalUrl =
|
||||||
|
LoadExternalUrl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- INTERNALS
|
||||||
|
|
||||||
|
|
||||||
|
{-| Elm Land depends on this function to connect pages and layouts
|
||||||
|
together into the overall app.
|
||||||
|
-}
|
||||||
|
map : (msg1 -> msg2) -> Effect msg1 -> Effect msg2
|
||||||
|
map fn effect =
|
||||||
|
case effect of
|
||||||
|
None ->
|
||||||
|
None
|
||||||
|
|
||||||
|
Batch list ->
|
||||||
|
Batch (List.map (map fn) list)
|
||||||
|
|
||||||
|
SendCmd cmd ->
|
||||||
|
SendCmd (Cmd.map fn cmd)
|
||||||
|
|
||||||
|
PushUrl url ->
|
||||||
|
PushUrl url
|
||||||
|
|
||||||
|
ReplaceUrl url ->
|
||||||
|
ReplaceUrl url
|
||||||
|
|
||||||
|
LoadExternalUrl url ->
|
||||||
|
LoadExternalUrl url
|
||||||
|
|
||||||
|
SendSharedMsg sharedMsg ->
|
||||||
|
SendSharedMsg sharedMsg
|
||||||
|
|
||||||
|
|
||||||
|
{-| Elm Land depends on this function to perform your effects.
|
||||||
|
-}
|
||||||
|
toCmd :
|
||||||
|
{ key : Browser.Navigation.Key
|
||||||
|
, url : Url
|
||||||
|
, shared : Shared.Model.Model
|
||||||
|
, fromSharedMsg : Shared.Msg.Msg -> msg
|
||||||
|
, batch : List msg -> msg
|
||||||
|
, toCmd : msg -> Cmd msg
|
||||||
|
}
|
||||||
|
-> Effect msg
|
||||||
|
-> Cmd msg
|
||||||
|
toCmd options effect =
|
||||||
|
case effect of
|
||||||
|
None ->
|
||||||
|
Cmd.none
|
||||||
|
|
||||||
|
Batch list ->
|
||||||
|
Cmd.batch (List.map (toCmd options) list)
|
||||||
|
|
||||||
|
SendCmd cmd ->
|
||||||
|
cmd
|
||||||
|
|
||||||
|
PushUrl url ->
|
||||||
|
Browser.Navigation.pushUrl options.key url
|
||||||
|
|
||||||
|
ReplaceUrl url ->
|
||||||
|
Browser.Navigation.replaceUrl options.key url
|
||||||
|
|
||||||
|
LoadExternalUrl url ->
|
||||||
|
Browser.Navigation.load url
|
||||||
|
|
||||||
|
SendSharedMsg sharedMsg ->
|
||||||
|
Task.succeed sharedMsg
|
||||||
|
|> Task.perform options.fromSharedMsg
|
70
templates/elm/frontend/src/Pages/Home_.elm
Normal file
70
templates/elm/frontend/src/Pages/Home_.elm
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
module Pages.Home_ exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Effect exposing (Effect)
|
||||||
|
import Route exposing (Route)
|
||||||
|
import Html
|
||||||
|
import Page exposing (Page)
|
||||||
|
import Shared
|
||||||
|
import View exposing (View)
|
||||||
|
|
||||||
|
|
||||||
|
page : Shared.Model -> Route () -> Page Model Msg
|
||||||
|
page shared route =
|
||||||
|
Page.new
|
||||||
|
{ init = init
|
||||||
|
, update = update
|
||||||
|
, subscriptions = subscriptions
|
||||||
|
, view = view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- INIT
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
init : () -> ( Model, Effect Msg )
|
||||||
|
init () =
|
||||||
|
( {}
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- UPDATE
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= NoOp
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> ( Model, Effect Msg )
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
NoOp ->
|
||||||
|
( model
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- SUBSCRIPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
subscriptions : Model -> Sub Msg
|
||||||
|
subscriptions model =
|
||||||
|
Sub.none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Model -> View Msg
|
||||||
|
view model =
|
||||||
|
{ title = "Pages.Home_"
|
||||||
|
, body = [ Html.text "/" ]
|
||||||
|
}
|
69
templates/elm/frontend/src/Pages/NotFound_.elm
Normal file
69
templates/elm/frontend/src/Pages/NotFound_.elm
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
module Pages.NotFound_ exposing (Model, Msg, page)
|
||||||
|
|
||||||
|
import Effect exposing (Effect)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Page exposing (Page)
|
||||||
|
import Route exposing (Route)
|
||||||
|
import Route.Path
|
||||||
|
import Shared
|
||||||
|
import View exposing (View)
|
||||||
|
|
||||||
|
|
||||||
|
page : Shared.Model -> Route () -> Page Model Msg
|
||||||
|
page shared route =
|
||||||
|
Page.new
|
||||||
|
{ init = init
|
||||||
|
, update = update
|
||||||
|
, subscriptions = subscriptions
|
||||||
|
, view = view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- INIT
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
init : () -> ( Model, Effect Msg )
|
||||||
|
init () =
|
||||||
|
( {}
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- UPDATE
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= NoOp
|
||||||
|
|
||||||
|
|
||||||
|
update : Msg -> Model -> ( Model, Effect Msg )
|
||||||
|
update msg model =
|
||||||
|
case msg of
|
||||||
|
NoOp ->
|
||||||
|
( model
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- SUBSCRIPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
subscriptions : Model -> Sub Msg
|
||||||
|
subscriptions model =
|
||||||
|
Sub.none
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEW
|
||||||
|
|
||||||
|
|
||||||
|
view : Model -> View Msg
|
||||||
|
view model =
|
||||||
|
View.fromString "Page not found"
|
74
templates/elm/frontend/src/Shared.elm
Normal file
74
templates/elm/frontend/src/Shared.elm
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
module Shared exposing
|
||||||
|
( Flags, decoder
|
||||||
|
, Model, Msg
|
||||||
|
, init, update, subscriptions
|
||||||
|
)
|
||||||
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
@docs Flags, decoder
|
||||||
|
@docs Model, Msg
|
||||||
|
@docs init, update, subscriptions
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Effect exposing (Effect)
|
||||||
|
import Json.Decode
|
||||||
|
import Route exposing (Route)
|
||||||
|
import Route.Path
|
||||||
|
import Shared.Model
|
||||||
|
import Shared.Msg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- FLAGS
|
||||||
|
|
||||||
|
|
||||||
|
type alias Flags =
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
decoder : Json.Decode.Decoder Flags
|
||||||
|
decoder =
|
||||||
|
Json.Decode.succeed {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- INIT
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
Shared.Model.Model
|
||||||
|
|
||||||
|
|
||||||
|
init : Result Json.Decode.Error Flags -> Route () -> ( Model, Effect Msg )
|
||||||
|
init flagsResult route =
|
||||||
|
( {}
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- UPDATE
|
||||||
|
|
||||||
|
|
||||||
|
type alias Msg =
|
||||||
|
Shared.Msg.Msg
|
||||||
|
|
||||||
|
|
||||||
|
update : Route () -> Msg -> Model -> ( Model, Effect Msg )
|
||||||
|
update route msg model =
|
||||||
|
case msg of
|
||||||
|
Shared.Msg.NoOp ->
|
||||||
|
( model
|
||||||
|
, Effect.none
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- SUBSCRIPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
subscriptions : Route () -> Model -> Sub Msg
|
||||||
|
subscriptions route model =
|
||||||
|
Sub.none
|
14
templates/elm/frontend/src/Shared/Model.elm
Normal file
14
templates/elm/frontend/src/Shared/Model.elm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module Shared.Model exposing (Model)
|
||||||
|
|
||||||
|
{-| -}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Normally, this value would live in "Shared.elm"
|
||||||
|
but that would lead to a circular dependency import cycle.
|
||||||
|
|
||||||
|
For that reason, both `Shared.Model` and `Shared.Msg` are in their
|
||||||
|
own file, so they can be imported by `Effect.elm`
|
||||||
|
|
||||||
|
-}
|
||||||
|
type alias Model =
|
||||||
|
{}
|
14
templates/elm/frontend/src/Shared/Msg.elm
Normal file
14
templates/elm/frontend/src/Shared/Msg.elm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module Shared.Msg exposing (Msg(..))
|
||||||
|
|
||||||
|
{-| -}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Normally, this value would live in "Shared.elm"
|
||||||
|
but that would lead to a circular dependency import cycle.
|
||||||
|
|
||||||
|
For that reason, both `Shared.Model` and `Shared.Msg` are in their
|
||||||
|
own file, so they can be imported by `Effect.elm`
|
||||||
|
|
||||||
|
-}
|
||||||
|
type Msg
|
||||||
|
= NoOp
|
72
templates/elm/frontend/src/View.elm
Normal file
72
templates/elm/frontend/src/View.elm
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
module View exposing
|
||||||
|
( View, map
|
||||||
|
, none, fromString
|
||||||
|
, toBrowserDocument
|
||||||
|
)
|
||||||
|
|
||||||
|
{-|
|
||||||
|
|
||||||
|
@docs View, map
|
||||||
|
@docs none, fromString
|
||||||
|
@docs toBrowserDocument
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
import Browser
|
||||||
|
import Html exposing (Html)
|
||||||
|
import Route exposing (Route)
|
||||||
|
import Shared.Model
|
||||||
|
|
||||||
|
|
||||||
|
type alias View msg =
|
||||||
|
{ title : String
|
||||||
|
, body : List (Html msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Used internally by Elm Land to create your application
|
||||||
|
so it works with Elm's expected `Browser.Document msg` type.
|
||||||
|
-}
|
||||||
|
toBrowserDocument :
|
||||||
|
{ shared : Shared.Model.Model
|
||||||
|
, route : Route ()
|
||||||
|
, view : View msg
|
||||||
|
}
|
||||||
|
-> Browser.Document msg
|
||||||
|
toBrowserDocument { view } =
|
||||||
|
{ title = view.title
|
||||||
|
, body = view.body
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Used internally by Elm Land to connect your pages together.
|
||||||
|
-}
|
||||||
|
map : (msg1 -> msg2) -> View msg1 -> View msg2
|
||||||
|
map fn view =
|
||||||
|
{ title = view.title
|
||||||
|
, body = List.map (Html.map fn) view.body
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| Used internally by Elm Land whenever transitioning between
|
||||||
|
authenticated pages.
|
||||||
|
-}
|
||||||
|
none : View msg
|
||||||
|
none =
|
||||||
|
{ title = ""
|
||||||
|
, body = []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{-| If you customize the `View` module, anytime you run `elm-land add page`,
|
||||||
|
the generated page will use this when adding your `view` function.
|
||||||
|
|
||||||
|
That way your app will compile after adding new pages, and you can see
|
||||||
|
the new page working in the web browser!
|
||||||
|
|
||||||
|
-}
|
||||||
|
fromString : String -> View msg
|
||||||
|
fromString moduleName =
|
||||||
|
{ title = moduleName
|
||||||
|
, body = [ Html.text moduleName ]
|
||||||
|
}
|
25
templates/elm/frontend/src/interop.ts
Normal file
25
templates/elm/frontend/src/interop.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// This returns the flags passed into your Elm application
|
||||||
|
export const flags = async ({ env } : ElmLand.FlagsArgs) => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called after your Elm app starts
|
||||||
|
export const onReady = ({ app, env } : ElmLand.OnReadyArgs) => {
|
||||||
|
console.log('Elm is ready', app)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Type definitions for Elm Land
|
||||||
|
namespace ElmLand {
|
||||||
|
export type FlagsArgs = {
|
||||||
|
env: Record<string, string>
|
||||||
|
}
|
||||||
|
export type OnReadyArgs = {
|
||||||
|
env: Record<string, string>
|
||||||
|
app: { ports?: Record<string, Port> }
|
||||||
|
}
|
||||||
|
export type Port = {
|
||||||
|
send?: (data: unknown) => void
|
||||||
|
subscribe?: (callback: (data: unknown) => unknown) => void
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue