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
+68
View File
@@ -42,6 +42,7 @@
hebrewById: new Map(),
calendarData: {}
};
let detailNavigator = null;
const TAROT_TRUMP_NUMBER_BY_NAME = {
"the fool": 0,
@@ -93,6 +94,7 @@
function getElements() {
return {
sectionEl: document.getElementById("holiday-section"),
sourceSelectEl: document.getElementById("holiday-source-select"),
yearInputEl: document.getElementById("holiday-year-input"),
searchInputEl: document.getElementById("holiday-search-input"),
@@ -101,6 +103,9 @@
listEl: document.getElementById("holiday-list"),
detailNameEl: document.getElementById("holiday-detail-name"),
detailSubEl: document.getElementById("holiday-detail-sub"),
detailPrevEl: document.getElementById("holiday-detail-prev"),
detailPositionEl: document.getElementById("holiday-detail-position"),
detailNextEl: document.getElementById("holiday-detail-next"),
detailBodyEl: document.getElementById("holiday-detail-body")
};
}
@@ -225,6 +230,7 @@
detailNameEl.textContent = "--";
detailSubEl.textContent = "Select a holiday to explore";
detailBodyEl.innerHTML = "";
syncDetailNavigation(elements);
return;
}
@@ -232,6 +238,66 @@
detailSubEl.textContent = `${holidayDataUi.calendarLabel(holiday?.calendarId)} - ${holidayDataUi.monthLabelForCalendar(state.calendarData, holiday?.calendarId, holiday?.monthId)}`;
detailBodyEl.innerHTML = renderHolidayDetail(holiday);
attachNavHandlers(detailBodyEl);
syncDetailNavigation(elements);
}
function getHolidaySequenceState() {
const total = state.filteredHolidays.length;
const currentIndex = state.filteredHolidays.findIndex((holiday) => holiday.id === state.selectedHolidayId);
return {
total,
currentIndex,
previousId: currentIndex > 0 ? state.filteredHolidays[currentIndex - 1].id : "",
nextId: currentIndex >= 0 && currentIndex < total - 1 ? state.filteredHolidays[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: getHolidaySequenceState,
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} holidays` : "No holidays";
},
selectTarget: (targetId, elements) => selectByHolidayId(targetId, elements) !== false,
afterSelect: (targetId, elements) => {
scrollHolidayIntoView(targetId, elements);
}
});
return detailNavigator;
}
function syncDetailNavigation(elements = getElements()) {
getDetailNavigator()?.sync(elements);
}
function scrollHolidayIntoView(holidayId, elements = getElements()) {
elements?.listEl
?.querySelector(`[data-holiday-id="${holidayId}"]`)
?.scrollIntoView({ block: "nearest" });
}
function selectAdjacentHoliday(offset, elements = getElements()) {
return getDetailNavigator()?.step(offset, elements) === true;
}
function bindKeyboardNavigation(elements) {
getDetailNavigator()?.bind(elements);
}
function applyFilters(elements) {
@@ -307,6 +373,8 @@
elements.searchInputEl.focus();
});
}
bindKeyboardNavigation(elements);
}
function attachNavHandlers(detailBodyEl) {