aboutsummaryrefslogtreecommitdiff
path: root/lib/src/runtime.ffi.mjs
diff options
context:
space:
mode:
authorHayleigh Thompson <me@hayleigh.dev>2023-09-19 23:40:03 +0100
committerHayleigh Thompson <me@hayleigh.dev>2023-09-19 23:40:03 +0100
commit92e8596b78982885803994b50c6b35f73f7a403e (patch)
tree13428243987317da540495215ed4d9e3938fb5cb /lib/src/runtime.ffi.mjs
parent985a9b0aa469cbe94fb95c433c97e2b321014341 (diff)
downloadlustre-92e8596b78982885803994b50c6b35f73f7a403e.tar.gz
lustre-92e8596b78982885803994b50c6b35f73f7a403e.zip
:recycle: So long monorepo.
Diffstat (limited to 'lib/src/runtime.ffi.mjs')
-rw-r--r--lib/src/runtime.ffi.mjs239
1 files changed, 0 insertions, 239 deletions
diff --git a/lib/src/runtime.ffi.mjs b/lib/src/runtime.ffi.mjs
deleted file mode 100644
index dd02f8b..0000000
--- a/lib/src/runtime.ffi.mjs
+++ /dev/null
@@ -1,239 +0,0 @@
-import { Empty } from "./gleam.mjs";
-import { map as result_map } from "../gleam_stdlib/gleam/result.mjs";
-
-export function morph(prev, curr, dispatch, parent) {
- if (curr[3]) {
- return prev?.nodeType === 1 &&
- prev.nodeName === curr[0].toUpperCase() &&
- prev.namespaceURI === curr[3]
- ? morphElement(prev, curr, curr[3], dispatch, parent)
- : createElement(prev, curr, curr[3], dispatch, parent);
- }
-
- if (curr[2]) {
- return prev?.nodeType === 1 && prev.nodeName === curr[0].toUpperCase()
- ? morphElement(prev, curr, null, dispatch, parent)
- : createElement(prev, curr, null, dispatch, parent);
- }
-
- if (curr[0] && typeof curr[0] === "string") {
- return prev?.nodeType === 3
- ? morphText(prev, curr)
- : createText(prev, curr);
- }
-
- return document.createComment(
- [
- "[internal lustre error] I couldn't work out how to render this element. This",
- "function should only be called internally by lustre's runtime: if you think",
- "this is an error, please open an issue at",
- "https://github.com/hayleigh-dot-dev/gleam-lustre/issues/new",
- ].join(" ")
- );
-}
-
-// ELEMENTS --------------------------------------------------------------------
-
-function createElement(prev, curr, ns, dispatch, parent = null) {
- const el = ns
- ? document.createElementNS(ns, curr[0])
- : document.createElement(curr[0]);
-
- el.$lustre = {};
-
- let attr = curr[1];
- while (attr.head) {
- morphAttr(
- el,
- attr.head[0],
- attr.head[0] === "class" && el.className
- ? `${el.className} ${attr.head[1]}`
- : attr.head[1],
- dispatch
- );
-
- attr = attr.tail;
- }
-
- if (customElements.get(curr[0])) {
- el._slot = curr[2];
- } else if (curr[0] === "slot") {
- let child = new Empty();
- let parentWithSlot = parent;
-
- while (parentWithSlot) {
- if (parentWithSlot._slot) {
- child = parentWithSlot._slot;
- break;
- } else {
- parentWithSlot = parentWithSlot.parentNode;
- }
- }
-
- while (child.head) {
- el.appendChild(morph(null, child.head, dispatch, el));
- child = child.tail;
- }
- } else {
- let child = curr[2];
- while (child.head) {
- el.appendChild(morph(null, child.head, dispatch, el));
- child = child.tail;
- }
-
- if (prev) prev.replaceWith(el);
- }
-
- return el;
-}
-
-function morphElement(prev, curr, ns, dispatch, parent) {
- const prevAttrs = prev.attributes;
- const currAttrs = new Map();
-
- let currAttr = curr[1];
- while (currAttr.head) {
- currAttrs.set(
- currAttr.head[0],
- currAttr.head[0] === "class" && currAttrs.has("class")
- ? `${currAttrs.get("class")} ${currAttr.head[1]}`
- : currAttr.head[1]
- );
-
- currAttr = currAttr.tail;
- }
-
- for (const { name, value: prevValue } of prevAttrs) {
- if (!currAttrs.has(name)) {
- prev.removeAttribute(name);
- } else {
- const value = currAttrs.get(name);
-
- if (value !== prevValue) {
- morphAttr(prev, name, value, dispatch);
- currAttrs.delete(name);
- }
- }
- }
-
- for (const [name, value] of currAttrs) {
- morphAttr(prev, name, value, dispatch);
- }
-
- if (customElements.get(curr[0])) {
- prev._slot = curr[2];
- } else if (curr[0] === "slot") {
- let prevChild = prev.firstChild;
- let currChild = new Empty();
- let parentWithSlot = parent;
-
- while (parentWithSlot) {
- if (parentWithSlot._slot) {
- currChild = parentWithSlot._slot;
- break;
- } else {
- parentWithSlot = parentWithSlot.parentNode;
- }
- }
-
- while (prevChild) {
- if (currChild.head) {
- morph(prevChild, currChild.head, dispatch, prev);
- currChild = currChild.tail;
- }
-
- prevChild = prevChild.nextSibling;
- }
-
- while (currChild.head) {
- prev.appendChild(morph(null, currChild.head, dispatch, prev));
- currChild = currChild.tail;
- }
- } else {
- let prevChild = prev.firstChild;
- let currChild = curr[2];
-
- while (prevChild) {
- if (currChild.head) {
- const next = prevChild.nextSibling;
- morph(prevChild, currChild.head, dispatch, prev);
- currChild = currChild.tail;
- prevChild = next;
- } else {
- const next = prevChild.nextSibling;
- prevChild.remove();
- prevChild = next;
- }
- }
-
- while (currChild.head) {
- prev.appendChild(morph(null, currChild.head, dispatch, prev));
- currChild = currChild.tail;
- }
- }
-
- return prev;
-}
-
-// ATTRIBUTES ------------------------------------------------------------------
-
-function morphAttr(el, name, value, dispatch) {
- switch (typeof value) {
- case "string":
- if (el.getAttribute(name) !== value) el.setAttribute(name, value);
- if (value === "") el.removeAttribute(name);
- if (name === "value" && el.value !== value) el.value = value;
- break;
-
- // Event listeners need to be handled slightly differently because we need
- // to be able to support custom events. We
- case name.startsWith("on") && "function": {
- if (el.$lustre[name] === value) break;
-
- const event = name.slice(2).toLowerCase();
- const handler = (e) => result_map(value(e), dispatch);
-
- 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;
-
- break;
- }
-
- default:
- el[name] = value;
- }
-}
-
-// TEXT ------------------------------------------------------------------------
-
-function createText(prev, curr) {
- if (!curr[0]) {
- prev?.remove();
- return null;
- }
-
- const el = document.createTextNode(curr[0]);
-
- if (prev) prev.replaceWith(el);
- return el;
-}
-
-function morphText(prev, curr) {
- const prevValue = prev.nodeValue;
- const currValue = curr[0];
-
- if (!currValue) {
- prev?.remove();
- return null;
- }
-
- if (prevValue !== currValue) prev.nodeValue = currValue;
-
- return prev;
-}