diff options
-rw-r--r-- | src/client-component.ffi.mjs | 8 | ||||
-rw-r--r-- | src/lustre.gleam | 31 |
2 files changed, 25 insertions, 14 deletions
diff --git a/src/client-component.ffi.mjs b/src/client-component.ffi.mjs index c64527f..1a3a7cb 100644 --- a/src/client-component.ffi.mjs +++ b/src/client-component.ffi.mjs @@ -16,7 +16,7 @@ export function register({ init, update, view, on_attribute_change }, name) { window.customElements.define( name, - makeComponent(init, update, view, on_attribute_change), + makeComponent(init, update, view, on_attribute_change) ); return new Ok(undefined); @@ -28,7 +28,7 @@ function makeComponent(init, update, view, on_attribute_change) { #application = null; static get observedAttributes() { - return on_attribute_change.entries().map(([name, _]) => name); + return on_attribute_change[0]?.entries().map(([name, _]) => name) ?? []; } constructor() { @@ -47,7 +47,7 @@ function makeComponent(init, update, view, on_attribute_change) { this.#application ? this.#application.send(new Dispatch(decoded[0])) : window.requestAnimationFrame(() => - this.#application.send(new Dispatch(decoded[0])), + this.#application.send(new Dispatch(decoded[0])) ); } @@ -66,7 +66,7 @@ function makeComponent(init, update, view, on_attribute_change) { init(), update, view, - this.#root, + this.#root ); this.appendChild(this.#root); } diff --git a/src/lustre.gleam b/src/lustre.gleam index 95c8939..7cb6d3f 100644 --- a/src/lustre.gleam +++ b/src/lustre.gleam @@ -158,20 +158,22 @@ // IMPORTS --------------------------------------------------------------------- -import argv import gleam/bool import gleam/dict.{type Dict} import gleam/dynamic.{type Decoder} import gleam/erlang/process.{type Subject} +import gleam/option.{type Option, None, Some} import gleam/otp/actor.{type StartError} import gleam/result +import lustre/effect.{type Effect} +import lustre/element.{type Element} +import lustre/internals/runtime +import lustre/server.{type Patch} +import argv import glint import lustre/cli/add import lustre/cli/build -import lustre/cli/try -import lustre/effect.{type Effect} -import lustre/element.{type Element, type Patch} -import lustre/internals/runtime +import lustre/cli/dev // MAIN ------------------------------------------------------------------------ @@ -193,7 +195,7 @@ pub fn main() { |> glint.add(at: ["add", "esbuild"], do: add.esbuild()) |> glint.add(at: ["build", "app"], do: build.app()) |> glint.add(at: ["build", "component"], do: build.component()) - |> glint.add(at: ["try"], do: try.run()) + |> glint.add(at: ["dev"], do: dev.run()) |> glint.run(args) } @@ -230,7 +232,14 @@ pub opaque type App(flags, model, msg) { init: fn(flags) -> #(model, Effect(msg)), update: fn(model, msg) -> #(model, Effect(msg)), view: fn(model) -> Element(msg), - on_attribute_change: Dict(String, Decoder(msg)), + // The `dict.mjs` module in the standard library is huge (20+kb!). For folks + // that don't ever build components and don't use a dictionary in any of their + // code we'd rather not thrust that increase in bundle size on them just to + // call `dict.new()`. + // + // Using `Option` here at least lets us say `None` for the empty case in the + // `application` constructor. + on_attribute_change: Option(Dict(String, Decoder(msg))), ) } @@ -341,7 +350,7 @@ pub fn application( update: fn(model, msg) -> #(model, Effect(msg)), view: fn(model) -> Element(msg), ) -> App(flags, model, msg) { - App(init, update, view, dict.new()) + App(init, update, view, None) } /// A `component` is a type of Lustre application designed to be embedded within @@ -368,7 +377,7 @@ pub fn component( view: fn(model) -> Element(msg), on_attribute_change: Dict(String, Decoder(msg)), ) -> App(flags, model, msg) { - App(init, update, view, on_attribute_change) + App(init, update, view, Some(on_attribute_change)) } // EFFECTS --------------------------------------------------------------------- @@ -456,8 +465,10 @@ fn do_start_actor( app: App(flags, model, msg), flags: flags, ) -> Result(Subject(Action(msg, ServerComponent)), Error) { + let on_attribute_change = option.unwrap(app.on_attribute_change, dict.new()) + app.init(flags) - |> runtime.start(app.update, app.view, app.on_attribute_change) + |> runtime.start(app.update, app.view, on_attribute_change) |> result.map_error(ActorError) } |