aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2023-08-19 22:40:55 +0100
committerHayleigh Thompson <me@hayleigh.dev>2023-08-19 22:40:55 +0100
commit8d05b2dea4afc46a03dc12e26d7b37d45140eaf9 (patch)
tree37ab92610f2fb8290c208ebb4137ad194afbb7d2
parent9919bc2702c89168d1805eaa0db9e4baff091260 (diff)
downloadlustre-8d05b2dea4afc46a03dc12e26d7b37d45140eaf9.tar.gz
lustre-8d05b2dea4afc46a03dc12e26d7b37d45140eaf9.zip
:sparkles: Allow starting args to be passed to an app's init function on start.
-rw-r--r--lib/src/lustre.ffi.mjs4
-rw-r--r--lib/src/lustre.gleam79
-rw-r--r--lib/test/examples/components.gleam12
-rw-r--r--lib/test/examples/counter.gleam8
-rw-r--r--lib/test/examples/input.gleam8
-rw-r--r--lib/test/examples/nested.gleam12
-rw-r--r--lib/test/examples/svg.gleam8
7 files changed, 61 insertions, 70 deletions
diff --git a/lib/src/lustre.ffi.mjs b/lib/src/lustre.ffi.mjs
index b99f6e2..998c598 100644
--- a/lib/src/lustre.ffi.mjs
+++ b/lib/src/lustre.ffi.mjs
@@ -25,7 +25,7 @@ export class App {
this.#view = render;
}
- start(selector = "body") {
+ start(selector, flags) {
if (this.#root) return this;
try {
@@ -33,7 +33,7 @@ export class App {
selector instanceof HTMLElement
? selector
: document.querySelector(selector);
- const [next, effects] = this.#init();
+ const [next, effects] = this.#init(flags);
this.#root = el;
this.#state = next;
diff --git a/lib/src/lustre.gleam b/lib/src/lustre.gleam
index 673f982..4c9ff22 100644
--- a/lib/src/lustre.gleam
+++ b/lib/src/lustre.gleam
@@ -42,34 +42,22 @@ import lustre/element.{Element}
/// | v
/// +--------+
/// | |
-/// | render |
+/// | view |
/// | |
/// +--------+
/// ```
///
-pub type App(model, msg)
+pub type App(flags, model, msg)
pub type Error {
ElementNotFound
ComponentAlreadyRegistered
}
-// These types aren't exposed, but they're just here to try and shrink the type
-// 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.
-//
-
-type Update(model, msg) =
- fn(model, msg) -> #(model, Effect(msg))
-
-type Render(model, msg) =
- fn(model) -> Element(msg)
-
// CONSTRUCTORS ----------------------------------------------------------------
@target(javascript)
-/// Create a basic lustre app that just renders some element on the page.
+/// 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.
///
@@ -93,12 +81,12 @@ type Render(model, msg) =
/// }
/// ```
///
-pub fn element(element: Element(msg)) -> App(Nil, msg) {
- let init = fn() { #(Nil, effect.none()) }
+pub fn element(element: Element(msg)) -> App(Nil, Nil, msg) {
+ let init = fn(_) { #(Nil, effect.none()) }
let update = fn(_, _) { #(Nil, effect.none()) }
- let render = fn(_) { element }
+ let view = fn(_) { element }
- application(init, update, render)
+ application(init, update, view)
}
@target(javascript)
@@ -132,7 +120,7 @@ pub fn element(element: Element(msg)) -> App(Nil, msg) {
/// }
/// }
///
-/// let render = fn (model) {
+/// let view = fn (model) {
/// element.div([], [
/// element.button([ event.on_click(Decr) ], [
/// element.text("-")
@@ -146,20 +134,20 @@ pub fn element(element: Element(msg)) -> App(Nil, msg) {
/// ])
/// }
///
-/// let app = lustre.simple(init, update, render)
+/// let app = lustre.simple(init, update, view)
/// assert Ok(_) = lustre.start(app, "#root")
/// }
/// ```
///
pub fn simple(
- init: fn() -> model,
+ init: fn(flags) -> model,
update: fn(model, msg) -> model,
- render: fn(model) -> Element(msg),
-) -> App(model, msg) {
- let init = fn() { #(init(), effect.none()) }
+ view: fn(model) -> Element(msg),
+) -> App(flags, model, msg) {
+ let init = fn(flags) { #(init(flags), effect.none()) }
let update = fn(model, msg) { #(update(model, msg), effect.none()) }
- application(init, update, render)
+ application(init, update, view)
}
@target(javascript)
@@ -182,14 +170,14 @@ pub fn simple(
/// }
/// }
///
-/// let render = fn (model) {
+/// let view = fn (model) {
/// element.div([], [
/// element.text("Time elapsed: ")
/// element.text(int.to_string(model))
/// ])
/// }
///
-/// let app = lustre.simple(init, update, render)
+/// let app = lustre.simple(init, update, view)
/// assert Ok(_) = lustre.start(app, "#root")
/// }
///
@@ -204,21 +192,23 @@ pub fn simple(
/// external fn set_timeout (f: fn () -> a, delay: Int) -> Nil
/// = "" "window.setTimeout"
///```
+///
@external(javascript, "./lustre.ffi.mjs", "setup")
-pub fn application(init: fn() -> #(model, Effect(msg)), update: Update(
- model,
- msg,
- ), render: Render(model, msg)) -> App(model, msg)
+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)
@target(javascript)
@external(javascript, "./lustre.ffi.mjs", "setup_component")
-pub fn component(name: String, init: fn() -> #(model, Effect(msg)), update: Update(
- model,
- msg,
- ), render: Render(model, msg), on_attribute_change: Map(String, Decoder(msg))) -> Result(
- Nil,
- Error,
-)
+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)
// EFFECTS ---------------------------------------------------------------------
@@ -234,7 +224,7 @@ pub fn component(name: String, init: fn() -> #(model, Effect(msg)), update: Upda
/// import lustre
///
/// pub fn main () {
-/// let app = lustre.appliation(init, update, render)
+/// let app = lustre.appliation(init, update, view)
/// assert Ok(dispatch) = lustre.start(app, "#root")
///
/// dispatch(Incr)
@@ -248,7 +238,8 @@ pub fn component(name: String, init: fn() -> #(model, Effect(msg)), update: Upda
/// app from the outside world.
///
@external(javascript, "./lustre.ffi.mjs", "start")
-pub fn start(app: App(model, msg), selector: String) -> Result(
- fn(msg) -> Nil,
- Error,
-)
+pub fn start(
+ app: App(flags, model, msg),
+ selector: String,
+ flags: flags,
+) -> Result(fn(msg) -> Nil, Error)
diff --git a/lib/test/examples/components.gleam b/lib/test/examples/components.gleam
index 722b796..ed2f7f3 100644
--- a/lib/test/examples/components.gleam
+++ b/lib/test/examples/components.gleam
@@ -21,7 +21,7 @@ pub fn main() {
"custom-counter",
counter_init,
counter_update,
- counter_render,
+ counter_view,
map.from_list([
#(
"count",
@@ -36,13 +36,13 @@ pub fn main() {
// A `simple` lustre application doesn't produce `Effect`s. These are best to
// start with if you're just getting started with lustre or you know you don't
// need the runtime to manage any side effects.
- let app = lustre.simple(init, update, render)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]")
+ let app = lustre.simple(init, update, view)
+ let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
Nil
}
-fn init() {
+fn init(_) {
[]
}
@@ -53,7 +53,7 @@ fn update(history, msg) {
}
}
-fn render(history) {
+fn view(history) {
let on_custom_click = {
use _ <- event.on("custom-click")
Some("click")
@@ -90,7 +90,7 @@ fn counter_update(count, msg) {
}
}
-fn counter_render(count) {
+fn counter_view(count) {
div(
[],
[
diff --git a/lib/test/examples/counter.gleam b/lib/test/examples/counter.gleam
index 759ebdf..4faf00c 100644
--- a/lib/test/examples/counter.gleam
+++ b/lib/test/examples/counter.gleam
@@ -12,8 +12,8 @@ pub fn main() {
// A `simple` lustre application doesn't produce `Effect`s. These are best to
// start with if you're just getting started with lustre or you know you don't
// need the runtime to manage any side effects.
- let app = lustre.simple(init, update, render)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]")
+ let app = lustre.simple(init, update, view)
+ let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
}
// MODEL -----------------------------------------------------------------------
@@ -21,7 +21,7 @@ pub fn main() {
pub type Model =
Int
-pub fn init() -> Model {
+pub fn init(_) -> Model {
0
}
@@ -43,7 +43,7 @@ pub fn update(model: Model, msg: Msg) -> Model {
// VIEW ------------------------------------------------------------------------
-pub fn render(model: Model) -> Element(Msg) {
+pub fn view(model: Model) -> Element(Msg) {
div(
[],
[
diff --git a/lib/test/examples/input.gleam b/lib/test/examples/input.gleam
index d59c0c9..ff4d794 100644
--- a/lib/test/examples/input.gleam
+++ b/lib/test/examples/input.gleam
@@ -14,8 +14,8 @@ pub fn main() {
// A `simple` lustre application doesn't produce `Effect`s. These are best to
// start with if you're just getting started with lustre or you know you don't
// need the runtime to manage any side effects.
- let app = lustre.simple(init, update, render)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]")
+ let app = lustre.simple(init, update, view)
+ let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
Nil
}
@@ -26,7 +26,7 @@ type Model {
Model(email: String, password: String, remember_me: Bool)
}
-fn init() -> Model {
+fn init(_) -> Model {
Model(email: "", password: "", remember_me: False)
}
@@ -56,7 +56,7 @@ fn update(model: Model, msg: Msg) -> Model {
// RENDER ----------------------------------------------------------------------
-fn render(model: Model) -> Element(Msg) {
+fn view(model: Model) -> Element(Msg) {
div(
[attribute.class("container")],
[
diff --git a/lib/test/examples/nested.gleam b/lib/test/examples/nested.gleam
index 47bb9d5..91c2da4 100644
--- a/lib/test/examples/nested.gleam
+++ b/lib/test/examples/nested.gleam
@@ -14,8 +14,8 @@ pub fn main() {
// A `simple` lustre application doesn't produce `Effect`s. These are best to
// start with if you're just getting started with lustre or you know you don't
// need the runtime to manage any side effects.
- let app = lustre.simple(init, update, render)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]")
+ let app = lustre.simple(init, update, view)
+ let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
Nil
}
@@ -25,10 +25,10 @@ pub fn main() {
type Model =
Map(Int, counter.Model)
-fn init() -> Model {
+fn init(_) -> Model {
use counters, id <- list.fold(list.range(1, 10), map.new())
- map.insert(counters, id, counter.init())
+ map.insert(counters, id, counter.init(Nil))
}
// UPDATE ----------------------------------------------------------------------
@@ -45,10 +45,10 @@ fn update(model: Model, msg: Msg) -> Model {
// RENDER ----------------------------------------------------------------------
-fn render(model: Model) -> Element(Msg) {
+fn view(model: Model) -> Element(Msg) {
let counters = {
use rest, id, counter <- map.fold(model, [])
- let el = element.map(counter.render(counter), pair.new(id, _))
+ let el = element.map(counter.view(counter), pair.new(id, _))
[el, ..rest]
}
diff --git a/lib/test/examples/svg.gleam b/lib/test/examples/svg.gleam
index c1cc5fb..e895f1a 100644
--- a/lib/test/examples/svg.gleam
+++ b/lib/test/examples/svg.gleam
@@ -14,8 +14,8 @@ pub fn main() {
// A `simple` lustre application doesn't produce `Effect`s. These are best to
// start with if you're just getting started with lustre or you know you don't
// need the runtime to manage any side effects.
- let app = lustre.simple(init, update, render)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]")
+ let app = lustre.simple(init, update, view)
+ let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
}
// MODEL -----------------------------------------------------------------------
@@ -23,7 +23,7 @@ pub fn main() {
pub type Model =
Int
-pub fn init() -> Model {
+pub fn init(_) -> Model {
0
}
@@ -45,7 +45,7 @@ pub fn update(model: Model, msg: Msg) -> Model {
// VIEW ------------------------------------------------------------------------
-pub fn render(model: Model) -> Element(Msg) {
+pub fn view(model: Model) -> Element(Msg) {
div(
[],
[