1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-03-31 11:35:52 +02:00

Compare commits

...

4 Commits

Author SHA1 Message Date
a459c0d786
📺 version 2025-03-18 17:32:41 +01:00
a1831d2cc4
🔤 corrects irland page headers 2025-03-18 17:30:42 +01:00
a8fa048522
📺 requestIdleCallback doesn need to be global 2025-03-18 17:24:01 +01:00
4dba3a292a
🔤 2025-03-18 17:23:23 +01:00
7 changed files with 48 additions and 44 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

@ -1,9 +1,8 @@
import { T, t } from "./utils/index.js";
export const info= {
title: t`Ireland Components`,
fullTitle: t`Interactive Demo Components with Server-Side Pre-Rendering`,
description: t`Creating live, interactive component examples in documentation with server-side
rendering and client-side hydration.`,
fullTitle: t`Server-Side Pre-Rendering and Client-Side Rehydration`,
description: t`Using Ireland components for server-side pre-rendering and client-side rehydration`,
};
import { el } from "deka-dom-el";

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "deka-dom-el",
"version": "0.9.3-alpha",
"version": "0.9.4-alpha",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "deka-dom-el",
"version": "0.9.3-alpha",
"version": "0.9.4-alpha",
"license": "MIT",
"devDependencies": {
"@size-limit/preset-small-lib": "~11.2",

View File

@ -1,10 +1,10 @@
{
"name": "deka-dom-el",
"version": "0.9.3-alpha",
"version": "0.9.4-alpha",
"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"
@ -52,7 +52,6 @@
"maxdepth": 3,
"maxcomplexity": 14,
"globals": {
"requestIdleCallback": false,
"AbortController": false,
"AbortSignal": false,
"FinalizationRegistry": false