diff options
author | Hayleigh Thompson <me@hayleigh.dev> | 2023-08-19 22:40:55 +0100 |
---|---|---|
committer | Hayleigh Thompson <me@hayleigh.dev> | 2023-08-19 22:40:55 +0100 |
commit | 8d05b2dea4afc46a03dc12e26d7b37d45140eaf9 (patch) | |
tree | 37ab92610f2fb8290c208ebb4137ad194afbb7d2 | |
parent | 9919bc2702c89168d1805eaa0db9e4baff091260 (diff) | |
download | lustre-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.mjs | 4 | ||||
-rw-r--r-- | lib/src/lustre.gleam | 79 | ||||
-rw-r--r-- | lib/test/examples/components.gleam | 12 | ||||
-rw-r--r-- | lib/test/examples/counter.gleam | 8 | ||||
-rw-r--r-- | lib/test/examples/input.gleam | 8 | ||||
-rw-r--r-- | lib/test/examples/nested.gleam | 12 | ||||
-rw-r--r-- | lib/test/examples/svg.gleam | 8 |
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( [], [ |