// Hash router. URLs are stable and shareable: the view, its filters, and paging // all live in the hash, so a reload restores exactly what was on screen. export function parseHash() { const raw = location.hash.slice(1) || "/workflow"; const [path, queryString = ""] = raw.split("?"); return { path, params: Object.fromEntries(new URLSearchParams(queryString)) }; } export function navigate(path, params = {}) { const clean = Object.fromEntries( Object.entries(params).filter(([, v]) => v !== undefined && v !== null && v !== "") ); const query = Object.keys(clean).length ? "?" + new URLSearchParams(clean) : ""; location.hash = path + query; } export function onRouteChange(handler) { window.addEventListener("hashchange", handler); window.addEventListener("DOMContentLoaded", handler); }