From e0d23b37aee16d9148abcf002308b8b78c95e8b1 Mon Sep 17 00:00:00 2001 From: Hayleigh Thompson Date: Sat, 9 Sep 2023 22:59:42 +0100 Subject: :memo: Direct users to external docs at pkg.hayleigh.dev --- lib/src/lustre.gleam | 177 +-------------------- lib/src/lustre/attribute.gleam | 7 +- lib/src/lustre/effect.gleam | 28 +--- lib/src/lustre/element.gleam | 10 +- lib/src/lustre/element/html.gleam | 317 +------------------------------------- lib/src/lustre/element/svg.gleam | 65 ++++++++ lib/src/lustre/event.gleam | 11 +- 7 files changed, 86 insertions(+), 529 deletions(-) diff --git a/lib/src/lustre.gleam b/lib/src/lustre.gleam index 209af29..840b82a 100644 --- a/lib/src/lustre.gleam +++ b/lib/src/lustre.gleam @@ -1,4 +1,5 @@ -//// Lustre is a declarative framework for building Web apps in Gleam. +//// To read the full documentation for this module, please visit +//// [https://pkg.hayleigh.dev/lustre/api/lustre](https://pkg.hayleigh.dev/lustre/api/lustre) // IMPORTS --------------------------------------------------------------------- @@ -9,43 +10,6 @@ import lustre/element.{Element} // TYPES ----------------------------------------------------------------------- -/// An `App` describes a Lustre application: what state it holds and what kind -/// of actions get dispatched to update that model. 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. -/// -/// ```text -/// +--------+ -/// | | -/// | update | -/// | | -/// +--------+ -/// ^ | -/// | | -/// Msg | | #(Model, Effect(Msg)) -/// | | -/// | v -/// +------+ +------------------------+ -/// | | #(Model, Effect(Msg)) | | -/// | init |------------------------>| Lustre Runtime | -/// | | | | -/// +------+ +------------------------+ -/// ^ | -/// | | -/// Msg | | Model -/// | | -/// | v -/// +--------+ -/// | | -/// | view | -/// | | -/// +--------+ -/// ``` /// pub type App(flags, model, msg) @@ -61,29 +25,6 @@ pub type Error { // CONSTRUCTORS ---------------------------------------------------------------- @target(javascript) -/// Create a basic lustre app that just views 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 apps don't have any *global* application state and so the -/// plumbing is a lot simpler. If you find yourself passing lots of state around, -/// you might want to consider using [`simple`](#simple) or [`application`](#application) -/// instead. -/// -/// ```gleam -/// import lustre -/// import lustre/element -/// -/// pub fn main () { -/// let app = lustre.element( -/// element.h1([], [ -/// element.text("Hello, world!") -/// ]) -/// ) -/// -/// assert Ok(_) = lustre.start(app, "#root") -/// } -/// ``` /// pub fn element(element: Element(msg)) -> App(Nil, Nil, msg) { let init = fn(_) { #(Nil, effect.none()) } @@ -94,54 +35,6 @@ pub fn element(element: Element(msg)) -> App(Nil, Nil, msg) { } @target(javascript) -/// If you start off with a simple `[element`](#element) app, you may find -/// yourself leaning on [`stateful`](./lustrel/element.html#stateful) elements -/// to manage model used throughout your app. If that's the case or if you know -/// you need some global model from the get-go, you might want to construct a -/// [`simple`](#simple) app instead. -/// -/// This is one app constructor that allows your HTML elements to dispatch actions -/// to update your program model. -/// -/// ```gleam -/// import gleam/int -/// import lustre -/// import lustre/element -/// import lustre/event -/// -/// type Msg { -/// Decr -/// Incr -/// } -/// -/// pub fn main () { -/// let init = 0 -/// -/// let update = fn (model, msg) { -/// case msg { -/// Decr -> model - 1 -/// Incr -> model + 1 -/// } -/// } -/// -/// let view = fn (model) { -/// element.div([], [ -/// element.button([ event.on_click(Decr) ], [ -/// element.text("-") -/// ]), -/// -/// element.text(int.to_string(model)), -/// -/// element.button([ event.on_click(Incr) ], [ -/// element.text("+") -/// ]) -/// ]) -/// } -/// -/// let app = lustre.simple(init, update, view) -/// assert Ok(_) = lustre.start(app, "#root") -/// } -/// ``` /// pub fn simple( init: fn(flags) -> model, @@ -155,47 +48,6 @@ pub fn simple( } @target(javascript) -/// An evolution of a [`simple`](#simple) app that allows you to return a -/// [`Effect`](./lustre/effect.html#Effect) from your `init` and `update`s. Commands give -/// us a way to perform side effects like sending an HTTP request or running a -/// timer and then dispatch actions back to the runtime to trigger an `update`. -/// -///``` -/// import lustre -/// import lustre/effect -/// import lustre/element -/// -/// pub fn main () { -/// let init = #(0, tick()) -/// -/// let update = fn (model, msg) { -/// case msg { -/// Tick -> #(model + 1, tick()) -/// } -/// } -/// -/// let view = fn (model) { -/// element.div([], [ -/// element.text("Time elapsed: ") -/// element.text(int.to_string(model)) -/// ]) -/// } -/// -/// let app = lustre.simple(init, update, view) -/// assert Ok(_) = lustre.start(app, "#root") -/// } -/// -/// fn tick () -> Effect(Msg) { -/// effect.from(fn (dispatch) { -/// setInterval(fn () { -/// dispatch(Tick) -/// }, 1000) -/// }) -/// } -/// -/// external fn set_timeout (f: fn () -> a, delay: Int) -> Nil -/// = "" "window.setTimeout" -///``` /// @external(javascript, "./lustre.ffi.mjs", "setup") pub fn application( @@ -217,29 +69,6 @@ pub fn component( // EFFECTS --------------------------------------------------------------------- @target(javascript) -/// 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 app and trigger an update. -/// -///``` -/// import lustre -/// -/// pub fn main () { -/// let app = lustre.appliation(init, update, view) -/// assert Ok(dispatch) = lustre.start(app, "#root") -/// -/// dispatch(Incr) -/// dispatch(Incr) -/// dispatch(Incr) -/// } -///``` -/// -/// This may not seem super useful at first, but by returning this dispatch -/// function from your `main` (or elsewhere) you can get events into your Lustre -/// app from the outside world. /// @external(javascript, "./lustre.ffi.mjs", "start") pub fn start( @@ -253,11 +82,13 @@ pub fn destroy(app: App(flags, model, msg)) -> Result(Nil, Error) // UTILS ----------------------------------------------------------------------- +/// @external(javascript, "./lustre.ffi.mjs", "is_browser") pub fn is_browser() -> Bool { False } +/// @external(javascript, "./lustre.ffi.mjs", "is_registered") pub fn is_registered(_name: String) -> Bool { False diff --git a/lib/src/lustre/attribute.gleam b/lib/src/lustre/attribute.gleam index 7c4aadf..2b55486 100644 --- a/lib/src/lustre/attribute.gleam +++ b/lib/src/lustre/attribute.gleam @@ -1,3 +1,6 @@ +//// To read the full documentation for this module, please visit +//// [https://pkg.hayleigh.dev/lustre/api/lustre/attribute](https://pkg.hayleigh.dev/lustre/api/lustre/attribute) + // IMPORTS --------------------------------------------------------------------- import gleam/dynamic.{Dynamic} @@ -10,8 +13,6 @@ import gleam/string_builder.{StringBuilder} // TYPES ----------------------------------------------------------------------- -/// Attributes are attached to specific elements. They're either key/value pairs -/// or event handlers. /// pub opaque type Attribute(msg) { Attribute(String, Dynamic, as_property: Bool) @@ -40,7 +41,6 @@ pub fn on( // MANIPULATIONS --------------------------------------------------------------- -/// /// pub fn map(attr: Attribute(a), f: fn(a) -> b) -> Attribute(b) { case attr { @@ -77,7 +77,6 @@ pub fn to_string(attr: Attribute(msg)) -> String { } } -/// /// pub fn to_string_builder(attr: Attribute(msg)) -> StringBuilder { case attr { diff --git a/lib/src/lustre/effect.gleam b/lib/src/lustre/effect.gleam index 1f91e09..964ddd2 100644 --- a/lib/src/lustre/effect.gleam +++ b/lib/src/lustre/effect.gleam @@ -1,12 +1,12 @@ +//// To read the full documentation for this module, please visit +//// [https://pkg.hayleigh.dev/lustre/api/lustre/effect](https://pkg.hayleigh.dev/lustre/api/lustre/effect) + // IMPORTS --------------------------------------------------------------------- import gleam/list // TYPES ----------------------------------------------------------------------- -/// A `Effect` represents some side effect we want the Lustre runtime to perform. -/// It is parameterised by our app's `action` type because some effects need to -/// get information back into your program. /// pub opaque type Effect(msg) { Effect(List(fn(fn(msg) -> Nil) -> Nil)) @@ -14,26 +14,6 @@ pub opaque type Effect(msg) { // CONSTRUCTORS ---------------------------------------------------------------- -/// Create a `Effect` from some custom side effect. This is mostly useful for -/// package authors, or for integrating other libraries into your Lustre app. -/// -/// We pass in a function that recieves a `dispatch` callback that can be used -/// to send messages to the Lustre runtime. We could, for example, create a `tick` -/// command that uses the `setTimeout` JavaScript API to send a message to the -/// runtime every second: -/// -/// ```gleam -/// import lustre/effect.{Effect} -/// -/// external fn set_interval(callback: fn() -> any, interval: Int) = -/// "" "window.setInterval" -/// -/// pub fn every_second(msg: msg) -> Effect(msg) { -/// use dispatch <- effect.from -/// -/// set_interval(fn() { dispatch(msg) }, 1000) -/// } -/// ``` /// pub fn from(effect: fn(fn(msg) -> Nil) -> Nil) -> Effect(msg) { Effect([effect]) @@ -49,7 +29,6 @@ pub fn none() -> Effect(msg) { // MANIPULATIONS --------------------------------------------------------------- -/// /// pub fn batch(effects: List(Effect(msg))) -> Effect(msg) { Effect({ @@ -58,6 +37,7 @@ pub fn batch(effects: List(Effect(msg))) -> Effect(msg) { }) } +/// pub fn map(effect: Effect(a), f: fn(a) -> b) -> Effect(b) { let Effect(l) = effect Effect(list.map( diff --git a/lib/src/lustre/element.gleam b/lib/src/lustre/element.gleam index 4e8abee..69217f0 100644 --- a/lib/src/lustre/element.gleam +++ b/lib/src/lustre/element.gleam @@ -1,3 +1,6 @@ +//// To read the full documentation for this module, please visit +//// [https://pkg.hayleigh.dev/lustre/api/lustre/element](https://pkg.hayleigh.dev/lustre/api/lustre/element) + // IMPORTS --------------------------------------------------------------------- import gleam/list @@ -7,7 +10,6 @@ import lustre/attribute.{Attribute} // TYPES ----------------------------------------------------------------------- -/// /// pub opaque type Element(msg) { Text(String) @@ -17,7 +19,6 @@ pub opaque type Element(msg) { // CONSTRUCTORS ---------------------------------------------------------------- -/// /// pub fn element( tag: String, @@ -27,7 +28,6 @@ pub fn element( Element(tag, attrs, children) } -/// /// pub fn namespaced( namespace: String, @@ -38,7 +38,6 @@ pub fn namespaced( ElementNs(tag, attrs, children, namespace) } -/// /// pub fn text(content: String) -> Element(msg) { Text(content) @@ -58,7 +57,6 @@ fn escape(escaped: String, content: String) -> String { // MANIPULATIONS --------------------------------------------------------------- -/// /// pub fn map(element: Element(a), f: fn(a) -> b) -> Element(b) { case element { @@ -81,14 +79,12 @@ pub fn map(element: Element(a), f: fn(a) -> b) -> Element(b) { // CONVERSIONS ----------------------------------------------------------------- -/// /// pub fn to_string(element: Element(msg)) -> String { to_string_builder(element) |> string_builder.to_string } -/// /// pub fn to_string_builder(element: Element(msg)) -> StringBuilder { case element { diff --git a/lib/src/lustre/element/html.gleam b/lib/src/lustre/element/html.gleam index 9eb4f5e..70ec6c6 100644 --- a/lib/src/lustre/element/html.gleam +++ b/lib/src/lustre/element/html.gleam @@ -1,19 +1,13 @@ +//// To read the full documentation for this module, please visit +//// [https://pkg.hayleigh.dev/lustre/api/lustre/element/html](https://pkg.hayleigh.dev/lustre/api/lustre/element/html) + // IMPORTS --------------------------------------------------------------------- import lustre/element.{Element, element, namespaced, text} import lustre/attribute.{Attribute} -// The doc comments (and order) for functions in this module are taken from the -// MDN Element reference: -// -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element -// - // HTML ELEMENTS: MAIN ROOT ---------------------------------------------------- -/// Represents the root (top-level element) of an HTML document, so it is also -/// referred to as the root element. All other elements must be descendants of -/// this element. /// pub fn html( attrs: List(Attribute(msg)), @@ -24,45 +18,31 @@ pub fn html( // HTML ELEMENTS: DOCUMENT METADATA -------------------------------------------- -/// Specifies the base URL to use for all relative URLs in a document. There can -/// be only one such element in a document. /// pub fn base(attrs: List(Attribute(msg))) -> Element(msg) { element("base", attrs, []) } -/// Contains machine-readable information (metadata) about the document, like its -/// title, scripts, and style sheets. /// pub fn head(attrs: List(Attribute(msg))) -> Element(msg) { element("head", attrs, []) } -/// Specifies relationships between the current document and an external resource. -/// This element is most commonly used to link to CSS but is also used to establish -/// site icons (both "favicon" style icons and icons for the home screen and apps -/// on mobile devices) among other things. /// pub fn link(attrs: List(Attribute(msg))) -> Element(msg) { element("link", attrs, []) } -/// Represents metadata that cannot be represented by other HTML meta-related -/// elements, like , ,