/* 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 buildInlineNavButton(label, nav, attrs = {}) { const dataAttrs = Object.entries(attrs) .map(([key, value]) => `data-${key}="${value}"`) .join(" "); return ``; } function buildAssociationButtons(associations, context) { const { getDisplayTarotName, resolveTarotTrumpNumber } = context; if (!associations || typeof associations !== "object") { return '
--
'; } const rows = []; if (associations.planetId) { rows.push(`
Planet ${buildInlineNavButton(planetLabel(associations.planetId, context), "planet", { "planet-id": associations.planetId })}
`); } if (associations.zodiacSignId) { rows.push(`
Zodiac ${buildInlineNavButton(zodiacLabel(associations.zodiacSignId, context), "zodiac", { "sign-id": associations.zodiacSignId })}
`); } 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})`; rows.push(`
Number ${buildInlineNavButton(label, "number", { "number-value": numberValue })}
`); } } } 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); rows.push(`
Tarot ${buildInlineNavButton(tarotLabel, "tarot-card", { "card-name": associations.tarotCard, "trump-number": tarotTrumpNumber ?? "" })}
`); } if (associations.godId || associations.godName) { const label = godLabel(associations.godId, associations.godName, context); rows.push(`
Deity ${buildInlineNavButton(label, "god", { "god-id": associations.godId || "", "god-name": associations.godName || label })}
`); } if (associations.hebrewLetterId) { rows.push(`
Hebrew ${buildInlineNavButton(hebrewLabel(associations.hebrewLetterId, context), "alphabet", { alphabet: "hebrew", "hebrew-letter-id": associations.hebrewLetterId })}
`); } if (associations.kabbalahPathNumber != null) { rows.push(`
Kabbalah ${buildInlineNavButton(`Path ${associations.kabbalahPathNumber}`, "kabbalah", { "path-no": associations.kabbalahPathNumber })}
`); } if (associations.iChingPlanetaryInfluence) { rows.push(`
I Ching ${buildInlineNavButton(associations.iChingPlanetaryInfluence, "iching", { "planetary-influence": associations.iChingPlanetaryInfluence })}
`); } if (!rows.length) { return '
--
'; } return rows.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 ? `
Source month ${buildInlineNavButton(`${calendarLabel(holiday?.calendarId)} ${monthName}`, "calendar-month", { "calendar-id": holiday.calendarId || "", "month-id": 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 }; })();