1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2024-11-24 09:29:37 +01:00
deka-dom-el/docs/p06-customElement.html

242 lines
178 KiB
HTML
Raw Normal View History

2024-06-05 16:20:12 +02:00
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Using custom elements in combinantion with DDE"><title>`deka-dom-el` — Web Components</title><!--<dde:mark type="component" name="metaAuthor" host="this" ssr/>--><meta name="author" content="Jan Andrle"><link type="text/plain" rel="author" href="https://jaandrle.github.io/humans.txt"><meta name="generator" content="deka-dom-el"><!--<dde:mark type="component" name="metaTwitter" host="this" ssr/>--><meta name="twitter:card" content="summary_large_image"><meta name="twitter:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="twitter:title" content="deka-dom-el"><meta name="twitter:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="twitter:creator" content="@jaandrle"><!--<dde:mark type="component" name="metaFacebook" host="this" ssr/>--><meta name="og:url" content="https://github.com/jaandrle/deka-dom-el"><meta name="og:title" content="deka-dom-el"><meta name="og:description" content="A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks."><meta name="og:creator" content="@jaandrle"><script src="https://cdn.jsdelivr.net/npm/shiki@0.9" defer=""></script><script type="module" src="code.js.js"></script><script src="https://flems.io/flems.html" type="text/javascript" charset="utf-8"></script><link rel="stylesheet" href="global.css"></head><body><!--<dde:mark type="component" name="page" host="this" ssr/>--><!--<dde:mark type="component" name="simplePage" host="this" ssr/>--><!--<dde:mark type="component" name="header" host="this" ssr/>--><header><h1>`deka-dom-el` — Web Components</h1><p>Using custom elements in combinantion with DDE</p></header><nav><a href="https://github.com/jaandrle/deka-dom-el"><svg class="icon" viewBox="0 0 32 32"><!--<dde:mark type="component" name="iconGitHub" host="parentElement" ssr/>--><path d="M 16,0.395c -8.836,0 -16,7.163 -16,16c 0,7.069 4.585,13.067 10.942,15.182c 0.8,0.148 1.094,-0.347 1.094,-0.77c 0,-0.381 -0.015,-1.642 -0.022,-2.979c -4.452,0.968 -5.391,-1.888 -5.391,-1.888c -0.728,-1.849 -1.776,-2.341 -1.776,-2.341c -1.452,-0.993 0.11,-0.973 0.11,-0.973c 1.606,0.113 2.452,1.649 2.452,1.649c 1.427,2.446 3.743,1.739 4.656,1.33c 0.143,-1.034 0.558,-1.74 1.016,-2.14c -3.554,-0.404 -7.29,-1.777 -7.29,-7.907c 0,-1.747 0.625,-3.174 1.649,-4.295c -0.166,-0.403 -0.714,-2.03 0.155,-4.234c 0,0 1.344,-0.43 4.401,1.64c 1.276,-0.355 2.645,-0.532 4.005,-0.539c 1.359,0.006 2.729,0.184 4.008,0.539c 3.054,-2.07 4.395,-1.64 4.395,-1.64c 0.871,2.204 0.323,3.831 0.157,4.234c 1.026,1.12 1.647,2.548 1.647,4.295c 0,6.145 -3.743,7.498 -7.306,7.895c 0.574,0.497 1.085,1.47 1.085,2.963c 0,2.141 -0.019,3.864 -0.019,4.391c 0,0.426 0.288,0.925 1.099,0.768c 6.354,-2.118 10.933,-8.113 10.933,-15.18c 0,-8.837 -7.164,-16 -16,-16Z"></path></svg>GitHub</a><a href="./" title="Introducing a&nbsp;library.">1. Introduction</a><a href="p02-elements" title="Basic concepts of elements modifications and creations.">2. Elements</a><a href="p03-events" title="Using not only events in UI declaratively.">3. Events and Addons</a><a href="p04-signals" title="Handling reactivity in UI via signals.">4. Signals and reactivity</a><a href="p05-scopes" title="Organizing UI into components">5. Scopes and components</a><a href="p06-customElement" title="Using custom elements in combinantion with DDE" class="current">6. Web Components</a></nav><main><h2>Using web components in combinantion with DDE</h2><p>The DDE library allows for use within <a title="MDN documentation page for Web Components" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components"><strong>Web Components</strong></a> for dom-tree generation. However, in order to be able to use signals (possibly mapping to registered <a title="MDN documentation page for observedAttributes" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using
import {
customElementRender,
customElementWithDDE,
observedAttributes,
} from "deka-dom-el";
/** @type {ddePublicElementTagNameMap} */
2024-05-23 22:18:19 +02:00
import { S } from "deka-dom-el/signals";
S.observedAttributes;
// “internal” utils
2024-02-03 14:36:17 +01:00
import { lifecyclesToEvents } from "deka-dom-el";
</code></div><h3 id="h-custom-elements-introduction"><!--<dde:mark type="component" name="h3" host="parentElement" ssr/>--><a href="#h-custom-elements-introduction" tabindex="-1">#</a> Custom Elements Introduction</h3><p>Web Components, specifically Custom Elements, are a&nbsp;set of web platform APIs that allow you to create new&nbsp;HTML tags with custom functionality encapsulated within them. This allows for the&nbsp;creation of reusable components that can be used across web applications. </p><p>To start with, lets see how to use native Custom Elements. As starting point please read <a title="MDN documentation page for Custom Elements" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements"><strong>Using Custom Elements</strong>on MDN</a>. To sum up and for mnemonic see following code overview:</p><div class="code" data-js="todo"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">export class HTMLCustomElement extends HTMLElement{
2024-06-05 16:20:12 +02:00
static tagName= "custom-element"; // just suggestion, we can use `el(HTMLCustomElement.tagName)`
static observedAttributes= [ "custom-attribute" ];
constructor(){
super();
// nice place to prepare custom element
}
connectedCallback(){
// nice place to render custom element
}
attributeChangedCallback(name, oldValue, newValue){
// listen to attribute changes (see `observedAttributes`)
}
disconnectedCallback(){
// nice place to clean up
}
// for example, we can mirror get/set prop to attribute
get customAttribute(){ return this.getAttribute("custom-attribute"); }
set customAttribute(value){ this.setAttribute("custom-attribute", value); }
}
2024-06-05 16:20:12 +02:00
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
</code></div><p>For more advanced use of Custom Elements, the summary <a title="Ideas and tips from WebReflection" href="https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4"><strong>Handy Custom Elements Patterns</strong></a> may be useful. Especially pay attention to linking HTML attributes and defining setters/getters, this is very helpful to use in combination with the library (<code>el(HTMLCustomElement.tagName, { customAttribute: "new-value" });</code>).</p><p>Also see the Life Cycle Events sections, very similarly we would like to use <a href="./p03-events.html" title="See events part of the library documentation">DDE events</a>. To do it, the library provides function <code>customElementWithDDE</code></p><!--<dde:mark type="component" name="example" host="this" ssr/>--><div id="code-example-1-n7xtdicpa" class="example"><!--<dde:mark type="component" name="code" host="parentElement" ssr/>--><code class="language-js">import { customElementWithDDE, el, on } from "./esm-with-signals.js";
2024-06-05 16:20:12 +02:00
export class HTMLCustomElement extends HTMLElement{
static tagName= "custom-element";
connectedCallback(){
this.append(
el("p", "Hello from custom element!")
);
}
}
customElementWithDDE(HTMLCustomElement);
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
const instance= el(HTMLCustomElement.tagName);
2024-06-07 10:04:34 +02:00
on.connected( // preffered
e=&gt; console.log("Element connected to the DOM (v1):", e)
)(instance);
instance.addEventListener(
"dde:connected",
e=&gt; console.log("Element connected to the DOM (v2):", e)
);
2024-06-05 16:20:12 +02:00
document.body.append(
instance,
);
</code></div><script>Flems(document.getElementById("code-example-1-n7xtdicpa"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import { customElementWithDDE, el, on } from \\\"./esm-with-signals.js\\\";\\nexport class HTMLCustomElement extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element\\\";\\n\\tconnectedCallback(){\\n\\t\\tthis.append(\\n\\t\\t\\tel(\\\"p\\\", \\\"Hello from custom element!\\\")\\n\\t\\t);\\n\\t}\\n}\\ncustomElementWithDDE(HTMLCustomElement);\\ncustomElements.define(HTMLCustomElement.tagName, HTMLCustomElement);\\n\\nconst instance= el(HTMLCustomElement.tagName);\\non.connected( // preffered\\n\\te=> console.log(\\\"Element connected to the DOM (v1):\\\", e)\\n)(instance);\\ninstance.addEventListener(\\n\\t\\\"dde:connected\\\",\\n\\te=> console.log(\\\"Element connected to the DOM (v2):\\\", e)\\n);\\ndocument.body.append(\\n\\tinstance,\\n);\\n\"},{\"name\":\"esm-with-signals.js\",\"content\":\"// src/signals-common.js\\nvar signals_global = {\\n\\tisSignal(attributes) {\\n\\t\\treturn false;\\n\\t},\\n\\tprocessReactiveAttribute(obj, key, attr, set) {\\n\\t\\treturn attr;\\n\\t}\\n};\\nfunction registerReactivity(def, global = true) {\\n\\tif (global) return Object.assign(signals_global, def);\\n\\tObject.setPrototypeOf(def, signals_global);\\n\\treturn def;\\n}\\nfunction signals(_this) {\\n\\treturn signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;\\n}\\n\\n// src/helpers.js\\nvar hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);\\nfunction isUndef(value) {\\n\\treturn typeof value === \\\"undefined\\\";\\n}\\nfunction typeOf(v) {\\n\\tconst t = typeof v;\\n\\tif (t !== \\\"object\\\") return t;\\n\\tif (v === null) return \\\"null\\\";\\n\\treturn Object.prototype.toString.call(v);\\n}\\nfunction onAbort(signal2, listener) {\\n\\tif (!signal2 || !(signal2 instanceof AbortSignal))\\n\\t\\treturn true;\\n\\tif (signal2.aborted)\\n\\t\\treturn;\\n\\tsignal2.addEventListener(\\\"abort\\\", listener);\\n\\treturn function cleanUp() {\\n\\t\\tsignal2.removeEventListener(\\\"abort\\\", listener);\\n\\t};\\n}\\nfunction observedAttributes(instance, observedAttribute2) {\\n\\tconst { observedAttributes: observedAttributes3 = [] } = instance.constructor;\\n\\treturn observedAttributes3.reduce(function(out, name) {\\n\\t\\tout[kebabToCamel(name)] = observedAttribute2(instance, name);\\n\\t\\treturn out;\\n\\t}, {});\\n}\\nfunction kebabToCamel(name) {\\n\\treturn name.replace(/-./g, (x) => x[1].toUpperCase());\\n}\\n\\n// src/dom-common.js\\nvar enviroment = {\\n\\tsetDeleteAttr,\\n\\tssr: \\\"\\\",\\n\\tD: globalThis.document,\\n\\tF: globalThis.DocumentFragment,\\n\\tH: globalThis.HTMLElement,\\n\\tS: globalThis.SVGElement,\\n\\tM: globalThis.MutationObserver\\n};\\nfunction setDeleteAttr(obj, prop, val) {\\n\\tReflect.set(obj, prop, val);\\n\\tif (!isUndef(val)) return;\\n\\tReflect.deleteProperty(obj, prop);\\n\\tif (obj instanceof enviroment.H && obj.getAttribute(prop) === \\\"undefined\\\")\\n\\t\\treturn obj.removeAttribute(prop);\\n\\tif (Reflect.get(obj, prop) === \\\"undefined\\\")\\n\\t\\treturn Reflect.set(obj, prop, \\\"\\\");\\n}\\nvar keyLTE = \\\"__dde_lifecyclesToEvents\\\";\\nvar evc = \\\"dde:connected\\\";\\nvar evd = \\\"dde:disconnected\\\";\\nvar eva = \\\"dde:attributeChanged\\\";\\n\\n// src/dom.js\\nvar scopes = [{\\n\\tget scope() {\\n\\t\\treturn enviroment.D.body;\\n\\t},\\n\\thost: (c) => c ? c(enviroment.D.body) : enviroment.D.body,\\n\\tprevent: true\\n}];\\nvar scope = {\\n\\tget current() {\\n\\t\\treturn scopes[scopes.length - 1];\\n\\t},\\n\\tget host() {\\n\\t\\treturn this.current.host;\\n\\t},\\n\\tpreventDefault() {\\n\\t\\tconst { current } = this;\\n\\t\\tcurrent.prevent = true;\\n\\t\\treturn current;\\n\\t},\\n\\tget state() {\\n\\t\\treturn [...scopes];\\n\\t},\\n\\tpush(s = {}) {\\n\\t\\treturn scopes.push(Object.assign({}, this.current, { prevent: false }, s));\\n\\t},\\n\\tpushRoot() {\\n\\t\\treturn scopes.push(scopes[0]);\\n\\t},\\n\\tpop() {\\n\\t\\tif (scopes.length === 1) return;\\n\\
2024-06-05 16:20:12 +02:00
customElementRender,
customElementWithDDE,
} from "./esm-with-signals.js";
export class HTMLCustomElement extends HTMLElement{
static tagName= "custom-element";
static observedAttributes= [ "attr" ];
connectedCallback(){
customElementRender(
this,
this.attachShadow({ mode: "open" }),
ddeComponent
);
}
set attr(value){ this.setAttribute("attr", value); }
get attr(){ return this.getAttribute("attr"); }
}
import { el, on, scope } from "./esm-with-signals.js";
function ddeComponent({ attr }){
scope.host(
2024-06-07 10:04:34 +02:00
on.connected(e=&gt; console.log(e.target.outerHTML)),
2024-06-05 16:20:12 +02:00
);
return el().append(
el("p", `Hello from Custom Element with attribute '${attr}'`)
2024-06-07 14:38:38 +02:00
);
2024-06-05 16:20:12 +02:00
}
customElementWithDDE(HTMLCustomElement);
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
document.body.append(
el(HTMLCustomElement.tagName, { attr: "Attribute" })
);
</code></div><script>Flems(document.getElementById("code-example-1-vivfgyxx9kw"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import {\\n\\tcustomElementRender,\\n\\tcustomElementWithDDE,\\n} from \\\"./esm-with-signals.js\\\";\\nexport class HTMLCustomElement extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element\\\";\\n\\tstatic observedAttributes= [ \\\"attr\\\" ];\\n\\tconnectedCallback(){\\n\\t\\tcustomElementRender(\\n\\t\\t\\tthis,\\n\\t\\t\\tthis.attachShadow({ mode: \\\"open\\\" }),\\n\\t\\t\\tddeComponent\\n\\t\\t);\\n\\t}\\n\\tset attr(value){ this.setAttribute(\\\"attr\\\", value); }\\n\\tget attr(){ return this.getAttribute(\\\"attr\\\"); }\\n}\\n\\nimport { el, on, scope } from \\\"./esm-with-signals.js\\\";\\nfunction ddeComponent({ attr }){\\n\\tscope.host(\\n\\t\\ton.connected(e=> console.log(e.target.outerHTML)),\\n\\t);\\n\\treturn el().append(\\n\\t\\tel(\\\"p\\\", `Hello from Custom Element with attribute '${attr}'`)\\n\\t);\\n}\\ncustomElementWithDDE(HTMLCustomElement);\\ncustomElements.define(HTMLCustomElement.tagName, HTMLCustomElement);\\n\\ndocument.body.append(\\n\\tel(HTMLCustomElement.tagName, { attr: \\\"Attribute\\\" })\\n);\\n\"},{\"name\":\"esm-with-signals.js\",\"content\":\"// src/signals-common.js\\nvar signals_global = {\\n\\tisSignal(attributes) {\\n\\t\\treturn false;\\n\\t},\\n\\tprocessReactiveAttribute(obj, key, attr, set) {\\n\\t\\treturn attr;\\n\\t}\\n};\\nfunction registerReactivity(def, global = true) {\\n\\tif (global) return Object.assign(signals_global, def);\\n\\tObject.setPrototypeOf(def, signals_global);\\n\\treturn def;\\n}\\nfunction signals(_this) {\\n\\treturn signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;\\n}\\n\\n// src/helpers.js\\nvar hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);\\nfunction isUndef(value) {\\n\\treturn typeof value === \\\"undefined\\\";\\n}\\nfunction typeOf(v) {\\n\\tconst t = typeof v;\\n\\tif (t !== \\\"object\\\") return t;\\n\\tif (v === null) return \\\"null\\\";\\n\\treturn Object.prototype.toString.call(v);\\n}\\nfunction onAbort(signal2, listener) {\\n\\tif (!signal2 || !(signal2 instanceof AbortSignal))\\n\\t\\treturn true;\\n\\tif (signal2.aborted)\\n\\t\\treturn;\\n\\tsignal2.addEventListener(\\\"abort\\\", listener);\\n\\treturn function cleanUp() {\\n\\t\\tsignal2.removeEventListener(\\\"abort\\\", listener);\\n\\t};\\n}\\nfunction observedAttributes(instance, observedAttribute2) {\\n\\tconst { observedAttributes: observedAttributes3 = [] } = instance.constructor;\\n\\treturn observedAttributes3.reduce(function(out, name) {\\n\\t\\tout[kebabToCamel(name)] = observedAttribute2(instance, name);\\n\\t\\treturn out;\\n\\t}, {});\\n}\\nfunction kebabToCamel(name) {\\n\\treturn name.replace(/-./g, (x) => x[1].toUpperCase());\\n}\\n\\n// src/dom-common.js\\nvar enviroment = {\\n\\tsetDeleteAttr,\\n\\tssr: \\\"\\\",\\n\\tD: globalThis.document,\\n\\tF: globalThis.DocumentFragment,\\n\\tH: globalThis.HTMLElement,\\n\\tS: globalThis.SVGElement,\\n\\tM: globalThis.MutationObserver\\n};\\nfunction setDeleteAttr(obj, prop, val) {\\n\\tReflect.set(obj, prop, val);\\n\\tif (!isUndef(val)) return;\\n\\tReflect.deleteProperty(obj, prop);\\n\\tif (obj instanceof enviroment.H && obj.getAttribute(prop) === \\\"undefined\\\")\\n\\t\\treturn obj.removeAttribute(prop);\\n\\tif (Reflect.get(obj, prop) === \\\"undefined\\\")\\n\\t\\treturn Reflect.set(obj, prop, \\\"\\\");\\n}\\nvar keyLTE = \\\"__dde_lifecyclesToEvents\\\";\\nvar evc = \\\"dde:connected\\\";\\nvar evd = \\\"dde:disconnected\\\";\\nvar eva = \\\"dde:attributeChanged\\\";\\n\\n// src/dom.js\\nvar scopes = [{\\n\\tget scope() {\\n\\t\\treturn enviroment.D.body;\\n\\t},\\n\\thost: (c) => c ? c(enviroment.D.body) : enviroment.D.body,\\n\\tprevent: true\\n}];\\nvar scope = {\\n\\tget current() {\\n\\t\\treturn scopes[scopes.length - 1];\\n\\t},\\n\\tget host() {\\n\\t\\treturn this.current.host;\\n\\t},\\n\\tpreventDefault() {\\n\\t\\tconst { current } = this;\\n\\t\\tcurrent.prevent = true;\\n\\t\\treturn current;
2024-06-07 16:14:15 +02:00
customElementRender,
customElementWithDDE,
observedAttributes,
el, on, scope
} from "./esm-with-signals.js";
import { S } from "./esm-with-signals.js";
export class HTMLCustomElement extends HTMLElement{
static tagName= "custom-element";
static observedAttributes= [ "attr" ];
connectedCallback(){
console.log(observedAttributes(this));
customElementRender(
this,
this.attachShadow({ mode: "open" }),
ddeComponent,
S.observedAttributes
);
}
set attr(value){ this.setAttribute("attr", value); }
get attr(){ return this.getAttribute("attr"); }
}
/** @param {{ attr: ddeSignal&lt;string, {}&gt; }} props */
function ddeComponent({ attr }){
scope.host(
on.connected(e=&gt; console.log(e.target.outerHTML)),
);
return el().append(
el("p", S(()=&gt; `Hello from Custom Element with attribute '${attr()}'`))
);
}
customElementWithDDE(HTMLCustomElement);
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
document.body.append(
el(HTMLCustomElement.tagName, { attr: "Attribute" })
);
setTimeout(
()=&gt; document.querySelector(HTMLCustomElement.tagName).setAttribute("attr", "New Value"),
3*750
);
</code></div><script>Flems(document.getElementById("code-example-1-u3dl2tjmoj4"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import {\\n\\tcustomElementRender,\\n\\tcustomElementWithDDE,\\n\\tobservedAttributes,\\n\\tel, on, scope \\n} from \\\"./esm-with-signals.js\\\";\\nimport { S } from \\\"./esm-with-signals.js\\\";\\nexport class HTMLCustomElement extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element\\\";\\n\\tstatic observedAttributes= [ \\\"attr\\\" ];\\n\\tconnectedCallback(){\\n\\t\\tconsole.log(observedAttributes(this));\\n\\t\\tcustomElementRender(\\n\\t\\t\\tthis,\\n\\t\\t\\tthis.attachShadow({ mode: \\\"open\\\" }),\\n\\t\\t\\tddeComponent,\\n\\t\\t\\tS.observedAttributes\\n\\t\\t);\\n\\t}\\n\\tset attr(value){ this.setAttribute(\\\"attr\\\", value); }\\n\\tget attr(){ return this.getAttribute(\\\"attr\\\"); }\\n}\\n\\n/** @param {{ attr: ddeSignal<string, {}> }} props */\\nfunction ddeComponent({ attr }){\\n\\tscope.host(\\n\\t\\ton.connected(e=> console.log(e.target.outerHTML)),\\n\\t);\\n\\treturn el().append(\\n\\t\\tel(\\\"p\\\", S(()=> `Hello from Custom Element with attribute '${attr()}'`))\\n\\t);\\n}\\ncustomElementWithDDE(HTMLCustomElement);\\ncustomElements.define(HTMLCustomElement.tagName, HTMLCustomElement);\\n\\ndocument.body.append(\\n\\tel(HTMLCustomElement.tagName, { attr: \\\"Attribute\\\" })\\n);\\nsetTimeout(\\n\\t()=> document.querySelector(HTMLCustomElement.tagName).setAttribute(\\\"attr\\\", \\\"New Value\\\"),\\n\\t3*750\\n);\\n\"},{\"name\":\"esm-with-signals.js\",\"content\":\"// src/signals-common.js\\nvar signals_global = {\\n\\tisSignal(attributes) {\\n\\t\\treturn false;\\n\\t},\\n\\tprocessReactiveAttribute(obj, key, attr, set) {\\n\\t\\treturn attr;\\n\\t}\\n};\\nfunction registerReactivity(def, global = true) {\\n\\tif (global) return Object.assign(signals_global, def);\\n\\tObject.setPrototypeOf(def, signals_global);\\n\\treturn def;\\n}\\nfunction signals(_this) {\\n\\treturn signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;\\n}\\n\\n// src/helpers.js\\nvar hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);\\nfunction isUndef(value) {\\n\\treturn typeof value === \\\"undefined\\\";\\n}\\nfunction typeOf(v) {\\n\\tconst t = typeof v;\\n\\tif (t !== \\\"object\\\") return t;\\n\\tif (v === null) return \\\"null\\\";\\n\\treturn Object.prototype.toString.call(v);\\n}\\nfunction onAbort(signal2, listener) {\\n\\tif (!signal2 || !(signal2 instanceof AbortSignal))\\n\\t\\treturn true;\\n\\tif (signal2.aborted)\\n\\t\\treturn;\\n\\tsignal2.addEventListener(\\\"abort\\\", listener);\\n\\treturn function cleanUp() {\\n\\t\\tsignal2.removeEventListener(\\\"abort\\\", listener);\\n\\t};\\n}\\nfunction observedAttributes(instance, observedAttribute2) {\\n\\tconst { observedAttributes: observedAttributes3 = [] } = instance.constructor;\\n\\treturn observedAttributes3.reduce(function(out, name) {\\n\\t\\tout[kebabToCamel(name)] = observedAttribute2(instance, name);\\n\\t\\treturn out;\\n\\t}, {});\\n}\\nfunction kebabToCamel(name) {\\n\\treturn name.replace(/-./g, (x) => x[1].toUpperCase());\\n}\\n\\n// src/dom-common.js\\nvar enviroment = {\\n\\tsetDeleteAttr,\\n\\tssr: \\\"\\\",\\n\\tD: globalThis.document,\\n\\tF: globalThis.DocumentFragment,\\n\\tH: globalThis.HTMLElement,\\n\\tS: globalThis.SVGElement,\\n\\tM: globalThis.MutationObserver\\n};\\nfunction setDeleteAttr(obj, prop, val) {\\n\\tReflect.set(obj, prop, val);\\n\\tif (!isUndef(val)) return;\\n\\tReflect.deleteProperty(obj, prop);\\n\\tif (obj instanceof enviroment.H && obj.getAttribute(prop) === \\\"undefined\\\")\\n\\t\\treturn obj.removeAttribute(prop);\\n\\tif (Reflect.get(obj, prop) === \\\"undefined\\\")\\n\\t\\treturn Reflect.set(obj, prop, \\\"\\\");\\n}\\nvar keyLTE = \\\"__dde_lifecyclesToEvents\\\";\\nvar evc = \\\"dde:connected\\\";\\nvar evd = \\\"dde:disconnected\\\";\\nvar eva = \\\"dde:attributeChanged\\\";\\n\\n// src/dom.js\\nvar scopes = [{\\n\\tget scope() {\\n\\t\\treturn enviroment.D.body;\\n\\t},\\n\\thost: (c) => c ? c(enviromen
2024-10-18 15:28:33 +02:00
el,
customElementRender,
customElementWithDDE,
} from "./esm-with-signals.js";
function ddeComponent(){
return el().append(
el("style", `
.red{ color: firebrick; }
`),
2024-10-18 15:28:33 +02:00
el("p", { className: "red" }).append(
"Hello from ", el("slot", "Custom Element"), "!"
)
);
}
export class A extends HTMLElement{
static tagName= "custom-element-without";
connectedCallback(){
customElementRender(
this,
this,
ddeComponent
);
}
}
customElementWithDDE(A);
customElements.define(A.tagName, A);
export class B extends HTMLElement{
static tagName= "custom-element-open";
connectedCallback(){
customElementRender(
this,
this.attachShadow({ mode: "open" }),
ddeComponent
);
}
}
customElementWithDDE(B);
customElements.define(B.tagName, B);
export class C extends HTMLElement{
static tagName= "custom-element-closed";
connectedCallback(){
customElementRender(
this,
this.attachShadow({ mode: "closed" }),
ddeComponent
);
}
}
customElementWithDDE(C);
customElements.define(C.tagName, C);
document.body.append(
el(A.tagName).append("Without shadowRoot"),
el("hr"),
el(B.tagName).append("Open shadowRoot"),
el("hr"),
el(C.tagName).append("Closed shadowRoot"),
el("style", `
.red{ color: crimson; }
`),
2024-10-18 15:28:33 +02:00
);
console.log(A.tagName, "expect modifications");
document.body.querySelector(A.tagName).querySelector("p").textContent+= " (editable with JS)";
console.log(B.tagName, "expect modifications");
document.body.querySelector(B.tagName).shadowRoot.querySelector("p").textContent+= " (editable with JS)";
console.log(C.tagName, "expect error ↓");
document.body.querySelector(C.tagName).querySelector("p").textContent+= " (editable with JS)";
</code></div><script>Flems(document.getElementById("code-example-1-1uj2c0nml4gw"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import {\\n\\tel,\\n\\tcustomElementRender,\\n\\tcustomElementWithDDE,\\n} from \\\"./esm-with-signals.js\\\";\\nfunction ddeComponent(){\\n\\treturn el().append(\\n\\t\\tel(\\\"style\\\", `\\n\\t\\t\\t.red{ color: firebrick; }\\n\\t\\t`),\\n\\t\\tel(\\\"p\\\", { className: \\\"red\\\" }).append(\\n\\t\\t\\t\\\"Hello from \\\", el(\\\"slot\\\", \\\"Custom Element\\\"), \\\"!\\\"\\n\\t\\t)\\n\\t);\\n}\\n\\nexport class A extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element-without\\\";\\n\\tconnectedCallback(){\\n\\t\\tcustomElementRender(\\n\\t\\t\\tthis,\\n\\t\\t\\tthis,\\n\\t\\t\\tddeComponent\\n\\t\\t);\\n\\t}\\n}\\ncustomElementWithDDE(A);\\ncustomElements.define(A.tagName, A);\\nexport class B extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element-open\\\";\\n\\tconnectedCallback(){\\n\\t\\tcustomElementRender(\\n\\t\\t\\tthis,\\n\\t\\t\\tthis.attachShadow({ mode: \\\"open\\\" }),\\n\\t\\t\\tddeComponent\\n\\t\\t);\\n\\t}\\n}\\ncustomElementWithDDE(B);\\ncustomElements.define(B.tagName, B);\\nexport class C extends HTMLElement{\\n\\tstatic tagName= \\\"custom-element-closed\\\";\\n\\tconnectedCallback(){\\n\\t\\tcustomElementRender(\\n\\t\\t\\tthis,\\n\\t\\t\\tthis.attachShadow({ mode: \\\"closed\\\" }),\\n\\t\\t\\tddeComponent\\n\\t\\t);\\n\\t}\\n}\\ncustomElementWithDDE(C);\\ncustomElements.define(C.tagName, C);\\n\\ndocument.body.append(\\n\\tel(A.tagName).append(\\\"Without shadowRoot\\\"),\\n\\tel(\\\"hr\\\"),\\n\\tel(B.tagName).append(\\\"Open shadowRoot\\\"),\\n\\tel(\\\"hr\\\"),\\n\\tel(C.tagName).append(\\\"Closed shadowRoot\\\"),\\n\\tel(\\\"style\\\", `\\n\\t\\t.red{ color: crimson; }\\n\\t`),\\n);\\nconsole.log(A.tagName, \\\"expect modifications\\\");\\ndocument.body.querySelector(A.tagName).querySelector(\\\"p\\\").textContent+= \\\" (editable with JS)\\\";\\nconsole.log(B.tagName, \\\"expect modifications\\\");\\ndocument.body.querySelector(B.tagName).shadowRoot.querySelector(\\\"p\\\").textContent+= \\\" (editable with JS)\\\";\\nconsole.log(C.tagName, \\\"expect error \\\");\\ndocument.body.querySelector(C.tagName).querySelector(\\\"p\\\").textContent+= \\\" (editable with JS)\\\";\\n\"},{\"name\":\"esm-with-signals.js\",\"content\":\"// src/signals-common.js\\nvar signals_global = {\\n\\tisSignal(attributes) {\\n\\t\\treturn false;\\n\\t},\\n\\tprocessReactiveAttribute(obj, key, attr, set) {\\n\\t\\treturn attr;\\n\\t}\\n};\\nfunction registerReactivity(def, global = true) {\\n\\tif (global) return Object.assign(signals_global, def);\\n\\tObject.setPrototypeOf(def, signals_global);\\n\\treturn def;\\n}\\nfunction signals(_this) {\\n\\treturn signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;\\n}\\n\\n// src/helpers.js\\nvar hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);\\nfunction isUndef(value) {\\n\\treturn typeof value === \\\"undefined\\\";\\n}\\nfunction typeOf(v) {\\n\\tconst t = typeof v;\\n\\tif (t !== \\\"object\\\") return t;\\n\\tif (v === null) return \\\"null\\\";\\n\\treturn Object.prototype.toString.call(v);\\n}\\nfunction onAbort(signal2, listener) {\\n\\tif (!signal2 || !(signal2 instanceof AbortSignal))\\n\\t\\treturn true;\\n\\tif (signal2.aborted)\\n\\t\\treturn;\\n\\tsignal2.addEventListener(\\\"abort\\\", listener);\\n\\treturn function cleanUp() {\\n\\t\\tsignal2.removeEventListener(\\\"abort\\\", listener);\\n\\t};\\n}\\nfunction observedAttributes(instance, observedAttribute2) {\\n\\tconst { observedAttributes: observedAttributes3 = [] } = instance.constructor;\\n\\treturn observedAttributes3.reduce(function(out, name) {\\n\\t\\tout[kebabToCamel(name)] = observedAttribute2(instance, name);\\n\\t\\treturn out;\\n\\t}, {});\\n}\\nfunction kebabToCamel(name) {\\n\\treturn name.replace(/-./g, (x) => x[1].toUpperCase());\\n}\\n\\n// src/dom-common.js\\nvar enviroment = {\\n\\tsetDeleteAttr,\\n\\tssr: \\\"\\\",\\n\\tD: globalThis.document,\\n\\tF: globalThis.DocumentFragm
customElementRender,
customElementWithDDE,
el,
simulateSlots
} from "./esm-with-signals.js";
export class HTMLCustomElement extends HTMLElement{
static tagName= "custom-slotting";
connectedCallback(){
const c= ()=&gt; simulateSlots(this, ddeComponent());
customElementRender(this, this, c);
}
}
customElementWithDDE(HTMLCustomElement);
customElements.define(HTMLCustomElement.tagName, HTMLCustomElement);
document.body.append(
el(HTMLCustomElement.tagName),
el(HTMLCustomElement.tagName).append(
"Slot"
),
el(ddeComponentSlot),
el(ddeComponentSlot).append(
"Slot"
),
);
function ddeComponent(){
return el().append(
el("p").append(
"Hello ", el("slot", "World")
)
);
}
function ddeComponentSlot(){
return simulateSlots(el().append(
el("p").append(
"Hello ", el("slot", "World")
)
));
}
</code></div><script>Flems(document.getElementById("code-example-1-uk9zrdg1yps"), JSON.parse("{\"files\":[{\"name\":\".js\",\"content\":\"import {\\n\\tcustomElementRender,\\n\\tcustomElementWithDDE,\\n\\tel,\\n\\tsimulateSlots\\n} from \\\"./esm-with-signals.js\\\";\\nexport class HTMLCustomElement extends HTMLElement{\\n\\tstatic tagName= \\\"custom-slotting\\\";\\n\\tconnectedCallback(){\\n\\t\\tconst c= ()=> simulateSlots(this, ddeComponent());\\n\\t\\tcustomElementRender(this, this, c);\\n\\t}\\n}\\ncustomElementWithDDE(HTMLCustomElement);\\ncustomElements.define(HTMLCustomElement.tagName, HTMLCustomElement);\\n\\ndocument.body.append(\\n\\tel(HTMLCustomElement.tagName),\\n\\tel(HTMLCustomElement.tagName).append(\\n\\t\\t\\\"Slot\\\"\\n\\t),\\n\\tel(ddeComponentSlot),\\n\\tel(ddeComponentSlot).append(\\n\\t\\t\\\"Slot\\\"\\n\\t),\\n);\\n\\nfunction ddeComponent(){\\n\\treturn el().append(\\n\\t\\tel(\\\"p\\\").append(\\n\\t\\t\\t\\\"Hello \\\", el(\\\"slot\\\", \\\"World\\\")\\n\\t\\t)\\n\\t);\\n}\\nfunction ddeComponentSlot(){\\n\\treturn simulateSlots(el().append(\\n\\t\\tel(\\\"p\\\").append(\\n\\t\\t\\t\\\"Hello \\\", el(\\\"slot\\\", \\\"World\\\")\\n\\t\\t)\\n\\t));\\n}\\n\"},{\"name\":\"esm-with-signals.js\",\"content\":\"// src/signals-common.js\\nvar signals_global = {\\n\\tisSignal(attributes) {\\n\\t\\treturn false;\\n\\t},\\n\\tprocessReactiveAttribute(obj, key, attr, set) {\\n\\t\\treturn attr;\\n\\t}\\n};\\nfunction registerReactivity(def, global = true) {\\n\\tif (global) return Object.assign(signals_global, def);\\n\\tObject.setPrototypeOf(def, signals_global);\\n\\treturn def;\\n}\\nfunction signals(_this) {\\n\\treturn signals_global.isPrototypeOf(_this) && _this !== signals_global ? _this : signals_global;\\n}\\n\\n// src/helpers.js\\nvar hasOwn = (...a) => Object.prototype.hasOwnProperty.call(...a);\\nfunction isUndef(value) {\\n\\treturn typeof value === \\\"undefined\\\";\\n}\\nfunction typeOf(v) {\\n\\tconst t = typeof v;\\n\\tif (t !== \\\"object\\\") return t;\\n\\tif (v === null) return \\\"null\\\";\\n\\treturn Object.prototype.toString.call(v);\\n}\\nfunction onAbort(signal2, listener) {\\n\\tif (!signal2 || !(signal2 instanceof AbortSignal))\\n\\t\\treturn true;\\n\\tif (signal2.aborted)\\n\\t\\treturn;\\n\\tsignal2.addEventListener(\\\"abort\\\", listener);\\n\\treturn function cleanUp() {\\n\\t\\tsignal2.removeEventListener(\\\"abort\\\", listener);\\n\\t};\\n}\\nfunction observedAttributes(instance, observedAttribute2) {\\n\\tconst { observedAttributes: observedAttributes3 = [] } = instance.constructor;\\n\\treturn observedAttributes3.reduce(function(out, name) {\\n\\t\\tout[kebabToCamel(name)] = observedAttribute2(instance, name);\\n\\t\\treturn out;\\n\\t}, {});\\n}\\nfunction kebabToCamel(name) {\\n\\treturn name.replace(/-./g, (x) => x[1].toUpperCase());\\n}\\n\\n// src/dom-common.js\\nvar enviroment = {\\n\\tsetDeleteAttr,\\n\\tssr: \\\"\\\",\\n\\tD: globalThis.document,\\n\\tF: globalThis.DocumentFragment,\\n\\tH: globalThis.HTMLElement,\\n\\tS: globalThis.SVGElement,\\n\\tM: globalThis.MutationObserver\\n};\\nfunction setDeleteAttr(obj, prop, val) {\\n\\tReflect.set(obj, prop, val);\\n\\tif (!isUndef(val)) return;\\n\\tReflect.deleteProperty(obj, prop);\\n\\tif (obj instanceof enviroment.H && obj.getAttribute(prop) === \\\"undefined\\\")\\n\\t\\treturn obj.removeAttribute(prop);\\n\\tif (Reflect.get(obj, prop) === \\\"undefined\\\")\\n\\t\\treturn Reflect.set(obj, prop, \\\"\\\");\\n}\\nvar keyLTE = \\\"__dde_lifecyclesToEvents\\\";\\nvar evc = \\\"dde:connected\\\";\\nvar evd = \\\"dde:disconnected\\\";\\nvar eva = \\\"dde:attributeChanged\\\";\\n\\n// src/dom.js\\nvar scopes = [{\\n\\tget scope() {\\n\\t\\treturn enviroment.D.body;\\n\\t},\\n\\thost: (c) => c ? c(enviroment.D.body) : enviroment.D.body,\\n\\tprevent: true\\n}];\\nvar scope = {\\n\\tget current() {\\n\\t\\treturn scopes[scopes.length - 1];\\n\\t},\\n\\tget host() {\\n\\t\\treturn this.current.host;\\n\\t},\\n\\tpreventDefault() {\\n\\t\\tconst { current } = this;\\n\\t\\tcurrent.prevent = true;\\n\\t\\treturn