2024-06-03 16:20:42 +02:00
|
|
|
|
import { T, t } from "./utils/index.js";
|
2024-05-22 21:43:49 +02:00
|
|
|
|
export const info= {
|
2024-06-04 16:00:37 +02:00
|
|
|
|
title: t`Web Components`,
|
2024-06-03 16:20:42 +02:00
|
|
|
|
description: t`Using custom elements in combinantion with DDE`,
|
2024-05-22 21:43:49 +02:00
|
|
|
|
};
|
2024-01-09 21:18:43 +01:00
|
|
|
|
|
|
|
|
|
import { el } from "deka-dom-el";
|
2024-05-22 21:43:49 +02:00
|
|
|
|
import { simplePage } from "./layout/simplePage.html.js";
|
2024-01-09 21:18:43 +01:00
|
|
|
|
import { example } from "./components/example.html.js";
|
|
|
|
|
import { h3 } from "./components/pageUtils.html.js";
|
|
|
|
|
import { mnemonic } from "./components/mnemonic/customElement-init.js";
|
|
|
|
|
import { code } from "./components/code.html.js";
|
|
|
|
|
/** @param {string} url */
|
|
|
|
|
const fileURL= url=> new URL(url, import.meta.url);
|
2024-05-31 14:14:48 +02:00
|
|
|
|
const references= {
|
2024-06-04 16:09:50 +02:00
|
|
|
|
/** Web Components on MDN */
|
|
|
|
|
mdn_web_components: {
|
2024-06-04 16:00:37 +02:00
|
|
|
|
title: t`MDN documentation page for Web Components`,
|
|
|
|
|
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components",
|
|
|
|
|
},
|
2024-06-04 16:09:50 +02:00
|
|
|
|
/** observedAttributes on MDN */
|
|
|
|
|
mdn_observedAttributes: {
|
2024-06-04 16:00:37 +02:00
|
|
|
|
title: t`MDN documentation page for observedAttributes`,
|
|
|
|
|
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#responding_to_attribute_changes",
|
|
|
|
|
},
|
2024-06-04 16:09:50 +02:00
|
|
|
|
/** Custom Elements on MDN */
|
|
|
|
|
mdn_custom_elements: {
|
2024-06-03 16:20:42 +02:00
|
|
|
|
title: t`MDN documentation page for Custom Elements`,
|
2024-05-31 14:14:48 +02:00
|
|
|
|
href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements",
|
|
|
|
|
},
|
2024-06-04 16:09:50 +02:00
|
|
|
|
/** Custom Elements tips from WebReflection */
|
|
|
|
|
custom_elements_tips: {
|
2024-06-03 16:20:42 +02:00
|
|
|
|
title: t`Ideas and tips from WebReflection`,
|
2024-05-31 14:14:48 +02:00
|
|
|
|
href: "https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4",
|
2024-06-10 15:52:47 +02:00
|
|
|
|
},
|
|
|
|
|
/** Shallow DOM on mdn */
|
|
|
|
|
mdn_shadow_dom_depth: {
|
|
|
|
|
title: t`MDN documentation page for Shadow DOM`,
|
|
|
|
|
href: "https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM",
|
|
|
|
|
},
|
2024-11-07 10:17:54 +01:00
|
|
|
|
/** 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",
|
|
|
|
|
},
|
2024-06-10 15:52:47 +02:00
|
|
|
|
/** Shallow DOM */
|
|
|
|
|
shadow_dom_depth: {
|
|
|
|
|
title: t`Everything you need to know about Shadow DOM (github repo praveenpuglia/shadow-dom-in-depth)`,
|
|
|
|
|
href: "https://github.com/praveenpuglia/shadow-dom-in-depth",
|
|
|
|
|
},
|
2024-05-31 14:14:48 +02:00
|
|
|
|
};
|
2024-01-09 21:18:43 +01:00
|
|
|
|
/** @param {import("./types.d.ts").PageAttrs} attrs */
|
|
|
|
|
export function page({ pkg, info }){
|
|
|
|
|
const page_id= info.id;
|
|
|
|
|
return el(simplePage, { info, pkg }).append(
|
2024-06-04 16:00:37 +02:00
|
|
|
|
el("h2", t`Using web components in combinantion with DDE`),
|
2024-06-03 16:20:42 +02:00
|
|
|
|
el("p").append(...T`
|
2024-11-07 10:17:54 +01:00
|
|
|
|
The DDE library allows for use within ${el("a", references.mdn_web_components).append( el("strong", t`Web Components`) )}
|
2024-06-04 16:00:37 +02:00
|
|
|
|
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.
|
2024-06-03 16:20:42 +02:00
|
|
|
|
`),
|
2024-01-09 21:18:43 +01:00
|
|
|
|
el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
|
|
|
|
|
|
2024-06-03 16:20:42 +02:00
|
|
|
|
el(h3, t`Custom Elements Introduction`),
|
2024-11-07 10:17:54 +01:00
|
|
|
|
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.
|
|
|
|
|
`),
|
2024-06-03 16:20:42 +02:00
|
|
|
|
el("p").append(...T`
|
2024-06-04 16:00:37 +02:00
|
|
|
|
To start with, let’s see how to use native Custom Elements. As starting point please read
|
2024-11-07 10:17:54 +01:00
|
|
|
|
${el("a", references.mdn_custom_elements).append( el("strong", t`Using Custom Elements`), t` on MDN` )}.
|
2024-06-04 16:00:37 +02:00
|
|
|
|
To sum up and for mnemonic see following code overview:
|
2024-06-03 16:20:42 +02:00
|
|
|
|
`),
|
2024-01-09 21:18:43 +01:00
|
|
|
|
el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }),
|
2024-06-03 16:20:42 +02:00
|
|
|
|
el("p").append(...T`
|
2024-06-04 16:00:37 +02:00
|
|
|
|
For more advanced use of Custom Elements, the summary ${el("a", references.custom_elements_tips)
|
2024-11-07 10:17:54 +01:00
|
|
|
|
.append( el("strong", t`Handy Custom Elements Patterns`) )} may be useful. Especially pay attention to
|
2024-06-04 16:00:37 +02:00
|
|
|
|
linking HTML attributes and defining setters/getters, this is very helpful to use in combination with
|
2024-11-07 10:17:54 +01:00
|
|
|
|
the library (${el("code", `el(HTMLCustomElement.tagName, { customAttribute: "${t`new-value`}" });`)}).
|
2024-06-03 16:20:42 +02:00
|
|
|
|
`),
|
2024-06-05 16:20:12 +02:00
|
|
|
|
el("p").append(...T`
|
|
|
|
|
Also see the Life Cycle Events sections, very similarly we would like to use
|
|
|
|
|
${el("a", { textContent: t`DDE events`, href: "./p03-events.html", title: t`See events part of the library documentation` })}.
|
|
|
|
|
To do it, the library provides function ${el("code", "customElementWithDDE")}…
|
|
|
|
|
`),
|
|
|
|
|
el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
|
|
|
|
|
|
|
|
|
|
el("h3", t`Custom Elements with DDE`),
|
2024-06-07 10:04:34 +02:00
|
|
|
|
el("p").append(...T`
|
|
|
|
|
The ${el("code", "customElementWithDDE")} function is only (small) part of the inregration of the library.
|
|
|
|
|
More important for coexistence is render component function as a body of the Custom Element. For that, you
|
|
|
|
|
can use ${el("code", "customElementRender")} with arguments instance reference, target for connection,
|
|
|
|
|
render function and optional properties (will be passed to the render function) see later…
|
|
|
|
|
`),
|
2024-06-05 16:20:12 +02:00
|
|
|
|
el(example, { src: fileURL("./components/examples/customElement/dde.js"), page_id }),
|
2024-06-07 10:04:34 +02:00
|
|
|
|
el("p").append(...T`
|
2024-06-07 14:38:38 +02:00
|
|
|
|
…as you can see, you can use components created based on the documentation previously introduced. To unlock
|
|
|
|
|
full potential, use with combination ${el("code", "customElementWithDDE")} (allows to use livecycle events)
|
|
|
|
|
and ${el("code", "observedAttributes")} (converts attributes to render function arguments —
|
|
|
|
|
${el("em", "default")}) or ${el("code", "S.observedAttributes")} (converts attributes to signals).
|
2024-06-07 10:04:34 +02:00
|
|
|
|
`),
|
2024-06-07 16:14:15 +02:00
|
|
|
|
el(example, { src: fileURL("./components/examples/customElement/observedAttributes.js"), page_id }),
|
2024-06-05 16:20:12 +02:00
|
|
|
|
|
2024-01-09 21:18:43 +01:00
|
|
|
|
|
2024-06-10 15:52:47 +02:00
|
|
|
|
el(h3, t`Shadow DOM`),
|
2024-11-07 10:17:54 +01:00
|
|
|
|
el("p").append(...T`
|
|
|
|
|
Shadow DOM is a web platform feature that allows for the encapsulation of a component’s internal DOM tree
|
|
|
|
|
from the rest of the document. This means that styles and scripts applied to the document will not affect
|
|
|
|
|
the component’s internal DOM, and vice versa.
|
|
|
|
|
`),
|
|
|
|
|
el(example, { src: fileURL("./components/examples/customElement/shadowRoot.js"), page_id }),
|
2024-06-10 15:52:47 +02:00
|
|
|
|
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
|
2024-11-07 10:17:54 +01:00
|
|
|
|
information can be ${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}.
|
2024-06-10 15:52:47 +02:00
|
|
|
|
`),
|
2024-11-07 10:17:54 +01:00
|
|
|
|
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.
|
|
|
|
|
`),
|
|
|
|
|
),
|
2024-06-10 15:52:47 +02:00
|
|
|
|
|
2024-01-09 21:18:43 +01:00
|
|
|
|
el(mnemonic)
|
|
|
|
|
);
|
|
|
|
|
}
|