/* ui-holidays-render.js - Render/search helpers for the holiday repository */ (function () { "use strict"; function planetLabel(planetId, context) { const { state, cap } = context; if (!planetId) { return "Planet"; } const planet = state.planetsById.get(planetId); if (!planet) { return cap(planetId); } return `${planet.symbol || ""} ${planet.name || cap(planetId)}`.trim(); } function zodiacLabel(signId, context) { const { state, cap } = context; if (!signId) { return "Zodiac"; } const sign = state.signsById.get(signId); if (!sign) { return cap(signId); } return `${sign.symbol || ""} ${sign.name || cap(signId)}`.trim(); } function godLabel(godId, godName, context) { const { state, cap } = context; if (godName) { return godName; } if (!godId) { return "Deity"; } const god = state.godsById.get(godId); return god?.name || cap(godId); } function hebrewLabel(hebrewLetterId, context) { const { state, cap } = context; if (!hebrewLetterId) { return "Hebrew Letter"; } const letter = state.hebrewById.get(hebrewLetterId); if (!letter) { return cap(hebrewLetterId); } return `${letter.char || ""} ${letter.name || cap(hebrewLetterId)}`.trim(); } function computeDigitalRoot(value) { let current = Math.abs(Math.trunc(Number(value))); if (!Number.isFinite(current)) { return null; } while (current >= 10) { current = String(current) .split("") .reduce((sum, digit) => sum + Number(digit), 0); } return current; } function buildAssociationButtons(associations, context) { const { getDisplayTarotName, resolveTarotTrumpNumber } = context; if (!associations || typeof associations !== "object") { return '
--
'; } const buttons = []; if (associations.planetId) { buttons.push( `` ); } if (associations.zodiacSignId) { buttons.push( `` ); } if (Number.isFinite(Number(associations.numberValue))) { const rawNumber = Math.trunc(Number(associations.numberValue)); if (rawNumber >= 0) { const numberValue = computeDigitalRoot(rawNumber); if (numberValue != null) { const label = rawNumber === numberValue ? `Number ${numberValue}` : `Number ${numberValue} (from ${rawNumber})`; buttons.push( `` ); } } } if (associations.tarotCard) { const trumpNumber = resolveTarotTrumpNumber(associations.tarotCard); const explicitTrumpNumber = Number(associations.tarotTrumpNumber); const tarotTrumpNumber = Number.isFinite(explicitTrumpNumber) ? explicitTrumpNumber : trumpNumber; const tarotLabel = getDisplayTarotName(associations.tarotCard, tarotTrumpNumber); buttons.push( `` ); } if (associations.godId || associations.godName) { const label = godLabel(associations.godId, associations.godName, context); buttons.push( `` ); } if (associations.hebrewLetterId) { buttons.push( `` ); } if (associations.kabbalahPathNumber != null) { buttons.push( `` ); } if (associations.iChingPlanetaryInfluence) { buttons.push( `` ); } if (!buttons.length) { return '
--
'; } return `
${buttons.join("")}
`; } function associationSearchText(associations, context) { const { getTarotCardSearchAliases } = context; if (!associations || typeof associations !== "object") { return ""; } const tarotAliases = associations.tarotCard && typeof getTarotCardSearchAliases === "function" ? getTarotCardSearchAliases(associations.tarotCard, { trumpNumber: associations.tarotTrumpNumber }) : []; return [ associations.planetId, associations.zodiacSignId, associations.numberValue, associations.tarotCard, associations.tarotTrumpNumber, ...tarotAliases, associations.godId, associations.godName, associations.hebrewLetterId, associations.kabbalahPathNumber, associations.iChingPlanetaryInfluence ].filter(Boolean).join(" "); } function holidaySearchText(holiday, context) { const { normalizeSearchValue } = context; return normalizeSearchValue([ holiday?.name, holiday?.kind, holiday?.date, holiday?.dateRange, holiday?.dateText, holiday?.monthDayStart, holiday?.calendarId, holiday?.description, associationSearchText(holiday?.associations, context) ].filter(Boolean).join(" ")); } function renderList(context) { const { elements, state, filterBySource, normalizeSourceFilter, calendarLabel, monthLabelForCalendar, selectByHolidayId } = context; const { listEl, countEl } = elements; if (!listEl) { return; } listEl.innerHTML = ""; state.filteredHolidays.forEach((holiday) => { const isSelected = holiday.id === state.selectedHolidayId; const itemEl = document.createElement("div"); itemEl.className = `planet-list-item${isSelected ? " is-selected" : ""}`; itemEl.setAttribute("role", "option"); itemEl.setAttribute("aria-selected", isSelected ? "true" : "false"); itemEl.dataset.holidayId = holiday.id; const sourceCalendar = calendarLabel(holiday.calendarId); const sourceMonth = monthLabelForCalendar(holiday.calendarId, holiday.monthId); const sourceDate = holiday?.dateText || holiday?.date || holiday?.dateRange || "--"; itemEl.innerHTML = `
${holiday?.name || holiday?.id || "Holiday"}
${sourceCalendar} - ${sourceMonth} - ${sourceDate}
`; itemEl.addEventListener("click", () => { selectByHolidayId(holiday.id, elements); }); listEl.appendChild(itemEl); }); if (countEl) { const sourceFiltered = filterBySource(state.holidays); const activeFilter = normalizeSourceFilter(state.selectedSource); const sourceLabel = activeFilter === "all" ? "" : ` (${calendarLabel(activeFilter)})`; countEl.textContent = state.searchQuery ? `${state.filteredHolidays.length} of ${sourceFiltered.length} holidays${sourceLabel}` : `${sourceFiltered.length} holidays${sourceLabel}`; } } function renderHolidayDetail(holiday, context) { const { state, calendarLabel, monthLabelForCalendar, resolveHolidayGregorianDate, formatGregorianReferenceDate, formatCalendarDateFromGregorian } = context; const gregorianDate = resolveHolidayGregorianDate(holiday); const gregorianRef = formatGregorianReferenceDate(gregorianDate); const hebrewRef = formatCalendarDateFromGregorian(gregorianDate, "hebrew"); const islamicRef = formatCalendarDateFromGregorian(gregorianDate, "islamic"); const confidence = String(holiday?.conversionConfidence || holiday?.datePrecision || "approximate").toLowerCase(); const confidenceLabel = (!(gregorianDate instanceof Date) || Number.isNaN(gregorianDate.getTime())) ? "unresolved" : (confidence === "exact" ? "exact" : "approximate"); const monthName = monthLabelForCalendar(holiday?.calendarId, holiday?.monthId); const holidayDate = holiday?.dateText || holiday?.date || holiday?.dateRange || "--"; const sourceMonthLink = holiday?.monthId ? `
` : ""; return `
Holiday Facts
Source Calendar
${calendarLabel(holiday?.calendarId)}
Source Month
${monthName}
Source Date
${holidayDate}
Reference Year
${state.selectedYear}
Conversion
${confidenceLabel}
Cross-Calendar Dates
Gregorian
${gregorianRef}
Hebrew
${hebrewRef}
Islamic
${islamicRef}
Description
${holiday?.description || "--"}
${sourceMonthLink}
Associations ${buildAssociationButtons(holiday?.associations, context)}
`; } window.HolidayRenderUi = { holidaySearchText, renderList, renderHolidayDetail }; })();