added thumbs generation for performation and also added a new deck format for registration

This commit is contained in:
2026-03-08 05:40:53 -07:00
parent 78abb582dd
commit 4713bbd54b
11 changed files with 1255 additions and 44 deletions

View File

@@ -45,6 +45,7 @@
const config = {
resolveTarotCardImage: null,
resolveTarotCardThumbnail: null,
getDisplayCardName: (card) => card?.name || "",
clearChildren: () => {},
normalizeTarotCardLookupName: (value) => String(value || "").trim().toLowerCase(),
@@ -59,6 +60,8 @@
getHouseBottomInfoModes: () => ({})
};
let houseImageObserver = null;
function init(nextConfig = {}) {
Object.assign(config, nextConfig || {});
}
@@ -597,6 +600,73 @@
return faceEl;
}
function disconnectHouseImageObserver() {
if (!houseImageObserver) {
return;
}
houseImageObserver.disconnect();
houseImageObserver = null;
}
function hydrateHouseCardImage(image) {
if (!(image instanceof HTMLImageElement)) {
return;
}
const nextSrc = String(image.dataset.src || "").trim();
if (!nextSrc || image.dataset.imageHydrated === "true") {
return;
}
image.dataset.imageHydrated = "true";
image.classList.add("is-loading");
image.src = nextSrc;
}
function getHouseImageObserver(elements) {
const root = elements?.tarotHouseOfCardsEl?.closest(".tarot-section-house-top") || null;
if (!root || typeof IntersectionObserver !== "function") {
return null;
}
if (houseImageObserver) {
return houseImageObserver;
}
houseImageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
return;
}
const target = entry.target;
observer.unobserve(target);
hydrateHouseCardImage(target);
});
}, {
root,
rootMargin: "160px 0px",
threshold: 0.01
});
return houseImageObserver;
}
function registerHouseCardImage(image, elements) {
if (!(image instanceof HTMLImageElement)) {
return;
}
const observer = getHouseImageObserver(elements);
if (!observer) {
hydrateHouseCardImage(image);
return;
}
observer.observe(image);
}
function createHouseCardButton(card, elements) {
const button = document.createElement("button");
button.type = "button";
@@ -620,16 +690,30 @@
button.title = labelText ? `${cardDisplayName || card.name} - ${labelText}` : (cardDisplayName || card.name);
button.setAttribute("aria-label", labelText ? `${cardDisplayName || card.name}, ${labelText}` : (cardDisplayName || card.name));
button.dataset.houseCardId = card.id;
const imageUrl = typeof config.resolveTarotCardImage === "function"
? config.resolveTarotCardImage(card.name)
: null;
const imageUrl = typeof config.resolveTarotCardThumbnail === "function"
? config.resolveTarotCardThumbnail(card.name)
: (typeof config.resolveTarotCardImage === "function" ? config.resolveTarotCardImage(card.name) : null);
if (showImage && imageUrl) {
const image = document.createElement("img");
image.className = "tarot-house-card-image";
image.src = imageUrl;
image.alt = cardDisplayName || card.name;
image.alt = "";
image.setAttribute("aria-hidden", "true");
image.loading = "lazy";
image.decoding = "async";
image.fetchPriority = config.isHouseFocusMode?.() === true ? "auto" : "low";
image.dataset.src = imageUrl;
image.addEventListener("load", () => {
image.classList.remove("is-loading");
image.classList.add("is-loaded");
}, { once: true });
image.addEventListener("error", () => {
image.classList.remove("is-loading");
image.classList.remove("is-loaded");
image.dataset.imageHydrated = "false";
});
button.appendChild(image);
registerHouseCardImage(image, elements);
} else if (showImage) {
const fallback = document.createElement("span");
fallback.className = "tarot-house-card-fallback";
@@ -1095,6 +1179,7 @@
}
const cards = config.getCards();
disconnectHouseImageObserver();
config.clearChildren(elements.tarotHouseOfCardsEl);
const cardLookupMap = getCardLookupMap(cards);