From 5744edadb9cd0afde3ea8ee6a153bf930ffc6643 Mon Sep 17 00:00:00 2001 From: Nose Date: Fri, 24 Apr 2026 00:38:44 -0700 Subject: [PATCH] updated card images --- app/ui-cube-chassis.js | 31 ++++++--- app/ui-cube-detail.js | 141 +++++++++++++++++++++++++++++++++++++++ app/ui-cube-selection.js | 5 +- app/ui-cube.js | 22 ++++++ app/ui-tarot-frame.js | 34 +++++++++- index.html | 10 +-- 6 files changed, 225 insertions(+), 18 deletions(-) diff --git a/app/ui-cube-chassis.js b/app/ui-cube-chassis.js index 1b450df..22269fc 100644 --- a/app/ui-cube-chassis.js +++ b/app/ui-cube-chassis.js @@ -22,6 +22,7 @@ getWallFaceLetter, getWallTarotCard, resolveCardImageUrl, + openTarotCardInfo, openTarotCardLightbox, MOTHER_CONNECTORS, formatDirectionName, @@ -48,6 +49,18 @@ svg.setAttribute("role", "img"); svg.setAttribute("aria-label", "Cube of Space interactive chassis"); + function openTarotTarget(cardName, fallbackSrc, fallbackLabel) { + if (typeof openTarotCardInfo === "function" && openTarotCardInfo(cardName) === true) { + return true; + } + + if (typeof openTarotCardLightbox === "function") { + return openTarotCardLightbox(cardName, fallbackSrc, fallbackLabel); + } + + return false; + } + const wallById = new Map(walls.map((wall) => [normalizeId(wall?.id), wall])); const projectedVertices = projectVertices(); const faces = Object.entries(FACE_GEOMETRY) @@ -144,14 +157,14 @@ cardImg.addEventListener("click", (event) => { event.stopPropagation(); selectWall(); - openTarotCardLightbox(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`); + openTarotTarget(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`); }); cardImg.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); event.stopPropagation(); selectWall(); - openTarotCardLightbox(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`); + openTarotTarget(wallTarotCard, cardUrl, `${wall?.name || wallId} wall tarot card`); } }); svg.appendChild(cardImg); @@ -263,14 +276,14 @@ connectorImg.addEventListener("click", (event) => { event.stopPropagation(); selectConnector(); - openTarotCardLightbox(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector"); + openTarotTarget(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector"); }); connectorImg.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); event.stopPropagation(); selectConnector(); - openTarotCardLightbox(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector"); + openTarotTarget(connectorTarotCard, connectorCardUrl, connector?.name || "Mother connector"); } }); group.appendChild(connectorImg); @@ -336,7 +349,7 @@ const selectEdge = () => { state.selectedEdgeId = edgeId; - state.selectedNodeType = "wall"; + state.selectedNodeType = "edge"; state.selectedConnectorId = null; if (!edgeWalls.includes(normalizeId(state.selectedWallId)) && edgeWalls[0]) { state.selectedWallId = edgeWalls[0]; @@ -399,14 +412,14 @@ cardImg.addEventListener("click", (event) => { event.stopPropagation(); selectEdge(); - openTarotCardLightbox(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge"); + openTarotTarget(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge"); }); cardImg.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); event.stopPropagation(); selectEdge(); - openTarotCardLightbox(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge"); + openTarotTarget(edgeTarotCard, edgeCardUrl, edge?.name || "Cube edge"); } }); marker.appendChild(cardImg); @@ -486,7 +499,7 @@ state.selectedNodeType = "center"; state.selectedConnectorId = null; render(getElements()); - openTarotCardLightbox(centerTarotCard, centerCardUrl, "Primal Point"); + openTarotTarget(centerTarotCard, centerCardUrl, "Primal Point"); }); centerImg.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { @@ -495,7 +508,7 @@ state.selectedNodeType = "center"; state.selectedConnectorId = null; render(getElements()); - openTarotCardLightbox(centerTarotCard, centerCardUrl, "Primal Point"); + openTarotTarget(centerTarotCard, centerCardUrl, "Primal Point"); } }); centerMarker.appendChild(centerImg); diff --git a/app/ui-cube-detail.js b/app/ui-cube-detail.js index 0d369fe..9c232de 100644 --- a/app/ui-cube-detail.js +++ b/app/ui-cube-detail.js @@ -520,6 +520,143 @@ renderEdgeCard(context, wall, bodyEl, wallEdgeDirections); } + function renderEdgeDetail(context) { + const { + state, + elements, + normalizeId, + normalizeEdgeId, + formatEdgeName, + getWallById, + getEdgeById, + getEdges, + getEdgeWalls, + getEdgeLetterId, + getEdgeLetter, + getEdgePathEntry, + getEdgeAstrologySymbol, + getHebrewLetterName, + toFiniteNumber, + onSelectWall + } = context; + + const edge = getEdgeById(state.selectedEdgeId) || getEdges()[0] || null; + if (!edge || !elements?.detailNameEl || !elements?.detailSubEl || !elements?.detailBodyEl) { + return false; + } + + const edgeId = normalizeEdgeId(edge.id); + const edgeWalls = getEdgeWalls(edge); + const currentWallId = normalizeId(state.selectedWallId); + const preferredWallId = edgeWalls.includes(currentWallId) + ? currentWallId + : normalizeId(edgeWalls[0]); + + if (preferredWallId) { + state.selectedWallId = preferredWallId; + } + state.selectedEdgeId = edgeId; + + const wallNames = edgeWalls + .map((wallId) => getWallById(wallId)?.name || wallId) + .filter(Boolean) + .join(" ↔ "); + const edgeName = toDisplayText(edge?.name) || formatEdgeName(edgeId); + const edgeLetterId = getEdgeLetterId(edge); + const edgeLetter = getEdgeLetter(edge); + const edgeLetterName = edgeLetterId ? (getHebrewLetterName(edgeLetterId) || edgeLetterId) : ""; + const edgeLetterText = edgeLetterId + ? [edgeLetter, edgeLetterName].filter(Boolean).join(" ") + : ""; + const edgePath = getEdgePathEntry(edge); + const astrologyType = toDisplayText(edgePath?.astrology?.type); + const astrologyName = toDisplayText(edgePath?.astrology?.name); + const astrologySymbol = getEdgeAstrologySymbol(edge); + const astrologyText = astrologySymbol && astrologyName + ? `${astrologySymbol} ${astrologyName}` + : astrologySymbol || astrologyName; + const tarotCard = toDisplayText(edgePath?.tarot?.card); + const tarotTrumpNumber = toFiniteNumber(edgePath?.tarot?.trumpNumber); + const pathNo = toFiniteNumber(edgePath?.pathNumber); + + elements.detailNameEl.textContent = `${edgeName} Edge`; + elements.detailSubEl.textContent = [edgeLetterText, astrologyText].filter(Boolean).join(" · ") || "Cube Edge"; + + const bodyEl = elements.detailBodyEl; + bodyEl.innerHTML = ""; + + const summary = document.createElement("div"); + summary.className = "planet-text"; + summary.innerHTML = ` +
+
Name
${toDetailValueMarkup(edgeName)}
+
Between
${toDetailValueMarkup(wallNames)}
+
Letter
${toDetailValueMarkup(edgeLetterText)}
+
Astrology
${toDetailValueMarkup(astrologyText)}
+
Tarot
${toDetailValueMarkup(tarotCard || (tarotTrumpNumber != null ? `Trump ${tarotTrumpNumber}` : ""))}
+
Path
${toDetailValueMarkup(pathNo != null ? `Path ${pathNo}` : "")}
+
+ `; + bodyEl.appendChild(createMetaCard("Edge Details", summary)); + + if (Array.isArray(edge?.keywords) && edge.keywords.length) { + bodyEl.appendChild(createMetaCard("Keywords", edge.keywords.join(", "))); + } + + if (edge?.description) { + bodyEl.appendChild(createMetaCard("Description", edge.description)); + } + + const linksCard = document.createElement("div"); + linksCard.className = "planet-meta-card"; + linksCard.innerHTML = "Correspondence Links"; + const links = document.createElement("div"); + links.className = "kab-god-links"; + + edgeWalls.forEach((wallId) => { + const wall = getWallById(wallId); + const button = document.createElement("button"); + button.type = "button"; + button.className = "kab-god-link"; + button.textContent = `${wall?.name || wallId} Wall`; + button.addEventListener("click", () => { + onSelectWall(wallId); + }); + links.appendChild(button); + }); + + if (edgeLetterId) { + links.appendChild(createNavButton(edgeLetter || "!", "nav:alphabet", { + alphabet: "hebrew", + hebrewLetterId: edgeLetterId + })); + } + + if (astrologyType === "zodiac" && astrologyName) { + links.appendChild(createNavButton(astrologyName, "nav:zodiac", { + signId: normalizeId(astrologyName) + })); + } + + if (tarotCard || tarotTrumpNumber != null) { + links.appendChild(createNavButton(tarotCard || `Trump ${tarotTrumpNumber}`, "nav:tarot-trump", { + cardName: tarotCard, + trumpNumber: tarotTrumpNumber + })); + } + + if (pathNo != null) { + links.appendChild(createNavButton(`Path ${pathNo}`, "nav:kabbalah-path", { pathNo })); + } + + if (links.childElementCount) { + linksCard.appendChild(links); + bodyEl.appendChild(linksCard); + } + + return true; + } + function renderDetail(context) { if (context.state.selectedNodeType === "connector" && renderConnectorDetail(context)) { return; @@ -529,6 +666,10 @@ return; } + if (context.state.selectedNodeType === "edge" && renderEdgeDetail(context)) { + return; + } + renderWallDetail(context); } diff --git a/app/ui-cube-selection.js b/app/ui-cube-selection.js index 62e114b..3e5ccf7 100644 --- a/app/ui-cube-selection.js +++ b/app/ui-cube-selection.js @@ -38,9 +38,10 @@ const resolvedEdgeId = candidateEdgeId && getEdgeById(candidateEdgeId) ? candidateEdgeId : normalizeEdgeId(wallEdges[0]?.id || getEdges()[0]?.id); + const wantsEdgeDetail = Boolean(candidateEdgeId) || normalizeId(placement?.nodeType) === "edge"; state.selectedEdgeId = resolvedEdgeId; - state.selectedNodeType = "wall"; + state.selectedNodeType = wantsEdgeDetail ? "edge" : "wall"; state.selectedConnectorId = null; render(getElements()); return true; @@ -60,7 +61,7 @@ : (edgeWalls.includes(currentWallId) ? currentWallId : (edgeWalls[0] || currentWallId)); state.selectedEdgeId = normalizeEdgeId(edge.id); - state.selectedNodeType = "wall"; + state.selectedNodeType = "edge"; state.selectedConnectorId = null; if (nextWallId) { diff --git a/app/ui-cube.js b/app/ui-cube.js index 64308be..eba2800 100644 --- a/app/ui-cube.js +++ b/app/ui-cube.js @@ -814,6 +814,27 @@ return window.TarotCardImages.resolveTarotCardImage(name) || null; } + function openTarotCardInfo(cardName, trumpNumber = null) { + const detail = {}; + const normalizedCardName = toDisplayText(cardName); + const normalizedTrumpNumber = toFiniteNumber(trumpNumber); + + if (normalizedCardName) { + detail.cardName = normalizedCardName; + } + + if (normalizedTrumpNumber != null) { + detail.trumpNumber = normalizedTrumpNumber; + } + + if (!detail.cardName && detail.trumpNumber == null) { + return false; + } + + document.dispatchEvent(new CustomEvent("nav:tarot-trump", { detail })); + return true; + } + function openTarotCardLightbox(cardName, fallbackSrc = "", fallbackLabel = "") { const openLightbox = window.TarotUiLightbox?.open; if (typeof openLightbox !== "function") { @@ -867,6 +888,7 @@ getWallFaceLetter, getWallTarotCard, resolveCardImageUrl, + openTarotCardInfo, openTarotCardLightbox, MOTHER_CONNECTORS, formatDirectionName, diff --git a/app/ui-tarot-frame.js b/app/ui-tarot-frame.js index 4a2314c..a62210b 100644 --- a/app/ui-tarot-frame.js +++ b/app/ui-tarot-frame.js @@ -5607,12 +5607,42 @@ function loadCardImage(src) { return new Promise((resolve) => { + const normalizedSrc = String(src || "").trim(); + if (!normalizedSrc) { + resolve(null); + return; + } + + const ensureLoaded = window.TarotCardImages?.ensureImageLoaded; + const attachImageFallback = () => { + const image = new Image(); + image.decoding = "async"; + image.onload = () => resolve(image); + image.onerror = () => resolve(null); + image.src = normalizedSrc; + }; + + if (typeof ensureLoaded === "function") { + Promise.resolve(ensureLoaded(normalizedSrc)) + .then((cachedImage) => { + if (cachedImage?.naturalWidth) { + resolve(cachedImage); + return; + } + + attachImageFallback(); + }) + .catch(() => { + attachImageFallback(); + }); + return; + } + const image = new Image(); - image.crossOrigin = "anonymous"; image.decoding = "async"; image.onload = () => resolve(image); image.onerror = () => resolve(null); - image.src = src; + image.src = normalizedSrc; }); } diff --git a/index.html b/index.html index a5485f3..3d1512d 100644 --- a/index.html +++ b/index.html @@ -1218,11 +1218,11 @@ - - + + - - + + @@ -1245,7 +1245,7 @@ - +