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

🔤 🐛 v0.9.1-alpha (#30)

* :tap: removed on.attributeChanged and static observedAttributes

*  import optimalization

*  scope.signal

* 🔤 🐛

*  🐛 registerReactivity and types

* 🔤

* 

* 🔤

* 🐛 Node in enviroment

*  todos

* 

*  🔤

*  lint

*  memo

* 🔤 🐛 memo

*  🔤 todomvc

* 🐛 types

* 🔤 p08 signal factory

* 🔤  types

*  🔤 lint

* 🔤

* 🔤

* 🔤

* 🔤

* 📺
This commit is contained in:
2025-03-12 18:37:42 +01:00
committed by GitHub
parent e1f321004d
commit 25d475ec04
83 changed files with 4899 additions and 2182 deletions

View File

@@ -48,7 +48,7 @@ export function page({ pkg, info }){
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.
`),
el("div", { class: "callout" }).append(
el("div", { className: "callout" }).append(
el("h4", t`What Makes Signals Special?`),
el("ul").append(
el("li", t`Fine-grained reactivity without complex state management`),
@@ -65,18 +65,18 @@ export function page({ pkg, info }){
Signals organize your code into three distinct parts, following the
${el("a", { textContent: t`3PS principle`, href: "./#h-3ps" })}:
`),
el("div", { class: "signal-diagram" }).append(
el("div", { class: "signal-part" }).append(
el("div", { className: "signal-diagram" }).append(
el("div", { className: "signal-part" }).append(
el("h4", t`PART 1: Create Signal`),
el(code, { content: "const count = S(0);", page_id }),
el("p", t`Define a reactive value that can be observed and changed`)
el("p", t`Define a reactive value that can be observed and changed`)
),
el("div", { class: "signal-part" }).append(
el("div", { className: "signal-part" }).append(
el("h4", t`PART 2: React to Changes`),
el(code, { content: "S.on(count, value => updateUI(value));", page_id }),
el("p", t`Subscribe to signal changes with callbacks or effects`)
),
el("div", { class: "signal-part" }).append(
el("div", { className: "signal-part" }).append(
el("h4", t`PART 3: Update Signal`),
el(code, { content: "count.set(count.get() + 1);", page_id }),
el("p", t`Modify the signal value, which automatically triggers updates`)
@@ -84,26 +84,26 @@ export function page({ pkg, info }){
),
el(example, { src: fileURL("./components/examples/signals/signals.js"), page_id }),
el("div", { class: "note" }).append(
el("div", { className: "note" }).append(
el("p").append(...T`
Signals implement the ${el("a", { textContent: t`Publishsubscribe 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 a shared signal,
without direct dependencies on each other. Compare for example with ${el("a", { textContent:
t`fpubsub library`, ...references.fpubsub })}.
Signals implement the ${el("a", { textContent: t`Publishsubscribe 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
a shared signal, without direct dependencies on each other. Compare for example with ${el("a", {
textContent: t`fpubsub library`, ...references.fpubsub })}.
`)
),
el(h3, t`Signal Essentials: Core API`),
el("div", { class: "function-table" }).append(
el("div", { className: "function-table" }).append(
el("dl").append(
el("dt", t`Creating a Signal`),
el("dt", t`Creating a Signal`),
el("dd", t`S(initialValue) → creates a signal with the given value`),
el("dt", t`Reading a Signal`),
el("dt", t`Reading a Signal`),
el("dd", t`signal.get() → returns the current value`),
el("dt", t`Writing to a Signal`),
el("dt", t`Writing to a Signal`),
el("dd", t`signal.set(newValue) → updates the value and notifies subscribers`),
el("dt", t`Subscribing to Changes`),
@@ -115,51 +115,53 @@ export function page({ pkg, info }){
)
),
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).
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, youll want to use Actions (covered below).
`),
el(h3, t`Derived Signals: Computed Values`),
el("p").append(...T`
Computed values (also called derived signals) automatically update when their dependencies change.
Create them by passing a function to S():
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`
Derived signals are read-only - you can't call .set() on them. Their value is always computed
from their dependencies. They're perfect for transforming or combining data from other signals.
Derived signals are read-only - you cant call ${el("code", ".set()")} on them. Their value is always
computed from their dependencies. Theyre 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`
When working with objects, arrays, or other complex data structures, Signal Actions provide
a structured way to modify state while maintaining reactivity.
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: "illustration" }).append(
el("div", { className: "illustration" }).append(
el("h4", t`Actions vs. Direct Mutation`),
el("div", { class: "comparison" }).append(
el("div", { class: "good-practice" }).append(
el("div", { className: "comparison" }).append(
el("div", { className: "good-practice" }).append(
el("h5", t`✅ With Actions`),
el(code, { content: `const todos = S([], {
add(text) {
this.value.push(text);
// Subscribers notified automatically
}
});
// Use the action
S.action(todos, "add", "New todo");`, page_id })
el(code, { content: `
const todos = S([], {
add(text) {
this.value.push(text);
// Subscribers notified automatically
}
});
// Use the action
S.action(todos, "add", "New todo");
`, page_id })
),
el("div", { class: "bad-practice" }).append(
el("div", { className: "bad-practice" }).append(
el("h5", t`❌ Without Actions`),
el(code, { content: `
const todos = S([]);
// Directly mutating the array
const items = todos.get();
items.push("New todo");
// This WON'T trigger updates!`, page_id }))
const todos = S([]);
// Directly mutating the array
const items = todos.get();
items.push("New todo");
// This WONT trigger updates!
`, page_id }))
),
),
el("p").append(...T`
@@ -182,16 +184,19 @@ items.push("New todo");
el("li", t`Act similar to reducers in other state management libraries`)
),
el("p").append(...T`
Here's a more complete example of a todo list using signal actions:
Heres 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", { class: "tip" }).append(
el("div", { className: "tip" }).append(
el("p").append(...T`
${el("strong", "Special Action Methods")}: Signal actions can implement special lifecycle hooks:
`),
el("ul").append(
el("li", t`[S.symbols.onclear]() - Called when the signal is cleared. Use it to clean up resources.`),
el("li").append(...T`
${el("code", "[S.symbols.onclear]()")} - Called when the signal is cleared. Use it to clean up
resources.
`),
)
),
@@ -200,39 +205,43 @@ items.push("New todo");
Signals really shine when connected to your UI. dd<el> provides several ways to bind signals to DOM elements:
`),
el("div", { class: "tabs" }).append(
el("div", { class: "tab", "data-tab": "attributes" }).append(
el("div", { className: "tabs" }).append(
el("div", { className: "tab", dataTab: "attributes" }).append(
el("h4", t`Reactive Attributes`),
el("p", t`Bind signal values directly to element attributes, properties, or styles:`),
el(code, { content: `// Create a signal
const color = S("blue");
el(code, { content: `
// Create a signal
const color = S("blue");
// Bind it to an element's style
el("div", {
style: {
color, // Updates when signal changes
fontWeight: S(() => color.get() === "red" ? "bold" : "normal")
}
}, "This text changes color");
// Bind it to an elements style
el("div", {
style: {
color, // Updates when signal changes
fontWeight: S(() => color.get() === "red" ? "bold" : "normal")
}
}, "This text changes color");
// Later:
color.set("red"); // UI updates automatically`, page_id })
// Later:
color.set("red"); // UI updates automatically
`, page_id }),
),
el("div", { class: "tab", "data-tab": "elements" }).append(
el("div", { className: "tab", dataTab: "elements" }).append(
el("h4", t`Reactive Elements`),
el("p", t`Dynamically create or update elements based on signal values:`),
el(code, { content: `// Create an array signal
const items = S(["Apple", "Banana", "Cherry"]);
el(code, { content: `
// Create an array signal
const items = S(["Apple", "Banana", "Cherry"]);
// Create a dynamic list that updates when items change
el("ul").append(
S.el(items, items =>
items.map(item => el("li", item))
)
);
// Create a dynamic list that updates when items change
el("ul").append(
S.el(items, items =>
items.map(item => el("li", item))
)
);
// Later:
S.action(items, "push", "Dragonfruit"); // List updates automatically`, page_id })
// Later:
S.action(items, "push", "Dragonfruit"); // List updates automatically
`, page_id }),
)
),
@@ -254,23 +263,24 @@ S.action(items, "push", "Dragonfruit"); // List updates automatically`, page_id
`),
el("ol").append(
el("li").append(...T`
${el("strong", "Keep signals small and focused")}: Use many small signals rather than a few large ones
${el("strong", "Keep signals small and focused")}: Use many small signals rather than a few large ones
`),
el("li").append(...T`
${el("strong", "Use derived signals for computations")}: Don't recompute values in multiple places
${el("strong", "Use derived signals for computations")}: Dont recompute values in multiple places
`),
el("li").append(...T`
${el("strong", "Clean up signal subscriptions")}: Use AbortController or scope.host() to prevent memory leaks
${el("strong", "Clean up signal subscriptions")}: Use AbortController (scope.host()) to prevent memory
leaks
`),
el("li").append(...T`
${el("strong", "Use actions for complex state")}: Don't directly mutate objects or arrays in signals
${el("strong", "Use actions for complex state")}: Dont directly mutate objects or arrays in signals
`),
el("li").append(...T`
${el("strong", "Avoid infinite loops")}: Be careful when one signal updates another in a subscription
${el("strong", "Avoid infinite loops")}: Be careful when one signal updates another in a subscription
`)
),
el("div", { class: "troubleshooting" }).append(
el("div", { className: "troubleshooting" }).append(
el("h4", t`Common Signal Pitfalls`),
el("dl").append(
el("dt", t`UI not updating when array/object changes`),