diff options
Diffstat (limited to 'docs/public/page')
-rw-r--r-- | docs/public/page/api/lustre.md | 195 | ||||
-rw-r--r-- | docs/public/page/api/lustre/attribute.md | 290 | ||||
-rw-r--r-- | docs/public/page/api/lustre/effect.md | 35 | ||||
-rw-r--r-- | docs/public/page/api/lustre/element.md | 58 | ||||
-rw-r--r-- | docs/public/page/api/lustre/element/html.md | 993 | ||||
-rw-r--r-- | docs/public/page/api/lustre/element/svg.md | 462 | ||||
-rw-r--r-- | docs/public/page/api/lustre/event.md | 146 | ||||
-rw-r--r-- | docs/public/page/docs/components.md | 8 | ||||
-rw-r--r-- | docs/public/page/docs/managing-state.md | 8 | ||||
-rw-r--r-- | docs/public/page/docs/quickstart.md | 272 | ||||
-rw-r--r-- | docs/public/page/docs/server-side-rendering.md | 8 | ||||
-rw-r--r-- | docs/public/page/docs/side-effects.md | 8 | ||||
-rw-r--r-- | docs/public/page/guides/mist.md | 8 | ||||
-rw-r--r-- | docs/public/page/guides/wisp.md | 8 |
14 files changed, 2499 insertions, 0 deletions
diff --git a/docs/public/page/api/lustre.md b/docs/public/page/api/lustre.md new file mode 100644 index 0000000..7ec5021 --- /dev/null +++ b/docs/public/page/api/lustre.md @@ -0,0 +1,195 @@ +# lustre + +## Applications + +### App | erlang javascript + +```gleam +pub type App(flags, model, msg) +``` + +The `App` type represents all the parts that make up a Lustre program in the +Model-View-Update architecture along with the runtime necessary to run it. + +Although the type itself is exposed to both the Erlang and JavaScript targets, +the functions in this module to construct an `App` are only available in the +JavaScript target, and `start` will only succeed when ran in the browser. + +In the future we may have a way to run Lustre applications on the backend, if +you have any ideas on how to achieve this I'd love to hear about them! + +### Error | erlang javascript + +```gleam +pub type Error { + AppAlreadyStarted + AppNotYetStarted + BadComponentName + ComponentAlreadyRegistered + ElementNotFound + NotABrowser +} +``` + +The `Error` type represents all the ways that a Lustre program can fail. These +include things like trying to start an application that has already been started, +registering a component with a name that is not valid, or trying to start an +application in a context that is not a browser. + +Often you will want to perform a couple of these actions together, and unifying +the error type makes this easy. In many of the examples we `let assert` that the +result is `Ok` but if you wanted to be a bit more dilligent you might use +`result.try` instead: + +```gleam +import gleam/result +import lustre + +pub fn main () { + use _ <- result.try(lustre.component("my-component", ...)) + let app = lustre.application(...) + use dispatch <- result.try(lustre.start(app, "[data-lustre-app]", Nil)) + + ... +} +``` + +### element | javascript + +```gleam +pub fn element(el: Element(msg)) -> App(Nil, Nil, msg) +``` + +An `element` application is the simplest kind of Lustre program. It takes an +`Element` to render and renders it to the DOM. These applications hold no state +and do not respond to messages, but that doesn't mean they are not interactive! + +It is possible for [`components`](#component) to be rendered inside an +`element` application, and these components can be interactive with their own +contained state and update loops. + +### simple | javascript + +```gleam +pub fn simple( + init: fn(flags) -> model, + update: fn(model, msg) -> model, + view: fn(model) -> Element(msg) +) -> App(flags, model, msg) +``` + +A `simple` program introduces the Model-View-Update architecture but leaves out +the ability to dispatch side effects. This means your programs are interactive +but cannot talk to the outside world. + +### application | javascript + +```gleam +pub fn application( + init: fn(flags) -> #(model, Effect(msg)), + update: fn(model, msg) -> #(model, Effect(msg)), + view: fn(model) -> Element(msg) +) -> App(flags, model, msg) +``` + +The `application` constructor is the most complete way to build a Lustre app. As +with [`simple`](#simple) it uses the Model-View-Update architecture, but now your +init and update functions can return side effects to be performed by the runtime +in the form of an [`Effect`](/api/lustre/effect#effect-type). + +### start | javascript + +```gleam +pub fn start( + app: App(flags, model, msg), + selector: String, + flags: flags, +) -> Result(fn(msg) -> Nil, Error) +``` + +Start an application by providing a CSS selector to find the element to mount the +application onto and any flags to pass to the application on first init. This +function returns a `Result` and may fail for a number of reasons. Check out the +[`Error`](#error-type) type for more information. + +### destroy | javascript + +```gleam +pub fn destroy(app: App(flags, model, msg)) -> Result(Nil, Error) +``` + +Tear down a running application and remove it from the DOM. This can fail if the +application has not yet been started. + +## Components + +Components take the same Model-View-Update building blocks used to create Lustre +applications and allow them to be used as reusable stateful components. This is +slightly different to how components are used in other frameworks like React +where "component" refers more generally to any reusable piece of UI. + +In Lustre, functions that return an `Element` are known as "view functions" and +components are more specific abstractions that encapsulate state and behaviour +you might not want to deal with in your top-level application. + +Resist the urge to reach for components too early. The Elm community has managed +to make do without components at all: you can get surprisingly far storing state +in your top level application and passing it down to different view functions. +This comes with the added benefit of it being much easier to reason about your +UI as a whole. + +### component | javascript + +```gleam +pub fn component( + name: String, + init: fn() -> #(model, Effect(msg)), + update: fn(model, msg) -> #(model, Effect(msg)), + view: fn(model) -> Element(msg), + on_attribute_change: Map(String, Decoder(msg)), +) -> Result(Nil, Error) +``` + +Register a component with the runtime from the familiar Model-View-Update building +blocks. Compared to an application, we have two additional arguments: + +- A name for the component. This name must follow the same rules laid out in the + [custom element spec](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name) + and should contain a hyphen (`-`) to avoid clashes with built-in HTML elements. +- A map of attribute names to listen for changes to and a decoder for each to + decode those attributes into messages to send to your component's `update` + function. + +If it feels like the API for registering components is a little more verbose than +you're used to, that's because it is! You can get surprisingly far storing state +in your top level application and passing it down to different view functions +without needing to use components at all. In fact, for communities like Elm this +is the _only_ way to do things. + +## Utilities + +### is_browser | erlang javascript + +```gleam +pub fn is_browser() -> Bool +``` + +Gleam has conditional compilation depending on whether you are targetting Erlang +or JavaScript, but sometimes you want to be a bit more specific than that and +check if you're running in the browser. + +This is a runtime check that will tell you just that. You could use this to create +a view function that renders something simple on the backend but more complex or +interactive on the frontend. + +### is_registered | erlang javascript + +```gleam +pub fn is_registered(name: String) -> Bool +``` + +Lustre's components are built directly on the +[custom element spec](https://html.spec.whatwg.org/multipage/custom-elements.html) +which means they share the same global registery as other custom elements. This +function can tell you if the name you want to use is already registered, by another +Lustre component or otherwise. diff --git a/docs/public/page/api/lustre/attribute.md b/docs/public/page/api/lustre/attribute.md new file mode 100644 index 0000000..b23000b --- /dev/null +++ b/docs/public/page/api/lustre/attribute.md @@ -0,0 +1,290 @@ +# lustre/attribute + +## Constructing attributes + +### Attribute | erlang javascript + +```gleam +pub opaque type Attribute(msg) +``` + +### attribute | erlang javascript + +```gleam +pub fn attribute(name: String, value: String) -> Attribute(msg) +``` + +### property | erlang javascript + +```gleam +pub fn property(name: String, value: any) -> Attribute(msg) +``` + +### on | erlang javascript + +```gleam +pub fn on( + name: String, + handler: fn(Dynamic) -> Result(msg, error) +) -> Attribute(msg) +``` + +## Mapping attributes + +### map | erlang javascript + +```gleam +pub fn map(attr: Attribute(a), f: fn(a) -> b) -> Attribute(b) +``` + +## Conversions + +### to_string | erlang javascript + +```gleam +pub fn to_string(attr: Attribute(msg)) -> String +``` + +### to_string_builder | erlang javascript + +```gleam +pub fn to_string_builder(attr: Attribute(msg)) -> StringBuilder +``` + +## Common attributes + +### style | erlang javascript + +```gleam +pub fn style(properties: List(#(String, String))) -> Attribute(msg) +``` + +### class | erlang javascript + +```gleam +pub fn class(name: String) -> Attribute(msg) +``` + +### classes | erlang javascript + +```gleam +pub fn classes(names: List(#(String, Bool))) -> Attribute(msg) +``` + +### id | erlang javascript + +```gleam +pub fn id(name: String) -> Attribute(msg) +``` + +## Input attributes + +### type\_ | erlang javascript + +```gleam +pub fn type_(name: String) -> Attribute(msg) +``` + +### value | erlang javascript + +```gleam +pub fn value(val: Dynamic) -> Attribute(msg) +``` + +### checked | erlang javascript + +```gleam +pub fn checked(is_checked: Bool) -> Attribute(msg) +``` + +### placeholder | erlang javascript + +```gleam +pub fn placeholder(text: String) -> Attribute(msg) +``` + +### selected | erlang javascript + +```gleam +pub fn selected(is_selected: Bool) -> Attribute(msg +``` + +## More input attributes + +### accept | erlang javascript + +```gleam +pub fn accept(types: List(String)) -> Attribute(msg) +``` + +### accept_charset | erlang javascript + +```gleam +pub fn accept_charset(types: List(String)) -> Attribute(msg) +``` + +### msg | erlang javascript + +```gleam +pub fn msg(uri: String) -> Attribute(msg) +``` + +### autocomplete | erlang javascript + +```gleam +pub fn autocomplete(name: String) -> Attribute(msg) +``` + +### autofocus | erlang javascript + +```gleam +pub fn autofocus(should_autofocus: Bool) -> Attribute(msg) +``` + +### disabled | erlang javascript + +```gleam +pub fn disabled(is_disabled: Bool) -> Attribute(msg) +``` + +### name | erlang javascript + +```gleam +pub fn name(name: String) -> Attribute(msg) +``` + +### pattern | erlang javascript + +```gleam +pub fn pattern(regex: String) -> Attribute(msg) +``` + +### readonly | erlang javascript + +```gleam +pub fn readonly(is_readonly: Bool) -> Attribute(msg) +``` + +### required | erlang javascript + +```gleam +pub fn required(is_required: Bool) -> Attribute(msg) +``` + +### for | erlang javascript + +```gleam +pub fn for(id: String) -> Attribute(msg) +``` + +## Range attributes + +### max | erlang javascript + +```gleam +pub fn max(val: String) -> Attribute(msg) +``` + +### min | erlang javascript + +```gleam +pub fn min(val: String) -> Attribute(msg) +``` + +### step | erlang javascript + +```gleam +pub fn step(val: String) -> Attribute(msg) +``` + +## Textarea attributes + +### cols | erlang javascript + +```gleam +pub fn cols(val: Int) -> Attribute(msg) +``` + +### rows | erlang javascript + +```gleam +pub fn rows(val: Int) -> Attribute(msg) +``` + +### wrap | erlang javascript + +```gleam +pub fn wrap(mode: String) -> Attribute(msg) +``` + +## Link attributes + +### href | erlang javascript + +```gleam +pub fn href(uri: String) -> Attribute(msg) +``` + +### target | erlang javascript + +```gleam +pub fn target(target: String) -> Attribute(msg) +``` + +### download | erlang javascript + +```gleam +pub fn download(filename: String) -> Attribute(msg) +``` + +### rel | erlang javascript + +```gleam +pub fn rel(relationship: String) -> Attribute(msg) +``` + +## Embedded content + +### gleam | erlang javascript + +```gleam +pub fn src(uri: String) -> Attribute(msg) +``` + +### gleam | erlang javascript + +```gleam +pub fn height(val: Int) -> Attribute(msg) +``` + +### gleam | erlang javascript + +```gleam +pub fn width(val: Int) -> Attribute(msg) +``` + +### gleam | erlang javascript + +```gleam +pub fn alt(text: String) -> Attribute(msg) +``` + +## Audio and video attributes + +### autoplay | erlang javascript + +```gleam +pub fn autoplay(should_autoplay: Bool) -> Attribute(msg) +``` + +### controls | erlang javascript + +```gleam +pub fn controls(visible: Bool) -> Attribute(msg) +``` + +### loop | erlang javascript + +```gleam +pub fn loop(should_loop: Bool) -> Attribute(msg) +``` diff --git a/docs/public/page/api/lustre/effect.md b/docs/public/page/api/lustre/effect.md new file mode 100644 index 0000000..3a0bf11 --- /dev/null +++ b/docs/public/page/api/lustre/effect.md @@ -0,0 +1,35 @@ +# lustre/effect + +## Constructing Effects + +### Effect | erlang javascript + +```gleam +pub opaque type Effect(msg) +``` + +### from | erlang javascript + +```gleam +pub fn from(effect: fn(fn(msg) -> Nil) -> Nil) -> Effect(msg) +``` + +### none | erlang javascript + +```gleam +pub fn none() -> Effect(msg) +``` + +### batch | erlang javascript + +```gleam +pub fn batch(effects: List(Effect(msg))) -> Effect(msg) +``` + +## Manipulating Effects + +### map | erlang javascript + +```gleam +pub fn map(effect: Effect(a), f: fn(a) -> b) -> Effect(b) +``` diff --git a/docs/public/page/api/lustre/element.md b/docs/public/page/api/lustre/element.md new file mode 100644 index 0000000..3510acd --- /dev/null +++ b/docs/public/page/api/lustre/element.md @@ -0,0 +1,58 @@ +# lustre/element + +## Constructing elements + +### Element | erlang javascript + +```gleam +pub opaque type Element(msg) +``` + +### element | erlang javascript + +```gleam +pub fn element( + tag: String, + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### namespaced | erlang javascript + +```gleam +pub fn namespaced( + namespace: String, + tag: String, + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### text | erlang javascript + +```gleam +pub fn text(content: String) -> Element(msg) +``` + +## Mapping elements + +### map | erlang javascript + +```gleam +pub fn map(element: Element(a), f: fn(a) -> b) -> Element(b) +``` + +## Conversions + +### to_string | erlang javascript + +```gleam +pub fn to_string(element: Element(msg)) -> String +``` + +### to_string_builder | erlang javascript + +```gleam +pub fn to_string_builder(element: Element(msg)) -> StringBuilder +``` diff --git a/docs/public/page/api/lustre/element/html.md b/docs/public/page/api/lustre/element/html.md new file mode 100644 index 0000000..883c66c --- /dev/null +++ b/docs/public/page/api/lustre/element/html.md @@ -0,0 +1,993 @@ +# lustre/element/html + +## Main Root + +### html | erlang javascript + +```gleam +pub fn html( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Document Metadata + +### base | erlang javascript + +```gleam +pub fn base(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### head | erlang javascript + +```gleam +pub fn head(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### link | erlang javascript + +```gleam +pub fn link(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### meta | erlang javascript + +```gleam +pub fn meta(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### style | erlang javascript + +```gleam +pub fn style(attrs: List(Attribute(msg)), css: String) -> Element(msg) +``` + +### title | erlang javascript + +```gleam +pub fn title(attrs: List(Attribute(msg)), content: String) -> Element(msg) +``` + +## Sectioning root + +### body | erlang javascript + +```gleam +pub fn body( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Content sectioning + +### address | erlang javascript + +```gleam +pub fn address( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### article | erlang javascript + +```gleam +pub fn article( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### aside | erlang javascript + +```gleam +pub fn aside( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### footer | erlang javascript + +```gleam +pub fn footer( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### header | erlang javascript + +```gleam +pub fn header( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h1 | erlang javascript + +```gleam +pub fn h1( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h2 | erlang javascript + +```gleam +pub fn h2( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h3 | erlang javascript + +```gleam +pub fn h3( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h4 | erlang javascript + +```gleam +pub fn h4( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h5 | erlang javascript + +```gleam +pub fn h5( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### h6 | erlang javascript + +```gleam +pub fn h6( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### hgroup | erlang javascript + +```gleam +pub fn hgroup( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### main | erlang javascript + +```gleam +pub fn main( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### nav | erlang javascript + +```gleam +pub fn nav( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### section | erlang javascript + +```gleam +pub fn section( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### search | erlang javascript + +```gleam +pub fn search( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Text content + +### blockquote | erlang javascript + +```gleam +pub fn blockquote( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### dd | erlang javascript + +```gleam +pub fn dd( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### div | erlang javascript + +```gleam +pub fn div( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### dl | erlang javascript + +```gleam +pub fn dl( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### dt | erlang javascript + +```gleam +pub fn dt( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### figcaption | erlang javascript + +```gleam +pub fn figcaption( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### figure | erlang javascript + +```gleam +pub fn figure( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### hr | erlang javascript + +```gleam +pub fn hr(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### li | erlang javascript + +```gleam +pub fn li( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### menu | erlang javascript + +```gleam +pub fn menu( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### ol | erlang javascript + +```gleam +pub fn ol( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### p | erlang javascript + +```gleam +pub fn p( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### pre | erlang javascript + +```gleam +pub fn pre( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### ul | erlang javascript + +```gleam +pub fn ul( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Inline text semantics + +### a | erlang javascript + +```gleam +pub fn a( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### abbr | erlang javascript + +```gleam +pub fn abbr( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### b | erlang javascript + +```gleam +pub fn b( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### bdi | erlang javascript + +```gleam +pub fn bdi( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### bdo | erlang javascript + +```gleam +pub fn bdo( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### br | erlang javascript + +```gleam +pub fn br(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### cite | erlang javascript + +```gleam +pub fn cite( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### code | erlang javascript + +```gleam +pub fn code( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### data | erlang javascript + +```gleam +pub fn data( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### dfn | erlang javascript + +```gleam +pub fn dfn( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### em | erlang javascript + +```gleam +pub fn em( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### i | erlang javascript + +```gleam +pub fn i( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### kbd | erlang javascript + +```gleam +pub fn kbd( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### mark | erlang javascript + +```gleam +pub fn mark( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### q | erlang javascript + +```gleam +pub fn q( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### rp | erlang javascript + +```gleam +pub fn rp( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### rt | erlang javascript + +```gleam +pub fn rt( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### ruby | erlang javascript + +```gleam +pub fn ruby( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### s | erlang javascript + +```gleam +pub fn s( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### samp | erlang javascript + +```gleam +pub fn samp( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### small | erlang javascript + +```gleam +pub fn small( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### span | erlang javascript + +```gleam +pub fn span( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### strong | erlang javascript + +```gleam +pub fn strong( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### sub | erlang javascript + +```gleam +pub fn sub( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### sup | erlang javascript + +```gleam +pub fn sup( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### time | erlang javascript + +```gleam +pub fn time( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### u | erlang javascript + +```gleam +pub fn u( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### var | erlang javascript + +```gleam +pub fn var( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### wbr | erlang javascript + +```gleam +pub fn wbr(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Image and multimedia + +### area | erlang javascript + +```gleam +pub fn area(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### audio | erlang javascript + +```gleam +pub fn audio( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### img | erlang javascript + +```gleam +pub fn img(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### map | erlang javascript + +```gleam +pub fn map( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### track | erlang javascript + +```gleam +pub fn track(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### video | erlang javascript + +```gleam +pub fn video( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Embedded content + +### embed | erlang javascript + +```gleam +pub fn embed(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### iframe | erlang javascript + +```gleam +pub fn iframe(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### object | erlang javascript + +```gleam +pub fn object(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### picture | erlang javascript + +```gleam +pub fn picture( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### portal | erlang javascript + +```gleam +pub fn portal(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### source | erlang javascript + +```gleam +pub fn source(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## SVG and MathML + +### svg | erlang javascript + +````gleam +pub fn svg( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) + +### math | erlang javascript + +```gleam +pub fn math( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +```` + +## Scripting + +### canvas | erlang javascript + +```gleam +pub fn canvas(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### noscript | erlang javascript + +```gleam +pub fn noscript( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### script | erlang javascript + +```gleam +pub fn script(attrs: List(Attribute(msg)), js: String) -> Element(msg) +``` + +## Demarcating edits + +### del | erlang javascript + +```gleam +pub fn del( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### ins | erlang javascript + +```gleam +pub fn ins( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Table content + +### caption | erlang javascript + +```gleam +pub fn caption( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### col | erlang javascript + +```gleam +pub fn col(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### colgroup | erlang javascript + +```gleam +pub fn colgroup( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### table | erlang javascript + +```gleam +pub fn table( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### tbody | erlang javascript + +```gleam +pub fn tbody( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### td | erlang javascript + +```gleam +pub fn td( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### tfoot | erlang javascript + +```gleam +pub fn tfoot( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### th | erlang javascript + +```gleam +pub fn th( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### thead | erlang javascript + +```gleam +pub fn thead( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### tr | erlang javascript + +```gleam +pub fn tr( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Forms + +### button | erlang javascript + +```gleam +pub fn button( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### datalist | erlang javascript + +```gleam +pub fn datalist( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### fieldset | erlang javascript + +```gleam +pub fn fieldset( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### form | erlang javascript + +```gleam +pub fn form( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### input | erlang javascript + +```gleam +pub fn input(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### label | erlang javascript + +```gleam +pub fn label( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### legend | erlang javascript + +```gleam +pub fn legend( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### meter | erlang javascript + +```gleam +pub fn meter( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### optgroup | erlang javascript + +```gleam +pub fn optgroup( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### option | erlang javascript + +```gleam +pub fn option(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### output | erlang javascript + +```gleam +pub fn output( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### progress | erlang javascript + +```gleam +pub fn progress( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### select | erlang javascript + +```gleam +pub fn select( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### textarea | erlang javascript + +```gleam +pub fn textarea(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Interactive elements + +### details | erlang javascript + +```gleam +pub fn details( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### dialog | erlang javascript + +```gleam +pub fn dialog( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### summary | erlang javascript + +```gleam +pub fn summary( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Web components + +### slot | erlang javascript + +```gleam +pub fn slot(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### template | erlang javascript + +```gleam +pub fn template( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` diff --git a/docs/public/page/api/lustre/element/svg.md b/docs/public/page/api/lustre/element/svg.md new file mode 100644 index 0000000..a7a0ec2 --- /dev/null +++ b/docs/public/page/api/lustre/element/svg.md @@ -0,0 +1,462 @@ +# lustre/element/svg + +## Animation elements + +### animate | erlang javascript + +```gleam +pub fn animate(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### animate_motion | erlang javascript + +```gleam +pub fn animate_motion(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### animate_transform | erlang javascript + +```gleam +pub fn animate_transform(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### mpath | erlang javascript + +```gleam +pub fn mpath(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### set | erlang javascript + +```gleam +pub fn set(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Basic shapes + +### circle | erlang javascript + +```gleam +pub fn circle(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### ellipse | erlang javascript + +```gleam +pub fn ellipse(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### line | erlang javascript + +```gleam +pub fn line(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### polygon | erlang javascript + +```gleam +pub fn polygon(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### polyline | erlang javascript + +```gleam +pub fn polyline(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### rect | erlang javascript + +```gleam +pub fn rect(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Container elements + +### a | erlang javascript + +```gleam +pub fn a( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### defs | erlang javascript + +```gleam +pub fn defs( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### g | erlang javascript + +```gleam +pub fn g( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### marker | erlang javascript + +```gleam +pub fn marker( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### mask | erlang javascript + +```gleam +pub fn mask( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### missing_glyph | erlang javascript + +```gleam +pub fn missing_glyph( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### pattern | erlang javascript + +```gleam +pub fn pattern( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### svg | erlang javascript + +```gleam +pub fn svg( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### switch | erlang javascript + +```gleam +pub fn switch( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### symbol | erlang javascript + +```gleam +pub fn symbol( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Descriptive elements + +### desc | erlang javascript + +```gleam +pub fn desc( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### metadata | erlang javascript + +```gleam +pub fn metadata( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### title | erlang javascript + +```gleam +pub fn title( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +## Filter effects + +### fe_blend | erlang javascript + +```gleam +pub fn fe_blend(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_color_matrix | erlang javascript + +```gleam +pub fn fe_color_matrix(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_component_transfer | erlang javascript + +```gleam +pub fn fe_component_transfer(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_composite | erlang javascript + +```gleam +pub fn fe_composite(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_convolve_matrix | erlang javascript + +```gleam +pub fn fe_convolve_matrix(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_diffuse_lighting | erlang javascript + +```gleam +pub fn fe_diffuse_lighting( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### fe_displacement_map | erlang javascript + +```gleam +pub fn fe_displacement_map(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_drop_shadow | erlang javascript + +```gleam +pub fn fe_drop_shadow(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_flood | erlang javascript + +```gleam +pub fn fe_flood(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_func_a | erlang javascript + +```gleam +pub fn fe_func_a(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_func_b | erlang javascript + +```gleam +pub fn fe_func_b(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_func_g | erlang javascript + +```gleam +pub fn fe_func_g(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_func_r | erlang javascript + +```gleam +pub fn fe_func_r(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_gaussian_blur | erlang javascript + +```gleam +pub fn fe_gaussian_blur(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_image | erlang javascript + +```gleam +pub fn fe_image(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_merge | erlang javascript + +```gleam +pub fn fe_merge( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### fe_merge_node | erlang javascript + +```gleam +pub fn fe_merge_node(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_morphology | erlang javascript + +```gleam +pub fn fe_morphology(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_offset | erlang javascript + +```gleam +pub fn fe_offset(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_specular_lighting | erlang javascript + +```gleam +pub fn fe_specular_lighting( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### fe_tile | erlang javascript + +```gleam +pub fn fe_tile( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### fe_turbulence | erlang javascript + +```gleam +pub fn fe_turbulence(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Gradient elements + +### linear_gradient | erlang javascript + +```gleam +pub fn linear_gradient( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### radial_gradient | erlang javascript + +```gleam +pub fn radial_gradient( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### stop | erlang javascript + +```gleam +pub fn stop(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Graphical elements + +### image | erlang javascript + +```gleam +pub fn image(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### path | erlang javascript + +```gleam +pub fn path(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### text | erlang javascript + +```gleam +pub fn text(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### use\_ | erlang javascript + +```gleam +pub fn use_(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Lighting elements + +### fe_distant_light | erlang javascript + +```gleam +pub fn fe_distant_light(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_point_light | erlang javascript + +```gleam +pub fn fe_point_light(attrs: List(Attribute(msg))) -> Element(msg) +``` + +### fe_spot_light | erlang javascript + +```gleam +pub fn fe_spot_light(attrs: List(Attribute(msg))) -> Element(msg) +``` + +## Non-rendered elements + +### clip_path | erlang javascript + +```gleam +pub fn clip_path( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### script | erlang javascript + +```gleam +pub fn script(attrs: List(Attribute(msg)), js: String) -> Element(msg) +``` + +### style | erlang javascript + +```gleam +pub fn style(attrs: List(Attribute(msg)), css: String) -> Element(msg) +``` + +## Renderable elements + +### foreign_object | erlang javascript + +```gleam +pub fn foreign_object( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### text_path | erlang javascript + +```gleam +pub fn text_path( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` + +### tspan | erlang javascript + +```gleam +pub fn tspan( + attrs: List(Attribute(msg)), + children: List(Element(msg)), +) -> Element(msg) +``` diff --git a/docs/public/page/api/lustre/event.md b/docs/public/page/api/lustre/event.md new file mode 100644 index 0000000..695cb7b --- /dev/null +++ b/docs/public/page/api/lustre/event.md @@ -0,0 +1,146 @@ +# lustre/event + +## Mouse events + +### on_click | erlang javascript + +```gleam +pub fn on_click(msg: msg) -> Attribute(msg) +``` + +### on_mouse_down | erlang javascript + +```gleam +pub fn on_mouse_down(msg: msg) -> Attribute(msg) +``` + +### on_mouse_up | erlang javascript + +```gleam +pub fn on_mouse_up(msg: msg) -> Attribute(msg) +``` + +### on_mouse_enter | erlang javascript + +```gleam +pub fn on_mouse_enter(msg: msg) -> Attribute(msg) +``` + +### on_mouse_leave | erlang javascript + +```gleam +pub fn on_mouse_leave(msg: msg) -> Attribute(msg) +``` + +### on_mouse_over | erlang javascript + +```gleam +pub fn on_mouse_over(msg: msg) -> Attribute(msg) +``` + +### on_mouse_out | erlang javascript + +```gleam +pub fn on_mouse_out(msg: msg) -> Attribute(msg) +``` + +## Keyboard events + +### on_keypress | erlang javascript + +```gleam +pub fn on_keypress(msg: fn(String) -> msg) -> Attribute(msg) +``` + +### on_keydown | erlang javascript + +```gleam +pub fn on_keydown(msg: fn(String) -> msg) -> Attribute(msg) +``` + +### on_keyup | erlang javascript + +```gleam +pub fn on_keyup(msg: fn(String) -> msg) -> Attribute(msg) +``` + +## Form messages + +### on_input | erlang javascript + +```gleam +pub fn on_input(msg: fn(String) -> msg) -> Attribute(msg) +``` + +### on_change | erlang javascript + +```gleam +pub fn on_change(msg: fn(Bool) -> msg) -> Attribute(msg) +``` + +### on_submit | erlang javascript + +```gleam +pub fn on_submit(msg: msg) -> Attribute(msg) +``` + +## Focus events + +### on_focus | erlang javascript + +```gleam +pub fn on_focus(msg: msg) -> Attribute(msg) +``` + +### on_blur | erlang javascript + +```gleam +pub fn on_blur(msg: msg) -> Attribute(msg) +``` + +## Custom events + +### on | erlang javascript + +```gleam +pub fn on( + name: String, + handler: fn(Dynamic) -> Result(msg, error) +) -> Attribute(msg) +``` + +### prevent_default | javascript + +```gleam +pub fn prevent_default(event: Dynamic) -> Nil +``` + +### stop_propagation | javascript + +```gleam +pub fn stop_propagation(event: Dynamic) -> Nil +``` + +### value | erlang javascript + +```gleam +pub fn value(event: Dynamic) -> Decoder(String) +``` + +### checked | erlang javascript + +```gleam +pub fn checked(event: Dynamic) -> Decoder(Bool) +``` + +### mouse_position | erlang javascript + +```gleam +pub fn mouse_position(event: Dynamic) -> Decoder(#(Float, Float)) +``` + +### emit | javascript + +```gleam +pub fn emit(event: String, data: any) -> Effect(msg) +``` diff --git a/docs/public/page/docs/components.md b/docs/public/page/docs/components.md new file mode 100644 index 0000000..6fecf43 --- /dev/null +++ b/docs/public/page/docs/components.md @@ -0,0 +1,8 @@ +# Components + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! diff --git a/docs/public/page/docs/managing-state.md b/docs/public/page/docs/managing-state.md new file mode 100644 index 0000000..7da5449 --- /dev/null +++ b/docs/public/page/docs/managing-state.md @@ -0,0 +1,8 @@ +# Managing state + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! diff --git a/docs/public/page/docs/quickstart.md b/docs/public/page/docs/quickstart.md new file mode 100644 index 0000000..f706478 --- /dev/null +++ b/docs/public/page/docs/quickstart.md @@ -0,0 +1,272 @@ +# Quickstart + +Lustre is a frontend web framework for Gleam. It is primarily focused on helping +you build robust single-page applications (SPAs), but it can also be used on the +server to render static HTML. To get an idea of what it's all about, here's a +quick overview of Lustre's key features: + +- Elm-inspired runtime with state management and controlled side effects out of + the box. +- A simple, declarative API for building type-safe user interfaces. +- Stateful components built as custom elements and useable just like any other + HTML element. +- Static HTML rendering anywhere Gleam can run: the BEAM, Node.js, Deno, or the + browser. + +In this quickstart guide we'll take a look at how to get up and running with +Lustre in both the browser and on the server. + +## In the browser | javascript + +To get started, we'll scaffold a new Gleam project using `gleam new`. If you've +found your way to this guide but don't already know what Gleam is you can read +about it over at [gleam.run](https://gleam.run). + +```shell +$ gleam new lustre_quickstart && gleam add lustre +``` + +In a real project you probably want to use a build tool like [vite](https://vitejs.dev) +along with the [vite-gleam](https://github.com/Enderchief/vite-gleam) plugin, but +to keep this guide simple we'll just show you what code you need to write and leave +the details on serving the app up to you. MDN have a handy guide covering some +different options to [set up a local web server for development](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server) +if you need some ideas. + +### Basic HTML setup + +With our Gleam project scaffolded, go ahead and create an `index.html` in the root +of the project. This is the minimal code you'll typically want to get started: + +```html +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>Lustre Quickstart</title> + + <script type="module"> + import { main } from "./build/dev/javascript/lustre_quickstart/app.mjs"; + + document.addEventListener("DOMContentLoaded", () => { + main(); + }); + </script> + </head> + + <body> + <div data-lustre-app></div> + </body> +</html> +``` + +We wait until the DOM has loaded before calling the our app's `main` function. +This will mount the Lustre app and start rendering. We also add the `data-lustre-app` +attribute to the element we want to mount the app to. You could use a class or an +id instead, or none of that: [`lustre.start`](/api/lustre#start) takes a CSS +selector so go wild! + +### Hello, world! + +Go ahead and rename the generated `lustre_quickstart.gleam` file to `app.gleam` +and replace the contents with the following: + +```gleam +import lustre +import lustre/element.{text} + +pub fn main() { + let app = lustre.element(text("Hello, world!")) + let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil) + + Nil +} +``` + +This will create a static Lustre app and mount it onto the element that matches +the CSS selector. While we're asserting everything is OK here, it is possible +for `lustre.start` to fail in a couple of ways. Check out the docs for the +[`lustre.Error`](/api/lustre#error-type) type if you want to know more. + +Run `gleam build` and serve the HTML with your preferred static file server (this +step is necessary: JavaScript modules can't be imported when just opening a HTML +file) and admire your handiwork. + +### Adding interactivity + +Now that we know how to get things up and running, let's try something a little +more exciting and add some interactivity. Replace the contents of your `app.gleam` +file with the code below and rebuild the project. + +```gleam +import gleam/int +import lustre +import lustre/element.{text} +import lustre/element/html.{div, button, p} +import lustre/event.{on_click} + +pub fn main() { + let app = lustre.simple(init, update, view) + let assert Ok(_) = lustre.start("[data-lustre-app]", Nil) + + Nil +} + +fn init(_) { + 0 +} + +type Msg { + Incr + Decr +} + +fn update(model, msg) { + case msg { + Incr -> model + 1 + Decr -> model - 1 + } +} + +fn view(model) { + let count = int.to_string(model) + + div([], [ + button([on_click(Decr)], [text(" + ")]), + p([], [text(count)]), + button([on_click(Incr)], [text(" - ")]) + ]) +} +``` + +You should know have a very exciting counter app! Almost every Lustre app will +boil down to the same three parts: + +- A `Model` type that represents your application's state and a function to + `init` it. +- A `Msg` type and an `update` function to update that state based on incoming + messages. +- A `view` function that takes the current state and renders some HTML. + +This architecture is not unique to Lustre. It was introduced by the Elm community +and known as the [Elm Architecture](https://guide.elm-lang.org/architecture/) +before making its way to React as [Redux](https://redux.js.org) and beyond, known +more generally as the Model-View-Update architecture. If you work through the +rest of our guides you'll see how this architecture helps keep side effects out +of our view code and how to create components that can encapsulate their own state +and update logic. + +For now though, we'll leave things here. If you're interested in seeing how Lustre +can be used to render static HTML on the server, read on! Otherwise, you can take +this counter application as a base and start building something of your own. +" + +## On the server | erlang javascript + +As we've seen, Lustre is primarily meant to be used in the browser to build +interactive SPAs. It is possible to render Lustre elements to static HTML and +simply use Lustre as a templating DSL. As before, we'll start by scaffolding a +new Gleam project and adding Lustre as a dependency: + +```shell +$ gleam new lustre_quickstart && gleam add lustre +``` + +The [`lustre/element`](/api/lustre/element) module contains functions to render +an element as either a `String` or `StringBuilder`. Copy the following code into +`lustre_quickstart.gleam`: + +```gleam +import gleam/io +import lustre/attribute.{attribute} +import lustre/element.{text} +import lustre/element/html.{html, head, title, body, div, h1} + +pub fn main() { + html([attribute("lang", "en")], [ + head([], [ + title([], [text("Lustre Quickstart")]) + ]), + body([], [ + h1([], [text("Hello, world!")]) + ]) + ]) + |> element.to_string + |> io.println +} +``` + +We can test this out by running `gleam run` and seeing the HTML printed to the +console. From here we could set up a web server using [Mist](/guides/mist) or +[Wisp](/guides/wisp) to serve the HTML to the browser or write it to a file using +[simplifile](https://hexdocs.pm/simplifile/). Because the API is the same for +both client and server rendering, it is easy to create reusable components that +can be rendered anywhere Gleam can run! + +### An example with Wisp + +Before we go, let's just take a quick look at what it would look like to use +Lustre in a [Wisp](https://hexdocs.pm/wisp) application. We won't scaffold out a +real app in this example, but we'll adapt one of the examples from Wisp's own +documentation. + +Specifically, we'll take a look at the `show_form` function from the +["working with form data"](https://github.com/lpil/wisp/blob/ea8a40bc20745f172695c8cc2dc0a63769f890a7/examples/2-working-with-form-data/src/app/router.gleam#L20) +example: + +```gleam +... + +pub fn show_form() -> Response { + // In a larger application a template library or HTML form library might + // be used here instead of a string literal. + let html = + string_builder.from_string( + "<form method='post'> + <label>Title: + <input type='text' name='title'> + </label> + <label>Name: + <input type='text' name='name'> + </label> + <input type='submit' value='Submit'> + </form>", + ) + wisp.ok() + |> wisp.html_body(html) +} +``` + +They've helpfully left a comment telling us that in a larger application we might +want to use a template library, and Lustre is up to the task! Let's refactor this +using Lustre: + +```gleam +import gleam/string +import lustre/attribute.{attribute} +import lustre/element +import lustre/element/html +... + +pub fn show_form() -> Response { + html.form([attribute("method", "post")], [ + labelled_input("Title"), + labelled_input("Name"), + html.input([attribute("type", "submit"), attribute("value", "Submit")]) + ]) + |> element.to_string_builder + |> wisp.html_body + |> wisp.ok +} + +fn labelled_input(name: String) -> Element(Nil) { + html.label([], [ + element.text(name <> ": "), + html.input([ + attribute("type", "text"), + attribute("name", string.lowercase(name)) + ]) + ]) +} +``` diff --git a/docs/public/page/docs/server-side-rendering.md b/docs/public/page/docs/server-side-rendering.md new file mode 100644 index 0000000..66d605c --- /dev/null +++ b/docs/public/page/docs/server-side-rendering.md @@ -0,0 +1,8 @@ +# Server-side rendering + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! diff --git a/docs/public/page/docs/side-effects.md b/docs/public/page/docs/side-effects.md new file mode 100644 index 0000000..1cf21e2 --- /dev/null +++ b/docs/public/page/docs/side-effects.md @@ -0,0 +1,8 @@ +# Side effects + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! diff --git a/docs/public/page/guides/mist.md b/docs/public/page/guides/mist.md new file mode 100644 index 0000000..9afa83b --- /dev/null +++ b/docs/public/page/guides/mist.md @@ -0,0 +1,8 @@ +# Using with Mist + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! diff --git a/docs/public/page/guides/wisp.md b/docs/public/page/guides/wisp.md new file mode 100644 index 0000000..84d4089 --- /dev/null +++ b/docs/public/page/guides/wisp.md @@ -0,0 +1,8 @@ +# Using with Wisp + +Whoopsie, I haven't got round to writing this guide yet. If you haven't checked +out the [quickstart guide](/docs/quickstart) that is probably the best place to +go to get up to speed. + +If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam +[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out! |