class ZComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { const type = this.getAttribute('type'); if (type == null) { throw `component without any type given.`; } const template = document.getElementById(`@${type}`); if (template == null) { throw `component '${type}' does not exist.`; } const node = document.importNode(template.content, true); this.shadowRoot.appendChild(node); Zenv.constructors[`component__${type}`](new Zenv(this)); } } class Zenv { static constructors = {}; constructor(doc) { this.document = doc; } component(type, slots) { const element = document.createElement('z-component'); element.setAttribute('type', type); for (const name in slots) { const slot = slots[name]; slot.setAttribute('slot', name); element.appendChild(slot); } return element; } populate_attributes(obj, attrs) { for (const attr in attrs) { if (typeof(obj[attr]) == 'object' && typeof(attrs[attr]) == 'object') { this.populate_attributes(obj[attr], attrs[attr]); } else { obj[attr] = attrs[attr]; } } } native(name, options) { const element = document.createElement(name); this.populate_attributes(element, options); return element; } by_id(id) { return this.document.shadowRoot.getElementById(id); } by_selector(query) { return this.document.shadowRoot.querySelector(query); } by_selector_all(query) { return this.document.shadowRoot.querySelectorAll(query); } get body() { return this.document.shadowRoot; } } Z = new Zenv(document.body); customElements.define("z-component", ZComponent);