aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2022-03-21 20:03:23 +0000
committerHayleigh Thompson <me@hayleigh.dev>2022-03-21 20:03:23 +0000
commit101bf051131105a8fd8e714d7d6dc910a6eb5ef9 (patch)
treeca302e933ba89d090045542814c9b84259b15f74
parent170a249f1bc5caae55ae5a3469f0fc6beef63568 (diff)
downloadlustre-101bf051131105a8fd8e714d7d6dc910a6eb5ef9.tar.gz
lustre-101bf051131105a8fd8e714d7d6dc910a6eb5ef9.zip
:sparkles: Add support for components with encapsulated state.
-rw-r--r--src/lustre.gleam19
-rw-r--r--src/lustre/element.gleam411
-rw-r--r--src/lustre/ffi.mjs28
3 files changed, 310 insertions, 148 deletions
diff --git a/src/lustre.gleam b/src/lustre.gleam
index 2058da6..0f119b1 100644
--- a/src/lustre.gleam
+++ b/src/lustre.gleam
@@ -2,17 +2,19 @@
// IMPORTS ---------------------------------------------------------------------
+
import lustre/element
import lustre/attribute
// TYPES -----------------------------------------------------------------------
+
///
pub opaque type Program(state, action) {
Program(
init: state,
update: Update(state, action),
- view: View(state, action)
+ render: View(state, action)
)
}
@@ -25,22 +27,19 @@ pub type Attribute(action) = attribute.Attribute(action)
///
type Update(state, action) = fn (state, action) -> state
-type View(state, action) = fn (state) -> Element(action)
+type Render(state, action) = fn (state) -> Element(action)
// CONSTRUCTORS ----------------------------------------------------------------
+
///
-pub fn create (init: state, update: Update(state, action), view: View(state, action)) -> Program(state, action) {
- Program(init, update, view)
+pub fn program (init: state, update: Update(state, action), render: Render(state, action)) -> Program(state, action) {
+ Program(init, update, render)
}
+// EFFECTS ---------------------------------------------------------------------
+
///
pub external fn start (program: Program(state, action), selector: String) -> Nil
= "./lustre/ffi.mjs" "mount"
-
-
-// CONVERSIONS -----------------------------------------------------------------
-///
-pub external fn to_element (program: Program(state, action)) -> Element(a)
- = "./lustre/ffi.mjs" "Program"
diff --git a/src/lustre/element.gleam b/src/lustre/element.gleam
index aa0d605..a1d3286 100644
--- a/src/lustre/element.gleam
+++ b/src/lustre/element.gleam
@@ -1,6 +1,7 @@
////
// IMPORTS ---------------------------------------------------------------------
+
import lustre/attribute.{ Attribute, attribute }
// TYPES -----------------------------------------------------------------------
@@ -10,484 +11,636 @@ pub external type Element(action)
// CONSTRUCTORS ----------------------------------------------------------------
+/// Construct a plain HTML element or registered Web Component by providing the
+/// tag name, a list of attributes (including event handlers), and a list of
+/// child elements.
///
-pub external fn element (tag: String, attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action)
- = "./ffi.mjs" "element"
+pub external fn html (tag: String, attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action)
+ = "./ffi.mjs" "html"
+/// A stateful element is exactly what it sounds like: some element with local
+/// encapsulated state! The `render` function we must provide is called with the
+/// element's current state as well as a function to set a new state. Whenever
+/// that function is called, the element is re-rendered.
+///
+/// You might be wondering where the `stateless` version of this function is.
+/// Those are just regular Gleam functions that return `Element`s!
+///
+pub external fn stateful (init: state, render: fn (state, fn (state) -> Nil) -> Element(action)) -> Element(action)
+ = "./ffi.mjs" "stateful"
+
+/// A fragment doesn't appear in the DOM, but allows us to treat a list of elements
+/// as if it were a single one.
+///
pub external fn fragment (children: List(Element(action))) -> Element(action)
= "./ffi.mjs" "fragment"
+/// Render a Gleam string as an HTML text node.
+///
pub external fn text (content: String) -> Element(action)
= "./ffi.mjs" "text"
+// MANIPULATIONS ---------------------------------------------------------------
+
+/// Transforms the actions produced by some element.
+///
+pub external fn map (element: Element(a), f: fn (a) -> b) -> Element(b)
+ = "./ffi.mjs" "map"
+
+
// CONSTRUCTING NODES ----------------------------------------------------------
// This list and grouping of nodes has been taken from the MDN reference at:
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
-// MAIN ROOT:
-pub fn html (attributes: List(Attribute(action)), head: Element(action), body: Element(action)) -> Element(action) {
- element("html", attributes, [ head, body ])
+// MAIN ROOT -------------------------------------------------------------------
+
+///
+pub fn html_ (attributes: List(Attribute(action)), head: Element(action), body: Element(action)) -> Element(action) {
+ html("html", attributes, [ head, body ])
}
-// DOCUMENT METADATA:
+// DOCUMENT METADATA -----------------------------------------------------------
+
+///
pub fn base (attributes: List(Attribute(action))) -> Element(action) {
- element("base", attributes, [])
+ html("base", attributes, [])
}
+///
pub fn head (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("head", attributes, children)
+ html("head", attributes, children)
}
+///
pub fn meta (attributes: List(Attribute(action))) -> Element(action) {
- element("meta", attributes, [])
+ html("meta", attributes, [])
}
+///
pub fn style (attributes: List(Attribute(action)), css: String) -> Element(action) {
- element("style", attributes, [ text(css) ])
+ html("style", attributes, [ text(css) ])
}
+///
pub fn title (attributes: List(Attribute(action)), name: String) -> Element(action) {
- element("title", attributes, [ text(name) ])
+ html("title", attributes, [ text(name) ])
}
-// SECTIONING ROOT:
+// SECTIONING ROOT -------------------------------------------------------------
+
+///
pub fn body (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("body", attributes, children)
+ html("body", attributes, children)
}
-// CONTENT SECTIONING:
+// CONTENT SECTIONING ----------------------------------------------------------
+
+///
pub fn address (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("address", attributes, children)
+ html("address", attributes, children)
}
+///
pub fn article (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("article", attributes, children)
+ html("article", attributes, children)
}
+///
pub fn aside (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("aside", attributes, children)
+ html("aside", attributes, children)
}
+///
pub fn footer (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("footer", attributes, children)
+ html("footer", attributes, children)
}
+///
pub fn header (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("header", attributes, children)
+ html("header", attributes, children)
}
+///
pub fn h1 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h1", attributes, children)
+ html("h1", attributes, children)
}
+///
pub fn h2 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h2", attributes, children)
+ html("h2", attributes, children)
}
+///
pub fn h3 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h3", attributes, children)
+ html("h3", attributes, children)
}
+///
pub fn h4 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h4", attributes, children)
+ html("h4", attributes, children)
}
+///
pub fn h5 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h5", attributes, children)
+ html("h5", attributes, children)
}
+///
pub fn h6 (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("h6", attributes, children)
+ html("h6", attributes, children)
}
+///
pub fn main (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("main", attributes, children)
+ html("main", attributes, children)
}
+///
pub fn nav (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("nav", attributes, children)
+ html("nav", attributes, children)
}
+///
pub fn section (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("section", attributes, children)
+ html("section", attributes, children)
}
-// TEXT CONTENT:
+// TEXT CONTENT ----------------------------------------------------------------
+
+///
pub fn blockquote (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("blockquote", attributes, children)
+ html("blockquote", attributes, children)
}
+///
pub fn dd (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("dd", attributes, children)
+ html("dd", attributes, children)
}
+///
pub fn div (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("div", attributes, children)
+ html("div", attributes, children)
}
+///
pub fn dl (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("dl", attributes, children)
+ html("dl", attributes, children)
}
+///
pub fn dt (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("dt", attributes, children)
+ html("dt", attributes, children)
}
+///
pub fn figcaption (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("figcaption", attributes, children)
+ html("figcaption", attributes, children)
}
+///
pub fn figure (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("figure", attributes, children)
+ html("figure", attributes, children)
}
+///
pub fn hr (attributes: List(Attribute(action))) -> Element(action) {
- element("hr", attributes, [])
+ html("hr", attributes, [])
}
+///
pub fn li (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("li", attributes, children)
+ html("li", attributes, children)
}
+///
pub fn menu (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("menu", attributes, children)
+ html("menu", attributes, children)
}
+///
pub fn ol (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("ol", attributes, children)
+ html("ol", attributes, children)
}
+///
pub fn p (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("p", attributes, children)
+ html("p", attributes, children)
}
+///
pub fn pre (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("pre", attributes, children)
+ html("pre", attributes, children)
}
+///
pub fn ul (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("ul", attributes, children)
+ html("ul", attributes, children)
}
-// INLINE TEXT SEMANTICS:
+// INLINE TEXT SEMANTICS -------------------------------------------------------
+
+///
pub fn a (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("a", attributes, children)
+ html("a", attributes, children)
}
+///
pub fn abbr (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("abbr", attributes, children)
+ html("abbr", attributes, children)
}
+///
pub fn b (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("b", attributes, children)
+ html("b", attributes, children)
}
+///
pub fn bdi (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("bdi", attributes, children)
+ html("bdi", attributes, children)
}
+///
pub fn bdo (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("bdo", attributes, children)
+ html("bdo", attributes, children)
}
+///
pub fn br (attributes: List(Attribute(action))) -> Element(action) {
- element("br", attributes, [])
+ html("br", attributes, [])
}
+///
pub fn cite (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("cite", attributes, children)
+ html("cite", attributes, children)
}
+///
pub fn code (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("code", attributes, children)
+ html("code", attributes, children)
}
+///
pub fn dfn (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("dfn", attributes, children)
+ html("dfn", attributes, children)
}
+///
pub fn em (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("em", attributes, children)
+ html("em", attributes, children)
}
+///
pub fn i (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("i", attributes, children)
+ html("i", attributes, children)
}
+///
pub fn kbd (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("kbd", attributes, children)
+ html("kbd", attributes, children)
}
+///
pub fn mark (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("mark", attributes, children)
+ html("mark", attributes, children)
}
+///
pub fn rp (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("rp", attributes, children)
+ html("rp", attributes, children)
}
+///
pub fn rt (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("rt", attributes, children)
+ html("rt", attributes, children)
}
+///
pub fn ruby (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("ruby", attributes, children)
+ html("ruby", attributes, children)
}
+///
pub fn s (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("s", attributes, children)
+ html("s", attributes, children)
}
+///
pub fn samp (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("samp", attributes, children)
+ html("samp", attributes, children)
}
+///
pub fn small (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("small", attributes, children)
+ html("small", attributes, children)
}
+///
pub fn span (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("span", attributes, children)
+ html("span", attributes, children)
}
+///
pub fn strong (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("strong", attributes, children)
+ html("strong", attributes, children)
}
+///
pub fn sub (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("sub", attributes, children)
+ html("sub", attributes, children)
}
+///
pub fn sup (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("sup", attributes, children)
+ html("sup", attributes, children)
}
+///
pub fn time (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("time", attributes, children)
+ html("time", attributes, children)
}
+///
pub fn u (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("u", attributes, children)
+ html("u", attributes, children)
}
+///
pub fn var_ (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("var", attributes, children)
+ html("var", attributes, children)
}
+///
pub fn wbr (attributes: List(Attribute(action))) -> Element(action) {
- element("wbr", attributes, [])
+ html("wbr", attributes, [])
}
-// IMAGE AND MULTIMEDIA:
+// IMAGE AND MULTIMEDIA --------------------------------------------------------
+
+///
pub fn area (attributes: List(Attribute(action))) -> Element(action) {
- element("area", attributes, [])
+ html("area", attributes, [])
}
+///
pub fn audio (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("audio", attributes, children)
+ html("audio", attributes, children)
}
+///
pub fn img (attributes: List(Attribute(action))) -> Element(action) {
- element("img", attributes, [])
+ html("img", attributes, [])
}
-pub fn map (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("map", attributes, children)
+///
+pub fn map_ (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
+ html("map", attributes, children)
}
+///
pub fn track (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("track", attributes, children)
+ html("track", attributes, children)
}
+///
pub fn video (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("video", attributes, children)
+ html("video", attributes, children)
}
-// EMBEDDED CONTENT:
+// EMBEDDED CONTENT ------------------------------------------------------------
+
+///
pub fn embed (attributes: List(Attribute(action))) -> Element(action) {
- element("embed", attributes, [])
+ html("embed", attributes, [])
}
+///
pub fn iframe (attributes: List(Attribute(action))) -> Element(action) {
- element("iframe", attributes, [])
+ html("iframe", attributes, [])
}
+///
pub fn object (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("object", attributes, children)
+ html("object", attributes, children)
}
+///
pub fn param (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("param", attributes, children)
+ html("param", attributes, children)
}
+///
pub fn picture (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("picture", attributes, children)
+ html("picture", attributes, children)
}
+///
pub fn portal (attributes: List(Attribute(action))) -> Element(action) {
- element("portal", attributes, [])
+ html("portal", attributes, [])
}
+///
pub fn source (attributes: List(Attribute(action))) -> Element(action) {
- element("source", attributes, [])
+ html("source", attributes, [])
}
-// SVG AND MATHML:
+// SVG AND MATHML --------------------------------------------------------------
+
+///
pub fn svg (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("svg", [attribute("xmlns", "http://www.w3.org/2000/svg"), ..attributes], children)
+ html("svg", [attribute("xmlns", "http://www.w3.org/2000/svg"), ..attributes], children)
}
+///
pub fn mathml (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("mathml", [attribute("xmlns", "http://www.w3.org/1998/Math/MathML"), ..attributes], children)
+ html("mathml", [attribute("xmlns", "http://www.w3.org/1998/Math/MathML"), ..attributes], children)
}
-// SCRIPTING:
+// SCRIPTING -------------------------------------------------------------------
+
+///
pub fn canvas (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("canvas", attributes, children)
+ html("canvas", attributes, children)
}
+///
pub fn noscript (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("noscript", attributes, children)
+ html("noscript", attributes, children)
}
-// DEMARCATING EDITS:
+// DEMARCATING EDITS -----------------------------------------------------------
+
+///
pub fn del (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("del", attributes, children)
+ html("del", attributes, children)
}
+///
pub fn ins (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("ins", attributes, children)
+ html("ins", attributes, children)
}
-// TABLE CONTENT:
+// TABLE CONTENT ---------------------------------------------------------------
+
+///
pub fn caption (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("caption", attributes, children)
+ html("caption", attributes, children)
}
+///
pub fn col (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("col", attributes, children)
+ html("col", attributes, children)
}
+///
pub fn colgroup (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("colgroup", attributes, children)
+ html("colgroup", attributes, children)
}
+///
pub fn table (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("table", attributes, children)
+ html("table", attributes, children)
}
+///
pub fn tbody (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("tbody", attributes, children)
+ html("tbody", attributes, children)
}
+///
pub fn td (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("td", attributes, children)
+ html("td", attributes, children)
}
+///
pub fn tfoot (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("tfoot", attributes, children)
+ html("tfoot", attributes, children)
}
+///
pub fn th (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("th", attributes, children)
+ html("th", attributes, children)
}
+///
pub fn thead (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("thead", attributes, children)
+ html("thead", attributes, children)
}
+///
pub fn tr (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("tr", attributes, children)
+ html("tr", attributes, children)
}
-// FORMS:
+// FORMS -----------------------------------------------------------------------
+
+///
pub fn button (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("button", attributes, children)
+ html("button", attributes, children)
}
+///
pub fn datalist (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("datalist", attributes, children)
+ html("datalist", attributes, children)
}
+///
pub fn fieldset (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("fieldset", attributes, children)
+ html("fieldset", attributes, children)
}
+///
pub fn form (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("form", attributes, children)
+ html("form", attributes, children)
}
+///
pub fn input (attributes: List(Attribute(action))) -> Element(action) {
- element("input", attributes, [])
+ html("input", attributes, [])
}
+///
pub fn label (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("label", attributes, children)
+ html("label", attributes, children)
}
+///
pub fn legend (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("legend", attributes, children)
+ html("legend", attributes, children)
}
+///
pub fn meter (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("meter", attributes, children)
+ html("meter", attributes, children)
}
+///
pub fn optgroup (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("optgroup", attributes, children)
+ html("optgroup", attributes, children)
}
+///
pub fn option (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("option", attributes, children)
+ html("option", attributes, children)
}
+///
pub fn output (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("output", attributes, children)
+ html("output", attributes, children)
}
+///
pub fn progress (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("progress", attributes, children)
+ html("progress", attributes, children)
}
+///
pub fn select (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("select", attributes, children)
+ html("select", attributes, children)
}
+///
pub fn textarea (attributes: List(Attribute(action))) -> Element(action) {
- element("textarea", attributes, [])
+ html("textarea", attributes, [])
}
-// INTERACTIVE ELEMENTS:
+// INTERACTIVE ELEMENTS --------------------------------------------------------
+
+///
pub fn details (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("details", attributes, children)
+ html("details", attributes, children)
}
+///
pub fn dialog (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("dialog", attributes, children)
+ html("dialog", attributes, children)
}
+///
pub fn summary (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("summary", attributes, children)
+ html("summary", attributes, children)
}
-// WEB COMPONENTS:
+// WEB COMPONENTS --------------------------------------------------------------
+
+///
pub fn slot (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("slot", attributes, children)
+ html("slot", attributes, children)
}
+///
pub fn template (attributes: List(Attribute(action)), children: List(Element(action))) -> Element(action) {
- element("template", attributes, children)
+ html("template", attributes, children)
}
diff --git a/src/lustre/ffi.mjs b/src/lustre/ffi.mjs
index 9d27c5e..0869e0e 100644
--- a/src/lustre/ffi.mjs
+++ b/src/lustre/ffi.mjs
@@ -1,24 +1,22 @@
import * as React from 'react'
import * as ReactDOM from 'react-dom'
-export const Program = ({ init, update, view }) => () => {
- return React.createElement(() => {
+// -----------------------------------------------------------------------------
+
+export const mount = ({ init, update, view }, selector) => {
+ const root = document.querySelector(selector)
+ const App = React.createElement(() => {
const [state, dispatch] = React.useReducer(update, init)
return view(state)(dispatch)
})
-}
-export const mount = (program, selector) => {
- const root = document.querySelector(selector)
- const App = Program(program)
-
- ReactDOM.render(App(), root)
+ ReactDOM.render(App, root)
}
// -----------------------------------------------------------------------------
-export const element = (tag, attributes, children) => (dispatch) => {
+export const html = (tag, attributes, children) => (dispatch) => {
const props = attributes.toArray().map(attr => {
switch (attr.constructor.name) {
case "Attribute":
@@ -51,6 +49,12 @@ export const element = (tag, attributes, children) => (dispatch) => {
)
}
+export const stateful = (init, render) => (dispatch) => {
+ const [state, setState] = React.useState(init)
+
+ return render(state, setState)(dispatch)
+}
+
export const fragment = (children) => (dispatch) => {
return React.createElement(React.Fragment, null,
...children.toArray().map(child => typeof child === 'function'
@@ -63,3 +67,9 @@ export const fragment = (children) => (dispatch) => {
// This is just an identity function! We need it because we want to trick Gleam
// into converting a `String` into an `Element(action)` .
export const text = (content) => content
+
+// -----------------------------------------------------------------------------
+
+export const map = (element, f) => (dispatch) => {
+ return element(action => dispatch(f(action)))
+}