1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-03-31 11:35:52 +02:00
This commit is contained in:
Jan Andrle 2025-03-18 17:23:23 +01:00
parent 8415f5cf6f
commit 4dba3a292a
Signed by: jaandrle
GPG Key ID: B3A25AED155AFFAB
5 changed files with 43 additions and 37 deletions

View File

@ -1,7 +1,7 @@
**Alpha**
| [source code on GitHub](https://github.com/jaandrle/deka-dom-el)
| [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
| [![git3moji](https://img.shields.io/badge/git3moji%E2%80%93v1-%E2%9A%A1%EF%B8%8F%F0%9F%90%9B%F0%9F%93%BA%F0%9F%91%AE%F0%9F%94%A4-fffad8.svg?style=flat-square)](https://robinpokorny.github.io/git3moji/) <!-- editorconfig-checker-disable-line -->
| [npm package](https://www.npmjs.com/package/deka-dom-el)
<p align="center">
<img src="docs/assets/logo.svg" alt="Deka DOM Elements Logo" width="180" height="180">
@ -24,9 +24,6 @@ function EmojiCounter({ initial }) {
const count = S(0);
const emoji = S(initial);
/** @param {HTMLOptionElement} el */
const isSelected= el=> (el.selected= el.value===initial);
// 🔄 View - UI updates automatically when signals change
return el().append(
el("p", {
@ -87,7 +84,7 @@ npm install deka-dom-el --save
…or via CDN / Direct Script:
For CDN links and various build formats (ESM/IIFE, with/without signals, minified/unminified), see the [interactive
format selector](https://jaandrle.github.io/deka-dom-el/) on the documentation site.
format selector](https://jaandrle.github.io/deka-dom-el/#h-getting-started) on the documentation site.
```html
<!-- Example with IIFE build (creates a global DDE object) -->

View File

@ -81,11 +81,11 @@ function Todos(){
)
)
),
S.el(todosS, todos => !todos.length
S.el(todosS, ({ length }) => !length
? el()
: el("footer", { className: "footer" }).append(
el("span", { className: "todo-count" }).append(
noOfLeft()
el("strong", length + " " + (length === 1 ? "item" : "items")),
),
memo("filters", ()=>
el("ul", { className: "filters" }).append(
@ -100,7 +100,7 @@ function Todos(){
)
),
),
todos.length - todosRemainingS.get() === 0
length - todosRemainingS.get() === 0
? el()
: memo("delete", () =>
el("button",
@ -110,13 +110,6 @@ function Todos(){
)
)
);
function noOfLeft(){
const length = todosRemainingS.get();
return el("strong").append(
length + " ",
length === 1 ? "item left" : "items left"
)
}
}
/**

View File

@ -16,7 +16,11 @@ import { getLibraryUrl } from "./components/getLibraryUrl.html.js";
/** @param {string} url */
const fileURL= url=> new URL(url, import.meta.url);
const references= {
w_mvv:{
npm: {
title: t`NPM package page for dd<el>`,
href: "https://www.npmjs.com/package/deka-dom-el",
},
w_mvv: {
title: t`Wikipedia: Modelviewviewmodel`,
href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel",
},
@ -106,6 +110,10 @@ export function page({ pkg, info }){
`),
el("h4", "npm installation"),
el(code, { content: "npm install deka-dom-el --save", language: "shell", page_id }),
el("p").append(T`
see ${el("a", { textContent: "package page", ...references.npm, target: "_blank" })}.
`),
el("h4", "CDN / Direct Script Usage"),
el("p").append(T`
Use the interactive selector below to choose your preferred format:

View File

@ -311,9 +311,9 @@ export function page({ pkg, info }){
el(code, { content: `
// Dynamic class attributes
el("a", {
textContent: "All",
className: S(()=> pageS.get() === "all" ? "selected" : ""),
href: "#"
textContent,
classList: { selected: S(()=> pageS.get() === textContent.toLowerCase()) },
href: \`#\${textContent.toLowerCase()}\`
})
// Reactive classList
@ -355,18 +355,25 @@ export function page({ pkg, info }){
el("h4", t`Memoizing UI Sections`),
el(code, { content: `
S.el(todosS, todos => memo(todos.length, length=> length
? el("footer", { className: "footer" }).append(
// Footer content...
S.el(todosS, ({ length }) => !length
? el()
: el("footer", { className: "footer" }).append(
// …
memo("filters", ()=>
// …
el("a", {
textContent,
classList: { selected: S(()=> pageS.get() === textContent.toLowerCase()) },
href: \`#\${textContent.toLowerCase()}\`
})
// …
)
: el()
))
`, page_id }),
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.
We memoize the UI section and uses derived signal for the classList. Re-rendering this part is therefore
unnecessary when the number of todos changes.
`),
el("div", { className: "tip" }).append(
@ -389,8 +396,10 @@ export function page({ pkg, info }){
`),
el(code, { content: `
// Event handlers in the main component
const onDelete = on("todo:delete", ev => S.action(todosS, "delete", ev.detail));
const onEdit = on("todo:edit", ev => S.action(todosS, "edit", ev.detail));
const onDelete = on("todo:delete", ev =>
S.action(todosS, "delete", /** @type {{ detail: Todo["id"] }} */(ev).detail));
const onEdit = on("todo:edit", ev =>
S.action(todosS, "edit", /** @type {{ detail: Partial<Todo> & { id: Todo["id"] } }} */(ev).detail));
`, page_id }),
el("h4", t`2. The TodoItem Component with Scopes and Local State`),
@ -522,25 +531,24 @@ export function page({ pkg, info }){
el("h4", t`Conditional Todo List`),
el(code, { content: `
S.el(todosS, todos => todos.length
? el("main", { className: "main" }).append(
? el()
: el("main", { className: "main" }).append(
// Main content with toggle all and todo list
)
: el()
)
`, page_id }),
el("h4", t`Conditional Edit Form`),
el(code, { content: `
S.el(isEditing, editing => editing
? el("form", null, onSubmitEdit).append(
S.el(isEditing, editing => !editing
? el()
: el("form", null, onSubmitEdit).append(
el("input", {
className: "edit",
name: "edit",
name: formEdit,
value: title,
"data-id": id
}, onBlurEdit, onKeyDown, addFocus)
)
: el()
)
`, page_id }),
@ -630,7 +638,7 @@ export function page({ pkg, info }){
${el("strong", "Declarative Class Management:")} Using the classList property for cleaner class handling
`),
el("li").append(T`
${el("strong", "Focus Management:")} Reliable input focus with setTimeout
${el("strong", "Focus Management:")} Reliable input focus with requestAnimationFrame
`),
el("li").append(T`
${el("strong", "Persistent Storage:")} Automatically saving application state with signal listeners

View File

@ -4,7 +4,7 @@
"description": "A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks.",
"author": "Jan Andrle <andrle.jan@centrum.cz>",
"license": "MIT",
"homepage": "https://github.com/jaandrle/deka-dom-el",
"homepage": "https://jaandrle.github.io/deka-dom-el/",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/jaandrle/deka-dom-el.git"