diff options
author | Hayleigh Thompson <me@hayleigh.dev> | 2023-09-19 23:40:03 +0100 |
---|---|---|
committer | Hayleigh Thompson <me@hayleigh.dev> | 2023-09-19 23:40:03 +0100 |
commit | 92e8596b78982885803994b50c6b35f73f7a403e (patch) | |
tree | 13428243987317da540495215ed4d9e3938fb5cb /lib/src/runtime.ffi.mjs | |
parent | 985a9b0aa469cbe94fb95c433c97e2b321014341 (diff) | |
download | lustre-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.mjs | 239 |
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; -} |