aboutsummaryrefslogtreecommitdiff
path: root/src/runtime.ffi.mjs
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2024-01-23 00:09:45 +0000
committerGitHub <noreply@github.com>2024-01-23 00:09:45 +0000
commit24f6962aa457d32319756f6217aafde7b0a9c752 (patch)
tree42119d9b073f56eabe9dda4ae2065ef4b2086e6a /src/runtime.ffi.mjs
parent45e671ac32de95ae1a0a9f9e98da8645d01af3cf (diff)
downloadlustre-24f6962aa457d32319756f6217aafde7b0a9c752.tar.gz
lustre-24f6962aa457d32319756f6217aafde7b0a9c752.zip
✨ Add universal components that can run on the server (#39)
* :heavy_plus_sign: Add gleam_erlang gleam_otp and gleam_json dependencies. * :sparkles: Add json encoders for elememnts and attributes. * :sparkles: Add the ability to perform an effect with a custom dispatch function. * :construction: Experiment with a server-side component runtime. * :construction: Expose special server click events. * :construction: Experiment with a server-side component runtime. * :construction: Experiment with a server-side component runtime. * :construction: Experiment with a server-side component runtime. * :construction: Create a basic server component client bundle. * :construction: Create a basic server component demo. * :bug: Fixed a bug where the runtime stopped performing patches. * :refactor: Roll back introduction of shadow dom. * :recycle: Refactor to Custom Element-based approach to encapsulating server components. * :truck: Move some things around. * :sparkles: Add a minified version of the server component runtime. * :wrench: Add lustre/server/* to internal modules. * :recycle: on_attribute_change and on_client_event handlers are now functions not dicts. * :recycle: Refactor server component event handling to no longer need explicit tags. * :fire: Remove unnecessary attempt to stringify events. * :memo: Start documeint lustre/server functions. * :construction: Experiment with a js implementation of the server component backend runtime. * :recycle: Experiment with an API that makes heavier use of conditional complilation. * :recycle: Big refactor to unify server components, client components, and client apps. * :bug: Fixed some bugs with client runtimes. * :recycle: Update examples to new lustre api/ * :truck: Move server demo into examples/ folder/ * :wrench: Add lustre/runtime to internal modules. * :construction: Experiment with a diffing implementation. * :wrench: Hide internal modules from docs. * :heavy_plus_sign: Update deps to latest versions. * :recycle: Move diffing and vdom code into separate internal modules. * :sparkles: Bring server components to feature parity with client components. * :recycle: Update server component demo. * :bug: Fix bug where attribute changes weren't properly broadcast. * :fire: Remove unused 'Patch' type. * :recycle: Stub out empty js implementations so we can build for js. * :memo: Docs for the docs gods. * :recycle: Rename lustre.server_component to lustre.component.
Diffstat (limited to 'src/runtime.ffi.mjs')
-rw-r--r--src/runtime.ffi.mjs61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/runtime.ffi.mjs b/src/runtime.ffi.mjs
index c3cec68..f7b711b 100644
--- a/src/runtime.ffi.mjs
+++ b/src/runtime.ffi.mjs
@@ -227,6 +227,32 @@ function morphElement(prev, curr, dispatch, parent) {
function morphAttr(el, name, value, dispatch) {
switch (typeof value) {
+ case name.startsWith("data-lustre-on-") && "string": {
+ if (!value) {
+ el.removeAttribute(name);
+ el.removeEventListener(event, el.$lustre[`${name}Handler`]);
+
+ break;
+ }
+ if (el.hasAttribute(name)) break;
+
+ const event = name.slice(15).toLowerCase();
+ const handler = (e) => dispatch(serverEventHandler(e));
+
+ if (el.$lustre[`${name}Handler`]) {
+ el.removeEventListener(event, el.$lustre[`${name}Handler`]);
+ }
+
+ el.addEventListener(event, handler);
+
+ el.$lustre[name] = value;
+ el.$lustre[`${name}Handler`] = handler;
+ el.$lustre.__registered_events.add(name);
+ el.setAttribute(name, value);
+
+ break;
+ }
+
case "string":
if (el.getAttribute(name) !== value) el.setAttribute(name, value);
if (value === "") el.removeAttribute(name);
@@ -281,3 +307,38 @@ function morphText(prev, curr) {
return prev;
}
+
+// UTILS -----------------------------------------------------------------------
+
+function serverEventHandler(event) {
+ const el = event.target;
+ const tag = el.getAttribute(`data-lustre-on-${event.type}`);
+ const data = JSON.parse(el.getAttribute("data-lustre-data") || "{}");
+ const include = JSON.parse(el.getAttribute("data-lustre-include") || "[]");
+
+ switch (event.type) {
+ case "input":
+ case "change":
+ include.push("target.value");
+ break;
+ }
+
+ return {
+ tag,
+ data: include.reduce((data, property) => {
+ const path = property.split(".");
+
+ for (let i = 0, o = data, e = event; i < path.length; i++) {
+ if (i === path.length - 1) {
+ o[path[i]] = e[path[i]];
+ } else {
+ o[path[i]] ??= {};
+ e = e[path[i]];
+ o = o[path[i]];
+ }
+ }
+
+ return data;
+ }, data),
+ };
+}