demo-dom-swapper.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. /**
  2. * This component helps test existing components work when encapsulated in another component's shadow DOM.
  3. *
  4. * Demo pages should set this component as the root, under `<body>`
  5. *
  6. * Note:* due to style encapsulation, demo styles need to be a child of the component
  7. */
  8. class DomSwapper extends HTMLElement {
  9. constructor() {
  10. super();
  11. this._context = "light";
  12. const shadow = this.attachShadow({ mode: "open" });
  13. const slot = document.createElement("slot");
  14. shadow.append(slot);
  15. this._slot = slot;
  16. }
  17. get context() {
  18. return this._context;
  19. }
  20. set context(value) {
  21. this._context = value;
  22. }
  23. /**
  24. * moves content between light and shadow DOM
  25. *
  26. * @param context
  27. */
  28. moveTo(context) {
  29. if (context === "light") {
  30. this.append(...Array.from(this.shadowRoot.children).filter((node) => node !== this._slot));
  31. this._context = "light";
  32. }
  33. else {
  34. if (!this._headStyles) {
  35. this._headStyles = this.recreateDemoStyle();
  36. }
  37. this.shadowRoot.append(...this._headStyles, ...this.shadowRoot.querySelector("slot").assignedNodes());
  38. this._context = "shadow";
  39. }
  40. }
  41. recreateDemoStyle() {
  42. return Array.from(document.querySelectorAll("head style:not([data-styles]), head link[rel=stylesheet]")).map((style) => style.cloneNode(true));
  43. }
  44. }
  45. customElements.define("demo-dom-swapper", DomSwapper);