various ui improvements, including a new sequence nav component and a new kabbalah detail view

This commit is contained in:
2026-05-28 18:19:13 -07:00
parent c423f1191d
commit 1433ec1495
17 changed files with 2274 additions and 120 deletions
+71
View File
@@ -63,6 +63,7 @@
hebrewById: new Map(),
dayLinksCache: new Map()
};
let detailNavigator = null;
const TAROT_TRUMP_NUMBER_BY_NAME = {
"the fool": 0,
@@ -200,6 +201,7 @@
function getElements() {
return {
sectionEl: document.getElementById("calendar-section"),
monthListEl: document.getElementById("calendar-month-list"),
monthCountEl: document.getElementById("calendar-month-count"),
listTitleEl: document.getElementById("calendar-list-title"),
@@ -210,6 +212,9 @@
searchClearEl: document.getElementById("calendar-search-clear"),
detailNameEl: document.getElementById("calendar-detail-name"),
detailSubEl: document.getElementById("calendar-detail-sub"),
detailPrevEl: document.getElementById("calendar-detail-prev"),
detailPositionEl: document.getElementById("calendar-detail-position"),
detailNextEl: document.getElementById("calendar-detail-next"),
detailBodyEl: document.getElementById("calendar-detail-body")
};
}
@@ -523,6 +528,66 @@
function renderDetail(elements) {
calendarDetailUi.renderDetail?.(elements);
syncDetailNavigation(elements);
}
function getMonthSequenceState() {
const total = state.filteredMonths.length;
const currentIndex = state.filteredMonths.findIndex((month) => month.id === state.selectedMonthId);
return {
total,
currentIndex,
previousId: currentIndex > 0 ? state.filteredMonths[currentIndex - 1].id : "",
nextId: currentIndex >= 0 && currentIndex < total - 1 ? state.filteredMonths[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: getMonthSequenceState,
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} months` : "No months";
},
selectTarget: (targetId, elements) => selectByMonthId(targetId, elements) !== false,
afterSelect: (targetId, elements) => {
scrollMonthIntoView(targetId, elements);
}
});
return detailNavigator;
}
function syncDetailNavigation(elements = getElements()) {
getDetailNavigator()?.sync(elements);
}
function scrollMonthIntoView(monthId, elements = getElements()) {
elements?.monthListEl
?.querySelector(`[data-month-id="${monthId}"]`)
?.scrollIntoView({ block: "nearest" });
}
function selectAdjacentMonth(offset, elements = getElements()) {
return getDetailNavigator()?.step(offset, elements) === true;
}
function bindKeyboardNavigation(elements) {
getDetailNavigator()?.bind(elements);
}
function applySearchFilter(elements) {
@@ -613,6 +678,10 @@
}
}
function bindDetailNavigation(elements) {
getDetailNavigator()?.bind(elements);
}
function loadCalendarType(calendarId, elements) {
const months = state.calendarData[calendarId];
if (!Array.isArray(months)) {
@@ -745,6 +814,8 @@
bindYearInput(elements);
bindSearchInput(elements);
bindCalendarTypeSelect(elements);
bindDetailNavigation(elements);
bindKeyboardNavigation(elements);
}
applySearchFilter(elements);