mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-11-04 07:09:15 +01:00 
			
		
		
		
	🔤 ⚡ T now uses DocumentFragment
This commit is contained in:
		@@ -27,7 +27,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Welcome to Deka DOM Elements (dd<el> or DDE) — a lightweight library for building dynamic UIs with
 | 
			
		||||
			a declarative syntax that stays close to the native DOM API. dd<el> gives you powerful reactive tools
 | 
			
		||||
			without the complexity and overhead of larger frameworks.
 | 
			
		||||
@@ -45,7 +45,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/introducing/helloWorld.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, { textContent: t`The 3PS Pattern: A Better Way to Build UIs`, id: "h-3ps" }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			At the heart of dd<el> is the 3PS (3-Part Separation) pattern. This simple yet powerful approach helps you
 | 
			
		||||
			organize your UI code into three distinct areas, making your applications more maintainable and easier
 | 
			
		||||
			to reason about.
 | 
			
		||||
@@ -62,22 +62,22 @@ export function page({ pkg, info }){
 | 
			
		||||
				)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The 3PS pattern separates your code into three clear parts:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Create State")}: Define your application’s reactive data using signals
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Bind to Elements")}: Define how UI elements react to state changes
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Update State")}: Modify state in response to user events or other triggers
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			By separating these concerns, your code becomes more modular, testable, and easier to maintain. This
 | 
			
		||||
			approach shares principles with more formal patterns like ${el("a", { textContent: "MVVM",
 | 
			
		||||
				...references.w_mvv })} and ${el("a", { textContent: "MVC", ...references.w_mvc })}, but with less
 | 
			
		||||
@@ -85,7 +85,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				The 3PS pattern becomes especially powerful when combined with components, allowing you to create
 | 
			
		||||
				reusable pieces of UI with encapsulated state and behavior. You’ll learn more about this in the
 | 
			
		||||
				following sections.
 | 
			
		||||
@@ -93,36 +93,36 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`How to Use This Documentation`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This guide will take you through dd<el>’s features step by step:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol", { start: 2 }).append(
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p02-elements.html" }).append(el("strong", "Elements"))} — Creating
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p02-elements.html" }).append(el("strong", "Elements"))} — Creating
 | 
			
		||||
				and manipulating DOM elements`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p03-events.html" }).append(el("strong", "Events and Addons"))} —
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p03-events.html" }).append(el("strong", "Events and Addons"))} —
 | 
			
		||||
				Handling user interactions and lifecycle events`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p04-signals.html" }).append(el("strong", "Signals"))} — Adding
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p04-signals.html" }).append(el("strong", "Signals"))} — Adding
 | 
			
		||||
				reactivity to your UI`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p05-scopes.html" }).append(el("strong", "Scopes"))} — Managing
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p05-scopes.html" }).append(el("strong", "Scopes"))} — Managing
 | 
			
		||||
				component lifecycles`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p06-customElement.html" }).append(el("strong", "Web Components"))} —
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p06-customElement.html" }).append(el("strong", "Web Components"))} —
 | 
			
		||||
				Building native custom elements`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p07-debugging.html" }).append(el("strong", "Debugging"))} — Tools to
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p07-debugging.html" }).append(el("strong", "Debugging"))} — Tools to
 | 
			
		||||
				help you build and fix your apps`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p08-extensions.html" }).append(el("strong", "Extensions"))} —
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p08-extensions.html" }).append(el("strong", "Extensions"))} —
 | 
			
		||||
				Integrating third-party functionalities`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p09-optimization.html" })
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p09-optimization.html" })
 | 
			
		||||
					.append(el("strong", "Performance Optimization"))} — Techniques for optimizing your applications`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p10-todomvc.html" }).append(el("strong", "TodoMVC"))} — A real-world
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p10-todomvc.html" }).append(el("strong", "TodoMVC"))} — A real-world
 | 
			
		||||
				application implementation`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p11-ssr.html" }).append(el("strong", "SSR"))} — Server-side
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p11-ssr.html" }).append(el("strong", "SSR"))} — Server-side
 | 
			
		||||
				rendering with dd<el>`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p12-ireland.html" }).append(el("strong", "Ireland Components"))} —
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p12-ireland.html" }).append(el("strong", "Ireland Components"))} —
 | 
			
		||||
				Interactive demos with server-side pre-rendering`),
 | 
			
		||||
			el("li").append(...T`${el("a", { href: "p13-appendix.html" }).append(el("strong", "Appendix & Summary"))} —
 | 
			
		||||
			el("li").append(T`${el("a", { href: "p13-appendix.html" }).append(el("strong", "Appendix & Summary"))} —
 | 
			
		||||
				Comprehensive reference and best practices`),
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Each section builds on the previous ones, so we recommend following them in order.
 | 
			
		||||
			Let’s get started with the basics of creating elements!
 | 
			
		||||
		`),
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Building user interfaces in JavaScript often involves creating and manipulating DOM elements.
 | 
			
		||||
			dd<el> provides a simple yet powerful approach to element creation that is declarative, chainable,
 | 
			
		||||
			and maintains a clean syntax close to HTML structure.
 | 
			
		||||
@@ -68,7 +68,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/elements/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Creating Elements: Native vs dd<el>`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			In standard JavaScript, you create DOM elements using the
 | 
			
		||||
			${el("a", references.mdn_create).append(el("code", "document.createElement()"))} method
 | 
			
		||||
			and then set properties individually or with ${el("code", "Object.assign()")}:
 | 
			
		||||
@@ -85,14 +85,14 @@ export function page({ pkg, info }){
 | 
			
		||||
				)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "el")} function provides a simple wrapper around ${el("code", "document.createElement")}
 | 
			
		||||
			with enhanced property assignment.
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/elements/dekaCreateElement.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Advanced Property Assignment`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "assign")} function is the heart of dd<el>’s element property handling. It is internally
 | 
			
		||||
			used to assign properties using the ${el("code", "el")} function. ${el("code", "assign")} provides
 | 
			
		||||
			intelligent assignment of both ${el("a", { textContent: "properties (IDL)", ...references.mdn_idl })}
 | 
			
		||||
@@ -104,28 +104,28 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("dd", t`Prefers IDL properties, falls back to setAttribute() when no writable property exists`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Data and ARIA Attributes`),
 | 
			
		||||
				el("dd").append(...T`Both ${el("code", "dataset")}.* and ${el("code", "data-")}* syntaxes supported
 | 
			
		||||
				el("dd").append(T`Both ${el("code", "dataset")}.* and ${el("code", "data-")}* syntaxes supported
 | 
			
		||||
					(same for ${el("em", "ARIA")})`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Style Handling`),
 | 
			
		||||
				el("dd").append(...T`Accepts string or object notation for ${el("code", "style")} property`),
 | 
			
		||||
				el("dd").append(T`Accepts string or object notation for ${el("code", "style")} property`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Class Management`),
 | 
			
		||||
				el("dd").append(...T`Works with ${el("code", "className")}, ${el("code", "class")}, or ${el("code",
 | 
			
		||||
				el("dd").append(T`Works with ${el("code", "className")}, ${el("code", "class")}, or ${el("code",
 | 
			
		||||
					"classList")} object for toggling classes`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Force Modes`),
 | 
			
		||||
				el("dd").append(...T`Use ${el("code", "=")} prefix to force attribute mode, ${el("code", ".")} prefix to
 | 
			
		||||
				el("dd").append(T`Use ${el("code", "=")} prefix to force attribute mode, ${el("code", ".")} prefix to
 | 
			
		||||
					force property mode`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Attribute Removal`),
 | 
			
		||||
				el("dd").append(...T`Pass ${el("code", "undefined")} to remove a property or attribute`)
 | 
			
		||||
				el("dd").append(T`Pass ${el("code", "undefined")} to remove a property or attribute`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/elements/dekaAssign.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				You can explore standard HTML element properties in the MDN documentation for
 | 
			
		||||
				${el("a", { textContent: "HTMLElement", ...references.mdn_el })} (base class)
 | 
			
		||||
				and specific element interfaces like ${el("a", { textContent: "HTMLParagraphElement", ...references.mdn_p })}.
 | 
			
		||||
@@ -133,7 +133,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Building DOM Trees with Chainable Methods`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			One of the most powerful features of dd<el> is its approach to building element trees.
 | 
			
		||||
			Unlike the native DOM API which doesn’t return the parent after ${el("code", "append()")}, dd<el>’s
 | 
			
		||||
			${el("code", "append()")} always returns the parent element:
 | 
			
		||||
@@ -150,28 +150,28 @@ export function page({ pkg, info }){
 | 
			
		||||
				)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This chainable pattern is much cleaner and easier to follow, especially for deeply nested elements.
 | 
			
		||||
			It also makes it simple to add multiple children to a parent element in a single fluent expression.
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/elements/dekaAppend.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Using Components to Build UI Fragments`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "el")} function is overloaded to support both tag names and function components.
 | 
			
		||||
			This lets you refactor complex UI trees into reusable pieces:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/elements/dekaBasicComponent.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Component functions receive the properties object as their first argument, just like regular elements.
 | 
			
		||||
			This makes it easy to pass data down to components and create reusable UI fragments.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				It’s helpful to use naming conventions similar to native DOM elements for your components.
 | 
			
		||||
				This allows you to keeps your code consistent with the DOM API.
 | 
			
		||||
			`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Use ${el("a", { textContent: "destructuring assignment", ...references.mdn_destruct })}
 | 
			
		||||
				to extract the properties from the ${el("code", "props")} and pass them to the component element:
 | 
			
		||||
				${el("code", "function component({ className }){ return el(\"p\", { className }); }")} for make
 | 
			
		||||
@@ -180,29 +180,29 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Working with SVG and Other Namespaces`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For non-HTML elements like SVG, MathML, or custom namespaces, dd<el> provides the ${el("code", "elNS")}
 | 
			
		||||
			function which corresponds to the native ${el("a", references.mdn_ns).append(el("code",
 | 
			
		||||
				"document.createElementNS"))}:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/elements/dekaElNS.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This function returns a namespace-specific element creator, allowing you to work with any element type
 | 
			
		||||
			using the same consistent interface.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Declarative DOM Creation`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use component functions for reusable UI fragments:")} Extract common UI patterns
 | 
			
		||||
				into reusable functions that return elements.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Leverage destructuring for cleaner component code:")} Use
 | 
			
		||||
				${el("a", { textContent: "destructuring", ...references.mdn_destruct })} to extract properties
 | 
			
		||||
				from the props object for cleaner component code.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Leverage chainable methods for better performance:")} Use chainable methods
 | 
			
		||||
				${el("code", ".append()")} to build complex DOM trees for better performance and cleaner code.
 | 
			
		||||
			`),
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Events are at the core of interactive web applications. dd<el> provides a clean, declarative approach to
 | 
			
		||||
			handling DOM events and extends this pattern with a powerful Addon system to incorporate additional
 | 
			
		||||
			functionalities into your UI templates.
 | 
			
		||||
@@ -60,7 +60,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/events/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Events and Listeners: Two Approaches`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			In JavaScript you can listen to native DOM events using
 | 
			
		||||
			${el("a", references.mdn_listen).append(el("code", "element.addEventListener(type, listener, options)"))}.
 | 
			
		||||
			dd<el> provides an alternative approach with arguments ordered differently to better fit its declarative
 | 
			
		||||
@@ -78,7 +78,7 @@ export function page({ pkg, info }){
 | 
			
		||||
				)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The main benefit of dd<el>’s approach is that it works as an Addon (see below), making it easy to integrate
 | 
			
		||||
			directly into element declarations.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -86,13 +86,13 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Removing Event Listeners`),
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Unlike the native addEventListener/removeEventListener pattern, dd<el> uses the ${el("a", {
 | 
			
		||||
				textContent: "AbortSignal", ...references.mdn_abortListener })} for declarative approach for removal:
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/events/abortSignal.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This is the same for signals (see next section) and works well with scopes and library extendability (
 | 
			
		||||
			see scopes and extensions section).
 | 
			
		||||
		`),
 | 
			
		||||
@@ -102,7 +102,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("div", { className: "tab", dataTab: "html-attr" }).append(
 | 
			
		||||
				el("h4", t`HTML Attribute Style`),
 | 
			
		||||
				el(code, { src: fileURL("./components/examples/events/attribute-event.js"), page_id }),
 | 
			
		||||
				el("p").append(...T`
 | 
			
		||||
				el("p").append(T`
 | 
			
		||||
					Forces usage as an HTML attribute. Corresponds to
 | 
			
		||||
					${el("code", `<button onclick="console.log(event)">click me</button>`)}. This can be particularly
 | 
			
		||||
					useful for SSR scenarios.
 | 
			
		||||
@@ -119,13 +119,13 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("p", t`Uses the addon pattern (so adds the event listener to the element), see above.`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For a deeper comparison of these approaches, see
 | 
			
		||||
			${el("a", { textContent: "WebReflection’s detailed analysis", ...references.web_events })}.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Understanding Addons`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Addons are a powerful pattern in dd<el> that extends beyond just event handling.
 | 
			
		||||
			An Addon is any function that accepts an HTML element as its first parameter.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -139,22 +139,22 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("li", t`Capture element references`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			You can use Addons as ≥3rd argument of the ${el("code", "el")} function, making it possible to
 | 
			
		||||
			extend your templates with additional functionality:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/events/templateWithListeners.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			As the example shows, you can provide types in JSDoc+TypeScript using the global type
 | 
			
		||||
			${el("code", "ddeElementAddon")}. Notice how Addons can also be used to get element references.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Lifecycle Events`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Addons are called immediately when an element is created, even before it’s connected to the live DOM.
 | 
			
		||||
			You can think of an Addon as an "oncreate" event handler.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> provides two additional lifecycle events that correspond to ${el("a", { textContent:
 | 
			
		||||
				"custom element", ...references.mdn_customElements })} lifecycle callbacks:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -170,7 +170,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/events/live-cycle.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				For regular elements (non-custom elements), dd<el> uses ${el("a",
 | 
			
		||||
					references.mdn_mutation).append(el("code", "MutationObserver"), " | MDN")} internally to track
 | 
			
		||||
				lifecycle events.
 | 
			
		||||
@@ -179,28 +179,28 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "warning" }).append(
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					Always use ${el("code", "on.*")} functions as library must ensure proper (MutationObserver)
 | 
			
		||||
					registration, not ${el("code", "on('dde:*', ...)")}, even the native event system is used with event
 | 
			
		||||
					names prefixed with ${el("code", "dde:")}.
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					Use lifecycle events sparingly, as they require internal tracking
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					Leverage parent-child relationships: when a parent is removed, all children are also removed
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					…see section later in documentation regarding hosts elements
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					dd<el> ensures that connected/disconnected events fire only once for better predictability
 | 
			
		||||
				`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Dispatching Custom Events`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This makes it easy to implement component communication through events, following standard web platform
 | 
			
		||||
			patterns. The curried approach allows for easy reuse of event dispatchers throughout your application.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -209,17 +209,17 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Clean up listeners")}: Use AbortSignal to prevent memory leaks
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Leverage lifecycle events")}: For component setup and teardown
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Delegate when possible")}: Add listeners to container elements when handling many
 | 
			
		||||
				similar elements
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Maintain consistency")}: Choose one event binding approach and stick with it
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals provide a simple yet powerful way to create reactive applications with dd<el>. They handle the
 | 
			
		||||
			fundamental challenge of keeping your UI in sync with changing data in a declarative, efficient way.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -55,13 +55,13 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("li", t`Automatic UI updates when data changes`),
 | 
			
		||||
				el("li", t`Clean separation between data, logic, and UI`),
 | 
			
		||||
				el("li", t`Small runtime with minimal overhead`),
 | 
			
		||||
				el("li").append(...T`${el("strong", "In future")} no dependencies or framework lock-in`)
 | 
			
		||||
				el("li").append(T`${el("strong", "In future")} no dependencies or framework lock-in`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/signals/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`The 3-Part Structure of Signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals organize your code into three distinct parts, following the
 | 
			
		||||
			${el("a", { textContent: t`3PS principle`, href: "./#h-3ps" })}:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -85,7 +85,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/signals.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Signals implement the ${el("a", { textContent: t`Publish–subscribe pattern`, ...references.wiki_pubsub
 | 
			
		||||
				})}, a form of ${el("a", { textContent: t`Event-driven programming`, ...references.wiki_event_driven
 | 
			
		||||
				})}.  This architecture allows different parts of your application to stay synchronized through
 | 
			
		||||
@@ -110,30 +110,30 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("dd", t`S.on(signal, callback) → runs callback whenever signal changes`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`Unsubscribing`),
 | 
			
		||||
				el("dd").append(...T`S.on(signal, callback, { signal: abortController.signal }) → Similarly to the
 | 
			
		||||
				el("dd").append(T`S.on(signal, callback, { signal: abortController.signal }) → Similarly to the
 | 
			
		||||
					${el("code", "on")} function to register DOM events listener.`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals can be created with any type of value, but they work best with ${el("a", { textContent:
 | 
			
		||||
				t`primitive types`, ...references.mdn_primitive })} like strings, numbers, and booleans.  For complex
 | 
			
		||||
			data types like objects and arrays, you’ll want to use Actions (covered below).
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Derived Signals: Computed Values`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Computed values (also called derived signals) automatically update when their dependencies change.
 | 
			
		||||
			Create them by passing ${el("strong", "a function")} to ${el("code", "S()")}:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/derived.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Derived signals are read-only - you can’t call ${el("code", ".set()")} on them. Their value is always
 | 
			
		||||
			computed from their dependencies. They’re perfect for transforming or combining data from other signals.
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/computations-abort.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Signal Actions: For Complex State`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When working with objects, arrays, or other complex data structures. Signal Actions provide
 | 
			
		||||
			a structured way to modify state while maintaining reactivity.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -164,7 +164,7 @@ export function page({ pkg, info }){
 | 
			
		||||
					`, page_id }))
 | 
			
		||||
				),
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			In some way, you can compare it with ${el("a", { textContent: "useReducer", ...references.mdn_use_reducer })}
 | 
			
		||||
			hook from React. So, the ${el("code", "S(<data>, <actions>)")} pattern creates a store “machine”. We can
 | 
			
		||||
			then invoke (dispatch) registered action by calling ${el("code", "S.action(<signal>, <name>, ...<args>)")}
 | 
			
		||||
@@ -174,7 +174,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/actions-demo.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Actions provide these benefits:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -183,17 +183,17 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`Prevent accidental direct mutations`),
 | 
			
		||||
			el("li", t`Act similar to reducers in other state management libraries`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Here’s a more complete example of a todo list using signal actions:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/actions-todos.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				${el("strong", "Special Action Methods")}: Signal actions can implement special lifecycle hooks:
 | 
			
		||||
			`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("code", "[S.symbols.onclear]()")} - Called when the signal is cleared. Use it to clean up
 | 
			
		||||
					resources.
 | 
			
		||||
				`),
 | 
			
		||||
@@ -201,7 +201,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Connecting Signals to the DOM`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals really shine when connected to your UI. dd<el> provides several ways to bind signals to DOM elements:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -245,37 +245,37 @@ export function page({ pkg, info }){
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "assign")} and ${el("code", "el")} functions detect signals automatically and handle binding.
 | 
			
		||||
			You can use special properties like ${el("code", "dataset")}, ${el("code", "ariaset")}, and
 | 
			
		||||
			${el("code", "classList")} for fine-grained control over specific attribute types.
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/dom-attrs.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			${el("code", "S.el()")} is especially powerful for conditional rendering and lists:
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/dom-el.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Follow these guidelines to get the most out of signals:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Keep signals small and focused")}: Use many small signals rather than a few large ones
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use derived signals for computations")}: Don’t recompute values in multiple places
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Clean up signal subscriptions")}: Use AbortController (scope.host()) to prevent memory
 | 
			
		||||
				leaks
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use actions for complex state")}: Don’t directly mutate objects or arrays in signals
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Avoid infinite loops")}: Be careful when one signal updates another in a subscription
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 
 | 
			
		||||
@@ -29,21 +29,21 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For state-less components we can use functions as UI components (see “Elements” page). But in real life,
 | 
			
		||||
			we may need to handle the component’s life-cycle and provide JavaScript the way to properly use
 | 
			
		||||
			the ${el("a", { textContent: t`Garbage collection`, ...references.garbage_collection })}.
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/scopes/intro.js"), page_id }),
 | 
			
		||||
		el("p").append(...T`The library therefore uses ${el("em", t`scopes`)} to provide these functionalities.`),
 | 
			
		||||
		el("p").append(T`The library therefore uses ${el("em", t`scopes`)} to provide these functionalities.`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Understanding Host Elements and Scopes`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("strong", "host")} is the name for the element representing the component. This is typically the
 | 
			
		||||
			element returned by a function. To get a reference, you can use ${el("code", "scope.host()")}. To apply addons,
 | 
			
		||||
			just use ${el("code", "scope.host(...<addons>)")}.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Scopes are primarily needed when signals are used in DOM templates (with ${el("code", "el")}, ${el("code",
 | 
			
		||||
				"assign")}, or ${el("code", "S.el")}). They provide a way for automatically removing signal listeners
 | 
			
		||||
			and cleaning up unused signals when components are removed from the DOM.
 | 
			
		||||
@@ -86,19 +86,19 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/scopes/scopes-and-hosts.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				${el("strong", "Best Practice:")} Always capture the host reference (or other scope related values) at
 | 
			
		||||
				the beginning of your component function using ${el("code", "const { host } = scope")} to avoid
 | 
			
		||||
				scope-related issues, especially with ${el("em", "asynchronous code")}.
 | 
			
		||||
			`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				If you are interested in the implementation details, see Class-Based Components section.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/scopes/good-practise.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Class-Based Components`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			While functional components are the primary pattern in dd<el>, you can also create class-based components.
 | 
			
		||||
			For this, we implement function ${el("code", "elClass")} and use it to demonstrate implementation details
 | 
			
		||||
			for better understanding of the scope logic.
 | 
			
		||||
@@ -106,7 +106,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/scopes/class-component.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Automatic Cleanup with Scopes`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			One of the most powerful features of scopes is automatic cleanup when components are removed from the DOM.
 | 
			
		||||
			This prevents memory leaks and ensures resources are properly released.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -126,7 +126,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/scopes/cleaning.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				In this example, when you click "Remove", the component is removed from the DOM, and all its associated
 | 
			
		||||
				resources are automatically cleaned up, including ${el("em",
 | 
			
		||||
					"the signal subscription that updates the text content")}. This happens because the library
 | 
			
		||||
@@ -135,12 +135,12 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Declarative vs Imperative Components`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The library DOM API and signals work best when used declaratively. It means you split your app’s logic
 | 
			
		||||
			into three parts as introduced in ${el("a", { textContent: "Signals (3PS)", ...references.signals })}.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Strictly speaking, the imperative way of using the library is not prohibited. Just be careful to avoid
 | 
			
		||||
				mixing the declarative approach (using signals) with imperative manipulation of elements.
 | 
			
		||||
			`)
 | 
			
		||||
@@ -165,20 +165,20 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Scopes and Components`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Capture host early:")} Use ${el("code", "const { host } = scope")} at component start
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Define signals as constants:")} ${el("code", "const counter = S(0);")}
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Prefer declarative patterns:")} Use signals to drive UI updates rather than manual DOM
 | 
			
		||||
				manipulation
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Keep components focused:")} Each component should do one thing well
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Add explicit cleanup:")} For resources not managed by dd<el>, use ${el("code",
 | 
			
		||||
					"on.disconnected")}
 | 
			
		||||
			`)
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> pairs powerfully with ${el("a", references.mdn_web_components).append(el("strong", t`Web
 | 
			
		||||
				Components`))} to create reusable, encapsulated custom elements with all the benefits of dd<el>’s
 | 
			
		||||
				declarative DOM construction and reactivity system.
 | 
			
		||||
@@ -76,29 +76,29 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/customElement/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Getting Started: Web Components Basics`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Web Components are a set of standard browser APIs that let you create custom HTML elements with
 | 
			
		||||
			encapsulated functionality. They consist of three main technologies:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Custom Elements:")} Create your own HTML tags with JS-defined behavior
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Shadow DOM:")} Encapsulate styles and markup within a component
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "HTML Templates:")} Define reusable markup structures (${el("em",
 | 
			
		||||
					"the dd<el> replaces this part")})
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Let’s start with a basic Custom Element example without dd<el> to establish the foundation:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				For complete information on Web Components, see the
 | 
			
		||||
				${el("a", references.mdn_custom_elements).append(el("strong", t`MDN documentation`))}.
 | 
			
		||||
				Also, ${el("a", references.custom_elements_tips).append(el("strong", t`Handy Custom Elements Patterns`))}
 | 
			
		||||
@@ -107,10 +107,10 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`dd<el> Integration: Step 1 - Event Handling`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The first step in integrating dd<el> with Web Components is enabling dd<el>’s event system to work with your
 | 
			
		||||
			Custom Elements. This is done with ${el("code", "customElementWithDDE")}, which makes your Custom Element
 | 
			
		||||
			compatible with dd<el>’s event handling. (${el("em").append(...T`Notice that customElementWithDDE is
 | 
			
		||||
			compatible with dd<el>’s event handling. (${el("em").append(T`Notice that customElementWithDDE is
 | 
			
		||||
			actually`)} ${el("a", { textContent: "decorator", ...references.decorators })})
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
@@ -127,14 +127,14 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				${el("strong", "Key Point:")} The ${el("code", "customElementWithDDE")} function adds event dispatching
 | 
			
		||||
				to your Custom Element lifecycle methods, making them work seamlessly with dd<el>’s event system.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`dd<el> Integration: Step 2 - Rendering Components`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The next step is to use dd<el>’s component rendering within your Custom Element. This is done with
 | 
			
		||||
			${el("code", "customElementRender")}, which connects your dd<el> component function to the Custom Element.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -159,32 +159,32 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/dde.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				In this example, we’re using Shadow DOM (${el("code", "this.attachShadow()")}) for encapsulation,
 | 
			
		||||
				but you can also render directly to the element with ${el("code", "customElementRender(this, ...)")}.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Reactive Web Components with Signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			One of the most powerful features of integrating dd<el> with Web Components is connecting HTML attributes
 | 
			
		||||
			to dd<el>’s reactive signals system. This creates truly reactive custom elements.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				${el("strong", "Two Ways to Handle Attributes:")}
 | 
			
		||||
			`),
 | 
			
		||||
			el("ol").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					Using standard attribute access (${el("code", "this.getAttribute(<name>)")}) - Passes attributes as
 | 
			
		||||
					regular values (static)
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("code", "S.observedAttributes")} - Transforms attributes into signals (reactive)
 | 
			
		||||
				`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Using the ${el("code", "S.observedAttributes")} creates a reactive connection between your element’s
 | 
			
		||||
			attributes and its internal rendering. When attributes change, your component automatically updates!
 | 
			
		||||
		`),
 | 
			
		||||
@@ -203,7 +203,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Working with Shadow DOM`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Shadow DOM provides encapsulation for your component’s styles and markup. When using dd<el> with Shadow DOM,
 | 
			
		||||
			you get the best of both worlds: encapsulation plus declarative DOM creation.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -223,14 +223,14 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/shadowRoot.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For more information on Shadow DOM, see
 | 
			
		||||
			${el("a", { textContent: t`Using Shadow DOM`, ...references.mdn_shadow_dom_depth })}, or the comprehensive
 | 
			
		||||
			${el("a", { textContent: t`Shadow DOM in Depth`, ...references.shadow_dom_depth })}.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Working with Slots`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		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")}:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -246,23 +246,23 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Web Components with dd<el>`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When combining dd<el> with Web Components, follow these recommendations:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Always use customElementWithDDE")} to enable event integration
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Prefer S.observedAttributes")} for reactive attribute connections
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Create reusable component functions")} that your custom elements render
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use scope.host()")} to clean up event listeners and subscriptions
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Add setters and getters")} for better property access to your element
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 
 | 
			
		||||
@@ -17,19 +17,19 @@ const fileURL= url=> new URL(url, import.meta.url);
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Debugging is an essential part of application development. This guide provides techniques
 | 
			
		||||
			and best practices for debugging applications built with dd<el>, with a focus on signals.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Debugging signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals are reactive primitives that update the UI when their values change. When debugging signals,
 | 
			
		||||
			you need to track their values, understand their dependencies, and identify why updates are or aren't happening.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Inspecting signal values`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The simplest way to debug a signal is to log its current value by calling the get method:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -38,7 +38,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			// without triggering updates
 | 
			
		||||
			console.log('Current value:', signal.valueOf());
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			You can also monitor signal changes by adding a listener:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -47,7 +47,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Debugging derived signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			With derived signals (created with ${el("code", "S(() => computation))")}), debugging is a bit more complex
 | 
			
		||||
			because the value depends on other signals. To understand why a derived signal isn’t updating correctly:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -69,7 +69,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/debugging/mutations.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Memory leaks with signal listeners`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signal listeners can cause memory leaks if not properly cleaned up. Always use AbortSignal
 | 
			
		||||
			to cancel listeners.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -84,12 +84,12 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/debugging/debouncing.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Browser DevTools tips for dd<el>`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When debugging in the browser, dd<el> provides several helpful DevTools-friendly features:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Identifying components in the DOM`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> marks components in the DOM with special comment nodes to help you identify component boundaries.
 | 
			
		||||
			Components created with ${el("code", "el(ComponentFunction)")} are marked with comment nodes
 | 
			
		||||
			${el("code", `<!--<dde:mark type="component" name="MyComponent" host="parentElement"/>-->`)} and
 | 
			
		||||
@@ -102,23 +102,23 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Finding reactive elements in the DOM`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When using ${el("code", "S.el()")}, dd<el> creates reactive elements in the DOM
 | 
			
		||||
			that are automatically updated when signal values change. These elements are wrapped in special
 | 
			
		||||
			comment nodes for debugging (to be true they are also used internally, so please do not edit them by hand):
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/debugging/dom-reactive-mark.html"), page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This is particularly useful when debugging why a reactive section isn’t updating as expected.
 | 
			
		||||
			You can inspect the elements between the comment nodes to see their current state and the
 | 
			
		||||
			signal connections through \`__dde_reactive\` of the host element.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`DOM inspection properties`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Elements created with the dd<el> library have special properties to aid in debugging:
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			${el("code", "<element>.__dde_reactive")} - An array property on DOM elements that tracks signal-to-element
 | 
			
		||||
			relationships.  This allows you to quickly identify which elements are reactive and what signals they’re
 | 
			
		||||
			bound to. Each entry in the array contains:
 | 
			
		||||
@@ -128,14 +128,14 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`Additional context information about the element or attribute`),
 | 
			
		||||
			el("li", t`Automatically managed by signal.el(), signal.observedAttributes(), and processReactiveAttribute()`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			These properties make it easier to understand the reactive structure of your application when inspecting
 | 
			
		||||
			elements.
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/debugging-dom.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Examining signal connections`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			${el("code", "<signal>.__dde_signal")} - A Symbol property used to identify and store the internal state of
 | 
			
		||||
			signal objects. It contains the following information:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -147,10 +147,10 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`defined: Stack trace information for debugging`),
 | 
			
		||||
			el("li", t`readonly: Boolean flag indicating if the signal is read-only`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			…to determine the current value of the signal, call ${el("code", "signal.valueOf()")}.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			You can inspect (host) element relationships and bindings with signals in the DevTools console using
 | 
			
		||||
			${el("code", "$0.__dde_reactive")} (for currently selected element). In the console you will see a list of
 | 
			
		||||
			${el("code", `[ [ signal, listener ], element, property ]`)}, where:
 | 
			
		||||
@@ -161,26 +161,26 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`element — the DOM element that is bound to the signal`),
 | 
			
		||||
			el("li", t`property — the attribute or property name which is changing based on the signal`),
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			…the structure of \`__dde_reactive\` utilizes the browser’s behavior of packing the first field,
 | 
			
		||||
			so you can see the element and property that changes in the console right away.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Debugging with breakpoints`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Effective use of breakpoints can help track signal flow:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Set breakpoints in signal update methods to track when values change
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Use conditional breakpoints to only break when specific signals change to certain values
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Set breakpoints in your signal computation functions to see when derived signals recalculate
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Use performance profiling to identify bottlenecks in signal updates
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 
 | 
			
		||||
@@ -16,21 +16,21 @@ const fileURL= url=> new URL(url, import.meta.url);
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> is designed with extensibility in mind. This page covers how to separate
 | 
			
		||||
			third-party functionalities and integrate them seamlessly with the library, focusing on
 | 
			
		||||
			proper resource cleanup and interoperability.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`DOM Element Extensions with Addons`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The primary method for extending DOM elements in dd<el> is through the Addon pattern.
 | 
			
		||||
			Addons are functions that take an element and applying some functionality to it. This pattern enables
 | 
			
		||||
			a clean, functional approach to element enhancement.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`What are Addons?`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Addons are simply functions with the signature: (element) => void. They:
 | 
			
		||||
			`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
@@ -52,13 +52,13 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Resource Cleanup with Abort Signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When extending elements with functionality that uses resources like event listeners, timers,
 | 
			
		||||
			or external subscriptions, it’s critical to clean up these resources when the element is removed
 | 
			
		||||
			from the DOM. dd<el> provides utilities for this through AbortSignal integration.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				The ${el("code", "scope.signal")} property creates an AbortSignal that automatically
 | 
			
		||||
				triggers when an element is disconnected from the DOM, making cleanup much easier to manage.
 | 
			
		||||
			`)
 | 
			
		||||
@@ -86,7 +86,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Building Library-Independent Extensions`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When creating extensions, it’s a good practice to make them as library-independent as possible.
 | 
			
		||||
			This approach enables better interoperability and future-proofing.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -125,13 +125,13 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Signal Extensions and Factory Patterns`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Unlike DOM elements, signal functionality in dd<el> currently lacks a standardized
 | 
			
		||||
			way to create library-independent extensions. This is because signals are implemented
 | 
			
		||||
			differently across libraries.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				In the future, JavaScript may include built-in signals through the
 | 
			
		||||
				${el("a", { href: "https://github.com/tc39/proposal-signals", textContent: "TC39 Signals Proposal" })}.
 | 
			
		||||
				dd<el> is designed with future compatibility in mind and will hopefully support these
 | 
			
		||||
@@ -140,7 +140,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`The Signal Factory Pattern`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			A powerful approach for extending signal functionality is the "Signal Factory" pattern.
 | 
			
		||||
			This approach encapsulates specific behavior in a function that creates and configures a signal.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -191,13 +191,13 @@ export function page({ pkg, info }){
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Note how the factory accepts the signal constructor as a parameter, making it easier to test
 | 
			
		||||
			and potentially migrate to different signal implementations in the future.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Other Signal Extension Approaches`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For simpler cases, you can also extend signals with clear interfaces and isolation to make
 | 
			
		||||
			future migration easier.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -221,7 +221,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				When designing signal extensions, consider creating specialized signals for common patterns like:
 | 
			
		||||
				forms, API requests, persistence, animations, or routing. These can significantly reduce
 | 
			
		||||
				boilerplate code in your applications.
 | 
			
		||||
@@ -229,19 +229,19 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Using Signals Independently`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			While signals are tightly integrated with DDE’s DOM elements, you can also use them independently.
 | 
			
		||||
			This can be useful when you need reactivity in non-UI code or want to integrate with other libraries.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			There are two ways to import signals:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Standard import")}: ${el("code", `import { S } from "deka-dom-el/signals";`)}
 | 
			
		||||
				— This automatically registers signals with DDE’s DOM reactivity system
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Independent import")}: ${el("code", `import { S } from "deka-dom-el/src/signals-lib";`)}
 | 
			
		||||
				— This gives you just the signal system without DOM integration
 | 
			
		||||
			`)
 | 
			
		||||
@@ -261,7 +261,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			count.set(5); // Logs: 5
 | 
			
		||||
			console.log(doubled.get()); // 10
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The independent signals API includes all core functionality (${el("code", "S()")}, ${el("code", "S.on()")},
 | 
			
		||||
			${el("code", "S.action()")}).
 | 
			
		||||
		`),
 | 
			
		||||
@@ -276,27 +276,27 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Extensions`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use AbortSignals for cleanup:")} Always implement proper resource cleanup with
 | 
			
		||||
				${el("code", "scope.signal")} or similar mechanisms
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Separate core logic from library adaptation:")} Make your core functionality work
 | 
			
		||||
				with standard DOM APIs when possible
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use signal factories for common patterns:")} Create reusable signal factories that encapsulate
 | 
			
		||||
				domain-specific behavior and state logic
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Document clearly:")} Provide clear documentation on how your extension works
 | 
			
		||||
				and what resources it uses
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Follow the Addon pattern:")} Keep to the (element) => element signature for
 | 
			
		||||
				DOM element extensions
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Avoid modifying global state:")} Extensions should be self-contained and not
 | 
			
		||||
				affect other parts of the application
 | 
			
		||||
			`)
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			As your applications grow, performance becomes increasingly important. dd<el> provides several
 | 
			
		||||
			techniques to optimize rendering performance, especially when dealing with large lists or frequently
 | 
			
		||||
			updating components. This guide focuses on memoization and other optimization strategies.
 | 
			
		||||
@@ -63,7 +63,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/optimization/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Memoization with memo: Native vs dd<el>`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			In standard JavaScript applications, optimizing list rendering often involves manual caching
 | 
			
		||||
			or relying on complex virtual DOM diffing algorithms. dd<el>'s ${el("code", "memo")} function
 | 
			
		||||
			provides a simpler, more direct approach:
 | 
			
		||||
@@ -106,13 +106,13 @@ export function page({ pkg, info }){
 | 
			
		||||
				)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("a", references.memo_docs).append(el("code", "memo"))} function in dd<el> allows you to
 | 
			
		||||
			cache and reuse DOM elements instead of recreating them on every render, which can
 | 
			
		||||
			significantly improve performance for components that render frequently or contain heavy computations.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The memo system is particularly useful for:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -122,7 +122,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Using memo with Signal Rendering`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The most common use case for memoization is within ${el("code", "S.el()")} when rendering lists with
 | 
			
		||||
			${el("code", "map()")}:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -136,7 +136,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			))))
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "memo")} function in this context:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
@@ -149,7 +149,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/optimization/memo.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Creating Memoization Scopes`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "memo()")} uses cache store defined via the ${el("code", "memo.scope")} function.
 | 
			
		||||
			That is actually what the ${el("code", "S.el")} is doing under the hood:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -173,7 +173,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			);
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The scope function accepts options to customize its behavior:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -193,12 +193,12 @@ export function page({ pkg, info }){
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`onlyLast Option`),
 | 
			
		||||
				el("dd").append(...T`Only keeps the cache from the most recent function call,
 | 
			
		||||
				el("dd").append(T`Only keeps the cache from the most recent function call,
 | 
			
		||||
					which is useful when the entire collection is replaced. ${el("strong", "This is default behavior of ")
 | 
			
		||||
					.append(el("code", "S.el"))}!`),
 | 
			
		||||
 | 
			
		||||
				el("dt", t`signal Option`),
 | 
			
		||||
				el("dd").append(...T`An ${el("a", references.mdn_abort).append(el("code", "AbortSignal"))}
 | 
			
		||||
				el("dd").append(T`An ${el("a", references.mdn_abort).append(el("code", "AbortSignal"))}
 | 
			
		||||
					that will clear the cache when aborted, helping with memory management`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
@@ -206,7 +206,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(h3, t`Additional Optimization Techniques`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Minimizing Signal Updates`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Signals are efficient, but unnecessary updates can impact performance:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -217,7 +217,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Optimizing List Rendering`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Beyond memoization, consider these approaches for optimizing list rendering:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -228,17 +228,17 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Memoization works best when your keys are stable and unique. Use IDs or other persistent
 | 
			
		||||
				identifiers rather than array indices, which can change when items are reordered.
 | 
			
		||||
				`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Alternatively you can use any “jsonable” value as key, when the primitive values aren’t enough.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Memory Management`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			To prevent memory leaks and reduce memory consumption:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -249,7 +249,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Choosing the Right Optimization Approach`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			While memo is powerful, it's not always the best solution:
 | 
			
		||||
		`),
 | 
			
		||||
		el("table").append(
 | 
			
		||||
@@ -280,12 +280,12 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Known Issues and Limitations`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			While memoization is a powerful optimization technique, there are some limitations and edge cases to be aware of:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Document Fragments and Memoization`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			One important limitation to understand is how memoization interacts with
 | 
			
		||||
			${el("a", references.mdn_fragment).append("DocumentFragment")} objects.
 | 
			
		||||
			Functions like ${el("code", "S.el")} internally use DocumentFragment to efficiently handle multiple elements,
 | 
			
		||||
@@ -305,7 +305,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			container.append(memoizedFragment); // Nothing gets appended
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This happens because a DocumentFragment is emptied when it's appended to the DOM. When the fragment
 | 
			
		||||
			is cached by memo and reused, it's already empty.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -327,7 +327,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			`, page_id })
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Generally, you should either:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
@@ -337,7 +337,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				This limitation isn't specific to dd<el> but is related to how DocumentFragment works in the DOM.
 | 
			
		||||
				Once a fragment is appended to the DOM, its child nodes are moved from the fragment to the target element,
 | 
			
		||||
				leaving the original fragment empty.
 | 
			
		||||
@@ -345,11 +345,11 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Performance Debugging`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			To identify performance bottlenecks in your dd<el> applications:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`Use ${el("a", references.mdn_perf).append("browser performance tools")} to profile
 | 
			
		||||
			el("li").append(T`Use ${el("a", references.mdn_perf).append("browser performance tools")} to profile
 | 
			
		||||
				rendering times`),
 | 
			
		||||
			el("li", t`Check for excessive signal updates using S.on() listeners with console.log`),
 | 
			
		||||
			el("li", t`Verify memo usage by inspecting cache hit rates`),
 | 
			
		||||
@@ -357,26 +357,26 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				For more details on debugging, see the ${el("a", { href: "p07-debugging.html", textContent: "Debugging" })} page.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices for Optimized Rendering`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use memo for list items:")} Memoize items in lists, especially when they contain complex components.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Clean up with AbortSignals:")} Connect memo caches to component lifecycles using AbortSignals.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Profile before optimizing:")} Identify actual bottlenecks before adding optimization.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Use derived signals:")} Compute derived values efficiently with signal computations.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Avoid memoizing fragments:")} Memoize individual elements or use container elements
 | 
			
		||||
				instead of DocumentFragments.
 | 
			
		||||
			`)
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			${el("a", references.todomvc).append("TodoMVC")} is a project that helps developers compare different
 | 
			
		||||
			frameworks by implementing the same todo application. This implementation showcases how dd<el>
 | 
			
		||||
			can be used to build a complete, real-world application with all the expected features of a modern
 | 
			
		||||
@@ -63,7 +63,7 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("li", t`Component scopes for proper encapsulation`)
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Below is a fully working TodoMVC implementation. You can interact with it directly in this
 | 
			
		||||
			documentation page. The example demonstrates how dd<el> handles common app development
 | 
			
		||||
			challenges in a clean, maintainable way.
 | 
			
		||||
@@ -72,7 +72,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/reallife/todomvc.js"), variant: "big", page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Application Architecture Overview`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The TodoMVC implementation is structured around several key components:
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
@@ -96,7 +96,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Reactive State Management with Signals`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The application uses three primary signals to manage state:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -118,7 +118,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			});
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("code", "todosSignal")} function creates a custom signal with actions for manipulating the todos:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -200,7 +200,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Using ${el("a", references.mdn_storage).append("localStorage")} allows the application to persist todos
 | 
			
		||||
				even when the page is refreshed. The ${el("code", "S.on")} listener ensures todos are saved
 | 
			
		||||
				after every state change, providing automatic persistence without explicit calls.
 | 
			
		||||
@@ -208,7 +208,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Integration of Signals and Reactive UI`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation demonstrates a clean integration between signal state and reactive UI:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -233,7 +233,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			)
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The derived signal automatically recalculates whenever either the todos list or the current filter changes,
 | 
			
		||||
			ensuring the UI always shows the correct filtered todos.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -268,7 +268,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			}
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The TodoItem component maintains its own local UI state with signals, providing immediate
 | 
			
		||||
			UI feedback while still communicating changes to the parent via events.
 | 
			
		||||
		`),
 | 
			
		||||
@@ -289,14 +289,14 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Binding signals directly to element properties creates a reactive UI that automatically updates
 | 
			
		||||
				when state changes, without the need for explicit DOM manipulation or virtual DOM diffing.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Performance Optimization with Memoization`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation uses ${el("code", "memo")} to optimize performance in several key areas:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -309,7 +309,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			)
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This approach ensures that:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -329,14 +329,14 @@ export function page({ pkg, info }){
 | 
			
		||||
			))
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			By memoizing based on the todos length, the entire footer component is only re-rendered
 | 
			
		||||
			when todos are added or removed, not when their properties change. This improves performance
 | 
			
		||||
			by avoiding unnecessary DOM operations.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Memoization is especially important for UI elements that are expensive to render or that contain
 | 
			
		||||
				many child elements. The ${el("code", "memo")} function allows precise control over when components
 | 
			
		||||
				should re-render, avoiding the overhead of virtual DOM diffing algorithms.
 | 
			
		||||
@@ -344,13 +344,13 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Component-Based Architecture with Events`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The TodoMVC implementation demonstrates a clean component architecture with custom events
 | 
			
		||||
			for communication between components:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`1. Main Component Event Handling`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The main Todos component sets up event listeners to handle actions from child components:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -360,7 +360,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`2. The TodoItem Component with Scopes and Local State`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Each todo item is rendered by the TodoItem component that uses scopes, local signals, and custom events:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -403,7 +403,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Using ${el("code", "scope")} and ${el("a", references.mdn_events).append("custom events")}
 | 
			
		||||
				creates a clean separation of concerns. Each TodoItem component dispatches events up to the parent
 | 
			
		||||
				without directly manipulating the application state, following a unidirectional data flow pattern.
 | 
			
		||||
@@ -411,7 +411,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Improved DOM Updates with classList`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation uses the reactive ${el("code", "classList")} property for efficient class updates:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -423,7 +423,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			);
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Benefits of using ${el("code", "classList")}:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -434,7 +434,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Improved Focus Management`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation uses a dedicated function for managing focus in edit inputs:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -462,7 +462,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			}, onBlurEdit, onKeyDown, addFocus)
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This approach offers several advantages:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -473,7 +473,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Using ${el("a", references.mdn_raf).append("requestAnimationFrame")} ensures that the focus operation
 | 
			
		||||
				happens after the browser has finished rendering the DOM changes, which is more reliable than
 | 
			
		||||
				using setTimeout.
 | 
			
		||||
@@ -481,7 +481,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Efficient Conditional Rendering`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation uses signals for efficient conditional rendering:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -520,7 +520,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Unlike frameworks that use a virtual DOM, dd<el> directly updates only the specific DOM elements
 | 
			
		||||
				that need to change. This approach is often more efficient for small to medium-sized applications,
 | 
			
		||||
				especially when combined with strategic memoization.
 | 
			
		||||
@@ -528,7 +528,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Type Safety with JSDoc Comments`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The implementation uses comprehensive JSDoc comments to provide type safety without requiring TypeScript:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { content: `
 | 
			
		||||
@@ -566,7 +566,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Using JSDoc comments provides many of the benefits of TypeScript (autocomplete, type checking,
 | 
			
		||||
				documentation) while maintaining pure JavaScript code. This approach works well with modern
 | 
			
		||||
				IDEs that support JSDoc type inference.
 | 
			
		||||
@@ -575,41 +575,41 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Best Practices Demonstrated`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Component Composition:")} Breaking the UI into focused, reusable components
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Performance Optimization:")} Strategic memoization to minimize DOM operations
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Reactive State Management:")} Using signals with derived computations
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Event-Based Communication:")} Using custom events for component communication
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Local Component State:")} Maintaining UI state within components for better encapsulation
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Declarative Class Management:")} Using the classList property for cleaner class handling
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Focus Management:")} Reliable input focus with requestAnimationFrame
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Persistent Storage:")} Automatically saving application state with signal listeners
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Type Safety:")} Using comprehensive JSDoc comments for type checking and documentation
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Composable Event Handlers:")} Attaching multiple event handlers to elements
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`Key Takeaways`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				This TodoMVC implementation showcases the strengths of dd<el> for building real-world applications:
 | 
			
		||||
			`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
@@ -622,7 +622,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			You can find the ${el("a", references.github_example).append("complete source code")} for this example on GitHub.
 | 
			
		||||
			Feel free to use it as a reference for your own projects or as a starting point for more complex applications.
 | 
			
		||||
		`),
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("div", { className: "warning" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				This part of the documentation is primarily intended for technical enthusiasts and authors of
 | 
			
		||||
				3rd-party libraries. It describes an advanced feature, not a core part of the library. Most users will
 | 
			
		||||
				not need to implement this functionality directly in their applications. This capability will hopefully
 | 
			
		||||
@@ -25,21 +25,21 @@ export function page({ pkg, info }){
 | 
			
		||||
				dd<el>.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> isn’t limited to browser environments. Thanks to its flexible architecture,
 | 
			
		||||
			it can be used for server-side rendering (SSR) to generate static HTML files.
 | 
			
		||||
			This is achieved through integration with for example ${el("a", { href: "https://github.com/tmpvar/jsdom",
 | 
			
		||||
			textContent: "jsdom" })}, a JavaScript implementation of web standards for Node.js.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Additionally, you might consider using these alternative solutions:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("a", { href: "https://github.com/capricorn86/happy-dom", textContent: "happy-dom" })} —
 | 
			
		||||
				A JavaScript implementation of a web browser without its graphical user interface that’s faster than jsdom
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("a", { href: "https://github.com/WebReflection/linkedom", textContent: "linkedom" })} —
 | 
			
		||||
				A lightweight DOM implementation specifically designed for SSR with significantly better performance
 | 
			
		||||
				than jsdom
 | 
			
		||||
@@ -48,7 +48,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Why Server-Side Rendering?`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			SSR offers several benefits:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -60,7 +60,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`How jsdom Integration Works`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The jsdom export in dd<el> provides the necessary tools to use the library in Node.js
 | 
			
		||||
			by integrating with jsdom. Here’s what it does:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -74,55 +74,55 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/start.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Basic SSR Example`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Here’s a simple example of how to use dd<el> for server-side rendering in a Node.js script:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/basic-example.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Building a Static Site Generator`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			You can build a complete static site generator with dd<el>. In fact, this documentation site
 | 
			
		||||
			is built using dd<el> for server-side rendering! Here’s how the documentation build process works:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/static-site-generator.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Working with Async Content in SSR`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The jsdom export includes a queue system to handle asynchronous operations during rendering.
 | 
			
		||||
			This is crucial for components that fetch data or perform other async tasks.
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/async-data.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Working with Dynamic Imports for SSR`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When structuring server-side rendering code, a crucial pattern to follow is using dynamic imports
 | 
			
		||||
			for both the deka-dom-el/jsdom module and your page components.
 | 
			
		||||
		`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Why is this important?
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Static imports are hoisted:")} JavaScript hoists import statements to the top of the file,
 | 
			
		||||
				executing them before any other code
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Environment registration timing:")} The jsdom module auto-registers the DOM environment
 | 
			
		||||
				when imported, which must happen ${el("em", "after")} you’ve created your JSDOM instance and
 | 
			
		||||
				${el("em", "before")} you import your components using ${el("code", "import { el } from \"deka-dom-el\";")}.
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Correct initialization order:")} You need to control the exact sequence of:
 | 
			
		||||
				create JSDOM → register environment → import components
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Follow this pattern when creating server-side rendered pages:
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/pages.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`SSR Considerations and Limitations`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When using dd<el> for SSR, keep these considerations in mind:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -131,19 +131,19 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`Some DOM features may behave differently in jsdom compared to real browsers`),
 | 
			
		||||
			el("li", t`For large sites, you may need to optimize memory usage by creating a new jsdom instance for each page`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			For advanced SSR applications, consider implementing hydration on the client-side to restore
 | 
			
		||||
			interactivity after the initial render.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Real Example: How This Documentation is Built`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This documentation site itself is built using dd<el>’s SSR capabilities.
 | 
			
		||||
			The build process collects all page components, renders them with jsdom, and outputs static HTML files.
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/ssr/static-site-generator.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The resulting static files can be deployed to any static hosting service,
 | 
			
		||||
			providing fast loading times and excellent SEO without the need for client-side JavaScript
 | 
			
		||||
			to render the initial content.
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("div", { className: "warning" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				This part of the documentation is primarily intended for technical enthusiasts and authors of
 | 
			
		||||
				3rd-party libraries. It describes an advanced feature, not a core part of the library. Most users will
 | 
			
		||||
				not need to implement this functionality directly in their applications. This capability will hopefully
 | 
			
		||||
@@ -29,7 +29,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`What Are Ireland Components?`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Ireland components are a special type of component that:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
@@ -38,24 +38,24 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`How Ireland Components Work`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The Ireland component system consists of several parts working together:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Server-side rendering:")} Components are pre-rendered during the documentation build process
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Component registration:")} Source files are copied to the documentation output directory
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Client-side scripting:")} JavaScript code is generated to load and render components
 | 
			
		||||
			`),
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Implementation Architecture`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The core of the Ireland system is implemented in ${el("code", "docs/components/ireland.html.js")}.
 | 
			
		||||
			It integrates with the SSR build process using the ${el("code", "registerClientFile")} function
 | 
			
		||||
			from ${el("code", "docs/ssr.js")}.
 | 
			
		||||
@@ -69,7 +69,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			})
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			During the build process (${el("code", "bs/docs.js")}), the following happens:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +81,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Core Implementation Details`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Let's look at the key parts of the ireland component implementation:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
@@ -253,7 +253,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`, page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Live Example`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Here’s a live example of an Ireland component showing a standard counter.
 | 
			
		||||
				The component is defined in ${el("code", "docs/components/examples/ireland-test/counter.js")} and
 | 
			
		||||
				rendered with the Ireland component system:
 | 
			
		||||
@@ -269,21 +269,21 @@ export function page({ pkg, info }){
 | 
			
		||||
				page_id
 | 
			
		||||
			}),
 | 
			
		||||
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				When the page is loaded, the component is also loaded and rendered. The counter state is maintained
 | 
			
		||||
				using signals, allowing for reactive updates as you click the buttons to increment and decrement the
 | 
			
		||||
				value.
 | 
			
		||||
			`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Practical Considerations and Limitations`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				When implementing Ireland components in real documentation, there are several important
 | 
			
		||||
				considerations to keep in mind:
 | 
			
		||||
			`),
 | 
			
		||||
 | 
			
		||||
			el("div", { className: "warning" }).append(
 | 
			
		||||
				el("h4", t`Module Resolution and Bundling`),
 | 
			
		||||
				el("p").append(...T`
 | 
			
		||||
				el("p").append(T`
 | 
			
		||||
					The examples shown here use bare module specifiers like ${el("code",
 | 
			
		||||
						`import { el } from "deka-dom-el"`)} which aren’t supported in all browsers without importmaps.
 | 
			
		||||
					In a production implementation, you would need to: `),
 | 
			
		||||
@@ -292,7 +292,7 @@ export function page({ pkg, info }){
 | 
			
		||||
					el("li", t`Bundle component dependencies to avoid multiple requests`),
 | 
			
		||||
					el("li", t`Ensure all module dependencies are properly resolved and copied to the output directory`)
 | 
			
		||||
				),
 | 
			
		||||
				el("p").append(...T`
 | 
			
		||||
				el("p").append(T`
 | 
			
		||||
					In this documentation, we replace the paths with ${el("code", "./esm-with-signals.js")} and provide
 | 
			
		||||
					a bundled version of the library, but more complex components might require a dedicated bundling step.
 | 
			
		||||
				`)
 | 
			
		||||
@@ -300,7 +300,7 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
			el("div", { className: "note" }).append(
 | 
			
		||||
				el("h4", t`Component Dependencies`),
 | 
			
		||||
				el("p").append(...T`
 | 
			
		||||
				el("p").append(T`
 | 
			
		||||
					Real-world components typically depend on multiple modules and assets. The Ireland system would need
 | 
			
		||||
					to be extended to:
 | 
			
		||||
				`),
 | 
			
		||||
@@ -312,7 +312,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			),
 | 
			
		||||
 | 
			
		||||
			el(h3, t`Advanced Usage`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				The Ireland system can be extended in several ways to address these limitations:
 | 
			
		||||
			`),
 | 
			
		||||
 | 
			
		||||
@@ -325,7 +325,7 @@ export function page({ pkg, info }){
 | 
			
		||||
				el("li", t`Implement state persistence between runs`)
 | 
			
		||||
			),
 | 
			
		||||
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				This documentation site itself is built using the techniques described here,
 | 
			
		||||
				showcasing how dd<el> can be used to create both the documentation and
 | 
			
		||||
				the interactive examples within it. The implementation here is simplified for clarity,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,45 +32,45 @@ const references= {
 | 
			
		||||
export function page({ pkg, info }){
 | 
			
		||||
	const page_id= info.id;
 | 
			
		||||
	return el(simplePage, { info, pkg }).append(
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			This reference guide provides a comprehensive summary of dd<el>'s key concepts, best practices,
 | 
			
		||||
			case studies, and advanced techniques. Use it as a quick reference when working with the library
 | 
			
		||||
			or to deepen your understanding of its design principles and patterns.
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Core Principles of dd<el>`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			At its foundation, dd<el> is built on several core principles that shape its design and usage:
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`Guiding Principles`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "DOM-First Approach:")} Working directly with the real DOM instead of virtual DOM
 | 
			
		||||
					abstractions
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Declarative Syntax:")} Creating UIs by describing what they should look like, not
 | 
			
		||||
					how to create them
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Minimal Overhead:")} Staying close to standard Web APIs without unnecessary
 | 
			
		||||
					abstractions
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Progressive Enhancement:")} Starting simple and adding complexity only when needed
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Functional Composition:")} Building UIs through function composition rather than
 | 
			
		||||
					inheritance
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Clear Patterns:")} Promoting maintainable code organization with the 3PS pattern
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Targeted Reactivity:")} Using signals for efficient, fine-grained updates
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Unix Philosophy:")} Doing one thing well and allowing composability with other tools
 | 
			
		||||
				`)
 | 
			
		||||
			)
 | 
			
		||||
@@ -79,7 +79,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(h3, t`Case Studies & Real-World Applications`),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`TodoMVC Implementation`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The ${el("a", references.todomvc).append("TodoMVC implementation")} showcases how dd<el> handles a complete,
 | 
			
		||||
			real-world application with all standard features of a modern web app:
 | 
			
		||||
		`),
 | 
			
		||||
@@ -92,40 +92,40 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`Custom event system for component communication`),
 | 
			
		||||
			el("li", t`Proper focus management and accessibility`)
 | 
			
		||||
		),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			Key takeaways from the TodoMVC example:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Signal factories like ${el("code", "routerSignal")} and ${el("code", "todosSignal")}
 | 
			
		||||
				encapsulate related functionality
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Custom events provide clean communication between components
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Targeted memoization improves rendering performance dramatically
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Derived signals simplify complex UI logic like filtering
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("h4", t`Migrating from Traditional Approaches`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			When migrating from traditional DOM manipulation or other frameworks to dd<el>:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ol").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Start with state:")}: Convert global variables or ad-hoc state to signals
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Replace query selectors:")}: Replace getElementById/querySelector with direct references to elements
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Convert imperative updates:")}: Replace manual DOM updates with declarative signal bindings
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Refactor into components:")}: Organize related UI elements into component functions
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
@@ -211,19 +211,19 @@ export function page({ pkg, info }){
 | 
			
		||||
		el("div").append(
 | 
			
		||||
			el("h4", t`Code Organization`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Follow the 3PS pattern:")}: Separate state creation, binding to elements, and state updates
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Use component functions:")}: Create reusable UI components as functions
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Create signal factories:")}: Extract reusable signal patterns into factory functions
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Leverage scopes:")}: Use scope for component context and clean resource management
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Event delegation:")}: Prefer component-level event handlers over many individual handlers
 | 
			
		||||
				`)
 | 
			
		||||
			)
 | 
			
		||||
@@ -232,23 +232,23 @@ export function page({ pkg, info }){
 | 
			
		||||
		el("div").append(
 | 
			
		||||
			el("h4", t`Performance Optimization`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Memoize list items:")}: Use ${el("code", "memo")} for items in frequently-updated lists
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Avoid unnecessary signal updates:")}: Only update signals when values actually change
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Use AbortSignals:")}: Clean up resources when components are removed
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Prefer derived signals:")}: Use computed values instead of manual updates
 | 
			
		||||
				`),
 | 
			
		||||
				el("li").append(...T`
 | 
			
		||||
				el("li").append(T`
 | 
			
		||||
					${el("strong", "Avoid memoizing fragments:")}: Never memoize DocumentFragments, only individual elements
 | 
			
		||||
				`)
 | 
			
		||||
			),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				See the ${el("a", references.performance).append("Performance Optimization Guide")} for detailed strategies.
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
@@ -324,56 +324,56 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Looking Ahead: Future Directions`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			The dd<el> library continues to evolve, with several areas of focus for future development:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Future Compatibility:")} Alignment with the TC39 Signals proposal for native browser support
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "SSR Improvements:")} Enhanced server-side rendering capabilities
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Ecosystem Growth:")} More utilities, patterns, and integrations with other libraries
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "Documentation Expansion:")} Additional examples, tutorials, and best practices
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("strong", "TypeScript Enhancements:")} Improved type definitions and inference
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Contribution and Community`),
 | 
			
		||||
		el("p").append(...T`
 | 
			
		||||
		el("p").append(T`
 | 
			
		||||
			dd<el> is an open-source project that welcomes contributions from the community:
 | 
			
		||||
		`),
 | 
			
		||||
		el("ul").append(
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				${el("a", references.github).append("GitHub Repository")}: Star, fork, and contribute to the project
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Bug reports and feature requests: Open issues on GitHub
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Documentation improvements: Help expand and clarify these guides
 | 
			
		||||
			`),
 | 
			
		||||
			el("li").append(...T`
 | 
			
		||||
			el("li").append(T`
 | 
			
		||||
				Examples and case studies: Share your implementations and solutions
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`Final Thoughts`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				dd<el> provides a lightweight yet powerful approach to building modern web interfaces
 | 
			
		||||
				with minimal overhead and maximal flexibility. By embracing standard web technologies
 | 
			
		||||
				rather than abstracting them away, it offers a development experience that scales
 | 
			
		||||
				from simple interactive elements to complex applications while remaining close
 | 
			
		||||
				to what makes the web platform powerful.
 | 
			
		||||
			`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
			el("p").append(T`
 | 
			
		||||
				Whether you're building a small interactive component or a full-featured application,
 | 
			
		||||
				dd<el>'s combination of declarative syntax, targeted reactivity, and pragmatic design
 | 
			
		||||
				provides the tools you need without the complexity you don't.
 | 
			
		||||
 
 | 
			
		||||
@@ -17,12 +17,14 @@
 | 
			
		||||
 *
 | 
			
		||||
 * @param {TemplateStringsArray} strings
 | 
			
		||||
 * @param {...(string|Node)} values
 | 
			
		||||
 * @returns {(string|Node)[]}
 | 
			
		||||
 * @returns {DocumentFragment}
 | 
			
		||||
 * */
 | 
			
		||||
export function T(strings, ...values){
 | 
			
		||||
	const out= [];
 | 
			
		||||
	tT(s=> out.push(s), strings, ...values);
 | 
			
		||||
	return out;
 | 
			
		||||
	const fragment= document.createDocumentFragment();
 | 
			
		||||
	fragment.append(...out);
 | 
			
		||||
	return fragment;
 | 
			
		||||
}
 | 
			
		||||
/**
 | 
			
		||||
 * Similarly to {@link T}, but for only strings.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user