diff --git a/README.md b/README.md index a9b94f2..3a2cafb 100644 --- a/README.md +++ b/README.md @@ -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/) +| [npm package](https://www.npmjs.com/package/deka-dom-el)

Deka DOM Elements Logo @@ -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 diff --git a/docs/components/examples/reallife/todomvc.js b/docs/components/examples/reallife/todomvc.js index b2c0985..09ef0af 100644 --- a/docs/components/examples/reallife/todomvc.js +++ b/docs/components/examples/reallife/todomvc.js @@ -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" - ) - } } /** diff --git a/docs/index.html.js b/docs/index.html.js index 3982987..5dad63a 100644 --- a/docs/index.html.js +++ b/docs/index.html.js @@ -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`, + href: "https://www.npmjs.com/package/deka-dom-el", + }, + w_mvv: { title: t`Wikipedia: Model–view–viewmodel`, 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: diff --git a/docs/p10-todomvc.html.js b/docs/p10-todomvc.html.js index d3f1854..8d1da9b 100644 --- a/docs/p10-todomvc.html.js +++ b/docs/p10-todomvc.html.js @@ -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 & { 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 diff --git a/package.json b/package.json index e1f7ba1..f3c29bd 100644 --- a/package.json +++ b/package.json @@ -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 ", "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"