Skip to content

Commit

Permalink
📝 Begin writing useful docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
hayleigh-dot-dev committed May 21, 2022
1 parent f759745 commit c7453b4
Showing 1 changed file with 58 additions and 25 deletions.
83 changes: 58 additions & 25 deletions src/lustre.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,67 @@

// IMPORTS ---------------------------------------------------------------------

import lustre/cmd
import lustre/element
import lustre/attribute
import lustre/cmd.{ Cmd }
import lustre/element.{ Element }
import gleam/result


// TYPES -----------------------------------------------------------------------

/// An `App` describes a Lustre application: what state it holds and what kind
/// of actions get dispatched to update that state. The only useful thing you can
/// do with an `App` is pass it to [`start`](#start).
///
/// You can construct an `App` from the two constructors exposed in this module:
/// [`basic`](#basic) and [`application`](#application). Although you can't do
/// anything but [`start`](#start) them, the constructors are separated in case
/// you want to set up an application but defer starting it until some later point
/// in time.
///
///```
/// ┌────────┐
/// │ │
/// │ update │
/// │ │
/// └──────┬─┘
/// ▲ │
/// │ │ #(State, Action)
/// Action │ │
/// │ │
/// │ ▼
/// ┌──────┐ ┌─────────┴──────────────┐
/// │ │ #(State, Action) │ │
/// │ init ├───────────────────►│ Lustre Runtime │
/// │ │ │ │
/// └──────┘ └──────────────┬─────────┘
/// ▲ │
/// │ │ State
/// Action │ │
/// │ ▼
/// ┌─┴──────┐
/// │ │
/// │ render │
/// │ │
/// └────────┘
///```
///
pub opaque type Program(state, action) {
Program(
/// <small>Someone please PR the Gleam docs generator to fix the monospace font,
/// thanks! 💖</small>
///
pub opaque type App(state, action) {
App(
init: #(state, Cmd(action)),
update: Update(state, action),
render: Render(state, action)
)
}

pub type Cmd(action) = cmd.Cmd(action)

pub type Element(action) = element.Element(action)
pub type Attribute(action) = attribute.Attribute(action)

pub type Error {
ElementNotFound
}

// These types aren't exposed, but they're just here to try and shrink the type
// annotations for `Program` and `program` a little bit. When generating docs,
// annotations for `App` and `application` a little bit. When generating docs,
// Gleam automatically expands type aliases so this is purely for the benefit of
// those reading the source.
//
Expand All @@ -40,49 +73,49 @@ type Render(state, action) = fn (state) -> Element(action)

// CONSTRUCTORS ----------------------------------------------------------------

/// Create a basic lustre program that just renders some element on the page.
/// Create a basic lustre app that just renders some element on the page.
/// Note that this doesn't mean the content is static! With `element.stateful`
/// you can still create components with local state.
///
/// Basic lustre programs don't have any *global* application state and so the
/// Basic lustre apps don't have any *global* application state and so the
/// plumbing is a lot simpler. If you find yourself passing lot's state of state
/// around, you might want to consider using `application` instead.
///
pub fn basic (element: Element(any)) -> Program(Nil, any) {
pub fn basic (element: Element(any)) -> App(Nil, any) {
let init = #(Nil, cmd.none())
let update = fn (_, _) { #(Nil, cmd.none()) }
let render = fn (_) { element }

Program(init, update, render)
App(init, update, render)
}

/// Create a more complex application mimicing TEA – the Elm architecture. We
/// start with some initial `state`, a function to update that state, and then
/// a render function to derive our program's view from that state.
/// a render function to derive our app's view from that state.
///
/// Events produced by elements are passed a `dispatch` function that can be
/// used to emit actions that trigger your `update` function to be called and
/// trigger a rerender.
///
pub fn application (init: #(state, Cmd(action)), update: Update(state, action), render: Render(state, action)) -> Program(state, action) {
Program(init, update, render)
pub fn application (init: #(state, Cmd(action)), update: Update(state, action), render: Render(state, action)) -> App(state, action) {
App(init, update, render)
}


// EFFECTS ---------------------------------------------------------------------

/// Once you have created a program with either `basic` or `application`, you
/// need to actually start it! This function will mount your program to the DOM
/// Once you have created a app with either `basic` or `application`, you
/// need to actually start it! This function will mount your app to the DOM
/// node that matches the query selector you provide.
///
/// If everything mounted OK, we'll get back a dispatch function that you can
/// call to send actions to your program and trigger an update.
/// call to send actions to your app and trigger an update.
///
pub fn start (program: Program(state, action), selector: String) -> Result(fn (action) -> Nil, Error) {
mount(program, selector)
pub fn start (app: App(state, action), selector: String) -> Result(fn (action) -> Nil, Error) {
mount(app, selector)
|> result.replace_error(ElementNotFound)
}


external fn mount (program: Program(state, action), selector: String) -> Result(fn (action) -> Nil, Nil)
external fn mount (app: App(state, action), selector: String) -> Result(fn (action) -> Nil, Nil)
= "./ffi.mjs" "mount"

0 comments on commit c7453b4

Please sign in to comment.