mirror of
				https://github.com/jaandrle/deka-dom-el
				synced 2025-11-03 22:59:16 +01:00 
			
		
		
		
	🔤 UI
This commit is contained in:
		@@ -31,7 +31,7 @@ ${host} {
 | 
			
		||||
	overflow: auto;
 | 
			
		||||
	border-radius: var(--border-radius);
 | 
			
		||||
	font-family: var(--font-mono);
 | 
			
		||||
	font-size: 0.8rem;
 | 
			
		||||
	font-size: .85rem;
 | 
			
		||||
	line-height: 1.5;
 | 
			
		||||
	position: relative;
 | 
			
		||||
	margin-block: 1rem;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ ${host} .runtime {
 | 
			
		||||
.CodeMirror {
 | 
			
		||||
	height: 100% !important;
 | 
			
		||||
	font-family: var(--font-mono) !important;
 | 
			
		||||
	font-size: 0.8rem !important;
 | 
			
		||||
	font-size: .85rem !important;
 | 
			
		||||
	line-height: 1.5 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
import { styles } from "./ssr.js";
 | 
			
		||||
styles.css`
 | 
			
		||||
:root {
 | 
			
		||||
	--primary: #b71c1c;
 | 
			
		||||
	--primary-light: #f05545;
 | 
			
		||||
	--primary-dark: #7f0000;
 | 
			
		||||
	--primary-rgb: 183, 28, 28;
 | 
			
		||||
	--secondary: #700037;
 | 
			
		||||
	--secondary-light: #ae1357;
 | 
			
		||||
	--secondary-dark: #4a0027;
 | 
			
		||||
	--secondary-rgb: 112, 0, 55;
 | 
			
		||||
	--primary: hsl(0, 74%, 42%);
 | 
			
		||||
	--primary-light: hsl(5, 87%, 61%);
 | 
			
		||||
	--primary-dark: hsl(0, 100%, 25%);
 | 
			
		||||
	--primary-hs: 0, 74%;
 | 
			
		||||
	--secondary: hsl(330, 100%, 22%);
 | 
			
		||||
	--secondary-light: hsl(339, 80%, 38%);
 | 
			
		||||
	--secondary-dark: hsl(328, 100%, 15%);
 | 
			
		||||
	--secondary-hs: 330, 100%;
 | 
			
		||||
 | 
			
		||||
	--font-main: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
 | 
			
		||||
		Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
 | 
			
		||||
@@ -20,50 +20,49 @@ styles.css`
 | 
			
		||||
	--header-height: 4rem;
 | 
			
		||||
	--border-radius: 0.375rem;
 | 
			
		||||
 | 
			
		||||
	--bg: #ffffff;
 | 
			
		||||
	--bg-sidebar: #fff5f5;
 | 
			
		||||
	--text: #1a1313;
 | 
			
		||||
	--text-light: #555050;
 | 
			
		||||
	--code-bg: #f9f2f2;
 | 
			
		||||
	--code-text: #9a0000;
 | 
			
		||||
	--border: #d8c0c0;
 | 
			
		||||
	--selection: rgba(183, 28, 28, 0.15);
 | 
			
		||||
	--marked: #b71c1c;
 | 
			
		||||
	--bg: hsl(0, 0%, 100%);
 | 
			
		||||
	--bg-sidebar: hsl(0, 100%, 98%);
 | 
			
		||||
	--text: hsl(0, 16%, 15%);
 | 
			
		||||
	--text-light: hsl(0, 4%, 33%);
 | 
			
		||||
	--code-bg: hsl(0, 39%, 97%);
 | 
			
		||||
	--code-text: hsl(0, 100%, 30%);
 | 
			
		||||
	--border: hsl(0, 32%, 80%);
 | 
			
		||||
	--selection: hsl(var(--primary-hs), 90%);
 | 
			
		||||
	--marked: var(--primary);
 | 
			
		||||
	--accent: var(--secondary);
 | 
			
		||||
	--shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
 | 
			
		||||
	--shadow: 0 2px 6px hsla(0, 0%, 0%, 0.15);
 | 
			
		||||
	--shadow-sm: 0 2px 4px hsla(0, 0%, 0%, 0.15);
 | 
			
		||||
 | 
			
		||||
	--link-color: #9a0000;
 | 
			
		||||
	--link-hover: #7f0000;
 | 
			
		||||
	--button-text: #ffffff;
 | 
			
		||||
 | 
			
		||||
	--link-color: hsl(0, 100%, 30%);
 | 
			
		||||
	--link-hover: hsl(0, 100%, 25%);
 | 
			
		||||
	--button-text: hsl(0, 0%, 100%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (prefers-color-scheme: dark) {
 | 
			
		||||
	:root {
 | 
			
		||||
		--bg: #121212;
 | 
			
		||||
		--bg-sidebar: #1a1212;
 | 
			
		||||
		--text: #ffffff;
 | 
			
		||||
		--text-light: #cccccc;
 | 
			
		||||
		--code-bg: #2c2020;
 | 
			
		||||
		--code-text: #ff9e80;
 | 
			
		||||
		--border: #4d3939;
 | 
			
		||||
		--selection: rgba(255, 99, 71, 0.25);
 | 
			
		||||
		--primary: #b74141;
 | 
			
		||||
		--primary-light: #ff867f;
 | 
			
		||||
		--primary-dark: #c62828;
 | 
			
		||||
		--secondary: #f02b47;
 | 
			
		||||
		--secondary-light: #ff6090;
 | 
			
		||||
		--secondary-dark: #b0003a;
 | 
			
		||||
		--bg: hsl(0, 0%, 7%);
 | 
			
		||||
		--bg-sidebar: hsl(0, 9%, 9%);
 | 
			
		||||
		--text: hsl(0, 0%, 100%);
 | 
			
		||||
		--text-light: hsl(0, 0%, 80%);
 | 
			
		||||
		--code-bg: hsl(0, 18%, 15%);
 | 
			
		||||
		--code-text: hsl(20, 100%, 75%);
 | 
			
		||||
		--border: hsl(0, 14%, 27%);
 | 
			
		||||
		--selection: hsla(9, 100%, 64%, 0.25);
 | 
			
		||||
		--primary: hsl(0, 48%, 49%);
 | 
			
		||||
		--primary-light: hsl(5, 100%, 75%);
 | 
			
		||||
		--primary-dark: hsl(0, 67%, 47%);
 | 
			
		||||
		--secondary: hsl(350, 87%, 55%);
 | 
			
		||||
		--secondary-light: hsl(341, 100%, 69%);
 | 
			
		||||
		--secondary-dark: hsl(340, 100%, 35%);
 | 
			
		||||
		--accent: var(--secondary);
 | 
			
		||||
 | 
			
		||||
		--link-color: #ff5252;
 | 
			
		||||
		--link-hover: #ff867f;
 | 
			
		||||
		--button-text: #ffffff;
 | 
			
		||||
		--link-color: hsl(0, 100%, 66%);
 | 
			
		||||
		--link-hover: hsl(5, 100%, 75%);
 | 
			
		||||
		--button-text: hsl(0, 0%, 100%);
 | 
			
		||||
 | 
			
		||||
		--nav-current-bg: #aa2222;
 | 
			
		||||
		--nav-current-text: #ffffff;
 | 
			
		||||
 | 
			
		||||
		--primary-rgb: 255, 82, 82;
 | 
			
		||||
		--secondary-rgb: 233, 30, 99;
 | 
			
		||||
		--primary-hs: 0, 48%;
 | 
			
		||||
		--secondary-hs: 350, 87%;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -78,7 +77,7 @@ html {
 | 
			
		||||
 | 
			
		||||
/* Accessibility improvements */
 | 
			
		||||
:focus {
 | 
			
		||||
	outline: 3px solid rgba(63, 81, 181, 0.5);
 | 
			
		||||
	outline: 3px solid hsl(231, 48%, 70%);
 | 
			
		||||
	outline-offset: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -87,7 +86,7 @@ html {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:focus-visible {
 | 
			
		||||
	outline: 3px solid rgba(63, 81, 181, 0.5);
 | 
			
		||||
	outline: 3px solid hsl(231, 48%, 70%);
 | 
			
		||||
	outline-offset: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +126,7 @@ body {
 | 
			
		||||
	background-color: var(--bg);
 | 
			
		||||
	color: var(--text);
 | 
			
		||||
	line-height: 1.6;
 | 
			
		||||
	font-size: 1rem;
 | 
			
		||||
	font-size: 1.05rem;
 | 
			
		||||
	display: grid;
 | 
			
		||||
	grid-template-columns: 100%;
 | 
			
		||||
	grid-template-areas:
 | 
			
		||||
@@ -342,20 +341,17 @@ h3:hover .heading-anchor {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.note {
 | 
			
		||||
	background-color: rgba(63, 81, 181, 0.08);
 | 
			
		||||
	border-left: 4px solid var(--primary);
 | 
			
		||||
	border-radius: 0 var(--border-radius) var(--border-radius) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tip {
 | 
			
		||||
	background-color: rgba(46, 204, 113, 0.08);
 | 
			
		||||
	border-left: 4px solid #2ecc71;
 | 
			
		||||
	border-left: 4px solid hsl(145, 63%, 49%);
 | 
			
		||||
	border-radius: 0 var(--border-radius) var(--border-radius) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warning {
 | 
			
		||||
	background-color: rgba(241, 196, 15, 0.08);
 | 
			
		||||
	border-left: 4px solid #f1c40f;
 | 
			
		||||
	border-left: 4px solid hsl(48, 89%, 50%);
 | 
			
		||||
	border-radius: 0 var(--border-radius) var(--border-radius) 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -372,12 +368,12 @@ h3:hover .heading-anchor {
 | 
			
		||||
 | 
			
		||||
.tip::before {
 | 
			
		||||
	content: "Tip";
 | 
			
		||||
	color: #2ecc71;
 | 
			
		||||
	color: hsl(145, 63%, 49%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.warning::before {
 | 
			
		||||
	content: "Warning";
 | 
			
		||||
	color: #f1c40f;
 | 
			
		||||
	color: hsl(48, 89%, 50%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Prev/Next buttons */
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ ${host} h1 {
 | 
			
		||||
 | 
			
		||||
${host} .version-badge {
 | 
			
		||||
	font-size: 0.75rem;
 | 
			
		||||
	background-color: rgba(150, 150, 150, 0.2);
 | 
			
		||||
	background-color: hsla(0, 0%, 59%, 0.2);
 | 
			
		||||
	padding: 0.25rem 0.5rem;
 | 
			
		||||
	border-radius: var(--border-radius);
 | 
			
		||||
}
 | 
			
		||||
@@ -57,13 +57,13 @@ ${host} .github-link {
 | 
			
		||||
	font-size: 0.875rem;
 | 
			
		||||
	padding: 0.375rem 0.75rem;
 | 
			
		||||
	border-radius: var(--border-radius);
 | 
			
		||||
	background-color: rgba(0, 0, 0, 0.2);
 | 
			
		||||
	background-color: hsla(0, 0%, 0%, 0.2);
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
	transition: background-color 0.2s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host} .github-link:hover {
 | 
			
		||||
	background-color: rgba(0, 0, 0, 0.3);
 | 
			
		||||
	background-color: hsla(0, 0%, 0%, 0.3);
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -85,39 +85,26 @@ ${host_nav} a {
 | 
			
		||||
	padding: 0.625rem 0.75rem;
 | 
			
		||||
	border-radius: var(--border-radius);
 | 
			
		||||
	color: var(--text);
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
	transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
 | 
			
		||||
	transition: background-color 0.1s ease, color 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
 | 
			
		||||
	line-height: 1.2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host_nav} a:hover {
 | 
			
		||||
	background-color: rgba(var(--primary-rgb), 0.08); /* Using CSS variables for better theming */
 | 
			
		||||
	text-decoration: none;
 | 
			
		||||
	transform: translateY(-1px);
 | 
			
		||||
	color: var(--primary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host_nav} a.current,
 | 
			
		||||
${host_nav} a[aria-current=page] {
 | 
			
		||||
	background-color: var(--nav-current-bg, var(--primary-dark));
 | 
			
		||||
	color: var(--nav-current-text, white);
 | 
			
		||||
	background-color: hsl(var(--primary-hs), 40%);
 | 
			
		||||
	color: whitesmoke;
 | 
			
		||||
	font-weight: 600;
 | 
			
		||||
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
 | 
			
		||||
	box-shadow: var(--shadow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host_nav} a.current:hover,
 | 
			
		||||
${host_nav} a[aria-current=page]:hover {
 | 
			
		||||
	background-color: var(--primary);
 | 
			
		||||
	color: white;
 | 
			
		||||
${host_nav} a:hover {
 | 
			
		||||
	background-color: hsl(var(--primary-hs), 45%);
 | 
			
		||||
	color: whitesmoke;
 | 
			
		||||
	transform: translateY(-1px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host_nav} a .nav-number {
 | 
			
		||||
	display: inline-block;
 | 
			
		||||
	width: 1.5rem;
 | 
			
		||||
	text-align: right;
 | 
			
		||||
	margin-right: 0.5rem;
 | 
			
		||||
	opacity: 0.7;
 | 
			
		||||
	color: rgb(from currentColor r g b / .75);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
${host_nav} a:first-child {
 | 
			
		||||
@@ -172,11 +159,6 @@ export function header({ info: { href, title, description }, pkg }){
 | 
			
		||||
		head({ title: pageTitle, description, pkg })
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	// Add theme color meta tag
 | 
			
		||||
	document.head.append(
 | 
			
		||||
		el("meta", { name: "theme-color", content: "#3f51b5" })
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	return el().append(
 | 
			
		||||
		// Header section with accessibility support
 | 
			
		||||
		el("header", { role: "banner", className: header.name }).append(
 | 
			
		||||
@@ -225,7 +207,7 @@ function nav({ href }){
 | 
			
		||||
				el("span", {
 | 
			
		||||
					className: "nav-number",
 | 
			
		||||
					"aria-hidden": "true",
 | 
			
		||||
					textContent: `${i+1}.`
 | 
			
		||||
					textContent: `${i+1}. `
 | 
			
		||||
				}),
 | 
			
		||||
				p.title
 | 
			
		||||
			);
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Signals provide a simple yet powerful way to create reactive applications with DDE. They handle the
 | 
			
		||||
			fundamental challenge of keeping your UI in sync with changing data in a declarative, efficient way.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-callout" }).append(
 | 
			
		||||
		el("div", { class: "callout" }).append(
 | 
			
		||||
			el("h4", t`What Makes Signals Special?`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li", t`Fine-grained reactivity without complex state management`),
 | 
			
		||||
@@ -66,7 +66,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Signals organize your code into three distinct parts, following the
 | 
			
		||||
			${el("a", { textContent: t`3PS principle`, href: "./#h-event-driven-programming--parts-separation--ps" })}:
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-signal-diagram" }).append(
 | 
			
		||||
		el("div", { class: "signal-diagram" }).append(
 | 
			
		||||
			el("div", { class: "signal-part" }).append(
 | 
			
		||||
				el("h4", t`α: Create Signal`),
 | 
			
		||||
				el(code, { content: "const count = S(0);", page_id }),
 | 
			
		||||
@@ -85,7 +85,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/signals.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-note" }).append(
 | 
			
		||||
		el("div", { class: "note" }).append(
 | 
			
		||||
			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 })}.
 | 
			
		||||
@@ -95,7 +95,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Signal Essentials: Core API`),
 | 
			
		||||
		el("div", { class: "dde-function-table" }).append(
 | 
			
		||||
		el("div", { class: "function-table" }).append(
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Creating a Signal`),
 | 
			
		||||
				el("dd", t`S(initialValue) → creates a signal with the given value`),
 | 
			
		||||
@@ -136,7 +136,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			When working with objects, arrays, or other complex data structures, Signal Actions provide
 | 
			
		||||
			a structured way to modify state while maintaining reactivity.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-illustration" }).append(
 | 
			
		||||
		el("div", { class: "illustration" }).append(
 | 
			
		||||
			el("h4", t`Actions vs. Direct Mutation`),
 | 
			
		||||
			el("div", { class: "comparison" }).append(
 | 
			
		||||
				el("div", { class: "bad-practice" }).append(
 | 
			
		||||
@@ -177,7 +177,7 @@ S.action(todos, "add", "New todo");`, page_id })
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/signals/actions-todos.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { class: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				${el("strong", "Special Action Methods")}: Signal actions can implement special lifecycle hooks:
 | 
			
		||||
			`),
 | 
			
		||||
@@ -193,7 +193,7 @@ S.action(todos, "add", "New todo");`, page_id })
 | 
			
		||||
			Signals really shine when connected to your UI. DDE provides several ways to bind signals to DOM elements:
 | 
			
		||||
		`),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-tabs" }).append(
 | 
			
		||||
		el("div", { class: "tabs" }).append(
 | 
			
		||||
			el("div", { class: "tab", "data-tab": "attributes" }).append(
 | 
			
		||||
				el("h4", t`Reactive Attributes`),
 | 
			
		||||
				el("p", t`Bind signal values directly to element attributes, properties, or styles:`),
 | 
			
		||||
@@ -263,7 +263,7 @@ S.action(items, "push", "Dragonfruit"); // List updates automatically`, page_id
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-troubleshooting" }).append(
 | 
			
		||||
		el("div", { class: "troubleshooting" }).append(
 | 
			
		||||
			el("h4", t`Common Signal Pitfalls`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`UI not updating when array/object changes`),
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Scopes provide a structured way to organize your UI code into reusable components that properly
 | 
			
		||||
			manage their lifecycle, handle cleanup, and maintain clear boundaries between different parts of your application.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-callout" }).append(
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`Why Use Scopes?`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li", t`Automatic resource cleanup when components are removed from DOM`),
 | 
			
		||||
@@ -46,7 +46,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/scopes/intro.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el(h3, t`Understanding Host Elements and Scopes`),
 | 
			
		||||
		el("div", { class: "dde-illustration" }).append(
 | 
			
		||||
		el("div", { className: "illustration" }).append(
 | 
			
		||||
			el("h4", t`Component Anatomy`),
 | 
			
		||||
			el("pre").append(el("code", `
 | 
			
		||||
┌─────────────────────────────────┐
 | 
			
		||||
@@ -77,7 +77,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			The ${el("strong", "host element")} is the root element of your component - typically the element returned
 | 
			
		||||
			by your component function. It serves as the identity of your component in the DOM.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-function-table" }).append(
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
			el("h4", t`scope.host()`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`When called with no arguments`),
 | 
			
		||||
@@ -89,7 +89,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/scopes/scopes-and-hosts.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				${el("strong", "Best Practice:")} Always capture the host reference at the beginning of your component function
 | 
			
		||||
				using ${el("code", "const { host } = scope")} to avoid scope-related issues, especially with asynchronous code.
 | 
			
		||||
@@ -111,7 +111,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			el("li", t`You need private methods and properties for your component`),
 | 
			
		||||
			el("li", t`You're transitioning from another class-based component system`)
 | 
			
		||||
		),
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				${el("strong", "Note:")} Even with class-based components, follow the best practice of storing the host reference
 | 
			
		||||
				early in your component code. This ensures proper access to the host throughout the component's lifecycle.
 | 
			
		||||
@@ -124,7 +124,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			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.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-illustration" }).append(
 | 
			
		||||
		el("div", { className: "illustration" }).append(
 | 
			
		||||
			el("h4", t`Lifecycle Flow`),
 | 
			
		||||
			el("pre").append(el("code", `
 | 
			
		||||
1. Component created → scope established
 | 
			
		||||
@@ -139,7 +139,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/scopes/cleaning.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-note" }).append(
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			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 the signal subscription that updates the text content.
 | 
			
		||||
@@ -152,8 +152,8 @@ export function page({ pkg, info }){
 | 
			
		||||
			Scopes work best with a declarative approach to UI building, especially when combined
 | 
			
		||||
			with ${el("a", { textContent: "signals", ...references.signals })} for state management.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-tabs" }).append(
 | 
			
		||||
			el("div", { class: "tab", "data-tab": "declarative" }).append(
 | 
			
		||||
		el("div", { className: "tabs" }).append(
 | 
			
		||||
			el("div", { className: "tab", "data-tab": "declarative" }).append(
 | 
			
		||||
				el("h4", t`✅ Declarative Approach`),
 | 
			
		||||
				el("p", t`Define what your UI should look like based on state:`),
 | 
			
		||||
				el("pre").append(el("code", `function Counter() {
 | 
			
		||||
@@ -175,7 +175,7 @@ export function page({ pkg, info }){
 | 
			
		||||
	);
 | 
			
		||||
}`))
 | 
			
		||||
			),
 | 
			
		||||
			el("div", { class: "tab", "data-tab": "imperative" }).append(
 | 
			
		||||
			el("div", { className: "tab", "data-tab": "imperative" }).append(
 | 
			
		||||
				el("h4", t`⚠️ Imperative Approach`),
 | 
			
		||||
				el("p", t`Manually update the DOM in response to events:`),
 | 
			
		||||
				el("pre").append(el("code", `function Counter() {
 | 
			
		||||
@@ -203,7 +203,7 @@ export function page({ pkg, info }){
 | 
			
		||||
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/scopes/declarative.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-note" }).append(
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				While DDE supports both declarative and imperative approaches, the declarative style is recommended
 | 
			
		||||
				as it leads to more maintainable code with fewer opportunities for bugs. Signals handle the complexity
 | 
			
		||||
@@ -231,7 +231,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-troubleshooting" }).append(
 | 
			
		||||
		el("div", { className: "troubleshooting" }).append(
 | 
			
		||||
			el("h4", t`Common Scope Pitfalls`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Losing host reference in async code`),
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			to create reusable, encapsulated custom elements with all the benefits of DDE's declarative DOM
 | 
			
		||||
			construction and reactivity system.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-callout" }).append(
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`Why Combine DDE with Web Components?`),
 | 
			
		||||
			el("ul").append(
 | 
			
		||||
				el("li", t`Declarative DOM creation within your components`),
 | 
			
		||||
@@ -92,7 +92,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`),
 | 
			
		||||
		el(code, { src: fileURL("./components/examples/customElement/native-basic.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-note" }).append(
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				For complete information on Web Components, see the
 | 
			
		||||
				${el("a", references.mdn_custom_elements).append(el("strong", t`MDN documentation`))}.
 | 
			
		||||
@@ -107,7 +107,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Custom Elements. This is done with ${el("code", "customElementWithDDE")}, which makes your Custom Element
 | 
			
		||||
			compatible with DDE's event handling.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-function-table" }).append(
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
			el("h4", t`customElementWithDDE`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Purpose`),
 | 
			
		||||
@@ -120,7 +120,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/customElementWithDDE.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			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 DDE's event system.
 | 
			
		||||
@@ -132,7 +132,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			The next step is to use DDE's component rendering within your Custom Element. This is done with
 | 
			
		||||
			${el("code", "customElementRender")}, which connects your DDE component function to the Custom Element.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-function-table" }).append(
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
			el("h4", t`customElementRender`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Purpose`),
 | 
			
		||||
@@ -151,7 +151,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/dde.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-note" }).append(
 | 
			
		||||
		el("div", { className: "note" }).append(
 | 
			
		||||
			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, ...)")}.
 | 
			
		||||
@@ -163,7 +163,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			One of the most powerful features of integrating DDE with Web Components is connecting HTML attributes
 | 
			
		||||
			to DDE's reactive signals system. This creates truly reactive custom elements.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				${el("strong", "Two Ways to Handle Attributes:")}
 | 
			
		||||
			`),
 | 
			
		||||
@@ -182,7 +182,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		`),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/observedAttributes.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-callout" }).append(
 | 
			
		||||
		el("div", { className: "callout" }).append(
 | 
			
		||||
			el("h4", t`How S.observedAttributes Works`),
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				1. Takes each attribute listed in static observedAttributes
 | 
			
		||||
@@ -198,7 +198,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Shadow DOM provides encapsulation for your component's styles and markup. When using DDE with Shadow DOM,
 | 
			
		||||
			you get the best of both worlds: encapsulation plus declarative DOM creation.
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-illustration" }).append(
 | 
			
		||||
		el("div", { className: "illustration" }).append(
 | 
			
		||||
			el("h4", t`Shadow DOM Encapsulation`),
 | 
			
		||||
			el("pre").append(el("code", `
 | 
			
		||||
┌─────────────────────────────────┐
 | 
			
		||||
@@ -232,7 +232,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			Slots allow users of your component to insert content inside it. When using DDE, you can simulate the
 | 
			
		||||
			slot mechanism with the ${el("code", "simulateSlots")} function:
 | 
			
		||||
		`),
 | 
			
		||||
		el("div", { class: "dde-function-table" }).append(
 | 
			
		||||
		el("div", { className: "function-table" }).append(
 | 
			
		||||
			el("h4", t`simulateSlots`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Purpose`),
 | 
			
		||||
@@ -243,7 +243,7 @@ export function page({ pkg, info }){
 | 
			
		||||
		),
 | 
			
		||||
		el(example, { src: fileURL("./components/examples/customElement/simulateSlots.js"), page_id }),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-tip" }).append(
 | 
			
		||||
		el("div", { className: "tip" }).append(
 | 
			
		||||
			el("p").append(...T`
 | 
			
		||||
				${el("strong", "When to use simulateSlots:")} This approach is useful when you need to distribute
 | 
			
		||||
				content from the light DOM into specific locations in the shadow DOM, particularly in environments
 | 
			
		||||
@@ -273,7 +273,7 @@ export function page({ pkg, info }){
 | 
			
		||||
			`)
 | 
			
		||||
		),
 | 
			
		||||
 | 
			
		||||
		el("div", { class: "dde-troubleshooting" }).append(
 | 
			
		||||
		el("div", { className: "troubleshooting" }).append(
 | 
			
		||||
			el("h4", t`Common Issues`),
 | 
			
		||||
			el("dl").append(
 | 
			
		||||
				el("dt", t`Events not firing properly`),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user