diff options
author | Hayleigh Thompson <me@hayleigh.dev> | 2024-06-13 23:53:23 +0100 |
---|---|---|
committer | Hayleigh Thompson <me@hayleigh.dev> | 2024-06-13 23:53:23 +0100 |
commit | 4081a0941fcf55ce60866d4dcd60fc6fc99e7e8b (patch) | |
tree | 7a8178431430f22d8d57e2ad49403aeaa2c313e9 | |
parent | 72bf9e650f66253ea8994fc0036aa7dc2f4bd165 (diff) | |
download | lustre-4081a0941fcf55ce60866d4dcd60fc6fc99e7e8b.tar.gz lustre-4081a0941fcf55ce60866d4dcd60fc6fc99e7e8b.zip |
:recycle: Correctly use shadow dom in custom elements.
-rw-r--r-- | src/client-component.ffi.mjs | 39 | ||||
-rw-r--r-- | src/server-component.mjs | 23 |
2 files changed, 56 insertions, 6 deletions
diff --git a/src/client-component.ffi.mjs b/src/client-component.ffi.mjs index 0dfc303..ce8607b 100644 --- a/src/client-component.ffi.mjs +++ b/src/client-component.ffi.mjs @@ -14,10 +14,19 @@ export function register({ init, update, view, on_attribute_change }, name) { return new Error(new ComponentAlreadyRegistered(name)); } - window.customElements.define( - name, - makeComponent(init, update, view, on_attribute_change), - ); + const Component = makeComponent(init, update, view, on_attribute_change); + + window.customElements.define(name, Component); + + for (const el of document.querySelectorAll(name)) { + const replaced = new Component(); + + for (const attr of el.attributes) { + replaced.setAttribute(attr.name, attr.value); + } + + el.replaceWith(replaced); + } return new Ok(undefined); } @@ -26,6 +35,7 @@ function makeComponent(init, update, view, on_attribute_change) { return class LustreClientComponent extends HTMLElement { #root = document.createElement("div"); #application = null; + #shadow = null; slotContent = []; @@ -35,6 +45,8 @@ function makeComponent(init, update, view, on_attribute_change) { constructor() { super(); + this.#shadow = this.attachShadow({ mode: "closed" }); + on_attribute_change[0]?.forEach((decoder, name) => { Object.defineProperty(this, name, { get() { @@ -60,6 +72,15 @@ function makeComponent(init, update, view, on_attribute_change) { } connectedCallback() { + const sheet = new CSSStyleSheet(); + + for (const { cssRules } of document.styleSheets) { + for (const rule of cssRules) { + sheet.insertRule(rule.cssText); + } + } + + this.#shadow.adoptedStyleSheets = [sheet]; this.#application = new LustreClientApplication( init(), update, @@ -67,7 +88,7 @@ function makeComponent(init, update, view, on_attribute_change) { this.#root, true, ); - this.appendChild(this.#root); + this.#shadow.append(this.#root); } attributeChangedCallback(key, _, next) { @@ -77,5 +98,13 @@ function makeComponent(init, update, view, on_attribute_change) { disconnectedCallback() { this.#application.send(new Shutdown()); } + + get adoptedStyleSheets() { + return this.#shadow.adoptedStyleSheets; + } + + set adoptedStyleSheets(value) { + this.#shadow.adoptedStyleSheets = value; + } }; } diff --git a/src/server-component.mjs b/src/server-component.mjs index 0700939..31cd364 100644 --- a/src/server-component.mjs +++ b/src/server-component.mjs @@ -18,10 +18,12 @@ export class LustreServerComponent extends HTMLElement { #observer = null; #root = null; #socket = null; + #shadow = null; constructor() { super(); + this.#shadow = this.attachShadow({ mode: "closed" }); this.#observer = new MutationObserver((mutations) => { const changed = []; @@ -48,7 +50,18 @@ export class LustreServerComponent extends HTMLElement { connectedCallback() { this.#root = document.createElement("div"); - this.appendChild(this.#root); + this.#shadow.appendChild(this.#root); + + const sheet = new CSSStyleSheet(); + + for (const { cssRules } of document.styleSheets) { + for (const rule of cssRules) { + console.log(rule); + sheet.insertRule(rule.cssText); + } + } + + this.#shadow.adoptedStyleSheets = [sheet]; } attributeChangedCallback(name, prev, next) { @@ -159,6 +172,14 @@ export class LustreServerComponent extends HTMLElement { disconnectedCallback() { this.#socket?.close(); } + + get adoptedStyleSheets() { + return this.#shadow.adoptedStyleSheets; + } + + set adoptedStyleSheets(value) { + this.#shadow.adoptedStyleSheets = value; + } } window.customElements.define("lustre-server-component", LustreServerComponent); |