mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-04-02 04:05:52 +02:00
🔤
This commit is contained in:
parent
8415f5cf6f
commit
4dba3a292a
@ -1,7 +1,7 @@
|
|||||||
**Alpha**
|
**Alpha**
|
||||||
| [source code on GitHub](https://github.com/jaandrle/deka-dom-el)
|
| [source code on GitHub](https://github.com/jaandrle/deka-dom-el)
|
||||||
| [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
|
| [*mirrored* on Gitea](https://gitea.jaandrle.cz/jaandrle/deka-dom-el)
|
||||||
| [](https://robinpokorny.github.io/git3moji/) <!-- editorconfig-checker-disable-line -->
|
| [npm package](https://www.npmjs.com/package/deka-dom-el)
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="docs/assets/logo.svg" alt="Deka DOM Elements Logo" width="180" height="180">
|
<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 count = S(0);
|
||||||
const emoji = S(initial);
|
const emoji = S(initial);
|
||||||
|
|
||||||
/** @param {HTMLOptionElement} el */
|
|
||||||
const isSelected= el=> (el.selected= el.value===initial);
|
|
||||||
|
|
||||||
// 🔄 View - UI updates automatically when signals change
|
// 🔄 View - UI updates automatically when signals change
|
||||||
return el().append(
|
return el().append(
|
||||||
el("p", {
|
el("p", {
|
||||||
@ -87,7 +84,7 @@ npm install deka-dom-el --save
|
|||||||
…or via CDN / Direct Script:
|
…or via CDN / Direct Script:
|
||||||
|
|
||||||
For CDN links and various build formats (ESM/IIFE, with/without signals, minified/unminified), see the [interactive
|
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
|
```html
|
||||||
<!-- Example with IIFE build (creates a global DDE object) -->
|
<!-- Example with IIFE build (creates a global DDE object) -->
|
||||||
|
@ -81,11 +81,11 @@ function Todos(){
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
S.el(todosS, todos => !todos.length
|
S.el(todosS, ({ length }) => !length
|
||||||
? el()
|
? el()
|
||||||
: el("footer", { className: "footer" }).append(
|
: el("footer", { className: "footer" }).append(
|
||||||
el("span", { className: "todo-count" }).append(
|
el("span", { className: "todo-count" }).append(
|
||||||
noOfLeft()
|
el("strong", length + " " + (length === 1 ? "item" : "items")),
|
||||||
),
|
),
|
||||||
memo("filters", ()=>
|
memo("filters", ()=>
|
||||||
el("ul", { className: "filters" }).append(
|
el("ul", { className: "filters" }).append(
|
||||||
@ -100,7 +100,7 @@ function Todos(){
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
todos.length - todosRemainingS.get() === 0
|
length - todosRemainingS.get() === 0
|
||||||
? el()
|
? el()
|
||||||
: memo("delete", () =>
|
: memo("delete", () =>
|
||||||
el("button",
|
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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,11 @@ import { getLibraryUrl } from "./components/getLibraryUrl.html.js";
|
|||||||
/** @param {string} url */
|
/** @param {string} url */
|
||||||
const fileURL= url=> new URL(url, import.meta.url);
|
const fileURL= url=> new URL(url, import.meta.url);
|
||||||
const references= {
|
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: Model–view–viewmodel`,
|
title: t`Wikipedia: Model–view–viewmodel`,
|
||||||
href: "https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel",
|
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("h4", "npm installation"),
|
||||||
el(code, { content: "npm install deka-dom-el --save", language: "shell", page_id }),
|
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("h4", "CDN / Direct Script Usage"),
|
||||||
el("p").append(T`
|
el("p").append(T`
|
||||||
Use the interactive selector below to choose your preferred format:
|
Use the interactive selector below to choose your preferred format:
|
||||||
|
@ -311,9 +311,9 @@ export function page({ pkg, info }){
|
|||||||
el(code, { content: `
|
el(code, { content: `
|
||||||
// Dynamic class attributes
|
// Dynamic class attributes
|
||||||
el("a", {
|
el("a", {
|
||||||
textContent: "All",
|
textContent,
|
||||||
className: S(()=> pageS.get() === "all" ? "selected" : ""),
|
classList: { selected: S(()=> pageS.get() === textContent.toLowerCase()) },
|
||||||
href: "#"
|
href: \`#\${textContent.toLowerCase()}\`
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reactive classList
|
// Reactive classList
|
||||||
@ -355,18 +355,25 @@ export function page({ pkg, info }){
|
|||||||
|
|
||||||
el("h4", t`Memoizing UI Sections`),
|
el("h4", t`Memoizing UI Sections`),
|
||||||
el(code, { content: `
|
el(code, { content: `
|
||||||
S.el(todosS, todos => memo(todos.length, length=> length
|
S.el(todosS, ({ length }) => !length
|
||||||
? el("footer", { className: "footer" }).append(
|
? el()
|
||||||
// Footer content...
|
: el("footer", { className: "footer" }).append(
|
||||||
|
// …
|
||||||
|
memo("filters", ()=>
|
||||||
|
// …
|
||||||
|
el("a", {
|
||||||
|
textContent,
|
||||||
|
classList: { selected: S(()=> pageS.get() === textContent.toLowerCase()) },
|
||||||
|
href: \`#\${textContent.toLowerCase()}\`
|
||||||
|
})
|
||||||
|
// …
|
||||||
)
|
)
|
||||||
: el()
|
|
||||||
))
|
))
|
||||||
`, page_id }),
|
`, 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
|
We memoize the UI section and uses derived signal for the classList. Re-rendering this part is therefore
|
||||||
when todos are added or removed, not when their properties change. This improves performance
|
unnecessary when the number of todos changes.
|
||||||
by avoiding unnecessary DOM operations.
|
|
||||||
`),
|
`),
|
||||||
|
|
||||||
el("div", { className: "tip" }).append(
|
el("div", { className: "tip" }).append(
|
||||||
@ -389,8 +396,10 @@ export function page({ pkg, info }){
|
|||||||
`),
|
`),
|
||||||
el(code, { content: `
|
el(code, { content: `
|
||||||
// Event handlers in the main component
|
// Event handlers in the main component
|
||||||
const onDelete = on("todo:delete", ev => S.action(todosS, "delete", ev.detail));
|
const onDelete = on("todo:delete", ev =>
|
||||||
const onEdit = on("todo:edit", ev => S.action(todosS, "edit", ev.detail));
|
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 }),
|
`, page_id }),
|
||||||
|
|
||||||
el("h4", t`2. The TodoItem Component with Scopes and Local State`),
|
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("h4", t`Conditional Todo List`),
|
||||||
el(code, { content: `
|
el(code, { content: `
|
||||||
S.el(todosS, todos => todos.length
|
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
|
// Main content with toggle all and todo list
|
||||||
)
|
)
|
||||||
: el()
|
|
||||||
)
|
)
|
||||||
`, page_id }),
|
`, page_id }),
|
||||||
|
|
||||||
el("h4", t`Conditional Edit Form`),
|
el("h4", t`Conditional Edit Form`),
|
||||||
el(code, { content: `
|
el(code, { content: `
|
||||||
S.el(isEditing, editing => editing
|
S.el(isEditing, editing => !editing
|
||||||
? el("form", null, onSubmitEdit).append(
|
? el()
|
||||||
|
: el("form", null, onSubmitEdit).append(
|
||||||
el("input", {
|
el("input", {
|
||||||
className: "edit",
|
className: "edit",
|
||||||
name: "edit",
|
name: formEdit,
|
||||||
value: title,
|
value: title,
|
||||||
"data-id": id
|
|
||||||
}, onBlurEdit, onKeyDown, addFocus)
|
}, onBlurEdit, onKeyDown, addFocus)
|
||||||
)
|
)
|
||||||
: el()
|
|
||||||
)
|
)
|
||||||
`, page_id }),
|
`, 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("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 setTimeout
|
${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("strong", "Persistent Storage:")} Automatically saving application state with signal listeners
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"description": "A low-code library that simplifies the creation of native DOM elements/components using small wrappers and tweaks.",
|
"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>",
|
"author": "Jan Andrle <andrle.jan@centrum.cz>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://github.com/jaandrle/deka-dom-el",
|
"homepage": "https://jaandrle.github.io/deka-dom-el/",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+ssh://git@github.com/jaandrle/deka-dom-el.git"
|
"url": "git+ssh://git@github.com/jaandrle/deka-dom-el.git"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user