1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-30 23:30:16 +02:00

🐛 finalizing WC + simulateSlots

This commit is contained in:
2024-11-07 10:17:54 +01:00
parent 969dfc5ee2
commit 8201c3dbbf
22 changed files with 2569 additions and 1755 deletions

View File

@@ -14,7 +14,8 @@ ${host}{
--shiki-token-punctuation: var(--code);
--shiki-token-link: #EE0000;
white-space: pre;
tab-size: 2;${""/* TODO: allow custom tab size?! */}
${""/* TODO: allow custom tab size?! */}
tab-size: 2;
overflow: scroll;
}
${host}[data-js=todo]{

View File

@@ -5,6 +5,9 @@ import {
} from "deka-dom-el";
function ddeComponent(){
return el().append(
el("style", `
.red{ color: firebrick; }
`),
el("p", { className: "red" }).append(
"Hello from ", el("slot", "Custom Element"), "!"
)
@@ -49,12 +52,18 @@ customElementWithDDE(C);
customElements.define(C.tagName, C);
document.body.append(
el("style", `
.red{ color: red; }
`),
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; }
`),
);
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)";

View File

@@ -0,0 +1,41 @@
import {
customElementRender,
customElementWithDDE,
el,
simulateSlots
} from "deka-dom-el";
export class HTMLCustomElement extends HTMLElement{
static tagName= "custom-slotting";
connectedCallback(){
const c= ()=> 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")
)
));
}

View File

@@ -17,6 +17,12 @@ export function mnemonic(){
),
el("li").append(
el("code", "lifecyclesToEvents(<class-declaration>)"), " — convert lifecycle methods to events, can be also used as decorator",
)
),
el("li").append(
el("code", "simulateSlots(<class-instance>, <body>[, <mapper>])"), " — simulate slots for Custom Elements without shadow DOM",
),
el("li").append(
el("code", "simulateSlots(<dde-component>[, <mapper>])"), " — simulate slots for “dde”/functional components",
),
);
}

View File

@@ -38,6 +38,11 @@ const references= {
title: t`MDN documentation page for Shadow DOM`,
href: "https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM",
},
/** Shallow DOM on mdn */
mdn_shadow_dom_slot: {
title: t`MDN documentation page for <slot>`,
href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot",
},
/** Shallow DOM */
shadow_dom_depth: {
title: t`Everything you need to know about Shadow DOM (github repo praveenpuglia/shadow-dom-in-depth)`,
@@ -50,7 +55,7 @@ export function page({ pkg, info }){
return el(simplePage, { info, pkg }).append(
el("h2", t`Using web components in combinantion with DDE`),
el("p").append(...T`
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong", "Web Components") )}
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong", t`Web Components`) )}
for dom-tree generation. However, in order to be able to use signals (possibly mapping to registered
${el("a", references.mdn_observedAttributes).append( el("code", "observedAttributes") )}) and additional
functionality is (unfortunately) required to use helpers provided by the library.
@@ -58,17 +63,22 @@ export function page({ pkg, info }){
el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
el(h3, t`Custom Elements Introduction`),
el("p").append(...T`
Web Components, specifically Custom Elements, are a set of web platform APIs that allow you to create
new HTML tags with custom functionality encapsulated within them. This allows for the creation of reusable
components that can be used across web applications.
`),
el("p").append(...T`
To start with, lets see how to use native Custom Elements. As starting point please read
${el("a", references.mdn_custom_elements).append( el("strong", "Using Custom Elements"), " on MDN" )}.
${el("a", references.mdn_custom_elements).append( el("strong", t`Using Custom Elements`), t` on MDN` )}.
To sum up and for mnemonic see following code overview:
`),
el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }),
el("p").append(...T`
For more advanced use of Custom Elements, the summary ${el("a", references.custom_elements_tips)
.append( el("strong", t`Handy Custom Elements' Patterns`) )} may be useful. Especially pay attention to
.append( el("strong", t`Handy Custom Elements Patterns`) )} 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 (${el("code", "el(HTMLCustomElement.tagName, { customAttribute: \"new-value\" });")}).
the library (${el("code", `el(HTMLCustomElement.tagName, { customAttribute: "${t`new-value`}" });`)}).
`),
el("p").append(...T`
Also see the Life Cycle Events sections, very similarly we would like to use
@@ -96,12 +106,38 @@ export function page({ pkg, info }){
el(h3, t`Shadow DOM`),
el("p").append(...T`
Regarding to ${el("code", "this.attachShadow({ mode: 'open' })")} see quick overview
${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}. An another source of
information can be ${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}. To
sum up, there in basic three ways to render component body:
Shadow DOM is a web platform feature that allows for the encapsulation of a components internal DOM tree
from the rest of the document. This means that styles and scripts applied to the document will not affect
the components internal DOM, and vice versa.
`),
el(example, { src: fileURL("./components/examples/customElement/shadowRoot.js"), page_id }),
el("p").append(...T`
Regarding to ${el("code", "this.attachShadow({ mode: 'open' })")} see quick overview
${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}. An another source of
information can be ${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}.
`),
el("p").append(...T`
Besides the encapsulation, the Shadow DOM allows for using the ${el("a", references.mdn_shadow_dom_slot).append(
el("strong", t`<slot>`), t` element(s)`)}. You can simulate this feature using ${el("code", "simulateSlots")}:
`),
el(example, { src: fileURL("./components/examples/customElement/simulateSlots.js"), page_id }),
el("p").append(...T`
To sum up:
`),
el("ul").append(
el("li").append(...T`
The use of shadow DOM to encapsulate the internal structure of the custom element, which affects how
the custom element can be styled and modified using JavaScript and CSS.
`),
el("li").append(...T`
The ability to access and modify the internal structure of the custom element using JavaScript, which
is affected by the use of shadow DOM and the mode of the shadow DOM.
`),
el("li").append(...T`
The use of slots to allow for the insertion of content from the parent document into the custom
element, which is affected by the use of shadow DOM and the mode of the shadow DOM.
`),
),
el(mnemonic)
);