Files
TaroTime/app/ui-planets.js
2026-03-07 01:09:00 -08:00

899 lines
29 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function () {
const { getTarotCardDisplayName, getTarotCardSearchAliases } = window.TarotCardImages || {};
const state = {
initialized: false,
entries: [],
filteredEntries: [],
searchQuery: "",
selectedId: "",
kabbalahTargetsByPlanetId: {},
monthRefsByPlanetId: new Map(),
cubePlacementsByPlanetId: new Map()
};
function normalizePlanetToken(value) {
return String(value || "")
.trim()
.toLowerCase()
.replace(/[^a-z]/g, "");
}
function toPlanetId(value) {
const token = normalizePlanetToken(value);
if (!token) return null;
if (token === "sun") return "sol";
if (token === "moon") return "luna";
if (["saturn", "jupiter", "mars", "sol", "venus", "mercury", "luna"].includes(token)) {
return token;
}
return null;
}
function appendKabbalahTarget(map, planetId, target) {
if (!planetId || !target) return;
if (!map[planetId]) map[planetId] = [];
const key = `${target.kind}:${target.number}`;
if (map[planetId].some((entry) => `${entry.kind}:${entry.number}` === key)) return;
map[planetId].push(target);
}
function buildKabbalahTargetsByPlanet(magickDataset) {
const tree = magickDataset?.grouped?.kabbalah?.["kabbalah-tree"];
const map = {};
if (!tree) return map;
(tree.sephiroth || []).forEach((seph) => {
const planetId = toPlanetId(seph?.planet);
if (!planetId) return;
appendKabbalahTarget(map, planetId, {
kind: "sephirah",
number: seph.number,
label: `Sephirah ${seph.number} · ${seph.name}`
});
});
(tree.paths || []).forEach((path) => {
if (path?.astrology?.type !== "planet") return;
const planetId = toPlanetId(path?.astrology?.name);
if (!planetId) return;
appendKabbalahTarget(map, planetId, {
kind: "path",
number: path.pathNumber,
label: `Path ${path.pathNumber} · ${path?.tarot?.card || path?.hebrewLetter?.transliteration || ""}`.trim()
});
});
return map;
}
function buildMonthReferencesByPlanet(referenceData) {
const map = new Map();
const months = Array.isArray(referenceData?.calendarMonths) ? referenceData.calendarMonths : [];
const holidays = Array.isArray(referenceData?.celestialHolidays) ? referenceData.celestialHolidays : [];
const monthById = new Map(months.map((month) => [month.id, month]));
function parseMonthDayToken(value) {
const text = String(value || "").trim();
const match = text.match(/^(\d{1,2})-(\d{1,2})$/);
if (!match) {
return null;
}
const monthNo = Number(match[1]);
const dayNo = Number(match[2]);
if (!Number.isInteger(monthNo) || !Number.isInteger(dayNo) || monthNo < 1 || monthNo > 12 || dayNo < 1 || dayNo > 31) {
return null;
}
return { month: monthNo, day: dayNo };
}
function parseMonthDayTokensFromText(value) {
const text = String(value || "");
const matches = [...text.matchAll(/(\d{1,2})-(\d{1,2})/g)];
return matches
.map((match) => ({ month: Number(match[1]), day: Number(match[2]) }))
.filter((token) => Number.isInteger(token.month) && Number.isInteger(token.day) && token.month >= 1 && token.month <= 12 && token.day >= 1 && token.day <= 31);
}
function toDateToken(token, year) {
if (!token) {
return null;
}
return new Date(year, token.month - 1, token.day, 12, 0, 0, 0);
}
function splitMonthDayRangeByMonth(startToken, endToken) {
const startDate = toDateToken(startToken, 2025);
const endBase = toDateToken(endToken, 2025);
if (!startDate || !endBase) {
return [];
}
const wrapsYear = endBase.getTime() < startDate.getTime();
const endDate = wrapsYear ? toDateToken(endToken, 2026) : endBase;
if (!endDate) {
return [];
}
const segments = [];
let cursor = new Date(startDate);
while (cursor.getTime() <= endDate.getTime()) {
const monthEnd = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 0, 12, 0, 0, 0);
const segmentEnd = monthEnd.getTime() < endDate.getTime() ? monthEnd : endDate;
segments.push({
monthNo: cursor.getMonth() + 1,
startDay: cursor.getDate(),
endDay: segmentEnd.getDate()
});
cursor = new Date(segmentEnd.getFullYear(), segmentEnd.getMonth(), segmentEnd.getDate() + 1, 12, 0, 0, 0);
}
return segments;
}
function tokenToString(monthNo, dayNo) {
return `${String(monthNo).padStart(2, "0")}-${String(dayNo).padStart(2, "0")}`;
}
function formatRangeLabel(monthName, startDay, endDay) {
if (!Number.isFinite(startDay) || !Number.isFinite(endDay)) {
return monthName;
}
if (startDay === endDay) {
return `${monthName} ${startDay}`;
}
return `${monthName} ${startDay}-${endDay}`;
}
function resolveRangeForMonth(month, options = {}) {
const monthOrder = Number(month?.order);
const monthStart = parseMonthDayToken(month?.start);
const monthEnd = parseMonthDayToken(month?.end);
if (!Number.isFinite(monthOrder) || !monthStart || !monthEnd) {
return {
startToken: String(month?.start || "").trim() || null,
endToken: String(month?.end || "").trim() || null,
label: month?.name || month?.id || "",
isFullMonth: true
};
}
let startToken = parseMonthDayToken(options.startToken);
let endToken = parseMonthDayToken(options.endToken);
if (!startToken || !endToken) {
const tokens = parseMonthDayTokensFromText(options.rawDateText);
if (tokens.length >= 2) {
startToken = tokens[0];
endToken = tokens[1];
} else if (tokens.length === 1) {
startToken = tokens[0];
endToken = tokens[0];
}
}
if (!startToken || !endToken) {
startToken = monthStart;
endToken = monthEnd;
}
const segments = splitMonthDayRangeByMonth(startToken, endToken);
const segment = segments.find((entry) => entry.monthNo === monthOrder) || null;
const useStart = segment ? { month: monthOrder, day: segment.startDay } : startToken;
const useEnd = segment ? { month: monthOrder, day: segment.endDay } : endToken;
const startText = tokenToString(useStart.month, useStart.day);
const endText = tokenToString(useEnd.month, useEnd.day);
const isFullMonth = startText === month.start && endText === month.end;
return {
startToken: startText,
endToken: endText,
label: isFullMonth
? (month.name || month.id)
: formatRangeLabel(month.name || month.id, useStart.day, useEnd.day),
isFullMonth
};
}
function pushRef(planetToken, month, options = {}) {
const planetId = toPlanetId(planetToken) || normalizePlanetToken(planetToken);
if (!planetId || !month?.id) {
return;
}
if (!map.has(planetId)) {
map.set(planetId, []);
}
const rows = map.get(planetId);
const range = resolveRangeForMonth(month, options);
const key = `${month.id}|${range.startToken || ""}|${range.endToken || ""}`;
if (rows.some((entry) => entry.key === key)) {
return;
}
rows.push({
id: month.id,
name: month.name || month.id,
order: Number.isFinite(Number(month.order)) ? Number(month.order) : 999,
label: range.label,
startToken: range.startToken,
endToken: range.endToken,
isFullMonth: range.isFullMonth,
key
});
}
months.forEach((month) => {
pushRef(month?.associations?.planetId, month);
const events = Array.isArray(month?.events) ? month.events : [];
events.forEach((event) => {
pushRef(event?.associations?.planetId, month, {
rawDateText: event?.dateRange || event?.date || ""
});
});
});
holidays.forEach((holiday) => {
const month = monthById.get(holiday?.monthId);
if (!month) {
return;
}
pushRef(holiday?.associations?.planetId, month, {
rawDateText: holiday?.dateRange || holiday?.date || ""
});
});
map.forEach((rows, key) => {
const preciseMonthIds = new Set(
rows
.filter((entry) => !entry.isFullMonth)
.map((entry) => entry.id)
);
const filtered = rows.filter((entry) => {
if (!entry.isFullMonth) {
return true;
}
return !preciseMonthIds.has(entry.id);
});
filtered.sort((left, right) => {
if (left.order !== right.order) {
return left.order - right.order;
}
const startLeft = parseMonthDayToken(left.startToken);
const startRight = parseMonthDayToken(right.startToken);
const dayLeft = startLeft ? startLeft.day : 999;
const dayRight = startRight ? startRight.day : 999;
if (dayLeft !== dayRight) {
return dayLeft - dayRight;
}
return String(left.label || left.name || "").localeCompare(String(right.label || right.name || ""));
});
map.set(key, filtered);
});
return map;
}
function buildCubePlacementsByPlanet(magickDataset) {
const map = new Map();
const cube = magickDataset?.grouped?.kabbalah?.cube || {};
const walls = Array.isArray(cube?.walls)
? cube.walls
: [];
const edges = Array.isArray(cube?.edges)
? cube.edges
: [];
function edgeWalls(edge) {
const explicitWalls = Array.isArray(edge?.walls)
? edge.walls.map((wallId) => String(wallId || "").trim().toLowerCase()).filter(Boolean)
: [];
if (explicitWalls.length >= 2) {
return explicitWalls.slice(0, 2);
}
return String(edge?.id || "")
.trim()
.toLowerCase()
.split("-")
.map((wallId) => wallId.trim())
.filter(Boolean)
.slice(0, 2);
}
function edgeLabel(edge) {
const explicitName = String(edge?.name || "").trim();
if (explicitName) {
return explicitName;
}
return edgeWalls(edge)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
}
function resolveCubeDirectionLabel(wallId, edge) {
const normalizedWallId = String(wallId || "").trim().toLowerCase();
const edgeId = String(edge?.id || "").trim().toLowerCase();
if (!normalizedWallId || !edgeId) {
return "";
}
const cubeUi = window.CubeSectionUi;
if (cubeUi && typeof cubeUi.getEdgeDirectionLabelForWall === "function") {
const directionLabel = String(cubeUi.getEdgeDirectionLabelForWall(normalizedWallId, edgeId) || "").trim();
if (directionLabel) {
return directionLabel;
}
}
return edgeLabel(edge);
}
const firstEdgeByWallId = new Map();
edges.forEach((edge) => {
edgeWalls(edge).forEach((wallId) => {
if (!firstEdgeByWallId.has(wallId)) {
firstEdgeByWallId.set(wallId, edge);
}
});
});
function pushPlacement(planetId, placement) {
if (!planetId || !placement?.wallId || !placement?.edgeId) {
return;
}
if (!map.has(planetId)) {
map.set(planetId, []);
}
const rows = map.get(planetId);
const key = `${placement.wallId}:${placement.edgeId}`;
if (rows.some((row) => `${row.wallId}:${row.edgeId}` === key)) {
return;
}
rows.push(placement);
}
walls.forEach((wall) => {
const planetId = toPlanetId(wall?.associations?.planetId || wall?.planet);
if (!planetId) {
return;
}
const wallId = String(wall?.id || "").trim().toLowerCase();
const edge = firstEdgeByWallId.get(wallId) || null;
pushPlacement(planetId, {
wallId,
edgeId: String(edge?.id || "").trim().toLowerCase(),
label: `Cube: ${wall?.name || "Wall"} Wall - ${resolveCubeDirectionLabel(wallId, edge) || "Direction"}`
});
});
return map;
}
function getElements() {
return {
planetCardListEl: document.getElementById("planet-card-list"),
planetSearchInputEl: document.getElementById("planet-search-input"),
planetSearchClearEl: document.getElementById("planet-search-clear"),
planetCountEl: document.getElementById("planet-card-count"),
planetDetailNameEl: document.getElementById("planet-detail-name"),
planetDetailTypeEl: document.getElementById("planet-detail-type"),
planetDetailSummaryEl: document.getElementById("planet-detail-summary"),
planetDetailFactsEl: document.getElementById("planet-detail-facts"),
planetDetailAtmosphereEl: document.getElementById("planet-detail-atmosphere"),
planetDetailNotableEl: document.getElementById("planet-detail-notable"),
planetDetailCorrespondenceEl: document.getElementById("planet-detail-correspondence")
};
}
function normalizeSearchValue(value) {
return String(value || "").trim().toLowerCase();
}
function buildPlanetSearchText(entry) {
const correspondence = entry?.correspondence || {};
const factValues = buildFactRows(entry).map(([, value]) => String(value || ""));
const tarotAliases = correspondence?.tarot?.majorArcana && typeof getTarotCardSearchAliases === "function"
? getTarotCardSearchAliases(correspondence.tarot.majorArcana)
: [];
const rawNumbers = [
entry?.meanDistanceFromSun?.kmMillions,
entry?.meanDistanceFromSun?.au,
entry?.orbitalPeriod?.days,
entry?.orbitalPeriod?.years,
entry?.rotationPeriodHours,
entry?.radiusKm,
entry?.diameterKm,
entry?.massKg,
entry?.gravityMs2,
entry?.escapeVelocityKms,
entry?.axialTiltDeg,
entry?.averageTempC,
entry?.moons
]
.filter((value) => Number.isFinite(value))
.map((value) => String(value));
const parts = [
entry?.name,
entry?.symbol,
entry?.classification,
entry?.summary,
entry?.atmosphere,
...(Array.isArray(entry?.notableFacts) ? entry.notableFacts : []),
...factValues,
...rawNumbers,
correspondence?.name,
correspondence?.symbol,
correspondence?.weekday,
correspondence?.tarot?.majorArcana,
...tarotAliases
];
return normalizeSearchValue(parts.filter(Boolean).join(" "));
}
function applySearchFilter(elements) {
const query = normalizeSearchValue(state.searchQuery);
state.filteredEntries = query
? state.entries.filter((entry) => buildPlanetSearchText(entry).includes(query))
: [...state.entries];
if (elements?.planetSearchClearEl) {
elements.planetSearchClearEl.disabled = !query;
}
renderList(elements);
if (!state.filteredEntries.some((entry) => entry.id === state.selectedId)) {
if (state.filteredEntries.length > 0) {
selectById(state.filteredEntries[0].id, elements);
}
return;
}
updateSelection(elements);
}
function clearChildren(element) {
if (element) {
element.replaceChildren();
}
}
function toNumber(value) {
return Number.isFinite(value) ? value : null;
}
function formatNumber(value, maximumFractionDigits = 2) {
if (!Number.isFinite(value)) {
return "--";
}
return new Intl.NumberFormat(undefined, {
maximumFractionDigits,
minimumFractionDigits: 0
}).format(value);
}
function formatSignedHours(value) {
if (!Number.isFinite(value)) {
return "--";
}
const absValue = Math.abs(value);
const formatted = `${formatNumber(absValue, 2)} h`;
return value < 0 ? `${formatted} (retrograde)` : formatted;
}
function formatMass(value) {
if (!Number.isFinite(value)) {
return "--";
}
return value.toExponential(3).replace("e+", " × 10^") + " kg";
}
function buildFactRows(entry) {
return [
["Mean distance from Sun", Number.isFinite(entry?.meanDistanceFromSun?.kmMillions) && Number.isFinite(entry?.meanDistanceFromSun?.au)
? `${formatNumber(entry.meanDistanceFromSun.kmMillions, 1)} million km (${formatNumber(entry.meanDistanceFromSun.au, 3)} AU)`
: "--"],
["Orbital period", Number.isFinite(entry?.orbitalPeriod?.days) && Number.isFinite(entry?.orbitalPeriod?.years)
? `${formatNumber(entry.orbitalPeriod.days, 2)} days (${formatNumber(entry.orbitalPeriod.years, 3)} years)`
: "--"],
["Rotation period", formatSignedHours(toNumber(entry?.rotationPeriodHours))],
["Radius", Number.isFinite(entry?.radiusKm) ? `${formatNumber(entry.radiusKm, 1)} km` : "--"],
["Diameter", Number.isFinite(entry?.diameterKm) ? `${formatNumber(entry.diameterKm, 1)} km` : "--"],
["Mass", formatMass(toNumber(entry?.massKg))],
["Surface gravity", Number.isFinite(entry?.gravityMs2) ? `${formatNumber(entry.gravityMs2, 3)} m/s²` : "--"],
["Escape velocity", Number.isFinite(entry?.escapeVelocityKms) ? `${formatNumber(entry.escapeVelocityKms, 2)} km/s` : "--"],
["Axial tilt", Number.isFinite(entry?.axialTiltDeg) ? `${formatNumber(entry.axialTiltDeg, 2)}°` : "--"],
["Average temperature", Number.isFinite(entry?.averageTempC) ? `${formatNumber(entry.averageTempC, 0)} °C` : "--"],
["Moons", Number.isFinite(entry?.moons) ? formatNumber(entry.moons, 0) : "--"]
];
}
function getDisplayTarotName(cardName, trumpNumber) {
if (!cardName) {
return "";
}
if (typeof getTarotCardDisplayName !== "function") {
return cardName;
}
if (Number.isFinite(Number(trumpNumber))) {
return getTarotCardDisplayName(cardName, { trumpNumber: Number(trumpNumber) }) || cardName;
}
return getTarotCardDisplayName(cardName) || cardName;
}
function renderCorrespondence(entry, containerEl) {
if (!containerEl) return;
containerEl.innerHTML = "";
const correspondence = entry?.correspondence;
if (!correspondence || typeof correspondence !== "object") {
const fallback = document.createElement("span");
fallback.className = "planet-text";
fallback.textContent = "No tarot/day correspondence in current local dataset.";
containerEl.appendChild(fallback);
}
const symbol = correspondence?.symbol || "";
const weekday = correspondence?.weekday || "";
const arcana = correspondence?.tarot?.majorArcana || "";
const trumpNo = correspondence?.tarot?.number;
const arcanaLabel = getDisplayTarotName(arcana, trumpNo);
// Symbol + weekday line
if (symbol || weekday) {
const line = document.createElement("span");
line.className = "planet-text";
line.textContent = [symbol, weekday].filter(Boolean).join(" \u00b7 ");
containerEl.appendChild(line);
}
// Tarot card link
if (arcana) {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "kab-tarot-link";
btn.style.marginTop = "8px";
btn.textContent = trumpNo != null ? `${arcanaLabel} \u00b7 Trump ${trumpNo}` : arcanaLabel;
btn.title = "Open in Tarot section";
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("nav:tarot-trump", {
detail: { trumpNumber: trumpNo ?? null, cardName: arcana }
}));
});
containerEl.appendChild(btn);
}
const planetId = toPlanetId(correspondence?.id || entry?.id || entry?.name) ||
normalizePlanetToken(correspondence?.id || entry?.id || entry?.name);
const kabbalahTargets = state.kabbalahTargetsByPlanetId[planetId] || [];
if (kabbalahTargets.length) {
const row = document.createElement("div");
row.className = "kab-god-links";
row.style.marginTop = "8px";
kabbalahTargets.forEach((target) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "kab-god-link";
btn.textContent = `View ${target.label}`;
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("nav:kabbalah-path", {
detail: { pathNo: Number(target.number) }
}));
});
row.appendChild(btn);
});
containerEl.appendChild(row);
}
const monthRefs = state.monthRefsByPlanetId.get(planetId) || [];
if (monthRefs.length) {
const meta = document.createElement("div");
meta.className = "kab-god-meta";
meta.textContent = "Calendar month correspondences";
containerEl.appendChild(meta);
const row = document.createElement("div");
row.className = "kab-god-links";
monthRefs.forEach((month) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "kab-god-link";
btn.textContent = `${month.label || month.name}`;
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("nav:calendar-month", {
detail: { monthId: month.id }
}));
});
row.appendChild(btn);
});
containerEl.appendChild(row);
}
const cubePlacements = state.cubePlacementsByPlanetId.get(planetId) || [];
if (cubePlacements.length) {
const meta = document.createElement("div");
meta.className = "kab-god-meta";
meta.textContent = "Cube placements";
containerEl.appendChild(meta);
const row = document.createElement("div");
row.className = "kab-god-links";
cubePlacements.forEach((placement) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "kab-god-link";
btn.textContent = `${placement.label}`;
btn.addEventListener("click", () => {
document.dispatchEvent(new CustomEvent("nav:cube", {
detail: {
planetId,
wallId: placement.wallId,
edgeId: placement.edgeId
}
}));
});
row.appendChild(btn);
});
containerEl.appendChild(row);
}
}
function renderDetail(entry, elements) {
if (!entry || !elements) {
return;
}
if (elements.planetDetailNameEl) {
const symbol = entry.symbol ? `${entry.symbol} ` : "";
elements.planetDetailNameEl.textContent = `${symbol}${entry.name || "--"}`;
}
if (elements.planetDetailTypeEl) {
elements.planetDetailTypeEl.textContent = entry.classification || "--";
}
if (elements.planetDetailSummaryEl) {
elements.planetDetailSummaryEl.textContent = entry.summary || "--";
}
clearChildren(elements.planetDetailFactsEl);
buildFactRows(entry).forEach(([label, value]) => {
const row = document.createElement("div");
row.className = "planet-fact-row";
const labelEl = document.createElement("span");
labelEl.className = "planet-fact-label";
labelEl.textContent = label;
const valueEl = document.createElement("span");
valueEl.className = "planet-fact-value";
valueEl.textContent = value;
row.append(labelEl, valueEl);
elements.planetDetailFactsEl?.appendChild(row);
});
if (elements.planetDetailAtmosphereEl) {
elements.planetDetailAtmosphereEl.textContent = entry.atmosphere || "--";
}
clearChildren(elements.planetDetailNotableEl);
const notableFacts = Array.isArray(entry.notableFacts) ? entry.notableFacts : [];
notableFacts.forEach((fact) => {
const item = document.createElement("li");
item.textContent = fact;
elements.planetDetailNotableEl?.appendChild(item);
});
if (elements.planetDetailCorrespondenceEl) {
renderCorrespondence(entry, elements.planetDetailCorrespondenceEl);
}
}
function updateSelection(elements) {
if (!elements?.planetCardListEl) {
return;
}
const buttons = elements.planetCardListEl.querySelectorAll(".planet-list-item");
buttons.forEach((button) => {
const isSelected = button.dataset.planetId === state.selectedId;
button.classList.toggle("is-selected", isSelected);
button.setAttribute("aria-selected", isSelected ? "true" : "false");
});
}
function selectById(id, elements) {
const entry = state.entries.find((planet) => planet.id === id);
if (!entry) {
return;
}
state.selectedId = entry.id;
updateSelection(elements);
renderDetail(entry, elements);
}
function renderList(elements) {
if (!elements?.planetCardListEl) {
return;
}
clearChildren(elements.planetCardListEl);
state.filteredEntries.forEach((entry) => {
const button = document.createElement("button");
button.type = "button";
button.className = "planet-list-item";
button.dataset.planetId = entry.id;
button.setAttribute("role", "option");
const nameEl = document.createElement("span");
nameEl.className = "planet-list-name";
const symbol = entry.symbol ? `${entry.symbol} ` : "";
nameEl.textContent = `${symbol}${entry.name || "--"}`;
const metaEl = document.createElement("span");
metaEl.className = "planet-list-meta";
metaEl.textContent = entry.classification || "--";
button.append(nameEl, metaEl);
elements.planetCardListEl.appendChild(button);
});
if (elements.planetCountEl) {
elements.planetCountEl.textContent = state.searchQuery
? `${state.filteredEntries.length} of ${state.entries.length} bodies`
: `${state.entries.length} bodies`;
}
}
function ensurePlanetSection(referenceData, magickDataset = null) {
if (state.initialized) {
return;
}
const elements = getElements();
if (!elements.planetCardListEl || !elements.planetDetailNameEl) {
return;
}
const baseList = Array.isArray(referenceData?.planetScience)
? referenceData.planetScience
: [];
if (baseList.length === 0) {
if (elements.planetDetailNameEl) {
elements.planetDetailNameEl.textContent = "Planet data unavailable";
}
if (elements.planetDetailSummaryEl) {
elements.planetDetailSummaryEl.textContent = "Could not load local science facts dataset.";
}
return;
}
const correspondences = referenceData?.planets && typeof referenceData.planets === "object"
? referenceData.planets
: {};
const correspondenceByName = Object.values(correspondences).reduce((acc, value) => {
const key = String(value?.name || "").trim().toLowerCase();
if (key) {
acc[key] = value;
}
return acc;
}, {});
state.kabbalahTargetsByPlanetId = buildKabbalahTargetsByPlanet(magickDataset);
state.monthRefsByPlanetId = buildMonthReferencesByPlanet(referenceData);
state.cubePlacementsByPlanetId = buildCubePlacementsByPlanet(magickDataset);
state.entries = baseList.map((entry) => {
const byId = correspondences[entry.id] || null;
const byName = correspondenceByName[String(entry?.name || "").trim().toLowerCase()] || null;
return {
...entry,
correspondence: byId || byName || null
};
});
state.filteredEntries = [...state.entries];
renderList(elements);
if (state.entries.length > 0) {
selectById(state.entries[0].id, elements);
}
elements.planetCardListEl.addEventListener("click", (event) => {
const target = event.target;
if (!(target instanceof Node)) {
return;
}
const button = target instanceof Element
? target.closest(".planet-list-item")
: null;
if (!(button instanceof HTMLButtonElement)) {
return;
}
const selectedId = button.dataset.planetId;
if (!selectedId) {
return;
}
selectById(selectedId, elements);
});
if (elements.planetSearchInputEl) {
elements.planetSearchInputEl.addEventListener("input", () => {
state.searchQuery = elements.planetSearchInputEl.value || "";
applySearchFilter(elements);
});
}
if (elements.planetSearchClearEl && elements.planetSearchInputEl) {
elements.planetSearchClearEl.addEventListener("click", () => {
elements.planetSearchInputEl.value = "";
state.searchQuery = "";
applySearchFilter(elements);
elements.planetSearchInputEl.focus();
});
}
state.initialized = true;
}
function selectByPlanetId(planetId) {
if (!state.initialized) return;
const el = getElements();
const needle = String(planetId || "").toLowerCase();
const entry = state.entries.find(e =>
String(e.id || "").toLowerCase() === needle ||
String(e.correspondence?.id || "").toLowerCase() === needle ||
String(e.name || "").toLowerCase() === needle
);
if (!entry) return;
selectById(entry.id, el);
el.planetCardListEl
?.querySelector(`[data-planet-id="${entry.id}"]`)
?.scrollIntoView({ block: "nearest" });
}
window.PlanetSectionUi = {
ensurePlanetSection,
selectByPlanetId
};
})();