aboutsummaryrefslogtreecommitdiff
path: root/docs/src/app/ui/hooks.gleam
diff options
context:
space:
mode:
Diffstat (limited to 'docs/src/app/ui/hooks.gleam')
-rw-r--r--docs/src/app/ui/hooks.gleam120
1 files changed, 0 insertions, 120 deletions
diff --git a/docs/src/app/ui/hooks.gleam b/docs/src/app/ui/hooks.gleam
deleted file mode 100644
index 5fd807e..0000000
--- a/docs/src/app/ui/hooks.gleam
+++ /dev/null
@@ -1,120 +0,0 @@
-// 🚨 This module makes quite judicious use of `dynamic.unsafe_coerce` to wire
-// things up. As things are, this is sound because we control things in such a
-// way that it's impossible to pass in things that don't match up to the expected
-// types.
-//
-// If you're defining a new hook to export for this module, pay extra attention
-// to make sure you aren't introducing any soundness issues! 🚨
-
-// IMPORTS ---------------------------------------------------------------------
-
-import gleam/dynamic.{Dynamic, dynamic}
-import gleam/function
-import gleam/map.{Map}
-import gleam/result
-import lustre.{Error}
-import lustre/attribute.{Attribute, property}
-import lustre/effect.{Effect}
-import lustre/element.{Element, element}
-import lustre/event
-
-// HOOKS: STATE ----------------------------------------------------------------
-
-///
-///
-pub fn use_state(
- init: state,
- view: fn(state, fn(state) -> Msg, fn(msg) -> Msg) -> Element(Msg),
-) -> Element(msg) {
- let attrs = [property("state", init), property("view", view), on_dispatch()]
- let assert Ok(_) = register_hook("use-state")
-
- element("use-state", attrs, [])
-}
-
-// HOOKS: REDUCER --------------------------------------------------------------
-
-///
-///
-pub fn use_reducer(
- init: state,
- update: fn(state, action) -> state,
- view: fn(state, fn(action) -> Msg, fn(action) -> Msg) -> Element(Msg),
-) -> Element(msg) {
- // The `use_reducer` hook is actually just the `use_state` hook under the hood
- // with a wrapper around the `set_state` callback. We could just call out to
- // `use_state` directly but we're doing it like this so that the DOM renders
- // a separate `use-reducer` element, which I think is nicer.
- let view = fn(state, set_state, emit) {
- view(state, function.compose(update(state, _), set_state), emit)
- }
- let attrs = [property("state", init), property("view", view), on_dispatch()]
- let assert Ok(_) = register_hook("use-reducer")
-
- element("use-reducer", attrs, [])
-}
-
-// HOOKS: INTERNAL COMPONENT ---------------------------------------------------
-
-fn register_hook(name: String) -> Result(Nil, Error) {
- // If a component is already registered we will just assume it's because this
- // hook as already been used before. This isn't really an error state so we'll
- // just return `Ok(Nil)` and let our hooks continue.
- case lustre.is_registered(name) {
- True -> Ok(Nil)
- False ->
- lustre.component(
- name,
- init_hook,
- update_hook,
- view_hook,
- map.from_list([
- #("state", dynamic.decode1(Set("state", _), Ok)),
- #("view", dynamic.decode1(Set("view", _), Ok)),
- ]),
- )
- }
-}
-
-type Model =
- Map(String, Dynamic)
-
-fn init_hook() -> #(Model, Effect(msg)) {
- #(map.new(), effect.none())
-}
-
-/// The type for messages handled internally by the different hooks. You typially
-/// won't need to import or refer to this type directly.
-///
-pub opaque type Msg {
- Set(String, Dynamic)
- Emit(Dynamic)
-}
-
-fn update_hook(model: Model, msg: Msg) -> #(Model, Effect(msg)) {
- case msg {
- Set(key, val) -> #(map.insert(model, key, val), effect.none())
- Emit(msg) -> #(model, event.emit("dispatch", msg))
- }
-}
-
-fn view_hook(model: Model) -> Element(Msg) {
- case map.get(model, "state"), map.get(model, "view") {
- Ok(state), Ok(view) -> {
- let state = dynamic.unsafe_coerce(state)
- let view = dynamic.unsafe_coerce(view)
-
- view(state, Set("state", _), Emit)
- }
- _, _ -> element.text("???")
- }
-}
-
-// EVENTS ----------------------------------------------------------------------
-
-fn on_dispatch() -> Attribute(msg) {
- use event <- event.on("dispatch")
- event
- |> dynamic.field("detail", dynamic)
- |> result.map(dynamic.unsafe_coerce)
-}