// Path router: /, /coin/, /portfolio, /trackers, /wallet/
. const routes = []; let cleanup = null; let view = null; export function route(re, make, nav) { routes.push({ re, make, nav }); } export function go(path, replace = false) { if (path === location.pathname + location.search) return; history[replace ? 'replaceState' : 'pushState'](null, '', path); mount(); } export function mount() { view ||= document.getElementById('view'); if (cleanup) { try { cleanup(); } catch {} cleanup = null; } view.replaceChildren(); const p = location.pathname; for (const r of routes) { const m = p.match(r.re); if (!m) continue; for (const a of document.querySelectorAll('[data-nav]')) a.classList.toggle('on', a.dataset.nav === r.nav); cleanup = r.make(view, ...m.slice(1)) || null; return; } history.replaceState(null, '', '/'); mount(); } // links marked data-link stay inside the page; ctrl / middle click still open a new tab document.addEventListener('click', e => { const a = e.target.closest('a[data-link]'); if (!a || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; e.preventDefault(); go(a.getAttribute('href')); }); window.addEventListener('popstate', mount);