export function initAsidePanels(options = {}) { const { barSelector = '.aside-icon-bar', panelSelector = '.app-sidebar-panel', titleSelector = '.app-sidebar-title', toolsSelector = '[data-aside-tools]', revealSidebarOnActivate = true, persistSidebarStateOnActivate = true } = options; const bar = document.querySelector(barSelector); if (!bar) return; const tabs = Array.from(bar.querySelectorAll('[data-aside-target]')); if (!tabs.length) return; const panels = Array.from(document.querySelectorAll(panelSelector)); const titleEl = document.querySelector(titleSelector); const toolsHost = document.querySelector(toolsSelector); const sidebarController = window.AppSidebar || null; const defaultTitle = titleEl?.dataset.asideTitleDefault || titleEl?.textContent || ''; const storageKey = bar.dataset.asideStorage || ''; const getPanelKey = (panel) => panel?.dataset?.asidePanel || ''; const getTabKey = (tab) => tab?.dataset?.asideTarget || ''; const getPanelTools = (panel) => panel?.querySelector('[data-aside-panel-tools]') || null; const getTabHref = (tab) => tab?.dataset?.asideHref || ''; const initPanelDetails = (panel) => { if (!panel || panel.dataset.detailsBound === '1') return; const storageKey = panel.dataset.asideDetailsStorage || ''; if (!storageKey) return; const detailsEls = Array.from(panel.querySelectorAll('details[data-details-key]')); if (!detailsEls.length) return; const readStored = () => { try { const raw = window.localStorage.getItem(storageKey); return raw ? JSON.parse(raw) : []; } catch (error) { return []; } }; const writeStored = (value) => { try { const list = Array.isArray(value) ? value : []; window.localStorage.setItem(storageKey, JSON.stringify(list)); } catch (error) { // ignore storage errors } }; const applyStored = () => { const stored = readStored(); if (!stored.length) return; detailsEls.forEach((details) => { details.open = stored.includes(details.dataset.detailsKey || ''); }); }; detailsEls.forEach((details) => { details.addEventListener('toggle', () => { const openKeys = detailsEls .filter((item) => item.open) .map((item) => item.dataset.detailsKey || '') .filter(Boolean); writeStored(openKeys); }); }); applyStored(); panel.dataset.detailsBound = '1'; }; const readStored = () => { if (!storageKey) return null; try { return window.localStorage.getItem(storageKey); } catch (error) { return null; } }; const writeStored = (key) => { if (!storageKey) return; try { window.localStorage.setItem(storageKey, key); } catch (error) { // ignore storage errors } }; const syncTools = (panel) => { if (!toolsHost) return; toolsHost.innerHTML = ''; const tools = getPanelTools(panel); if (!tools) return; toolsHost.innerHTML = tools.innerHTML; }; const openSidebar = (persist) => { if (!revealSidebarOnActivate || !sidebarController) return; if (!sidebarController.isCollapsed()) return; sidebarController.open({ persist }); }; const setActive = (key, { fromUser = false } = {}) => { if (!key) return; let activePanel = null; panels.forEach((panel) => { const isActive = getPanelKey(panel) === key; if (isActive) activePanel = panel; panel.hidden = !isActive; panel.setAttribute('aria-hidden', isActive ? 'false' : 'true'); }); tabs.forEach((tab) => { const isActive = getTabKey(tab) === key; tab.classList.toggle('active', isActive); tab.setAttribute('aria-selected', isActive ? 'true' : 'false'); tab.setAttribute('tabindex', isActive ? '0' : '-1'); }); if (titleEl) { const nextTitle = activePanel?.dataset?.asideTitle || defaultTitle; if (nextTitle) { titleEl.textContent = nextTitle; } } if (activePanel) { syncTools(activePanel); initPanelDetails(activePanel); } writeStored(key); if (fromUser) { openSidebar(persistSidebarStateOnActivate); } }; const getInitialKey = () => { const stored = readStored(); if (stored && panels.some((panel) => getPanelKey(panel) === stored)) { return stored; } const activeTab = tabs.find((tab) => tab.classList.contains('active')); if (activeTab) return getTabKey(activeTab); const visiblePanel = panels.find((panel) => !panel.hidden); if (visiblePanel) return getPanelKey(visiblePanel); return getTabKey(tabs[0]); }; setActive(getInitialKey(), { fromUser: false }); tabs.forEach((tab) => { tab.addEventListener('click', (event) => { event.preventDefault(); const key = getTabKey(tab); const isActive = tab.classList.contains('active'); const href = getTabHref(tab); if (href) { const base = document.baseURI || window.location.origin; const targetUrl = new URL(href, base); const currentUrl = new URL(window.location.href); const isSame = targetUrl.pathname === currentUrl.pathname && targetUrl.search === currentUrl.search; if (!isSame) { setActive(key, { fromUser: true }); window.location.href = targetUrl.toString(); return; } } if (sidebarController && sidebarController.isCollapsed()) { sidebarController.open({ persist: persistSidebarStateOnActivate }); setActive(key, { fromUser: true }); return; } if (isActive && sidebarController) { sidebarController.close({ persist: true }); return; } setActive(key, { fromUser: true }); }); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => initAsidePanels()); } else { initAsidePanels(); }