diff options
author | Hayleigh Thompson <me@hayleigh.dev> | 2024-01-31 22:20:46 +0000 |
---|---|---|
committer | Hayleigh Thompson <me@hayleigh.dev> | 2024-01-31 22:20:46 +0000 |
commit | e68be4621a154c1c3d533ab160b29cbb404e50fe (patch) | |
tree | edff9e6266587aa97784a44f3f950d1087be8d04 /examples/06-custom-effects/src/app.gleam | |
parent | ff321580a14ba0ef38beaa9ce92df212f6729f83 (diff) | |
download | lustre-e68be4621a154c1c3d533ab160b29cbb404e50fe.tar.gz lustre-e68be4621a154c1c3d533ab160b29cbb404e50fe.zip |
:construction: Start writing an example for custom effects.
Diffstat (limited to 'examples/06-custom-effects/src/app.gleam')
-rw-r--r-- | examples/06-custom-effects/src/app.gleam | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/examples/06-custom-effects/src/app.gleam b/examples/06-custom-effects/src/app.gleam new file mode 100644 index 0000000..289de5d --- /dev/null +++ b/examples/06-custom-effects/src/app.gleam @@ -0,0 +1,92 @@ +import gleam/option.{type Option, None, Some} +import lustre +import lustre/attribute +import lustre/effect.{type Effect} +import lustre/element.{type Element} +import lustre/event +// These examples are written with lustre_ui in mind. They'll work regardless, +// but to see what lustre_ui can do make sure to run each of these examples with +// the `--include-styles` flag: +// +// $ gleam run -m lustre/try -- --include-styles +// +// In your own apps, make sure to add the `lustre_ui` dependency and include the +// stylesheet somewhere. +import lustre/ui + +// MAIN ------------------------------------------------------------------------ + +pub fn main() { + let app = lustre.application(init, update, view) + let assert Ok(_) = lustre.start(app, "#app", Nil) +} + +// MODEL ----------------------------------------------------------------------- + +type Model { + Model(message: Option(String)) +} + +fn init(_) -> #(Model, Effect(Msg)) { + #(Model(message: None), read_localstorage("message", GotMessage)) +} + +// UPDATE ---------------------------------------------------------------------- + +pub opaque type Msg { + GotInput(String) + GotMessage(Result(String, Nil)) +} + +fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) { + case msg { + GotInput(input) -> #( + Model(message: Some(input)), + write_localstorage("message", input), + ) + GotMessage(Ok(message)) -> #(Model(message: Some(message)), effect.none()) + GotMessage(Error(_)) -> #(model, effect.none()) + } +} + +fn read_localstorage( + key: String, + to_msg: fn(Result(String, Nil)) -> msg, +) -> Effect(msg) { + effect.from(fn(dispatch) { + do_read_localstorage(key) + |> to_msg + |> dispatch + }) +} + +@external(javascript, "./app.ffi.mjs", "read_localstorage") +fn do_read_localstorage(_key: String) -> Result(String, Nil) { + Error(Nil) +} + +fn write_localstorage(key: String, value: String) -> Effect(msg) { + effect.from(fn(_) { do_write_localstorage(key, value) }) +} + +@external(javascript, "./app.ffi.mjs", "write_localstorage") +fn do_write_localstorage(_key: String, _value: String) -> Nil { + Nil +} + +// VIEW ------------------------------------------------------------------------ + +fn view(model: Model) -> Element(Msg) { + let styles = [#("width", "100vw"), #("height", "100vh")] + let message = option.unwrap(model.message, "") + + ui.centre( + [attribute.style(styles)], + ui.field( + [], + [], + ui.input([attribute.value(message), event.on_input(GotInput)]), + [element.text("Type a message and refresh the page")], + ), + ) +} |