diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server-component.mjs | 34 | ||||
-rw-r--r-- | src/vdom.ffi.mjs | 16 |
2 files changed, 39 insertions, 11 deletions
diff --git a/src/server-component.mjs b/src/server-component.mjs index d4cb4a9..855ff9d 100644 --- a/src/server-component.mjs +++ b/src/server-component.mjs @@ -19,6 +19,7 @@ export class LustreServerComponent extends HTMLElement { #root = null; #socket = null; #shadow = null; + #stylesOffset = 0; constructor() { super(); @@ -52,11 +53,13 @@ export class LustreServerComponent extends HTMLElement { for (const link of document.querySelectorAll("link")) { if (link.rel === "stylesheet") { this.#shadow.appendChild(link.cloneNode(true)); + this.#stylesOffset++; } } for (const style of document.querySelectorAll("style")) { this.#shadow.appendChild(style.cloneNode(true)); + this.#stylesOffset++; } this.#root = document.createElement("div"); @@ -152,16 +155,27 @@ export class LustreServerComponent extends HTMLElement { morph(vdom) { this.#root = morph(this.#root, vdom, (handler) => (event) => { + const data = JSON.parse(this.getAttribute("data-lustre-data") || "{}"); const msg = handler(event); + + msg.data = merge(data, msg.data); + this.#socket?.send(JSON.stringify([Constants.event, msg.tag, msg.data])); }); } diff([diff]) { - this.#root = patch(this.#root, diff, (handler) => (event) => { - const msg = handler(event); - this.#socket?.send(JSON.stringify([Constants.event, msg.tag, msg.data])); - }); + this.#root = patch( + this.#root, + diff, + (handler) => (event) => { + const msg = handler(event); + this.#socket?.send( + JSON.stringify([Constants.event, msg.tag, msg.data]), + ); + }, + this.#stylesOffset, + ); } emit([event, data]) { @@ -182,3 +196,15 @@ export class LustreServerComponent extends HTMLElement { } window.customElements.define("lustre-server-component", LustreServerComponent); + +// UTILS ----------------------------------------------------------------------- + +function merge(target, source) { + for (const key in source) { + if (source[key] instanceof Object) + Object.assign(source[key], merge(target[key], source[key])); + } + + Object.assign(target || {}, source); + return target; +} diff --git a/src/vdom.ffi.mjs b/src/vdom.ffi.mjs index c3d12e2..0c645c1 100644 --- a/src/vdom.ffi.mjs +++ b/src/vdom.ffi.mjs @@ -84,7 +84,7 @@ export function morph(prev, next, dispatch, isComponent = false) { return out; } -export function patch(root, diff, dispatch) { +export function patch(root, diff, dispatch, stylesOffset = 0) { const rootParent = root.parentNode; // A diff is a tuple of three arrays: created, removed, updated. Each of these @@ -101,7 +101,7 @@ export function patch(root, diff, dispatch) { for (const created of diff[0]) { const key = created[0].split("-"); const next = created[1]; - const prev = getDeepChild(rootParent, key); + const prev = getDeepChild(rootParent, key, stylesOffset); let result; @@ -113,7 +113,7 @@ export function patch(root, diff, dispatch) { // tree. This can happen because we might get a patch that tells us some node // was created at a path that doesn't exist yet. else { - const parent = getDeepChild(rootParent, key.slice(0, -1)); + const parent = getDeepChild(rootParent, key.slice(0, -1), stylesOffset); const temp = document.createTextNode(""); parent.appendChild(temp); result = morph(temp, next, dispatch); @@ -130,7 +130,7 @@ export function patch(root, diff, dispatch) { // the removed element. for (const removed of diff[1]) { const key = removed[0].split("-"); - const deletedNode = getDeepChild(rootParent, key); + const deletedNode = getDeepChild(rootParent, key, stylesOffset); deletedNode.remove(); } @@ -139,7 +139,7 @@ export function patch(root, diff, dispatch) { for (const updated of diff[2]) { const key = updated[0].split("-"); const patches = updated[1]; - const prev = getDeepChild(rootParent, key); + const prev = getDeepChild(rootParent, key, stylesOffset); const handlersForEl = registeredHandlers.get(prev); for (const created of patches[0]) { @@ -455,13 +455,15 @@ function getKeyedChildren(el) { return keyedChildren; } -function getDeepChild(el, path) { +function getDeepChild(el, path, stylesOffset) { let n; let rest; let child = el; + let isFirstInPath = true; while ((([n, ...rest] = path), n !== undefined)) { - child = child.childNodes.item(n); + child = child.childNodes.item(isFirstInPath ? n + stylesOffset : n); + isFirstInPath = false; path = rest; } |