(() => { const initMobileSheet = () => { const sheet = document.querySelector("[data-mobile-sheet]"); const navStack = document.querySelector("[data-mobile-nav-stack]"); const openButtons = document.querySelectorAll("[data-mobile-sheet-open]"); if (!sheet || !navStack || !openButtons.length) return; const closeSheet = () => { sheet.hidden = true; navStack.classList.remove("is-open"); openButtons.forEach((button) => button.classList.remove("is-open")); }; const openSheet = () => { sheet.hidden = false; navStack.classList.add("is-open"); openButtons.forEach((button) => button.classList.add("is-open")); }; const toggleSheet = () => { if (sheet.hidden) { openSheet(); } else { closeSheet(); } }; openButtons.forEach((button) => { button.addEventListener("click", toggleSheet); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { closeSheet(); } }); sheet.querySelectorAll("a").forEach((link) => { link.addEventListener("click", closeSheet); }); sheet.querySelectorAll("button[data-theme-toggle]").forEach((button) => { button.addEventListener("click", closeSheet); }); }; const initFilterInputs = () => { document.querySelectorAll("[data-filter-input]").forEach((input) => { const listSelector = input.getAttribute("data-filter-target"); if (!listSelector) return; const container = document.querySelector(listSelector); if (!container) return; const items = Array.from(container.querySelectorAll("[data-filter-label]")); const filterGroups = Array.from(container.querySelectorAll("[data-filter-group]")); const resultLimit = Number.parseInt(input.getAttribute("data-filter-limit") || "", 10); const hasLimit = Number.isFinite(resultLimit) && resultLimit > 0; const scoreItem = (label, term) => { if (label === term) return 0; if (label.startsWith(term)) return 1; if (label.split(/\s+/).some((part) => part.startsWith(term))) return 2; if (label.includes(term)) return 3; return 99; }; const syncGroups = () => { filterGroups.forEach((group) => { const visibleChildren = Array.from(group.querySelectorAll("[data-filter-label]")).some((item) => !item.hidden); const card = group.closest(".component-group, .template-list-card, .panel, .planner-subsection"); if (card) { card.hidden = !visibleChildren; } else { group.hidden = !visibleChildren; } }); }; const applyFilter = () => { const term = input.value.trim().toLowerCase(); if (!term) { items.forEach((item, index) => { item.hidden = hasLimit ? index >= resultLimit : false; }); syncGroups(); return; } const rankedMatches = items .map((item, index) => { const haystack = (item.getAttribute("data-filter-label") || "").toLowerCase(); const score = scoreItem(haystack, term); return { item, index, score, matches: score < 99 }; }) .filter((entry) => entry.matches) .sort((left, right) => left.score - right.score || left.index - right.index); const allowedItems = new Set( (hasLimit ? rankedMatches.slice(0, resultLimit) : rankedMatches).map((entry) => entry.item) ); items.forEach((item) => { item.hidden = !allowedItems.has(item); }); syncGroups(); }; input.addEventListener("input", applyFilter); applyFilter(); }); }; const initIosPullToRefresh = () => { const isAppleTouchDevice = /iP(ad|hone|od)/.test(navigator.userAgent) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1); if (!isAppleTouchDevice) return; let startY = 0; let maxPull = 0; let tracking = false; window.addEventListener("touchstart", (event) => { if (window.scrollY > 0) { tracking = false; return; } startY = event.touches[0].clientY; maxPull = 0; tracking = true; }, { passive: true }); window.addEventListener("touchmove", (event) => { if (!tracking) return; const currentY = event.touches[0].clientY; maxPull = Math.max(maxPull, currentY - startY); }, { passive: true }); window.addEventListener("touchend", () => { if (tracking && maxPull > 96 && window.scrollY <= 2) { window.location.reload(); } tracking = false; maxPull = 0; }, { passive: true }); document.addEventListener("gesturestart", (event) => { event.preventDefault(); }); document.addEventListener("touchmove", (event) => { if (event.touches.length > 1) { event.preventDefault(); } }, { passive: false }); }; document.addEventListener("DOMContentLoaded", () => { initMobileSheet(); initFilterInputs(); initIosPullToRefresh(); }); })();