diff --git a/app/ui-zodiac.js b/app/ui-zodiac.js index 37f23b9..0e8d5bd 100644 --- a/app/ui-zodiac.js +++ b/app/ui-zodiac.js @@ -36,6 +36,7 @@ monthRefsBySignId: new Map(), cubePlacementBySignId: new Map() }; + let detailNavigator = null; function hasTarotAccess() { return window.TarotAppConfig?.hasTarotAccess?.() === true; @@ -44,12 +45,16 @@ // ── Elements ────────────────────────────────────────────────────────── function getElements() { return { + sectionEl: document.getElementById("zodiac-section"), listEl: document.getElementById("zodiac-sign-list"), countEl: document.getElementById("zodiac-sign-count"), searchEl: document.getElementById("zodiac-search-input"), searchClearEl: document.getElementById("zodiac-search-clear"), detailNameEl: document.getElementById("zodiac-detail-name"), detailSubEl: document.getElementById("zodiac-detail-sub"), + detailPrevEl: document.getElementById("zodiac-detail-prev"), + detailPositionEl: document.getElementById("zodiac-detail-position"), + detailNextEl: document.getElementById("zodiac-detail-next"), detailBodyEl: document.getElementById("zodiac-detail-body") }; } @@ -316,6 +321,61 @@ if (els.detailNameEl) els.detailNameEl.textContent = "--"; if (els.detailSubEl) els.detailSubEl.textContent = "Select a sign to explore"; if (els.detailBodyEl) els.detailBodyEl.innerHTML = ""; + syncDetailNavigation(els); + } + + function getSequenceState() { + const total = state.filteredEntries.length; + const currentIndex = state.filteredEntries.findIndex((entry) => entry.id === state.selectedId); + + return { + total, + currentIndex, + previousId: currentIndex > 0 ? state.filteredEntries[currentIndex - 1].id : "", + nextId: currentIndex >= 0 && currentIndex < total - 1 ? state.filteredEntries[currentIndex + 1].id : "" + }; + } + + function getDetailNavigator() { + if (detailNavigator || typeof window.TarotSequenceNav?.createSequenceNavigator !== "function") { + return detailNavigator; + } + + detailNavigator = window.TarotSequenceNav.createSequenceNavigator({ + getElements, + isActive: (elements) => Boolean(elements?.sectionEl && elements.sectionEl.hidden === false), + getSequenceState, + getPrevButton: (elements) => elements?.detailPrevEl, + getNextButton: (elements) => elements?.detailNextEl, + getPositionEl: (elements) => elements?.detailPositionEl, + formatPositionText: ({ total, currentIndex }) => { + if (total > 0 && currentIndex >= 0) { + const suffix = state.searchQuery ? " shown" : ""; + return `${currentIndex + 1} of ${total}${suffix}`; + } + + return total > 0 ? `${total} signs` : "No signs"; + }, + selectTarget: (targetId, elements) => { + selectById(targetId, elements); + return true; + }, + afterSelect: (targetId, elements) => { + elements?.listEl + ?.querySelector(`[data-id="${targetId}"]`) + ?.scrollIntoView({ block: "nearest" }); + } + }); + + return detailNavigator; + } + + function syncDetailNavigation(elements = getElements()) { + getDetailNavigator()?.sync(elements); + } + + function bindKeyboardNavigation(elements = getElements()) { + getDetailNavigator()?.bind(elements); } // ── Selection ───────────────────────────────────────────────────────── @@ -325,6 +385,7 @@ state.selectedId = id; renderList(els); renderDetail(sign, els); + syncDetailNavigation(els); } // ── Public select (for incoming navigation) ─────────────────────────── @@ -345,6 +406,9 @@ const current = state.entries.find((entry) => entry.id === state.selectedId); if (current) { renderDetail(current, els); + syncDetailNavigation(els); + } else { + syncDetailNavigation(els); } return; } @@ -361,9 +425,12 @@ const els = getElements(); applyFilter(); renderList(els); + bindKeyboardNavigation(els); if (state.entries.length > 0) { selectById(state.entries[0].id, els); + } else { + syncDetailNavigation(els); } // Search @@ -380,6 +447,8 @@ state.selectedId = null; resetDetail(els); } + } else { + syncDetailNavigation(els); } }); } diff --git a/index.html b/index.html index 8afe813..2de7237 100644 --- a/index.html +++ b/index.html @@ -1195,6 +1195,11 @@