aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2023-11-04 13:23:15 +0000
committerHayleigh Thompson <me@hayleigh.dev>2023-11-04 13:23:15 +0000
commit2fa8731d3e31763ba4dbaf074157a0ed6862bc1e (patch)
treede3b4c0acdbd6b324630cb34065e362ddff88b1e
parente0155c7be10901ceb4d11cb5333f92bc272b5499 (diff)
downloadlustre-2fa8731d3e31763ba4dbaf074157a0ed6862bc1e.tar.gz
lustre-2fa8731d3e31763ba4dbaf074157a0ed6862bc1e.zip
:sparkles: Add the 'effect.event' constructor and use it for 'event.emit'.
-rw-r--r--src/lustre.ffi.mjs7
-rw-r--r--src/lustre/effect.gleam15
-rw-r--r--src/lustre/event.gleam5
3 files changed, 15 insertions, 12 deletions
diff --git a/src/lustre.ffi.mjs b/src/lustre.ffi.mjs
index 95770e4..918f7e2 100644
--- a/src/lustre.ffi.mjs
+++ b/src/lustre.ffi.mjs
@@ -125,13 +125,6 @@ export const setup = (init, update, render) => new App(init, update, render);
export const start = (app, selector, flags) => app.start(selector, flags);
export const destroy = (app) => app.destroy();
-export const emit = (name, data) =>
- // Normal `Effect`s constructed in Gleam from `effect.from` don't get told
- // about the second argument, but it's there 👀.
- from((_, emit) => {
- emit(name, data);
- });
-
// HTML EVENTS -----------------------------------------------------------------
export const prevent_default = (e) => e.preventDefault?.();
diff --git a/src/lustre/effect.gleam b/src/lustre/effect.gleam
index ea20c3a..19378da 100644
--- a/src/lustre/effect.gleam
+++ b/src/lustre/effect.gleam
@@ -3,6 +3,7 @@
// IMPORTS ---------------------------------------------------------------------
+import gleam/dynamic.{type Dynamic}
import gleam/list
import gleam/function
@@ -10,7 +11,7 @@ import gleam/function
///
pub opaque type Effect(msg) {
- Effect(all: List(fn(fn(msg) -> Nil, fn(msg) -> Nil) -> Nil))
+ Effect(all: List(fn(fn(msg) -> Nil, fn(String, Dynamic) -> Nil) -> Nil))
}
// CONSTRUCTORS ----------------------------------------------------------------
@@ -23,6 +24,17 @@ pub fn from(effect: fn(fn(msg) -> Nil) -> Nil) -> Effect(msg) {
Effect([fn(dispatch, _) { effect(dispatch) }])
}
+/// Emit a custom event from a component as an effect. Parents can listen to these
+/// events in their `view` function like any other HTML event.
+///
+/// You *probably* don't need to use this type of effect if you're not making use
+/// of Lustre's components, but in rare cases it may be useful to emit custom
+/// events from the DOM node that your Lustre application is mounted to.
+///
+pub fn event(name: String, data: data) -> Effect(msg) {
+ Effect([fn(_, emit) { emit(name, dynamic.from(data)) }])
+}
+
/// Typically our app's `update` function needs to return a tuple of
/// `#(model, Effect(msg))`. When we don't need to perform any side effects we
/// can just return `none()`!
@@ -48,7 +60,6 @@ pub fn map(effect: Effect(a), f: fn(a) -> b) -> Effect(b) {
fn(dispatch, emit) {
let dispatch = function.compose(f, dispatch)
- let emit = function.compose(f, emit)
effect(dispatch, emit)
}
diff --git a/src/lustre/event.gleam b/src/lustre/event.gleam
index a19ec3a..3c101d1 100644
--- a/src/lustre/event.gleam
+++ b/src/lustre/event.gleam
@@ -16,9 +16,8 @@ type Decoded(a) =
// EFFECTS ---------------------------------------------------------------------
///
-@external(javascript, "../lustre.ffi.mjs", "emit")
-pub fn emit(_event: String, _data: any) -> Effect(msg) {
- effect.none()
+pub fn emit(event: String, data: any) -> Effect(msg) {
+ effect.event(event, data)
}
// CUSTOM EVENTS ---------------------------------------------------------------