(function () { "use strict"; const ARABIC_DISPLAY_NAMES = { alif: "Alif", ba: "Ba", jeem: "Jeem", dal: "Dal", ha: "Ha", waw: "Waw", zayn: "Zayn", ha_khaa: "Haa", ta_tay: "Tta", ya: "Ya", kaf: "Kaf", lam: "Lam", meem: "Meem", nun: "Nun", seen: "Seen", ayn: "Ayn", fa: "Fa", sad: "Sad", qaf: "Qaf", ra: "Ra", sheen: "Sheen", ta: "Ta", tha: "Tha", kha: "Kha", dhal: "Dhal", dad: "Dad", dha: "Dha", ghayn: "Ghayn" }; function createAlphabetBrowser(dependencies) { const { state, normalizeId, getDomRefs, renderDetail } = dependencies || {}; function capitalize(value) { return value ? value.charAt(0).toUpperCase() + value.slice(1) : ""; } function arabicDisplayName(letter) { return ARABIC_DISPLAY_NAMES[letter && letter.name] || (String(letter && letter.name || "").charAt(0).toUpperCase() + String(letter && letter.name || "").slice(1)); } function getLetters() { if (!state.alphabets) return []; if (state.activeAlphabet === "all") { const alphabetOrder = ["hebrew", "greek", "english", "arabic", "enochian"]; return alphabetOrder.flatMap((alphabet) => { const rows = Array.isArray(state.alphabets?.[alphabet]) ? state.alphabets[alphabet] : []; return rows.map((row) => ({ ...row, __alphabet: alphabet })); }); } return state.alphabets[state.activeAlphabet] || []; } function alphabetForLetter(letter) { if (state.activeAlphabet === "all") { return String(letter?.__alphabet || "").trim().toLowerCase(); } return state.activeAlphabet; } function letterKeyByAlphabet(alphabet, letter) { if (alphabet === "hebrew") return letter.hebrewLetterId; if (alphabet === "greek") return letter.name; if (alphabet === "english") return letter.letter; if (alphabet === "arabic") return letter.name; if (alphabet === "enochian") return letter.id; return String(letter.index); } function letterKey(letter) { const alphabet = alphabetForLetter(letter); const key = letterKeyByAlphabet(alphabet, letter); if (state.activeAlphabet === "all") { return `${alphabet}:${key}`; } return key; } function displayGlyph(letter) { const alphabet = alphabetForLetter(letter); if (alphabet === "hebrew") return letter.char; if (alphabet === "greek") return letter.char; if (alphabet === "english") return letter.letter; if (alphabet === "arabic") return letter.char; if (alphabet === "enochian") return letter.char; return "?"; } function displayLabel(letter) { const alphabet = alphabetForLetter(letter); if (alphabet === "hebrew") return letter.name; if (alphabet === "greek") return letter.displayName; if (alphabet === "english") return letter.letter; if (alphabet === "arabic") return arabicDisplayName(letter); if (alphabet === "enochian") return letter.title; return "?"; } function displaySub(letter) { const alphabet = alphabetForLetter(letter); if (alphabet === "hebrew") return `${letter.transliteration} · ${letter.letterType} · ${letter.numerology}`; if (alphabet === "greek") return `${letter.transliteration} · isopsephy ${letter.numerology}${letter.archaic ? " · archaic" : ""}`; if (alphabet === "english") return `Pythagorean ${letter.pythagorean}`; if (alphabet === "arabic") return `${letter.transliteration} · abjad ${letter.abjad} · ${letter.nameArabic}`; if (alphabet === "enochian") return `${letter.transliteration} · ${Array.isArray(letter.englishLetters) ? letter.englishLetters.join("/") : ""} · value ${letter.numerology}`; return ""; } function normalizeLetterType(value) { const key = String(value || "").trim().toLowerCase(); if (["mother", "double", "simple"].includes(key)) { return key; } return ""; } function getHebrewLetterTypeMap() { const map = new Map(); const hebrewLetters = Array.isArray(state.alphabets?.hebrew) ? state.alphabets.hebrew : []; hebrewLetters.forEach((entry) => { const hebrewId = normalizeId(entry?.hebrewLetterId); const letterType = normalizeLetterType(entry?.letterType); if (hebrewId && letterType) { map.set(hebrewId, letterType); } }); return map; } function resolveLetterType(letter) { const direct = normalizeLetterType(letter?.letterType); if (direct) { return direct; } const hebrewId = normalizeId(letter?.hebrewLetterId); if (!hebrewId) { return ""; } return getHebrewLetterTypeMap().get(hebrewId) || ""; } function buildLetterSearchText(letter) { const chunks = []; chunks.push(String(displayLabel(letter) || "")); chunks.push(String(displayGlyph(letter) || "")); chunks.push(String(displaySub(letter) || "")); chunks.push(String(letter?.transliteration || "")); chunks.push(String(letter?.meaning || "")); chunks.push(String(letter?.nameArabic || "")); chunks.push(String(letter?.title || "")); chunks.push(String(letter?.letter || "")); chunks.push(String(letter?.displayName || "")); chunks.push(String(letter?.name || "")); chunks.push(String(letter?.index || "")); chunks.push(String(resolveLetterType(letter) || "")); return chunks.join(" ").toLowerCase(); } function getFilteredLetters() { const letters = getLetters(); const query = String(state.filters.query || "").trim().toLowerCase(); const letterTypeFilter = normalizeLetterType(state.filters.letterType); const numericPosition = /^\d+$/.test(query) ? Number(query) : null; return letters.filter((letter) => { if (letterTypeFilter) { const entryType = resolveLetterType(letter); if (entryType !== letterTypeFilter) { return false; } } if (!query) { return true; } const index = Number(letter?.index); if (Number.isFinite(numericPosition) && Number.isFinite(index) && index === numericPosition) { return true; } return buildLetterSearchText(letter).includes(query); }); } function syncFilterControls() { const { searchInputEl, typeFilterEl, searchClearEl } = getDomRefs(); if (searchInputEl && searchInputEl.value !== state.filters.query) { searchInputEl.value = state.filters.query; } if (typeFilterEl && typeFilterEl.value !== state.filters.letterType) { typeFilterEl.value = state.filters.letterType; } if (searchClearEl) { const hasFilter = Boolean(String(state.filters.query || "").trim()) || Boolean(state.filters.letterType); searchClearEl.disabled = !hasFilter; } } function applyFiltersAndRender() { const filteredLetters = getFilteredLetters(); const selectedInFiltered = filteredLetters.some((letter) => letterKey(letter) === state.selectedKey); if (!selectedInFiltered) { state.selectedKey = filteredLetters[0] ? letterKey(filteredLetters[0]) : null; } renderList(); const selected = filteredLetters.find((letter) => letterKey(letter) === state.selectedKey) || filteredLetters[0] || null; if (selected) { renderDetail(selected); return; } resetDetail(); const { detailSubEl } = getDomRefs(); if (detailSubEl) { detailSubEl.textContent = "No letters match the current filter."; } } function bindFilterControls() { const { searchInputEl, typeFilterEl, searchClearEl } = getDomRefs(); if (searchInputEl) { searchInputEl.addEventListener("input", () => { state.filters.query = String(searchInputEl.value || ""); syncFilterControls(); applyFiltersAndRender(); }); } if (typeFilterEl) { typeFilterEl.addEventListener("change", () => { state.filters.letterType = normalizeLetterType(typeFilterEl.value); syncFilterControls(); applyFiltersAndRender(); }); } if (searchClearEl) { searchClearEl.addEventListener("click", () => { state.filters.query = ""; state.filters.letterType = ""; syncFilterControls(); applyFiltersAndRender(); }); } } function enochianGlyphKey(letter) { return String(letter?.id || letter?.char || "").trim().toUpperCase(); } function enochianGlyphCode(letter) { const key = enochianGlyphKey(letter); return key ? key.codePointAt(0) || 0 : 0; } function enochianGlyphUrl(letter) { const code = enochianGlyphCode(letter); return code ? (window.TarotDataService?.toApiAssetUrl?.(`img/enochian/char(${code}).png`) || "") : ""; } function enochianGlyphImageHtml(letter, className) { const src = enochianGlyphUrl(letter); const key = enochianGlyphKey(letter) || "?"; if (!src) { return `${key}`; } return `Enochian ${key}`; } function renderList() { const { listEl, countEl } = getDomRefs(); if (!listEl) return; const allLetters = getLetters(); const letters = getFilteredLetters(); if (countEl) { countEl.textContent = letters.length === allLetters.length ? `${letters.length}` : `${letters.length}/${allLetters.length}`; } listEl.innerHTML = ""; letters.forEach((letter) => { const key = letterKey(letter); const item = document.createElement("div"); item.className = "planet-list-item alpha-list-item" + (key === state.selectedKey ? " is-selected" : ""); item.setAttribute("role", "option"); item.setAttribute("aria-selected", key === state.selectedKey ? "true" : "false"); item.dataset.key = key; const glyph = document.createElement("span"); const alphabet = alphabetForLetter(letter); const glyphVariantClass = alphabet === "arabic" ? " alpha-list-glyph--arabic" : alphabet === "enochian" ? " alpha-list-glyph--enochian" : ""; glyph.className = "alpha-list-glyph" + glyphVariantClass; if (alphabet === "enochian") { const image = document.createElement("img"); image.className = "alpha-enochian-glyph-img alpha-enochian-glyph-img--list"; image.src = enochianGlyphUrl(letter); image.alt = `Enochian ${enochianGlyphKey(letter) || "?"}`; image.loading = "lazy"; image.decoding = "async"; image.addEventListener("error", () => { glyph.textContent = enochianGlyphKey(letter) || "?"; }); glyph.appendChild(image); } else { glyph.textContent = displayGlyph(letter); } const meta = document.createElement("span"); meta.className = "alpha-list-meta"; const alphaLabel = alphabet ? `${capitalize(alphabet)} · ` : ""; meta.innerHTML = `${alphaLabel}${displayLabel(letter)}
${displaySub(letter)}`; item.appendChild(glyph); item.appendChild(meta); item.addEventListener("click", () => selectLetter(key)); listEl.appendChild(item); }); } function resetDetail() { const { detailNameEl, detailSubEl, detailBodyEl } = getDomRefs(); if (detailNameEl) { detailNameEl.textContent = "--"; detailNameEl.classList.remove("alpha-detail-glyph"); } if (detailSubEl) detailSubEl.textContent = "Select a letter to explore"; if (detailBodyEl) detailBodyEl.innerHTML = ""; } function selectLetter(key) { state.selectedKey = key; renderList(); const letters = getFilteredLetters(); const letter = letters.find((entry) => letterKey(entry) === key) || getLetters().find((entry) => letterKey(entry) === key); if (letter) { renderDetail(letter); } } function updateTabs() { const { tabAll, tabHebrew, tabGreek, tabEnglish, tabArabic, tabEnochian } = getDomRefs(); [tabAll, tabHebrew, tabGreek, tabEnglish, tabArabic, tabEnochian].forEach((btn) => { if (!btn) return; btn.classList.toggle("alpha-tab-active", btn.dataset.alpha === state.activeAlphabet); }); } function switchAlphabet(alpha, selectKey) { state.activeAlphabet = alpha; state.selectedKey = selectKey || null; updateTabs(); syncFilterControls(); renderList(); if (selectKey) { const letters = getFilteredLetters(); const letter = letters.find((entry) => letterKey(entry) === selectKey) || getLetters().find((entry) => letterKey(entry) === selectKey); if (letter) { renderDetail(letter); } } else { resetDetail(); } } return { arabicDisplayName, getLetters, alphabetForLetter, letterKeyByAlphabet, letterKey, displayGlyph, displayLabel, displaySub, normalizeLetterType, getHebrewLetterTypeMap, resolveLetterType, buildLetterSearchText, getFilteredLetters, syncFilterControls, applyFiltersAndRender, bindFilterControls, enochianGlyphKey, enochianGlyphCode, enochianGlyphUrl, enochianGlyphImageHtml, renderList, resetDetail, selectLetter, switchAlphabet, updateTabs }; } window.AlphabetBrowserUi = { createAlphabetBrowser }; })();