/** * This component helps test existing components work when encapsulated in another component's shadow DOM. * * Demo pages should set this component as the root, under `` * * Note:* due to style encapsulation, demo styles need to be a child of the component */ class DomSwapper extends HTMLElement { constructor() { super(); this._context = "light"; const shadow = this.attachShadow({ mode: "open" }); const slot = document.createElement("slot"); shadow.append(slot); this._slot = slot; } get context() { return this._context; } set context(value) { this._context = value; } /** * moves content between light and shadow DOM * * @param context */ moveTo(context) { if (context === "light") { this.append(...Array.from(this.shadowRoot.children).filter((node) => node !== this._slot)); this._context = "light"; } else { if (!this._headStyles) { this._headStyles = this.recreateDemoStyle(); } this.shadowRoot.append(...this._headStyles, ...this.shadowRoot.querySelector("slot").assignedNodes()); this._context = "shadow"; } } recreateDemoStyle() { return Array.from(document.querySelectorAll("head style:not([data-styles]), head link[rel=stylesheet]")).map((style) => style.cloneNode(true)); } } customElements.define("demo-dom-swapper", DomSwapper);