1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-01 04:12:14 +02:00

🐛 📺 v0.9.5-alpha (#44)

*  📺 package (version and publint)

* 🔤 docs typos

* 🐛 this address / fixes #43

*  tiny el optimalization

* 🔤 improve docs wording

* 🔤 case-studies/products.js (AbortSignal)

* 🔤 🐛 case-studies/image-gallery.js
This commit is contained in:
2025-03-21 14:43:25 +01:00
committed by GitHub
parent 4c450ae763
commit f2c85ec983
19 changed files with 180 additions and 84 deletions

View File

@ -82,10 +82,10 @@ export function ImageGallery(images= imagesSample) {
closeLightbox();
break;
case 'ArrowLeft':
document.querySelector('.lightbox-prev-btn').click();
onPrevImage(e);
break;
case 'ArrowRight':
document.querySelector('.lightbox-next-btn').click();
onNextImage(e);
break;
}
}
@ -126,12 +126,12 @@ export function ImageGallery(images= imagesSample) {
el("div", {
className: "gallery-item",
dataTag: image.alt.toLowerCase()
}).append(
}, onImageClick(image.id)).append(
el("img", {
src: image.src,
alt: image.alt,
loading: "lazy"
}, onImageClick(image.id)),
}),
el("div", { className: "gallery-item-caption" }).append(
el("h3", image.title),
el("p", image.alt)
@ -146,41 +146,41 @@ export function ImageGallery(images= imagesSample) {
S.el(isLightboxOpen, open => !open
? el()
: el("div", { className: "lightbox-overlay" }, on("click", closeLightbox)).append(
el("div", {
className: "lightbox-content",
onClick: e => e.stopPropagation() // Prevent closing when clicking inside
}).append(
el("button", {
className: "lightbox-close-btn",
"aria-label": "Close lightbox"
}, on("click", closeLightbox)).append("×"),
el("div", {
className: "lightbox-content",
onClick: e => e.stopPropagation() // Prevent closing when clicking inside
}).append(
el("button", {
className: "lightbox-close-btn",
ariaLabel: "Close lightbox",
}, on("click", closeLightbox)).append("×"),
el("button", {
className: "lightbox-prev-btn",
"aria-label": "Previous image"
}, on("click", onPrevImage)).append(""),
el("button", {
className: "lightbox-prev-btn",
ariaLabel: "Previous image",
}, on("click", onPrevImage)).append(""),
el("button", {
className: "lightbox-next-btn",
"aria-label": "Next image"
}, on("click", onNextImage)).append(""),
el("button", {
className: "lightbox-next-btn",
ariaLabel: "Next image",
}, on("click", onNextImage)).append(""),
S.el(selectedImage, img => !img
? el()
: el("div", { className: "lightbox-image-container" }).append(
el("img", {
src: img.src,
alt: img.alt,
className: "lightbox-image"
}),
el("div", { className: "lightbox-caption" }).append(
el("h2", img.title),
el("p", img.alt)
)
)
S.el(selectedImage, img => !img
? el()
: el("div", { className: "lightbox-image-container" }).append(
el("img", {
src: img.src,
alt: img.alt,
className: "lightbox-image",
}),
el("div", { className: "lightbox-caption" }).append(
el("h2", img.title),
el("p", img.alt),
),
)
)
)
),
),
),
),
);
}

View File

@ -1,9 +1,13 @@
import { el, on } from "deka-dom-el";
import { el, on, scope } from "deka-dom-el";
import { S } from "deka-dom-el/signals";
export function ProductCatalog() {
const { signal }= scope;
const itemsPerPage = 5;
const products = asyncSignal(S, fetchProducts, { initial: [], keepLast: true });
const products = asyncSignal(S,
fetchProducts,
{ initial: [], keepLast: true, signal });
const searchTerm = S("");
const handleSearch = (e) => searchTerm.set(e.target.value);
const sortOrder = S("default");
@ -220,10 +224,14 @@ function simulateNetworkDelay(min = 300, max = 1200) {
* @template T
* @param {typeof S} S - Signal constructor
* @param {(params: { signal: AbortSignal }) => Promise<T>} invoker - Async function to execute
* @param {{ initial?: T, keepLast?: boolean }} options - Configuration options
* @param {{ initial?: T, keepLast?: boolean, signal?: AbortSignal }} options - Configuration options
* @returns {Object} Status signals and control methods
*/
export function asyncSignal(S, invoker, { initial, keepLast } = {}) {
export function asyncSignal(S, invoker, { initial, keepLast, signal } = {}) {
/** @type {(s: AbortSignal) => AbortSignal} */
const anySignal = !signal || !AbortSignal.any // TODO: make better
? s=> s
: s=> AbortSignal.any([s, signal]);
// Status tracking signals
const status = S("pending");
const result = S(initial);
@ -242,7 +250,7 @@ export function asyncSignal(S, invoker, { initial, keepLast } = {}) {
try {
const data = await invoker({
signal: controller.signal,
signal: anySignal(controller.signal),
});
if (!controller.signal.aborted) {
status.set("resolved");

View File

@ -74,13 +74,11 @@ export function h3({ textContent, id }){
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
return el("h3", { id }).append(
el("a", {
className: "heading-anchor",
href: "#"+id,
textContent: "#",
title: `Link to this section: ${textContent}`,
"aria-label": `Link to section ${textContent}`
className: "heading-anchor",
href: "#"+id,
title: `Link to this section: ${textContent}`,
}),
" ",
"# ",
textContent,
);
}