@jasonshimmy/custom-elements-runtime 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/custom-elements-runtime.cjs.js +1 -18
  2. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  3. package/dist/custom-elements-runtime.es.js +150 -3644
  4. package/dist/custom-elements-runtime.es.js.map +1 -1
  5. package/dist/custom-elements-runtime.router.cjs.js +19 -19
  6. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  7. package/dist/custom-elements-runtime.router.es.js +762 -451
  8. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  9. package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
  10. package/dist/custom-elements-runtime.ssr.es.js +1 -1
  11. package/dist/custom-elements-runtime.transitions.cjs.js +1 -1
  12. package/dist/custom-elements-runtime.transitions.es.js +1 -1
  13. package/dist/index.d.ts +2 -0
  14. package/dist/namespace-helpers-BCVTzhAO.cjs +5 -0
  15. package/dist/namespace-helpers-BCVTzhAO.cjs.map +1 -0
  16. package/dist/namespace-helpers-CF28TyaG.js +786 -0
  17. package/dist/namespace-helpers-CF28TyaG.js.map +1 -0
  18. package/dist/router.d.ts +82 -21
  19. package/dist/runtime/monitoring/health-monitor.d.ts +99 -0
  20. package/dist/runtime/render.d.ts +1 -1
  21. package/dist/runtime/scheduler.d.ts +46 -0
  22. package/dist/template-compiler-CXHEnaBh.cjs +17 -0
  23. package/dist/template-compiler-CXHEnaBh.cjs.map +1 -0
  24. package/dist/template-compiler-DD_VZrte.js +3729 -0
  25. package/dist/template-compiler-DD_VZrte.js.map +1 -0
  26. package/dist/{transitions-CZ21fzhh.js → transitions-Bx0Nc9zR.js} +256 -255
  27. package/dist/transitions-Bx0Nc9zR.js.map +1 -0
  28. package/dist/{transitions-RXe2brRm.cjs → transitions-DfcqL-X4.cjs} +4 -4
  29. package/dist/transitions-DfcqL-X4.cjs.map +1 -0
  30. package/package.json +9 -8
  31. package/dist/namespace-helpers-BsKQl3aH.cjs +0 -5
  32. package/dist/namespace-helpers-BsKQl3aH.cjs.map +0 -1
  33. package/dist/namespace-helpers-Dw1mgQab.js +0 -692
  34. package/dist/namespace-helpers-Dw1mgQab.js.map +0 -1
  35. package/dist/transitions-CZ21fzhh.js.map +0 -1
  36. package/dist/transitions-RXe2brRm.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-runtime.router.es.js","sources":["../src/lib/router.ts"],"sourcesContent":["import { html } from './runtime/template-compiler';\nimport { component } from './runtime/component';\nimport {\n useProps,\n useOnConnected,\n useOnDisconnected,\n useStyle,\n} from './runtime/hooks';\nimport { ref, computed } from './runtime/reactive';\nimport { createStore, type Store } from './store';\nimport { devError, devWarn } from './runtime/logger';\nimport { match } from './directives';\n\nexport type RouteComponent =\n | { new (...args: unknown[]): unknown } // class components\n | ((...args: unknown[]) => unknown); // functional components\n\nexport interface RouteState {\n path: string;\n params: Record<string, string>;\n query: Record<string, string>;\n // Optional fragment (hash) portion of the URL, without the leading '#'\n fragment?: string;\n}\n\nexport type GuardResult = boolean | string | Promise<boolean | string>;\n\nexport interface Route {\n path: string;\n\n /**\n * Statically available component (already imported)\n */\n component?: string | (() => unknown);\n\n /**\n * Lazy loader that resolves to something renderable\n */\n load?: () => Promise<{\n default: string | HTMLElement | ((...args: unknown[]) => unknown);\n }>;\n\n /**\n * Runs before matching — return false to cancel,\n * or a string to redirect\n */\n beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs right before navigation commits — can cancel or redirect\n */\n onEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs after navigation completes — cannot cancel\n */\n afterEnter?: (to: RouteState, from: RouteState) => void;\n}\n\nexport interface RouterLinkProps {\n to: string;\n tag: string;\n replace: boolean;\n exact: boolean;\n activeClass: string;\n exactActiveClass: string;\n ariaCurrentValue: string;\n disabled: boolean;\n external: boolean;\n class?: string;\n style?: string;\n}\n\nexport interface RouterLinkComputed {\n current: RouteState;\n isExactActive: boolean;\n isActive: boolean;\n className: string;\n ariaCurrent: string;\n isButton: boolean;\n disabledAttr: string;\n externalAttr: string;\n}\n\nexport interface RouterConfig {\n routes: Route[];\n base?: string;\n initialUrl?: string; // For SSR: explicitly pass the URL\n /**\n * Configure fragment (hash) scrolling behavior. Either a boolean to enable/disable\n * or an object to enable and provide an offset in pixels to account for fixed\n * headers.\n */\n scrollToFragment?:\n | boolean\n | {\n enabled?: boolean;\n offset?: number; // pixels\n timeoutMs?: number; // ms to wait for element to appear\n };\n}\n\nexport const parseQuery = (search: string): Record<string, string> => {\n if (!search) return {};\n if (typeof URLSearchParams === 'undefined') return {};\n return Object.fromEntries(new URLSearchParams(search));\n};\n\n// Serialize a query object into a leading `?a=b&c=d` string. Returns empty\n// string when there are no keys. Centralized so client history URLs and\n// other code use consistent encoding.\nexport const serializeQuery = (q: Record<string, string> | undefined) => {\n if (!q || Object.keys(q).length === 0) return '';\n try {\n return '?' + new URLSearchParams(q as Record<string, string>).toString();\n } catch {\n return '';\n }\n};\n\n// Detect obviously dangerous javascript: URIs. We intentionally block these\n// from becoming clickable hrefs to avoid accidental XSS when `to` is\n// derived from untrusted input.\nconst isDangerousScheme = (s: string) => {\n if (!s) return false;\n return /^\\s*javascript\\s*:/i.test(s);\n};\n\n// Cache compiled route regexes to avoid rebuilding on every navigation.\ntype CompiledRoute =\n | { regex: RegExp; paramNames: string[] }\n | { invalid: true };\nconst compileCache: WeakMap<Route, CompiledRoute> = new WeakMap();\n\nfunction escapeSeg(seg: string) {\n return seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function normalizePathForRoute(p: string) {\n if (!p) return '/';\n // Collapse duplicate slashes, ensure leading slash, remove trailing slash\n let out = p.replace(/\\/+/g, '/');\n if (!out.startsWith('/')) out = '/' + out;\n if (out.length > 1 && out.endsWith('/')) out = out.slice(0, -1);\n return out;\n}\n\nfunction compileRoute(route: Route): CompiledRoute {\n const raw = route.path || '/';\n const routePath = normalizePathForRoute(raw);\n\n const segments =\n routePath === '/' ? [] : routePath.split('/').filter(Boolean);\n\n const paramNames: string[] = [];\n const regexParts: string[] = [];\n\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n\n // Anonymous wildcard\n if (seg === '*') {\n // splat must be terminal\n if (i !== segments.length - 1) {\n devWarn(\n `Route '${route.path}' contains a '*' splat in a non-terminal position; splats must be the last segment. This route will be ignored.`,\n );\n return { invalid: true };\n }\n const name = `splat${paramNames.length}`;\n paramNames.push(name);\n // mark splat token; pattern will be built specially so the\n // preceding slash can be optional (allow empty splat)\n regexParts.push('__SPLAT__');\n continue;\n }\n\n const paramMatch = seg.match(/^:([A-Za-z0-9_-]+)(\\*)?$/);\n if (paramMatch) {\n const name = paramMatch[1];\n const isSplat = !!paramMatch[2];\n // If splat, ensure terminal\n if (isSplat && i !== segments.length - 1) {\n devWarn(\n `Route '${route.path}' contains a splat param ':${name}*' in a non-terminal position; splats must be the last segment. This route will be ignored.`,\n );\n return { invalid: true };\n }\n paramNames.push(name);\n regexParts.push(isSplat ? '__SPLAT__' : '([^/]+)');\n continue;\n }\n\n // Static\n regexParts.push(escapeSeg(seg));\n }\n\n let pattern: string;\n if (regexParts.length === 0) {\n pattern = '^/$';\n } else {\n const last = regexParts[regexParts.length - 1];\n if (last === '__SPLAT__') {\n const prefix = regexParts.slice(0, -1).join('/');\n if (!prefix) {\n // route is like '/:rest*' or '/*' -> allow '/' or '/x' etc.\n pattern = '^(?:/(.*))?(?:/)?$';\n } else {\n pattern = `^/${prefix}(?:/(.*))?(?:/)?$`;\n }\n } else {\n pattern = `^/${regexParts.join('/')}(?:/)?$`;\n }\n }\n try {\n const regex = new RegExp(pattern);\n return { regex, paramNames };\n } catch (e) {\n devWarn(`Failed to compile route regex for '${route.path}': ${String(e)}`);\n return { invalid: true };\n }\n}\n\nexport const matchRoute = (\n routes: Route[],\n path: string,\n): { route: Route | null; params: Record<string, string> } => {\n const incoming = normalizePathForRoute(path);\n\n for (const route of routes) {\n let compiled = compileCache.get(route);\n if (!compiled) {\n compiled = compileRoute(route);\n compileCache.set(route, compiled);\n }\n\n if ((compiled as { invalid?: true }).invalid) continue;\n\n const { regex, paramNames } = compiled as {\n regex: RegExp;\n paramNames: string[];\n };\n const m = regex.exec(incoming);\n if (m) {\n const params: Record<string, string> = {};\n const safeDecode = (v: string) => {\n try {\n return decodeURIComponent(v);\n } catch {\n return v;\n }\n };\n\n for (let i = 0; i < paramNames.length; i++) {\n const raw = m[i + 1] || '';\n params[paramNames[i]] = raw ? safeDecode(raw) : '';\n }\n\n return { route, params };\n }\n }\n\n return { route: null, params: {} };\n};\n\n/**\n * Find the first route that matches the given path.\n * Consolidates repeated inline checks like `routes.find(r => matchRoute([r], path).route !== null)`\n */\nfunction findMatchedRoute(routes: Route[], path: string): Route | null {\n for (const r of routes) {\n if (matchRoute([r], path).route !== null) return r;\n }\n return null;\n}\n\n// Async component loader cache\nconst componentCache: Record<\n string,\n string | HTMLElement | ((...args: unknown[]) => unknown)\n> = {};\n\n/**\n * Loads a route's component, supporting both static and async.\n * @param route Route object\n * @returns Promise resolving to the component\n */\nexport async function resolveRouteComponent(\n route: Route,\n): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)> {\n if (route.component) return route.component;\n if (route.load) {\n if (componentCache[route.path]) return componentCache[route.path];\n try {\n const mod = await route.load();\n componentCache[route.path] = mod.default;\n return mod.default;\n } catch {\n throw new Error(`Failed to load component for route: ${route.path}`);\n }\n }\n throw new Error(`No component or loader defined for route: ${route.path}`);\n}\n\nexport function useRouter(config: RouterConfig) {\n const { routes, base = '', initialUrl, scrollToFragment = true } = config;\n\n // Canonicalize base so callers and internal logic have a single\n // representation. Normalized base will be '' for root or '/x' (no\n // trailing slash). This prevents accidental double-prefixing like\n // '/app/app/about' and makes startsWith checks reliable.\n const canonicalBase = (() => {\n if (!base) return '';\n const nb = normalizePathForRoute(base);\n return nb === '/' ? '' : nb;\n })();\n\n // Normalize scroll config: either boolean or object { enabled?, offset?, timeoutMs }\n const _scrollConfig =\n typeof scrollToFragment === 'boolean'\n ? { enabled: !!scrollToFragment, offset: 0, timeoutMs: 2000 }\n : {\n enabled: scrollToFragment.enabled ?? true,\n offset: scrollToFragment.offset ?? 0,\n timeoutMs: scrollToFragment.timeoutMs ?? 2000,\n };\n\n // getLocation/initial include an optional `fragment` field in practice.\n let getLocation: () => {\n path: string;\n query: Record<string, string>;\n fragment?: string;\n };\n let initial: {\n path: string;\n query: Record<string, string>;\n fragment?: string;\n };\n let store: Store<RouteState>;\n let update: (replace?: boolean) => Promise<void>;\n let push: (path: string) => Promise<void>;\n let replaceFn: (path: string) => Promise<void>;\n let back: () => void;\n\n // Run matching route guards/hooks\n const runBeforeEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.beforeEnter) return true;\n try {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('beforeEnter error', err);\n return false;\n }\n };\n\n const runOnEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.onEnter) return true;\n try {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('onEnter error', err);\n return false;\n }\n };\n\n const runAfterEnter = (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.afterEnter) return;\n try {\n matched.afterEnter(to, from);\n } catch (err) {\n devError('afterEnter error', err);\n }\n };\n\n // Scroll-to-fragment helpers: a cancellable per-navigation flow that\n // first attempts immediate scroll, then uses rAF and MutationObserver as\n // a robust fallback. Resolves true if scroll executed, false if timed out\n // or cancelled.\n let _navToken = 0;\n let _activeObserver: MutationObserver | null = null;\n let _activeTimeout: number | null = null;\n let _activeResolve: ((v: boolean) => void) | null = null;\n\n async function doScrollToElement(id: string, offset = 0) {\n try {\n const el = document.getElementById(id) as HTMLElement | null;\n if (!el) return false;\n if (offset && offset > 0) {\n try {\n const rect = el.getBoundingClientRect();\n const top = Math.max(0, window.scrollY + rect.top - offset);\n if (typeof window.scrollTo === 'function') {\n window.scrollTo({ top, behavior: 'auto' });\n }\n } catch {\n try {\n el.scrollIntoView();\n } catch {\n /* swallow */\n }\n }\n } else {\n if (typeof el.scrollIntoView === 'function') {\n try {\n el.scrollIntoView({\n behavior: 'auto',\n block: 'start',\n inline: 'nearest',\n });\n } catch {\n try {\n el.scrollIntoView();\n } catch {\n /* swallow */\n }\n }\n }\n }\n return true;\n } catch {\n return false;\n }\n }\n\n function clearActiveScrollAttempt() {\n if (_activeObserver) {\n try {\n _activeObserver.disconnect();\n } catch {\n /* swallow */\n }\n _activeObserver = null;\n }\n if (_activeTimeout) {\n try {\n clearTimeout(_activeTimeout);\n } catch {\n /* swallow */\n }\n _activeTimeout = null;\n }\n // NOTE: do NOT resolve/clear `_activeResolve` here. Resolution of the\n // active promise must be handled explicitly by the creator/canceller so\n // we avoid double-resolve races where both cleanup and the active\n // flow attempt try to resolve the same promise. Clearing observer/timeout\n // here is sufficient for cleanup; callers should resolve any prior\n // `_activeResolve` before calling this helper.\n }\n\n function startScrollForNavigation(\n id: string,\n offset: number | undefined,\n timeoutMs: number | undefined,\n ) {\n _navToken += 1;\n const myToken = _navToken;\n\n // If there is a previous pending resolver, resolve it as cancelled\n // (false) so callers awaiting it observe cancellation before we clear\n // internal observers/timeouts. This ensures the previous Promise is\n // resolved exactly once with `false` when a new navigation/scroll\n // attempt starts.\n if (_activeResolve) {\n try {\n _activeResolve(false);\n } catch {\n /* swallow */\n }\n _activeResolve = null;\n }\n\n clearActiveScrollAttempt();\n\n return new Promise<boolean>((resolve) => {\n // Register the new active resolver for potential cancellation by a\n // future navigation. We deliberately set this after clearing prior\n // observers/timeouts and resolving any previous resolver above.\n _activeResolve = resolve;\n\n const finish = (did: boolean) => {\n if (myToken !== _navToken) return;\n clearActiveScrollAttempt();\n try {\n resolve(did);\n } finally {\n // Avoid retaining a reference to the resolver after it has\n // been used — prevents later attempts from re-calling an old\n // function and keeps lifecycle explicit.\n _activeResolve = null;\n }\n };\n\n const tryNow = async () => {\n if (myToken !== _navToken) return finish(false);\n if (await doScrollToElement(id, offset)) return finish(true);\n\n // After rAF try once more so layout can settle\n if (typeof window.requestAnimationFrame === 'function') {\n window.requestAnimationFrame(async () => {\n if (myToken !== _navToken) return finish(false);\n if (await doScrollToElement(id, offset)) return finish(true);\n\n if (myToken !== _navToken) return finish(false);\n const container =\n document.querySelector('router-view') || document.body;\n try {\n const obs = new MutationObserver(async () => {\n if (myToken !== _navToken) return;\n if (await doScrollToElement(id, offset)) {\n finish(true);\n }\n });\n _activeObserver = obs;\n obs.observe(container as Node, {\n childList: true,\n subtree: true,\n attributes: false,\n });\n\n _activeTimeout = window.setTimeout(() => {\n if (myToken !== _navToken) return;\n try {\n obs.disconnect();\n } catch {\n /* swallow */\n }\n _activeObserver = null;\n _activeTimeout = null;\n finish(false);\n }, timeoutMs ?? 2000);\n } catch {\n // Fallback to polling\n const MAX_RETRIES = 40;\n const RETRY_DELAY = 50;\n let n = 0;\n const poll = async () => {\n if (myToken !== _navToken) return finish(false);\n if (await doScrollToElement(id, offset)) return finish(true);\n n += 1;\n if (n < MAX_RETRIES) window.setTimeout(poll, RETRY_DELAY);\n else finish(false);\n };\n poll();\n }\n });\n } else {\n // no rAF — try MutationObserver immediately\n const container =\n document.querySelector('router-view') || document.body;\n try {\n const obs = new MutationObserver(async () => {\n if (myToken !== _navToken) return;\n if (await doScrollToElement(id, offset)) {\n finish(true);\n }\n });\n _activeObserver = obs;\n obs.observe(container as Node, {\n childList: true,\n subtree: true,\n attributes: false,\n });\n _activeTimeout = window.setTimeout(() => {\n if (myToken !== _navToken) return;\n try {\n obs.disconnect();\n } catch {\n /* swallow */\n }\n _activeObserver = null;\n _activeTimeout = null;\n finish(false);\n }, timeoutMs ?? 2000);\n } catch {\n // fallback polling\n const MAX_RETRIES = 40;\n const RETRY_DELAY = 50;\n let n = 0;\n const poll = async () => {\n if (myToken !== _navToken) return finish(false);\n if (await doScrollToElement(id, offset)) return finish(true);\n n += 1;\n if (n < MAX_RETRIES) window.setTimeout(poll, RETRY_DELAY);\n else finish(false);\n };\n poll();\n }\n }\n };\n\n queueMicrotask(tryNow);\n });\n }\n\n const navigate = async (path: string, replace = false) => {\n try {\n // Separate fragment (hash) from path so matching ignores it while\n // the fragment is preserved on the RouteState.\n const hashIndex = path.indexOf('#');\n const fragment = hashIndex >= 0 ? path.slice(hashIndex + 1) : '';\n const rawPath = hashIndex >= 0 ? path.slice(0, hashIndex) : path;\n // Parse query string (if any) so queries are available on RouteState\n // and do not end up inside the normalized path used for matching.\n const qIndex = rawPath.indexOf('?');\n const pathBeforeQuery = qIndex >= 0 ? rawPath.slice(0, qIndex) : rawPath;\n const query = qIndex >= 0 ? parseQuery(rawPath.slice(qIndex)) : {};\n const stripped = pathBeforeQuery.startsWith(canonicalBase)\n ? pathBeforeQuery.slice(canonicalBase.length)\n : pathBeforeQuery;\n const normalized = normalizePathForRoute(stripped || '/');\n const loc = {\n path: normalized,\n query,\n fragment,\n };\n const match = matchRoute(routes, loc.path);\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n fragment: (loc as { fragment?: string }).fragment,\n };\n\n // beforeEnter guard\n const allowedBefore = await runBeforeEnter(to, from);\n if (!allowedBefore) return;\n\n // onEnter guard (right before commit)\n const allowedOn = await runOnEnter(to, from);\n if (!allowedOn) return;\n\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const qstr = serializeQuery(loc.query);\n const href =\n canonicalBase +\n loc.path +\n (qstr || '') +\n (loc.fragment ? '#' + loc.fragment : '');\n if (replace) {\n window.history.replaceState({}, '', href);\n } else {\n window.history.pushState({}, '', href);\n }\n }\n\n store.setState(to);\n\n // afterEnter hook (post commit)\n runAfterEnter(to, from);\n\n // If there's a fragment (hash) preserve it on the URL and attempt to\n // scroll to the element with that id on client-side navigation.\n try {\n const frag = (to as { fragment?: string }).fragment;\n if (\n _scrollConfig.enabled &&\n frag &&\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n ) {\n // Start the robust scroll flow (observer + timeout + cancellation)\n startScrollForNavigation(\n String(frag),\n _scrollConfig.offset,\n _scrollConfig.timeoutMs,\n ).catch(() => {});\n }\n } catch {\n /* swallow */\n }\n } catch (err) {\n devError('Navigation error:', err);\n }\n };\n\n // If an explicit `initialUrl` is provided we treat this as SSR/static rendering\n // even if a `window` exists (useful for hydration tests). Browser mode only\n // applies when `initialUrl` is undefined.\n if (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n typeof initialUrl === 'undefined'\n ) {\n // Browser mode\n getLocation = () => {\n const url = new URL(window.location.href);\n const raw = url.pathname;\n const stripped = raw.startsWith(canonicalBase)\n ? raw.slice(canonicalBase.length)\n : raw;\n const path = normalizePathForRoute(stripped || '/');\n const query = parseQuery(url.search);\n const fragment = url.hash && url.hash.length ? url.hash.slice(1) : '';\n return { path, query, fragment };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n fragment: (initial as { fragment?: string }).fragment,\n });\n\n update = async (replace = false) => {\n const loc = getLocation();\n await navigate(loc.path, replace);\n };\n\n window.addEventListener('popstate', () => update(true));\n\n push = (path: string) => navigate(path, false);\n replaceFn = (path: string) => navigate(path, true);\n back = () => window.history.back();\n } else {\n // SSR mode\n getLocation = () => {\n const url = new URL(initialUrl || '/', 'http://localhost');\n const raw = url.pathname;\n const stripped = raw.startsWith(canonicalBase)\n ? raw.slice(canonicalBase.length)\n : raw;\n const path = normalizePathForRoute(stripped || '/');\n const query = parseQuery(url.search);\n const fragment = url.hash && url.hash.length ? url.hash.slice(1) : '';\n return { path, query, fragment };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n fragment: (initial as { fragment?: string }).fragment,\n });\n\n update = async () => {\n const loc = getLocation();\n await navigateSSR(loc.path);\n };\n\n // SSR navigation contract:\n // - `push` / `replace` call into `navigateSSR` and return a Promise.\n // - On the server we intentionally surface navigation failures so\n // server-side logic (or tests) can react: missing routes or thrown\n // errors from `beforeEnter`/`onEnter` will cause the Promise to\n // reject. This lets the server render 404s or abort builds.\n // - For valid routes the server-side navigation resolves and updates\n // the internal store state so rendered output matches the target\n // path. The `back()` operation is client-only and is a synchronous\n // no-op in SSR mode.\n const navigateSSR = async (path: string) => {\n try {\n const hashIndex = path.indexOf('#');\n const fragment = hashIndex >= 0 ? path.slice(hashIndex + 1) : '';\n const rawPath = hashIndex >= 0 ? path.slice(0, hashIndex) : path;\n // Parse query on SSR navigation as well so server-side logic and\n // tests can observe query params.\n const qIndex = rawPath.indexOf('?');\n const pathBeforeQuery =\n qIndex >= 0 ? rawPath.slice(0, qIndex) : rawPath;\n const query = qIndex >= 0 ? parseQuery(rawPath.slice(qIndex)) : {};\n const stripped = pathBeforeQuery.startsWith(canonicalBase)\n ? pathBeforeQuery.slice(canonicalBase.length)\n : pathBeforeQuery;\n const normalized = normalizePathForRoute(stripped || '/');\n const loc = {\n path: normalized,\n query,\n fragment,\n };\n const match = matchRoute(routes, loc.path);\n // In SSR mode we intentionally surface navigation errors (missing\n // route) to the caller so server-side logic may handle them. If no\n // route matches, throw and let the caller observe the rejection.\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n fragment: (loc as { fragment?: string }).fragment,\n };\n\n // beforeEnter guard\n const matched = findMatchedRoute(routes, to.path);\n if (matched?.beforeEnter) {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n // onEnter guard\n if (matched?.onEnter) {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n store.setState(to);\n\n // afterEnter hook\n if (matched?.afterEnter) {\n matched.afterEnter(to, from);\n }\n } catch (err) {\n // Surface SSR navigation errors so callers (and tests) can observe\n // failures during server-side resolution.\n devError('SSR navigation error:', err);\n throw err;\n }\n };\n\n push = async (path: string) => navigateSSR(path);\n replaceFn = async (path: string) => navigateSSR(path);\n back = () => {};\n }\n\n return {\n store,\n push,\n replace: replaceFn,\n back,\n subscribe: store.subscribe,\n matchRoute: (path: string) => matchRoute(routes, path),\n getCurrent: (): RouteState => store.getState(),\n resolveRouteComponent,\n base: canonicalBase,\n // Public API: allow components or tests to explicitly request scrolling to\n // a fragment when they know their DOM is ready. Returns true if scrolled.\n scrollToFragment: (frag?: string) => {\n const id = frag || (store.getState() as RouteState).fragment;\n if (!id) return Promise.resolve(false);\n if (typeof window === 'undefined' || typeof document === 'undefined')\n return Promise.resolve(false);\n return startScrollForNavigation(\n String(id),\n _scrollConfig.offset,\n _scrollConfig.timeoutMs,\n );\n },\n };\n}\n\n/**\n * Explicit Router instance type exported for clearer typing across the\n * codebase and tests.\n */\nexport interface Router {\n store: Store<RouteState>;\n push: (path: string) => Promise<void>;\n replace: (path: string) => Promise<void>;\n back: () => void;\n subscribe: Store<RouteState>['subscribe'];\n matchRoute: (path: string) => {\n route: Route | null;\n params: Record<string, string>;\n };\n getCurrent: () => RouteState;\n resolveRouteComponent: typeof resolveRouteComponent;\n base: string;\n scrollToFragment: (frag?: string) => Promise<boolean>;\n}\n\n// SSR/static site support: match route for a given path\nexport function matchRouteSSR(routes: Route[], path: string) {\n return matchRoute(routes, path);\n}\n\n// Module-level reference to the latest initialized router. Tests and\n// components may rely on re-initializing the router during their setup,\n// so exposing this lets components pick up the most recent instance.\nlet activeRouter: ReturnType<typeof useRouter> | null = null;\n\n/**\n * Singleton router instance for global access.\n *\n * Define here to prevent circular dependency\n * issue with component.\n */\n\nexport function initRouter(config: RouterConfig) {\n const router = useRouter(config);\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n activeRouter = router;\n\n component('router-view', async () => {\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current route so the component re-renders when router updates\n if (!r) return html`<div>Router not initialized.</div>`;\n\n const current = ref(r.getCurrent());\n\n // We'll capture the unsubscribe function when the component connects\n // and register a disconnect cleanup during render-time (useOnDisconnected\n // must be called during the component render/execution).\n let unsubRouterView: (() => void) | undefined;\n\n useOnConnected(() => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterView = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-view subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-view subscribe failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterView === 'function') {\n try {\n unsubRouterView();\n } catch (e) {\n devWarn('router-view unsubscribe failed', e);\n }\n }\n });\n\n const match = r.matchRoute(current.value.path);\n if (!match || !match.route) return html`<div>Not found</div>`;\n\n // Resolve the component (supports cached async loaders)\n try {\n const compRaw = await r.resolveRouteComponent(match.route);\n const comp = compRaw as\n | string\n | HTMLElement\n | ((...args: unknown[]) => unknown)\n | undefined;\n // String tag (custom element) -> render as VNode\n if (typeof comp === 'string') {\n return { tag: comp, props: {}, children: [] };\n }\n\n // Function component (sync or async) -> call and return its VNode(s)\n if (typeof comp === 'function') {\n const out = comp();\n const resolved = out instanceof Promise ? out : Promise.resolve(out);\n return resolved.then((resolvedComp) => {\n if (typeof resolvedComp === 'string')\n return { tag: resolvedComp, props: {}, children: [] };\n return resolvedComp;\n });\n }\n\n return html`<div>Invalid route component</div>`;\n } catch {\n return html`<div>Invalid route component</div>`;\n }\n });\n\n component('router-link', () => {\n // Declare props via useProps so observedAttributes are correct\n const props = useProps<Partial<RouterLinkProps>>({\n to: '',\n tag: 'a',\n replace: false,\n exact: false,\n activeClass: 'active',\n exactActiveClass: 'exact-active',\n ariaCurrentValue: 'page',\n disabled: false,\n external: false,\n // allow host `class` and `style` attributes to be read via useProps\n class: '',\n style: '',\n });\n\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current state so link updates when route changes\n const current = ref(r.getCurrent());\n // Capture unsubscribe for link subscriptions and register disconnect\n // cleanup during render time.\n let unsubRouterLink: (() => void) | undefined;\n\n // Keep a minimal internal host-scoped style for element display.\n // Host `style` will be applied to the inner anchor/button element.\n useStyle(() => `a,button{display:inline-block;}`);\n\n // We capture host attributes at connection time and migrate them to\n // internal refs so we can remove them from the host. This prevents\n // global/author CSS targeting the host from styling the host element\n // itself while still allowing authors to use `class`/`style` on the\n // router-link to style the inner anchor/button.\n const hostClassRef = ref((props.class as string) || '');\n const hostStyleRef = ref((props.style as string) || '');\n\n useOnConnected((ctx?: unknown) => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterLink = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-link subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-link subscribe failed', e);\n }\n\n // Migrate host `class`/`style` into internal refs and remove them\n // from the host so only the inner element is styled.\n try {\n const host = (ctx as { _host?: HTMLElement } | undefined)?._host;\n if (host instanceof HTMLElement) {\n const hc = host.getAttribute('class');\n const hs = host.getAttribute('style');\n if (hc) hostClassRef.value = hc;\n if (hs) hostStyleRef.value = hs;\n // Remove attributes from host to avoid styling the host\n if (hc !== null) host.removeAttribute('class');\n if (hs !== null) host.removeAttribute('style');\n }\n } catch (e) {\n devWarn('router-link host migration failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterLink === 'function') {\n try {\n unsubRouterLink();\n } catch (e) {\n devWarn('router-link unsubscribe failed', e);\n }\n }\n });\n\n const isExactActive = computed(() => {\n const runtimeBase = r?.base ?? '';\n const targetRaw = (props.to as string) || '';\n // If the target is an absolute or protocol-relative URL, it's external\n // and should not be considered active.\n if (\n /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(targetRaw) ||\n targetRaw.startsWith('//')\n )\n return false;\n // strip fragment and query from target when comparing. Default to '/'\n const targetPathOnly = (targetRaw.split('#')[0] || '/').split('?')[0];\n try {\n // Remove runtime base if present on the provided target so comparisons\n // are made against the router-internal path format (paths stored\n // without base).\n let tgtCandidate = targetPathOnly;\n if (runtimeBase && tgtCandidate.startsWith(runtimeBase)) {\n tgtCandidate = tgtCandidate.slice(runtimeBase.length) || '/';\n }\n const cur = normalizePathForRoute(current.value.path);\n const tgt = normalizePathForRoute(tgtCandidate);\n return cur === tgt;\n } catch {\n return current.value.path === targetPathOnly;\n }\n });\n\n const isActive = computed(() => {\n const runtimeBase = r?.base ?? '';\n const targetRaw = (props.to as string) || '';\n // External targets are never \"active\" in the SPA sense\n if (\n /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(targetRaw) ||\n targetRaw.startsWith('//')\n )\n return false;\n // strip fragment and query from target when comparing\n const targetPathOnly = (targetRaw.split('#')[0] || '/').split('?')[0];\n if (props.exact) return isExactActive.value;\n try {\n // Normalize and strip base from target to compare against\n let tgtCandidate = targetPathOnly;\n if (runtimeBase && tgtCandidate.startsWith(runtimeBase)) {\n tgtCandidate = tgtCandidate.slice(runtimeBase.length) || '/';\n }\n const cur = normalizePathForRoute(current.value.path);\n const tgt = normalizePathForRoute(tgtCandidate);\n // Special-case the root target: '/' should only be active when\n // the current path is exactly '/'. Without this, '/' matches all\n // routes (every path starts with '/').\n if (tgt === '/') return cur === '/';\n // Consider active when current is the target or a child of the target\n if (cur === tgt) return true;\n // Ensure we match whole path segment (avoid '/guide-api' matching '/guide')\n return cur.startsWith(tgt.endsWith('/') ? tgt : tgt + '/');\n } catch {\n return (\n current.value &&\n typeof current.value.path === 'string' &&\n current.value.path.startsWith(targetPathOnly)\n );\n }\n });\n\n // Compute a normalized href for the inner anchor so middle-click / open-in-new-tab\n // uses a canonical absolute path (includes base and fragment). We keep using\n // props.to for router navigation so current behavior (literal `to`) remains.\n const hrefTarget = computed(() => {\n const raw = String(props.to || '');\n // Block obviously dangerous javascript: URIs from becoming clickable\n // hrefs. See isDangerousScheme for rationale.\n if (isDangerousScheme(raw)) return null;\n\n // Preserve absolute URLs with a scheme (http:, mailto:, data:, etc.)\n // and protocol-relative URLs that begin with `//`.\n if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(raw) || raw.startsWith('//'))\n return raw;\n\n // Split fragment and query explicitly so both are preserved.\n const [pathWithQuery, frag] = raw.split('#');\n const [pathOnly, query] = (pathWithQuery || '').split('?');\n\n // Read base dynamically from the current router instance so repeated\n // calls to initRouter (tests) do not leave a stale captured value.\n const runtimeBase = r?.base ?? '';\n // If the provided path already contains the runtime base, strip it to\n // avoid duplicating e.g. '/app/app/about'. Keep a fallback of '/'.\n let candidate = pathOnly || '/';\n if (runtimeBase && candidate.startsWith(runtimeBase)) {\n candidate = candidate.slice(runtimeBase.length) || '/';\n }\n const norm = normalizePathForRoute(candidate || '/');\n return (\n runtimeBase +\n norm +\n (query ? '?' + query : '') +\n (frag ? '#' + frag : '')\n );\n });\n\n // Build user classes reactively from the host `class` attribute prop.\n // We intentionally apply classes to the inner element so the consumer\n // can style the link via `class=\"...\"`.\n const userClasses = computed(() => {\n const rawHost =\n (hostClassRef && hostClassRef.value) || (props.class as string) || '';\n const list = rawHost.split(/\\s+/).filter(Boolean);\n const map: Record<string, boolean> = {};\n for (const c of list) map[c] = true;\n return map;\n });\n\n const classObject = computed(() => ({\n ...userClasses.value,\n [(props.activeClass as string) || 'active']: isActive.value,\n [(props.exactActiveClass as string) || 'exact-active']:\n isExactActive.value,\n }));\n\n // Compute a final class string (template accepts object or string; we\n // convert to string to safely include host classes and conditionals).\n const classString = computed(() =>\n Object.keys(classObject.value)\n .filter((k) => classObject.value[k])\n .join(' '),\n );\n\n const tagName = computed(() => (props.tag as string) || 'a');\n const isButton = computed(() => tagName.value === 'button');\n // Instead of pre-building attribute fragments as strings (which can\n // accidentally inject invalid attribute names into the template and\n // cause DOMExceptions), compute simple booleans/values and apply\n // attributes explicitly in the template below.\n // Return null when not exact so the attribute is omitted from the DOM\n const ariaCurrentValue = computed<null | string>(() =>\n isExactActive.value ? (props.ariaCurrentValue as string) : null,\n );\n const isDisabled = computed(() => !!props.disabled);\n // External should only apply to anchor tags (links). Make the check explicit.\n // Detect absolute/protocol-relative URLs as external even if the prop\n // wasn't explicitly set by the caller. Only apply to anchor tags.\n const isExternal = computed(() => {\n const toStr = String(props.to || '');\n const looksAbsolute =\n /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(toStr) || toStr.startsWith('//');\n return (looksAbsolute || !!props.external) && tagName.value === 'a';\n });\n\n // Inline style from host `style` attribute.\n const inlineStyle = computed(\n () =>\n (hostStyleRef && hostStyleRef.value) || (props.style as string) || '',\n );\n\n const navigate = (e: MouseEvent) => {\n // Respect pre-handled events, non-left clicks, and modifier keys so\n // default browser behaviors (open-in-new-tab, context menu) work.\n if (\n e.defaultPrevented ||\n e.button !== 0 ||\n e.metaKey ||\n e.altKey ||\n e.ctrlKey ||\n e.shiftKey\n )\n return;\n\n if (isDisabled.value) {\n // Prevent navigation and let assistive tech see disabled state\n e.preventDefault();\n return;\n }\n\n // Block dangerous javascript: URIs explicitly to avoid accidental XSS\n const _targetRaw = String(props.to || '');\n if (isDangerousScheme(_targetRaw)) {\n try {\n e.preventDefault();\n } catch {\n /* swallow */\n }\n devWarn('Blocked unsafe javascript: URI in router-link.to');\n return;\n }\n\n // If this is an external anchor, allow default browser behavior\n if (isExternal.value) return;\n\n e.preventDefault();\n if (props.replace) {\n r.replace(props.to as string);\n } else {\n r.push(props.to as string);\n }\n };\n\n return html`\n ${match()\n .when(\n isButton.value,\n html`\n <button\n part=\"button\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n disabled=\"${isDisabled.value ? '' : null}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n @click=\"${navigate}\"\n >\n <slot></slot>\n </button>\n `,\n )\n .otherwise(html`\n <a\n part=\"link\"\n href=\"${isDisabled.value ? null : hrefTarget.value}\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n target=\"${isExternal.value ? '_blank' : null}\"\n rel=\"${isExternal.value ? 'noopener noreferrer' : null}\"\n @click=\"${navigate}\"\n ><slot></slot\n ></a>\n `)\n .done()}\n `;\n });\n\n return router;\n}\n"],"names":["parseQuery","search","serializeQuery","q","isDangerousScheme","s","compileCache","escapeSeg","seg","normalizePathForRoute","p","out","compileRoute","route","raw","routePath","segments","paramNames","regexParts","i","devWarn","name","paramMatch","isSplat","pattern","prefix","e","matchRoute","routes","path","incoming","compiled","regex","m","params","safeDecode","v","findMatchedRoute","r","componentCache","resolveRouteComponent","mod","useRouter","config","base","initialUrl","scrollToFragment","canonicalBase","nb","_scrollConfig","getLocation","initial","store","update","push","replaceFn","back","runBeforeEnter","to","from","matched","result","navigate","err","devError","runOnEnter","runAfterEnter","_navToken","_activeObserver","_activeTimeout","_activeResolve","doScrollToElement","id","offset","el","rect","top","clearActiveScrollAttempt","startScrollForNavigation","timeoutMs","myToken","resolve","finish","did","container","obs","n","poll","replace","hashIndex","fragment","rawPath","qIndex","pathBeforeQuery","query","stripped","loc","match","qstr","href","frag","url","createStore","navigateSSR","matchRouteSSR","activeRouter","initRouter","router","component","html","current","ref","unsubRouterView","useOnConnected","useOnDisconnected","comp","resolvedComp","props","useProps","unsubRouterLink","useStyle","hostClassRef","hostStyleRef","ctx","host","hc","hs","isExactActive","computed","runtimeBase","targetRaw","targetPathOnly","tgtCandidate","cur","tgt","isActive","hrefTarget","pathWithQuery","pathOnly","candidate","norm","userClasses","list","map","c","classObject","classString","k","tagName","isButton","ariaCurrentValue","isDisabled","isExternal","toStr","inlineStyle","_targetRaw"],"mappings":"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"}
1
+ {"version":3,"file":"custom-elements-runtime.router.es.js","sources":["../src/lib/router.ts"],"sourcesContent":["import { html } from './runtime/template-compiler';\nimport { component } from './runtime/component';\nimport {\n useProps,\n useOnConnected,\n useOnDisconnected,\n useStyle,\n} from './runtime/hooks';\nimport { ref, computed } from './runtime/reactive';\nimport { flushDOMUpdates } from './runtime/scheduler';\nimport { createStore, type Store } from './store';\nimport { devError, devWarn } from './runtime/logger';\nimport { match } from './directives';\n\n/**\n * Represents a component that can be rendered by the router.\n * Can be either a class constructor or a function component.\n */\nexport type RouteComponent =\n | { new (...args: unknown[]): unknown } // class components\n | ((...args: unknown[]) => unknown); // functional components\n\n/**\n * Represents the current state of the router.\n */\nexport interface RouteState {\n /** The current path without base, query, or fragment */\n path: string;\n /** Route parameters extracted from dynamic path segments */\n params: Record<string, string>;\n /** Query parameters from the URL search string */\n query: Record<string, string>;\n /** Optional fragment (hash) portion of the URL, without the leading '#' */\n fragment?: string;\n}\n\n/**\n * Result type for route guards.\n * - `true`: Allow navigation\n * - `false`: Block navigation\n * - `string`: Redirect to the specified path\n */\nexport type GuardResult = boolean | string | Promise<boolean | string>;\n\n/**\n * Defines a route in the router configuration.\n */\nexport interface Route {\n /** The path pattern for this route (e.g., '/users/:id') */\n path: string;\n\n /** Statically available component (already imported) */\n component?: string | (() => unknown);\n\n /** Lazy loader that resolves to something renderable */\n load?: () => Promise<{\n default: string | HTMLElement | ((...args: unknown[]) => unknown);\n }>;\n\n /** Guard that runs before matching — return false to cancel, or a string to redirect */\n beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /** Guard that runs right before navigation commits — can cancel or redirect */\n onEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /** Hook that runs after navigation completes — cannot cancel */\n afterEnter?: (to: RouteState, from: RouteState) => void;\n}\n\n/**\n * Props interface for the router-link component.\n */\nexport interface RouterLinkProps {\n /** Target path or URL to navigate to */\n to: string;\n /** HTML tag to render ('a' or 'button') */\n tag: string;\n /** Whether to use replace instead of push navigation */\n replace: boolean;\n /** Whether to use exact matching for active state */\n exact: boolean;\n /** CSS class applied when link is active */\n activeClass: string;\n /** CSS class applied when link is exactly active */\n exactActiveClass: string;\n /** Value for aria-current attribute when exactly active */\n ariaCurrentValue: string;\n /** Whether the link is disabled */\n disabled: boolean;\n /** Whether this is an external link */\n external: boolean;\n /** Additional CSS classes */\n class?: string;\n /** Additional inline styles */\n style?: string;\n}\n\nexport interface RouterLinkComputed {\n current: RouteState;\n isExactActive: boolean;\n isActive: boolean;\n className: string;\n ariaCurrent: string;\n isButton: boolean;\n disabledAttr: string;\n externalAttr: string;\n}\n\n/**\n * Configuration object for initializing the router.\n */\nexport interface RouterConfig {\n /** Array of route definitions */\n routes: Route[];\n /** Base path for all routes */\n base?: string;\n /** Initial URL for SSR mode */\n initialUrl?: string;\n /** Configure fragment (hash) scrolling behavior */\n scrollToFragment?:\n | boolean\n | {\n /** Whether fragment scrolling is enabled */\n enabled?: boolean;\n /** Offset in pixels to account for fixed headers */\n offset?: number;\n /** Timeout in ms to wait for element to appear */\n timeoutMs?: number;\n };\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst DEFAULT_SCROLL_CONFIG = {\n enabled: true,\n offset: 0,\n timeoutMs: 2000,\n} as const;\n\n// ============================================================================\n// UTILITY FUNCTIONS\n// ============================================================================\n\n/**\n * Parse URL search string into query parameters object.\n * @param search - The search string (with or without leading '?')\n * @returns Object with query parameter key-value pairs\n */\nexport const parseQuery = (search: string): Record<string, string> => {\n if (!search) return {};\n if (typeof URLSearchParams === 'undefined') return {};\n return Object.fromEntries(new URLSearchParams(search));\n};\n\n/**\n * Serialize query parameters object into URL search string.\n * @param q - Query parameters object\n * @returns Search string with leading '?' or empty string\n */\nexport const serializeQuery = (q: Record<string, string> | undefined) => {\n if (!q || Object.keys(q).length === 0) return '';\n try {\n return '?' + new URLSearchParams(q as Record<string, string>).toString();\n } catch {\n return '';\n }\n};\n\n/**\n * Detect dangerous javascript: URIs to prevent XSS attacks.\n * @param s - URL string to check\n * @returns True if the URL uses a dangerous scheme\n */\nconst isDangerousScheme = (s: string): boolean => {\n if (!s) return false;\n return /^\\s*javascript\\s*:/i.test(s);\n};\n\n/**\n * Check if a URL is absolute (has protocol or is protocol-relative).\n * @param url - URL string to check\n * @returns True if the URL is absolute\n */\nconst isAbsoluteUrl = (url: string): boolean => {\n return /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(url) || url.startsWith('//');\n};\n\n/**\n * Safely decode a URI component, returning original value on error.\n * @param value - String to decode\n * @returns Decoded string or original value if decoding fails\n */\nconst safeDecode = (value: string): string => {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\n/**\n * Canonicalize base path for consistent handling.\n * @param base - Base path string\n * @returns Canonicalized base path (empty string for root)\n */\nconst canonicalizeBase = (base: string): string => {\n if (!base) return '';\n const normalized = normalizePathForRoute(base);\n return normalized === '/' ? '' : normalized;\n};\n\n// Cache compiled route regexes to avoid rebuilding on every navigation.\ntype CompiledRoute =\n | { regex: RegExp; paramNames: string[] }\n | { invalid: true };\nconst compileCache: WeakMap<Route, CompiledRoute> = new WeakMap();\n\nfunction escapeSeg(seg: string) {\n return seg.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Normalize a path for consistent route matching.\n * Ensures leading slash, removes trailing slash, and collapses duplicate slashes.\n * @param p - Path string to normalize\n * @returns Normalized path string\n */\nexport function normalizePathForRoute(p: string): string {\n if (!p) return '/';\n // Collapse duplicate slashes, ensure leading slash, remove trailing slash\n let out = p.replace(/\\/+/g, '/');\n if (!out.startsWith('/')) out = '/' + out;\n if (out.length > 1 && out.endsWith('/')) out = out.slice(0, -1);\n return out;\n}\n\nfunction compileRoute(route: Route): CompiledRoute {\n const raw = route.path || '/';\n const routePath = normalizePathForRoute(raw);\n\n const segments =\n routePath === '/' ? [] : routePath.split('/').filter(Boolean);\n\n const paramNames: string[] = [];\n const regexParts: string[] = [];\n\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n\n // Anonymous wildcard\n if (seg === '*') {\n // splat must be terminal\n if (i !== segments.length - 1) {\n devWarn(\n `Route '${route.path}' contains a '*' splat in a non-terminal position; splats must be the last segment. This route will be ignored.`,\n );\n return { invalid: true };\n }\n const name = `splat${paramNames.length}`;\n paramNames.push(name);\n // mark splat token; pattern will be built specially so the\n // preceding slash can be optional (allow empty splat)\n regexParts.push('__SPLAT__');\n continue;\n }\n\n const paramMatch = seg.match(/^:([A-Za-z0-9_-]+)(\\*)?$/);\n if (paramMatch) {\n const name = paramMatch[1];\n const isSplat = !!paramMatch[2];\n // If splat, ensure terminal\n if (isSplat && i !== segments.length - 1) {\n devWarn(\n `Route '${route.path}' contains a splat param ':${name}*' in a non-terminal position; splats must be the last segment. This route will be ignored.`,\n );\n return { invalid: true };\n }\n paramNames.push(name);\n regexParts.push(isSplat ? '__SPLAT__' : '([^/]+)');\n continue;\n }\n\n // Static\n regexParts.push(escapeSeg(seg));\n }\n\n let pattern: string;\n if (regexParts.length === 0) {\n pattern = '^/$';\n } else {\n const last = regexParts[regexParts.length - 1];\n if (last === '__SPLAT__') {\n const prefix = regexParts.slice(0, -1).join('/');\n if (!prefix) {\n // route is like '/:rest*' or '/*' -> allow '/' or '/x' etc.\n pattern = '^(?:/(.*))?(?:/)?$';\n } else {\n pattern = `^/${prefix}(?:/(.*))?(?:/)?$`;\n }\n } else {\n pattern = `^/${regexParts.join('/')}(?:/)?$`;\n }\n }\n try {\n const regex = new RegExp(pattern);\n return { regex, paramNames };\n } catch (e) {\n devWarn(`Failed to compile route regex for '${route.path}': ${String(e)}`);\n return { invalid: true };\n }\n}\n\nexport const matchRoute = (\n routes: Route[],\n path: string,\n): { route: Route | null; params: Record<string, string> } => {\n const incoming = normalizePathForRoute(path);\n\n for (const route of routes) {\n let compiled = compileCache.get(route);\n if (!compiled) {\n compiled = compileRoute(route);\n compileCache.set(route, compiled);\n }\n\n if ((compiled as { invalid?: true }).invalid) continue;\n\n const { regex, paramNames } = compiled as {\n regex: RegExp;\n paramNames: string[];\n };\n const m = regex.exec(incoming);\n if (m) {\n const params: Record<string, string> = {};\n\n for (let i = 0; i < paramNames.length; i++) {\n const rawValue = m[i + 1] || '';\n params[paramNames[i]] = rawValue ? safeDecode(rawValue) : '';\n }\n\n return { route, params };\n }\n }\n\n return { route: null, params: {} };\n};\n\n/**\n * Find the first route that matches the given path.\n * Consolidates repeated inline checks like `routes.find(r => matchRoute([r], path).route !== null)`\n */\nfunction findMatchedRoute(routes: Route[], path: string): Route | null {\n for (const r of routes) {\n if (matchRoute([r], path).route !== null) return r;\n }\n return null;\n}\n\n// Async component loader cache with size limit to prevent memory leaks\nconst MAX_COMPONENT_CACHE_SIZE = 50;\nlet componentCache: Record<\n string,\n {\n component: string | HTMLElement | ((...args: unknown[]) => unknown);\n lastAccessed: number;\n }\n> = {};\n\n// Separate cache for loading promises to prevent race conditions\nlet loadingCache: Record<\n string,\n Promise<string | HTMLElement | ((...args: unknown[]) => unknown)>\n> = {};\n\n/**\n * Clear component cache to prevent memory leaks\n */\nfunction clearComponentCache(): void {\n componentCache = {};\n loadingCache = {};\n}\n\n/**\n * Evict least recently used components when cache exceeds size limit\n */\nfunction evictLRUComponents(): void {\n const entries = Object.entries(componentCache);\n if (entries.length <= MAX_COMPONENT_CACHE_SIZE) return;\n\n // Sort by lastAccessed (oldest first) and remove oldest entries\n const sortedEntries = entries.sort(\n ([, a], [, b]) => a.lastAccessed - b.lastAccessed,\n );\n const toRemove = sortedEntries.slice(\n 0,\n entries.length - MAX_COMPONENT_CACHE_SIZE,\n );\n\n for (const [path] of toRemove) {\n delete componentCache[path];\n }\n}\n\n/**\n * Loads a route's component, supporting both static and async.\n * @param route Route object\n * @returns Promise resolving to the component\n */\nexport async function resolveRouteComponent(\n route: Route,\n): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)> {\n if (route.component) return route.component;\n if (route.load) {\n const cached = componentCache[route.path];\n if (cached) {\n // Update last accessed time for LRU tracking\n cached.lastAccessed = Date.now();\n return cached.component;\n }\n\n // Check if already loading to prevent race conditions\n if (loadingCache[route.path] !== undefined) {\n return loadingCache[route.path];\n }\n\n // In SSR context, we need to handle components synchronously when possible\n const isSSR = typeof window === 'undefined';\n\n try {\n // Create loading promise\n const loadPromise = route\n .load()\n .then((mod) => {\n // Evict old components if cache is full\n evictLRUComponents();\n\n const component = mod.default;\n componentCache[route.path] = {\n component,\n lastAccessed: Date.now(),\n };\n\n // Remove from loading cache\n delete loadingCache[route.path];\n\n return component;\n })\n .catch((err) => {\n // Remove from loading cache on error\n delete loadingCache[route.path];\n const errorMsg = err instanceof Error ? err.message : String(err);\n if (isSSR) {\n // In SSR, surface errors more prominently\n devError(\n `SSR component load failed for route: ${route.path}. ${errorMsg}`,\n );\n }\n throw new Error(\n `Failed to load component for route: ${route.path}. ${errorMsg}`,\n );\n });\n\n // Store loading promise to prevent concurrent loads\n loadingCache[route.path] = loadPromise;\n\n return await loadPromise;\n } catch (err) {\n // More descriptive error with original error details\n const errorMsg = err instanceof Error ? err.message : String(err);\n throw new Error(\n `Failed to load component for route: ${route.path}. ${errorMsg}`,\n );\n }\n }\n throw new Error(`No component or loader defined for route: ${route.path}`);\n}\n\nexport function useRouter(config: RouterConfig) {\n const { routes, base = '', initialUrl, scrollToFragment = true } = config;\n\n // Canonicalize base so callers and internal logic have a single\n // representation. Normalized base will be '' for root or '/x' (no\n // trailing slash). This prevents accidental double-prefixing like\n // '/app/app/about' and makes startsWith checks reliable.\n const canonicalBase = canonicalizeBase(base);\n\n // Normalize scroll configuration\n const _scrollConfig =\n typeof scrollToFragment === 'boolean'\n ? { ...DEFAULT_SCROLL_CONFIG, enabled: scrollToFragment }\n : { ...DEFAULT_SCROLL_CONFIG, ...scrollToFragment };\n\n // getLocation/initial include an optional `fragment` field in practice.\n let getLocation: () => {\n path: string;\n query: Record<string, string>;\n fragment?: string;\n };\n let initial: {\n path: string;\n query: Record<string, string>;\n fragment?: string;\n };\n let store: Store<RouteState>;\n let update: (replace?: boolean) => Promise<void>;\n let push: (path: string) => Promise<void>;\n let replaceFn: (path: string) => Promise<void>;\n let back: () => void;\n\n // Track redirects to prevent infinite loops\n const redirectTracker = new Set<string>();\n const MAX_REDIRECT_DEPTH = 10;\n let redirectDepth = 0;\n\n // Run matching route guards/hooks\n const runBeforeEnter = async (\n to: RouteState,\n from: RouteState,\n ): Promise<boolean | string> => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.beforeEnter) return true;\n try {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Check for redirect loops\n const redirectKey = `${to.path}->${result}`;\n if (\n redirectTracker.has(redirectKey) ||\n redirectDepth >= MAX_REDIRECT_DEPTH\n ) {\n devError(`Redirect loop detected: ${redirectKey}`);\n return false;\n }\n return result; // Return redirect path instead of navigating immediately\n }\n return result !== false;\n } catch (err) {\n devError('beforeEnter error', err);\n // Reset store to previous state on guard error to maintain consistency\n try {\n store.setState(from);\n } catch {\n /* swallow setState errors */\n }\n // Always let guard errors bubble up for proper error handling\n throw err;\n }\n };\n\n const runOnEnter = async (\n to: RouteState,\n from: RouteState,\n ): Promise<boolean | string> => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.onEnter) return true;\n try {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n // Check for redirect loops\n const redirectKey = `${to.path}->${result}`;\n if (\n redirectTracker.has(redirectKey) ||\n redirectDepth >= MAX_REDIRECT_DEPTH\n ) {\n devError(`Redirect loop detected: ${redirectKey}`);\n return false;\n }\n return result; // Return redirect path instead of navigating immediately\n }\n return result !== false;\n } catch (err) {\n devError('onEnter error', err);\n // Reset store to previous state on guard error to maintain consistency\n try {\n store.setState(from);\n } catch {\n /* swallow setState errors */\n }\n // Always let guard errors bubble up for proper error handling\n throw err;\n }\n };\n\n const runAfterEnter = (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.afterEnter) return;\n try {\n matched.afterEnter(to, from);\n } catch (err) {\n devError('afterEnter error', err);\n }\n };\n\n // Cache for route matching to avoid repeated expensive operations\n const matchCache = new Map<\n string,\n { route: Route | null; params: Record<string, string> }\n >();\n const MATCH_CACHE_SIZE = 100;\n\n const cachedMatchRoute = (path: string) => {\n if (matchCache.has(path)) {\n return matchCache.get(path)!;\n }\n\n const result = matchRoute(routes, path);\n\n // Implement proper LRU by clearing oldest entries when cache is full\n if (matchCache.size >= MATCH_CACHE_SIZE) {\n // Remove oldest 25% of entries to avoid frequent cleanup\n const entriesToRemove = Math.floor(MATCH_CACHE_SIZE * 0.25);\n const keys = Array.from(matchCache.keys());\n for (let i = 0; i < entriesToRemove && i < keys.length; i++) {\n matchCache.delete(keys[i]);\n }\n }\n\n matchCache.set(path, result);\n return result;\n };\n\n // Scroll management with per-promise tracking\n const cleanupScrollState = () => {\n // No global cleanup needed - each promise manages its own lifecycle\n };\n\n async function doScrollToElement(id: string, offset = 0): Promise<boolean> {\n try {\n const element = document.getElementById(id);\n if (!element) {\n return false;\n }\n\n if (offset > 0) {\n try {\n const rect = element.getBoundingClientRect();\n const top = Math.max(0, window.scrollY + rect.top - offset);\n if (typeof window.scrollTo === 'function') {\n window.scrollTo({ top, behavior: 'auto' });\n }\n } catch {\n try {\n element.scrollIntoView();\n } catch {\n return false;\n }\n }\n } else {\n if (typeof element.scrollIntoView === 'function') {\n try {\n element.scrollIntoView({\n behavior: 'auto',\n block: 'start',\n inline: 'nearest',\n });\n } catch {\n try {\n element.scrollIntoView();\n } catch {\n return false;\n }\n }\n }\n }\n return true;\n } catch {\n return false;\n }\n }\n\n // Scroll with per-promise lifecycle management and retry for missing elements\n function startScrollForNavigation(\n id: string,\n offset: number = 0,\n timeoutMs: number = 2000,\n ): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n let resolved = false;\n let timeoutId: number | null = null;\n const startTime = Date.now();\n\n const safeResolve = (value: boolean) => {\n if (resolved) return;\n resolved = true;\n if (timeoutId) clearTimeout(timeoutId);\n resolve(value);\n };\n\n const attemptScroll = async () => {\n if (resolved) return;\n\n try {\n // Try immediate scroll first\n if (await doScrollToElement(id, offset)) {\n return safeResolve(true);\n }\n\n // For missing elements, continue retrying until timeout\n const retryScroll = async () => {\n if (resolved) return;\n\n const elapsed = Date.now() - startTime;\n if (elapsed >= timeoutMs) {\n return safeResolve(false);\n }\n\n try {\n if (await doScrollToElement(id, offset)) {\n return safeResolve(true);\n }\n\n // Try again after a short delay\n requestAnimationFrame(retryScroll);\n } catch (error) {\n devWarn('Scroll retry attempt failed:', error);\n // Continue retrying even if one attempt fails\n requestAnimationFrame(retryScroll);\n }\n };\n\n // Start retry loop after initial attempt\n requestAnimationFrame(retryScroll);\n } catch (error) {\n devWarn('Initial scroll attempt failed:', error);\n safeResolve(false);\n }\n };\n\n // Set timeout as final safety net\n timeoutId = setTimeout(() => {\n safeResolve(false);\n }, timeoutMs);\n\n // Start the attempt immediately with error handling\n attemptScroll().catch((error) => {\n devWarn('Scroll attempt failed:', error);\n safeResolve(false);\n });\n });\n }\n\n // Navigation lock to prevent concurrent navigation race conditions\n let isNavigating = false;\n\n const navigate = async (path: string, replace = false): Promise<void> => {\n // Prevent concurrent navigation\n if (isNavigating) {\n devWarn(`Navigation to ${path} blocked - navigation already in progress`);\n return;\n }\n\n isNavigating = true;\n redirectDepth = 0;\n redirectTracker.clear();\n\n try {\n await performNavigation(path, replace);\n } finally {\n isNavigating = false;\n redirectDepth = 0;\n redirectTracker.clear();\n }\n };\n\n // Extract path parsing logic for reuse in SSR\n const parseNavigationPath = (path: string) => {\n const hashIndex = path.indexOf('#');\n const fragment = hashIndex >= 0 ? path.slice(hashIndex + 1) : '';\n const rawPath = hashIndex >= 0 ? path.slice(0, hashIndex) : path;\n const qIndex = rawPath.indexOf('?');\n const pathBeforeQuery = qIndex >= 0 ? rawPath.slice(0, qIndex) : rawPath;\n const query = qIndex >= 0 ? parseQuery(rawPath.slice(qIndex)) : {};\n const stripped = pathBeforeQuery.startsWith(canonicalBase)\n ? pathBeforeQuery.slice(canonicalBase.length)\n : pathBeforeQuery;\n const normalized = normalizePathForRoute(stripped || '/');\n return {\n path: normalized,\n query,\n fragment,\n };\n };\n\n const performNavigation = async (\n path: string,\n replace = false,\n ): Promise<void> => {\n try {\n const loc = parseNavigationPath(path);\n const match = cachedMatchRoute(loc.path);\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n fragment: (loc as { fragment?: string }).fragment,\n };\n\n // beforeEnter guard\n const beforeEnterResult = await runBeforeEnter(to, from);\n if (beforeEnterResult === false) return;\n if (typeof beforeEnterResult === 'string') {\n // Handle redirect\n redirectDepth++;\n const redirectKey = `${to.path}->${beforeEnterResult}`;\n redirectTracker.add(redirectKey);\n await performNavigation(beforeEnterResult, true);\n return;\n }\n\n // onEnter guard (right before commit)\n const onEnterResult = await runOnEnter(to, from);\n if (onEnterResult === false) return;\n if (typeof onEnterResult === 'string') {\n // Handle redirect\n redirectDepth++;\n const redirectKey = `${to.path}->${onEnterResult}`;\n redirectTracker.add(redirectKey);\n await performNavigation(onEnterResult, true);\n return;\n }\n\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const qstr = serializeQuery(loc.query);\n const href =\n canonicalBase +\n loc.path +\n (qstr || '') +\n (loc.fragment ? '#' + loc.fragment : '');\n if (replace) {\n window.history.replaceState({}, '', href);\n } else {\n window.history.pushState({}, '', href);\n }\n }\n\n store.setState(to);\n\n // afterEnter hook (post commit)\n runAfterEnter(to, from);\n\n // If there's a fragment (hash) preserve it on the URL and attempt to\n // scroll to the element with that id on client-side navigation.\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n try {\n const frag = (to as { fragment?: string }).fragment;\n if (_scrollConfig.enabled && frag) {\n // Start the robust scroll flow (observer + timeout + cancellation)\n startScrollForNavigation(\n String(frag),\n _scrollConfig.offset,\n _scrollConfig.timeoutMs,\n ).catch(() => {});\n }\n } catch {\n /* swallow */\n }\n }\n } catch (err) {\n devError('Navigation error:', err);\n\n // If this is a guard error, re-throw it so the promise rejects properly\n if (\n err instanceof Error &&\n (err.stack?.includes('runBeforeEnter') ||\n err.stack?.includes('runOnEnter'))\n ) {\n throw err;\n }\n\n // For other navigation errors, ensure store state remains consistent\n try {\n const current = store.getState();\n const targetMatches = matchRoute(routes, current.path);\n if (!targetMatches.route) {\n // If current state is invalid, reset to a valid route or root\n let fallbackRoute = routes.find((r) => r.path === '/');\n if (!fallbackRoute) {\n // Find any route that doesn't have dynamic segments as fallback\n fallbackRoute = routes.find(\n (r) => !r.path.includes(':') && !r.path.includes('*'),\n );\n }\n if (!fallbackRoute && routes.length > 0) {\n fallbackRoute = routes[0];\n }\n\n if (fallbackRoute) {\n const fallbackMatch = matchRoute(routes, fallbackRoute.path);\n store.setState({\n path: fallbackRoute.path,\n params: fallbackMatch.params,\n query: {},\n });\n } else {\n devError('No fallback route available for error recovery');\n }\n }\n } catch (recoveryError) {\n devWarn(\n 'State recovery failed during navigation error:',\n recoveryError,\n );\n }\n }\n };\n\n // Validate routes configuration\n const validateRoutes = (routeList: Route[]): boolean => {\n if (!routeList || routeList.length === 0) {\n devError('Router configuration error: No routes provided');\n return false;\n }\n\n const pathSet = new Set<string>();\n for (const route of routeList) {\n if (!route.path) {\n devError('Router configuration error: Route missing path', route);\n return false;\n }\n\n if (pathSet.has(route.path)) {\n devWarn(`Duplicate route path detected: ${route.path}`);\n }\n pathSet.add(route.path);\n\n if (!route.component && !route.load) {\n devWarn(`Route '${route.path}' has no component or load function`);\n }\n }\n return true;\n };\n\n // Validate configuration before proceeding (non-fatal for compatibility)\n validateRoutes(routes);\n\n // Pre-compile all routes for better SSR performance\n const isSSRMode =\n typeof window === 'undefined' || typeof initialUrl !== 'undefined';\n if (isSSRMode) {\n for (const route of routes) {\n // Force compilation of all routes during SSR initialization\n cachedMatchRoute(route.path);\n }\n devWarn(`Pre-compiled ${routes.length} routes for SSR`);\n }\n\n // If an explicit `initialUrl` is provided we treat this as SSR/static rendering\n // even if a `window` exists (useful for hydration tests). Browser mode only\n // applies when `initialUrl` is undefined.\n if (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n typeof initialUrl === 'undefined'\n ) {\n // Browser mode\n getLocation = () => {\n try {\n const url = new URL(window.location.href);\n const raw = url.pathname;\n const stripped = raw.startsWith(canonicalBase)\n ? raw.slice(canonicalBase.length)\n : raw;\n const path = normalizePathForRoute(stripped || '/');\n const query = parseQuery(url.search);\n const fragment = url.hash && url.hash.length ? url.hash.slice(1) : '';\n return { path, query, fragment };\n } catch (error) {\n devWarn('Invalid URL detected, falling back to safe defaults', error);\n return { path: '/', query: {}, fragment: '' };\n }\n };\n\n initial = getLocation();\n const match = cachedMatchRoute(initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n fragment: (initial as { fragment?: string }).fragment,\n });\n\n update = async (replace = false) => {\n const loc = getLocation();\n await navigate(loc.path, replace);\n };\n\n const handlePopState = () => update(true);\n window.addEventListener('popstate', handlePopState);\n\n push = (path: string) => navigate(path, false);\n replaceFn = (path: string) => navigate(path, true);\n back = () => window.history.back();\n } else {\n // SSR mode\n getLocation = () => {\n try {\n const url = new URL(initialUrl || '/', 'http://localhost');\n const raw = url.pathname;\n const stripped = raw.startsWith(canonicalBase)\n ? raw.slice(canonicalBase.length)\n : raw;\n const path = normalizePathForRoute(stripped || '/');\n const query = parseQuery(url.search);\n const fragment = url.hash && url.hash.length ? url.hash.slice(1) : '';\n return { path, query, fragment };\n } catch (error) {\n devWarn(\n 'Invalid SSR URL detected, falling back to safe defaults',\n error,\n );\n return { path: '/', query: {}, fragment: '' };\n }\n };\n\n initial = getLocation();\n const match = cachedMatchRoute(initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n fragment: (initial as { fragment?: string }).fragment,\n });\n\n update = async () => {\n const loc = getLocation();\n await navigateSSR(loc.path);\n };\n\n // SSR navigation contract:\n // - `push` / `replace` call into `navigateSSR` and return a Promise.\n // - On the server we intentionally surface navigation failures so\n // server-side logic (or tests) can react: missing routes or thrown\n // errors from `beforeEnter`/`onEnter` will cause the Promise to\n // reject. This lets the server render 404s or abort builds.\n // - For valid routes the server-side navigation resolves and updates\n // the internal store state so rendered output matches the target\n // path. The `back()` operation is client-only and is a synchronous\n // no-op in SSR mode.\n const navigateSSR = async (path: string) => {\n // Prevent infinite recursion in SSR mode\n redirectDepth++;\n if (redirectDepth > MAX_REDIRECT_DEPTH) {\n devError(`SSR redirect depth exceeded for path: ${path}`);\n return;\n }\n\n try {\n const loc = parseNavigationPath(path);\n const match = cachedMatchRoute(loc.path);\n // In SSR mode we intentionally surface navigation errors (missing\n // route) to the caller so server-side logic may handle them. If no\n // route matches, throw and let the caller observe the rejection.\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n fragment: (loc as { fragment?: string }).fragment,\n };\n\n // beforeEnter guard with redirect tracking - let errors bubble up in SSR\n const matched = findMatchedRoute(routes, to.path);\n if (matched?.beforeEnter) {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Handle redirect with tracking\n const redirectKey = `${to.path}->${result}`;\n redirectTracker.add(redirectKey);\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n // onEnter guard with redirect tracking - let errors bubble up in SSR\n if (matched?.onEnter) {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n // Handle redirect with tracking\n const redirectKey = `${to.path}->${result}`;\n redirectTracker.add(redirectKey);\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n store.setState(to);\n\n // afterEnter hook\n if (matched?.afterEnter) {\n matched.afterEnter(to, from);\n }\n } catch (err) {\n // Surface SSR navigation errors so callers (and tests) can observe\n // failures during server-side resolution.\n devError('SSR navigation error:', err);\n throw err;\n }\n };\n\n push = async (path: string) => {\n redirectDepth = 0;\n redirectTracker.clear();\n return navigateSSR(path);\n };\n replaceFn = async (path: string) => {\n redirectDepth = 0;\n redirectTracker.clear();\n return navigateSSR(path);\n };\n back = () => {};\n }\n\n const router = {\n _cleanupScrollState: cleanupScrollState,\n store,\n push,\n replace: replaceFn,\n back,\n subscribe: store.subscribe,\n matchRoute: (path: string) => cachedMatchRoute(path),\n getCurrent: (): RouteState => store.getState(),\n resolveRouteComponent,\n base: canonicalBase,\n // Public API: allow components or tests to explicitly request scrolling to\n // a fragment when they know their DOM is ready. Returns true if scrolled.\n scrollToFragment: (frag?: string) => {\n const id = frag || (store.getState() as RouteState).fragment;\n if (!id) return Promise.resolve(false);\n if (typeof window === 'undefined' || typeof document === 'undefined')\n return Promise.resolve(false);\n return startScrollForNavigation(\n id,\n _scrollConfig.offset,\n _scrollConfig.timeoutMs,\n );\n },\n };\n\n return router;\n}\n\n/**\n * Explicit Router instance type exported for clearer typing across the\n * codebase and tests.\n */\n/**\n * Router instance interface providing navigation and state management.\n */\nexport interface Router {\n /** Reactive store containing current route state */\n store: Store<RouteState>;\n /** Navigate to a path (adds to history) */\n push: (path: string) => Promise<void>;\n /** Navigate to a path (replaces current history entry) */\n replace: (path: string) => Promise<void>;\n /** Go back in browser history */\n back: () => void;\n /** Subscribe to route state changes */\n subscribe: Store<RouteState>['subscribe'];\n /** Match a path against configured routes */\n matchRoute: (path: string) => {\n route: Route | null;\n params: Record<string, string>;\n };\n /** Get current route state */\n getCurrent: () => RouteState;\n /** Resolve a route's component */\n resolveRouteComponent: typeof resolveRouteComponent;\n /** Base path for the router */\n base: string;\n /** Scroll to a fragment/hash element */\n scrollToFragment: (frag?: string) => Promise<boolean>;\n}\n\n// SSR/static site support: match route for a given path\nexport function matchRouteSSR(routes: Route[], path: string) {\n return matchRoute(routes, path);\n}\n\n// Module-level reference to the latest initialized router. Tests and\n// components may rely on re-initializing the router during their setup,\n// so exposing this lets components pick up the most recent instance.\nlet activeRouter: ReturnType<typeof useRouter> | null = null;\n\n// Proxy that provides a stable API for consumers (components/tests).\n// Subscriptions and method calls are forwarded to the currently active\n// router instance. When `activeRouter` changes (via `initRouter`) the\n// proxy rebinds and forwards updates to its listeners so components do\n// not need to re-register on re-init.\ntype RouterListener = (s: RouteState) => void;\nconst _proxyListeners: Set<RouterListener> = new Set();\nlet _proxyInnerUnsub: (() => void) | null = null;\n\nfunction _rebindProxy() {\n // Unsubscribe previous inner subscription to prevent memory leaks\n if (_proxyInnerUnsub) {\n try {\n _proxyInnerUnsub();\n } catch {\n // Ignore unsubscribe errors\n }\n _proxyInnerUnsub = null;\n }\n\n if (activeRouter) {\n // Subscribe to the new router and forward updates\n try {\n // We'll detect whether the inner subscription invokes synchronously.\n // Some store implementations call subscribers immediately; others\n // don't. To guarantee exactly-one initial delivery we record whether\n // the inner callback ran during subscribe and only emit a manual\n // snapshot when it did not.\n let innerCalledSync = false;\n _proxyInnerUnsub = activeRouter.subscribe((s) => {\n innerCalledSync = true;\n // Forward to listeners, using Set iteration which is safe for concurrent modification\n for (const listener of _proxyListeners) {\n try {\n listener(s);\n } catch {\n /* swallow listener errors */\n }\n }\n });\n\n // Update proxy base to reflect active router\n try {\n activeRouterProxy.base = activeRouter.base;\n } catch {\n /* swallow */\n }\n\n // If the inner subscription did not synchronously invoke, emit a\n // single initial snapshot so listeners that were registered while\n // no active router existed receive the current state exactly once.\n if (!innerCalledSync) {\n const cur = activeRouter.getCurrent();\n for (const listener of _proxyListeners) {\n try {\n listener(cur);\n } catch {\n /* swallow */\n }\n }\n } else {\n // Even if inner subscription called synchronously, ensure all listeners\n // receive the current state immediately to handle router re-initialization\n const cur = activeRouter.getCurrent();\n for (const listener of _proxyListeners) {\n try {\n listener(cur);\n } catch {\n /* swallow */\n }\n }\n }\n\n // After synchronously forwarding the current snapshot to proxy\n // listeners, flush any pending DOM updates in browser environments\n // so callers that immediately inspect the DOM observe the updated\n // rendered state.\n try {\n if (typeof window !== 'undefined') flushDOMUpdates();\n } catch {\n /* swallow */\n }\n } catch {\n _proxyInnerUnsub = null;\n }\n }\n}\n\nexport const activeRouterProxy: Router = {\n store: {\n subscribe(listener: RouterListener) {\n if (activeRouter) return activeRouter.store.subscribe(listener);\n // immediate no-op subscribe - provide safe fallback state\n try {\n listener({ path: '/', params: {}, query: {} });\n } catch {\n /* swallow listener errors */\n }\n return () => {};\n },\n getState() {\n return activeRouter\n ? activeRouter.getCurrent()\n : { path: '/', params: {}, query: {} };\n },\n setState(\n partial:\n | Partial<RouteState>\n | ((prev: RouteState) => Partial<RouteState>),\n ) {\n if (!activeRouter) return;\n try {\n if (typeof partial === 'function') {\n activeRouter.store.setState(\n partial as (prev: RouteState) => Partial<RouteState>,\n );\n } else {\n activeRouter.store.setState(partial as Partial<RouteState>);\n }\n } catch {\n /* swallow */\n }\n },\n },\n subscribe(listener: RouterListener) {\n // Defensive check - ensure listener is a function\n if (typeof listener !== 'function') {\n devWarn('activeRouterProxy.subscribe: listener must be a function');\n return () => {};\n }\n\n // Add the listener to the proxy set\n _proxyListeners.add(listener);\n\n // Ensure we are bound to the active router. If not bound, rebind so\n // the inner subscription will forward updates to `_proxyListeners`.\n if (activeRouter) {\n if (!_proxyInnerUnsub) {\n // Rebind will synchronously forward the current state to all\n // proxy listeners (including the one we just pushed). Don't\n // call the listener again here to avoid double-invocation.\n _rebindProxy();\n } else {\n // Inner subscription already present; deliver a synchronous\n // snapshot only to the newly added listener.\n try {\n const currentState = activeRouter.getCurrent();\n if (currentState) {\n listener(currentState);\n }\n } catch (err) {\n devWarn('activeRouterProxy subscription failed', err);\n }\n }\n } else {\n // No active router yet - provide fallback state\n try {\n listener({ path: '/', params: {}, query: {} });\n } catch (err) {\n devWarn('activeRouterProxy fallback state delivery failed', err);\n }\n }\n\n // Return unsubscribe with additional safety checks\n return () => {\n try {\n _proxyListeners.delete(listener);\n // If no more proxy listeners remain, unsubscribe inner subscription\n // to avoid retaining unused references. It will be rebound on demand.\n if (_proxyListeners.size === 0 && _proxyInnerUnsub) {\n try {\n _proxyInnerUnsub();\n } catch (err) {\n devWarn('activeRouterProxy inner unsubscribe failed', err);\n }\n _proxyInnerUnsub = null;\n }\n } catch (err) {\n devWarn('activeRouterProxy unsubscribe failed', err);\n }\n };\n },\n getCurrent() {\n return activeRouter\n ? activeRouter.getCurrent()\n : { path: '/', params: {}, query: {} };\n },\n async push(path: string) {\n if (!activeRouter) return Promise.resolve();\n return activeRouter.push(path);\n },\n async replace(path: string) {\n if (!activeRouter) return Promise.resolve();\n return activeRouter.replace(path);\n },\n back() {\n if (!activeRouter) return;\n return activeRouter.back();\n },\n matchRoute(path: string) {\n return activeRouter\n ? activeRouter.matchRoute(path)\n : { route: null, params: {} };\n },\n resolveRouteComponent(route: Route) {\n return activeRouter\n ? activeRouter.resolveRouteComponent(route)\n : Promise.reject(new Error('No active router'));\n },\n base: '',\n scrollToFragment(frag?: string) {\n return activeRouter\n ? activeRouter.scrollToFragment(frag)\n : Promise.resolve(false);\n },\n};\n\n/**\n * Singleton router instance for global access.\n *\n * Define here to prevent circular dependency\n * issue with component.\n */\n\nexport function initRouter(config: RouterConfig) {\n // Clear component cache on reinitialization to prevent stale components\n clearComponentCache();\n\n const router = useRouter(config);\n\n // Clean up scroll state from any previous router instance\n if (activeRouter) {\n try {\n activeRouter._cleanupScrollState?.();\n } catch {\n // Ignore cleanup errors - function may not exist in older instances\n }\n }\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n activeRouter = router;\n // Rebind the proxy so any existing subscribers are forwarded to the\n // newly initialized router immediately.\n try {\n _rebindProxy();\n try {\n // Only attempt to flush DOM updates in browser environments.\n if (typeof window !== 'undefined') flushDOMUpdates();\n } catch {\n // Ignore DOM flush errors\n }\n\n // Additional flush after rebind to ensure all router-link components\n // have updated their active states before any synchronous inspection\n try {\n if (typeof window !== 'undefined') {\n // Use a microtask to allow reactive computations to complete\n queueMicrotask(() => {\n try {\n flushDOMUpdates();\n } catch {\n /* swallow */\n }\n });\n }\n } catch {\n /* swallow */\n }\n } catch {\n // Ignore proxy rebind errors\n }\n\n component('router-view', async () => {\n // Prefer the latest initialized router (tests may re-init). Resolve the\n // router lazily so components connect to whichever router is currently\n // active instead of capturing a stale instance at definition time.\n // Reactive current route so the component re-renders when router updates\n if (!activeRouter) return html`<div>Router not initialized.</div>`;\n\n const current = ref(activeRouterProxy.getCurrent());\n const isSSR = typeof window === 'undefined';\n\n // We'll capture the unsubscribe function when the component connects\n // and register a disconnect cleanup during render-time (useOnDisconnected\n // must be called during the component render/execution).\n let unsubRouterView: (() => void) | undefined;\n\n // Only set up subscriptions in browser environment\n if (!isSSR) {\n useOnConnected(() => {\n try {\n if (typeof activeRouterProxy.subscribe === 'function') {\n unsubRouterView = activeRouterProxy.subscribe((s) => {\n try {\n // Validate state before updating to prevent corruption\n if (s && typeof s === 'object' && typeof s.path === 'string') {\n current.value = s;\n } else {\n devWarn('router-view received invalid state', s);\n // Fallback to safe default state\n current.value = { path: '/', params: {}, query: {} };\n }\n } catch (e) {\n devWarn('router-view subscription update failed', e);\n // Attempt to recover with safe state\n try {\n current.value = { path: '/', params: {}, query: {} };\n } catch {\n /* swallow recovery errors */\n }\n }\n });\n }\n } catch (e) {\n devWarn('router-view subscribe failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterView === 'function') {\n try {\n unsubRouterView();\n } catch (e) {\n devWarn('router-view unsubscribe failed', e);\n }\n unsubRouterView = undefined; // Clear reference to prevent memory leaks\n }\n });\n }\n\n const match = activeRouterProxy.matchRoute(current.value.path);\n if (!match || !match.route) return html`<div>Not found</div>`;\n\n // Resolve the component (supports cached async loaders)\n try {\n const compRaw = await activeRouterProxy.resolveRouteComponent(\n match.route!,\n );\n const comp = compRaw as\n | string\n | HTMLElement\n | ((...args: unknown[]) => unknown)\n | undefined;\n // String tag (custom element) -> render as VNode\n if (typeof comp === 'string') {\n return { tag: comp, props: {}, children: [] };\n }\n\n // Function component (sync or async) -> call and return its VNode(s)\n if (typeof comp === 'function') {\n const out = comp();\n const resolved = out instanceof Promise ? out : Promise.resolve(out);\n return resolved.then((resolvedComp) => {\n if (typeof resolvedComp === 'string')\n return { tag: resolvedComp, props: {}, children: [] };\n return resolvedComp;\n });\n }\n\n return html`<div>Invalid route component</div>`;\n } catch {\n return html`<div>Invalid route component</div>`;\n }\n });\n\n component('router-link', () => {\n // Declare props via useProps so observedAttributes are correct\n const props = useProps<Partial<RouterLinkProps>>({\n to: '',\n tag: 'a',\n replace: false,\n exact: false,\n activeClass: 'active',\n exactActiveClass: 'exact-active',\n ariaCurrentValue: 'page',\n disabled: false,\n external: false,\n // allow host `class` and `style` attributes to be read via useProps\n class: '',\n style: '',\n });\n\n const isSSR = typeof window === 'undefined';\n const current = ref(activeRouterProxy.getCurrent());\n\n // For SSR, compute stable active states to prevent hydration mismatches\n const stableCurrentPath = current.value?.path || '/';\n const targetPath = String(props.to || '');\n\n // Pre-compute SSR-safe active states\n const ssrActiveStates = isSSR\n ? {\n isExactActive: computeExactActive(\n stableCurrentPath,\n targetPath,\n activeRouterProxy.base,\n ),\n isActive: computeActive(\n stableCurrentPath,\n targetPath,\n activeRouterProxy.base,\n ),\n isExternal: isAbsoluteUrl(targetPath) || !!props.external,\n }\n : null;\n\n let unsubRouterLink: (() => void) | undefined;\n\n // Keep a minimal internal host-scoped style for element display.\n // Host `style` will be applied to the inner anchor/button element.\n useStyle(() => `a,button{display:inline-block;}`);\n\n // We capture host attributes at connection time and migrate them to\n // internal refs so we can remove them from the host. This prevents\n // global/author CSS targeting the host from styling the host element\n // itself while still allowing authors to use `class`/`style` on the\n // router-link to style the inner anchor/button.\n const hostClassRef = ref((props.class as string) || '');\n const hostStyleRef = ref((props.style as string) || '');\n\n // Only set up DOM interactions in browser environment\n if (!isSSR) {\n let syncCheckInterval: ReturnType<typeof setInterval> | null = null;\n\n useOnConnected((ctx?: unknown) => {\n try {\n if (typeof activeRouterProxy.subscribe === 'function') {\n unsubRouterLink = activeRouterProxy.subscribe((s) => {\n try {\n // Validate state before updating to prevent corruption\n if (s && typeof s === 'object' && typeof s.path === 'string') {\n current.value = s;\n } else {\n devWarn('router-link received invalid state', s);\n // Fallback to safe default state\n current.value = { path: '/', params: {}, query: {} };\n }\n } catch (e) {\n devWarn('router-link subscription update failed', e);\n // Attempt to recover with safe state\n try {\n current.value = { path: '/', params: {}, query: {} };\n } catch {\n /* swallow recovery errors */\n }\n }\n });\n\n // Immediately sync current state after subscription to ensure\n // correct active state even if router was initialized after component creation\n try {\n const currentState = activeRouterProxy.getCurrent();\n if (currentState && typeof currentState.path === 'string') {\n current.value = currentState;\n }\n } catch (e) {\n devWarn('router-link initial state sync failed', e);\n }\n\n // Set up periodic sync check to ensure state accuracy after router changes\n // This catches edge cases where subscription updates might be missed\n syncCheckInterval = setInterval(() => {\n try {\n const latestState = activeRouterProxy.getCurrent();\n if (latestState && typeof latestState.path === 'string') {\n // Only update if state actually changed to avoid unnecessary re-renders\n if (\n JSON.stringify(current.value) !==\n JSON.stringify(latestState)\n ) {\n current.value = latestState;\n }\n }\n } catch {\n // Silent failure - don't spam console with periodic check errors\n }\n }, 100); // Check every 100ms\n }\n } catch (e) {\n devWarn('router-link subscribe failed', e);\n }\n\n // Migrate host `class`/`style` into internal refs and remove them\n // from the host so only the inner element is styled.\n try {\n const host = (ctx as { _host?: HTMLElement } | undefined)?._host;\n if (host instanceof HTMLElement) {\n const hc = host.getAttribute('class');\n const hs = host.getAttribute('style');\n if (hc) hostClassRef.value = hc;\n if (hs) hostStyleRef.value = hs;\n // Remove attributes from host to avoid styling the host\n if (hc !== null) host.removeAttribute('class');\n if (hs !== null) host.removeAttribute('style');\n // Re-render to ensure migrated host classes/styles are applied\n // to the internal anchor/button element.\n try {\n // The `ctx` passed into useOnConnected is the component context\n // which exposes `_requestRender`. Call that to re-render after\n // migrating host attributes into internal refs.\n (\n ctx as unknown as { _requestRender?: () => void }\n )?._requestRender?.();\n // Ensure DOM updates from the scheduled render are flushed so\n // callers (and tests) can synchronously observe migrated\n // classes/styles on the inner anchor/button.\n try {\n flushDOMUpdates();\n } catch {\n /* ignore */\n }\n } catch {\n /* ignore */\n }\n }\n } catch (e) {\n devWarn('router-link host migration failed', e);\n }\n });\n\n useOnDisconnected(() => {\n // Clean up router subscription\n if (typeof unsubRouterLink === 'function') {\n try {\n unsubRouterLink();\n } catch (e) {\n devWarn('router-link unsubscribe failed', e);\n } finally {\n unsubRouterLink = undefined; // Clear reference to prevent memory leaks\n }\n }\n\n // Clean up sync check interval\n if (syncCheckInterval) {\n try {\n clearInterval(syncCheckInterval);\n } catch (e) {\n devWarn('router-link sync interval cleanup failed', e);\n } finally {\n syncCheckInterval = null;\n }\n }\n });\n }\n\n // Use pre-computed values for SSR or dynamic computed for client\n const isExactActive = computed(() => {\n if (isSSR && ssrActiveStates) {\n return ssrActiveStates.isExactActive;\n }\n\n try {\n const runtimeBase = activeRouterProxy.base ?? '';\n const targetRaw = (props.to as string) || '';\n\n // Defensive check for current value\n if (!current.value || typeof current.value.path !== 'string') {\n return false;\n }\n\n return computeExactActive(current.value.path, targetRaw, runtimeBase);\n } catch (err) {\n devWarn('isExactActive computation error', err);\n return false;\n }\n });\n\n const isActive = computed(() => {\n if (isSSR && ssrActiveStates) {\n return ssrActiveStates.isActive;\n }\n\n try {\n const runtimeBase = activeRouterProxy.base ?? '';\n const targetRaw = (props.to as string) || '';\n\n // Defensive check for current value\n if (!current.value || typeof current.value.path !== 'string') {\n return false;\n }\n\n if (props.exact) return isExactActive.value;\n return computeActive(current.value.path, targetRaw, runtimeBase);\n } catch (err) {\n devWarn('isActive computation error', err);\n return false;\n }\n });\n\n // Compute a normalized href for the inner anchor so middle-click / open-in-new-tab\n // uses a canonical absolute path (includes base and fragment). We keep using\n // props.to for router navigation so current behavior (literal `to`) remains.\n const hrefTarget = computed(() => {\n const raw = String(props.to || '');\n // Block obviously dangerous javascript: URIs from becoming clickable\n // hrefs. See isDangerousScheme for rationale.\n if (isDangerousScheme(raw)) return null;\n\n // Preserve absolute URLs with a scheme (http:, mailto:, data:, etc.)\n // and protocol-relative URLs that begin with `//`.\n if (isAbsoluteUrl(raw)) return raw;\n\n // Split fragment and query explicitly so both are preserved.\n const [pathWithQuery, frag] = raw.split('#');\n const [pathOnly, query] = (pathWithQuery || '').split('?');\n\n // Read base dynamically from the current router instance so repeated\n // calls to initRouter (tests) do not leave a stale captured value.\n const runtimeBase = activeRouterProxy.base ?? '';\n // If the provided path already contains the runtime base, strip it to\n // avoid duplicating e.g. '/app/app/about'. Keep a fallback of '/'.\n // Use more robust base removal that handles normalization edge cases.\n let candidate = pathOnly || '/';\n if (runtimeBase && runtimeBase !== '/') {\n // Normalize both base and candidate to ensure consistent comparison\n const normalizedBase = normalizePathForRoute(runtimeBase);\n const normalizedCandidate = normalizePathForRoute(candidate);\n if (normalizedCandidate.startsWith(normalizedBase)) {\n candidate = normalizedCandidate.slice(normalizedBase.length) || '/';\n } else {\n candidate = normalizedCandidate;\n }\n }\n const norm = normalizePathForRoute(candidate || '/');\n return (\n runtimeBase +\n norm +\n (query ? '?' + query : '') +\n (frag ? '#' + frag : '')\n );\n });\n\n // Build user classes reactively from the host `class` attribute prop.\n // We intentionally apply classes to the inner element so the consumer\n // can style the link via `class=\"...\"`.\n const userClasses = computed(() => {\n const rawHost =\n (hostClassRef && hostClassRef.value) || (props.class as string) || '';\n const list = rawHost.split(/\\s+/).filter(Boolean);\n const map: Record<string, boolean> = {};\n for (const c of list) map[c] = true;\n return map;\n });\n\n const classObject = computed(() => ({\n ...userClasses.value,\n [(props.activeClass as string) || 'active']: isActive.value,\n [(props.exactActiveClass as string) || 'exact-active']:\n isExactActive.value,\n }));\n\n // Compute a final class string (template accepts object or string; we\n // convert to string to safely include host classes and conditionals).\n const classString = computed(() =>\n Object.keys(classObject.value)\n .filter((k) => classObject.value[k])\n .join(' '),\n );\n\n const tagName = computed(() => (props.tag as string) || 'a');\n const isButton = computed(() => tagName.value === 'button');\n // Instead of pre-building attribute fragments as strings (which can\n // accidentally inject invalid attribute names into the template and\n // cause DOMExceptions), compute simple booleans/values and apply\n // attributes explicitly in the template below.\n // Return null when not exact so the attribute is omitted from the DOM\n const ariaCurrentValue = computed<null | string>(() =>\n isExactActive.value ? (props.ariaCurrentValue as string) : null,\n );\n const isDisabled = computed(() => !!props.disabled);\n // External should only apply to anchor tags (links). Make the check explicit.\n // Detect absolute/protocol-relative URLs as external even if the prop\n // wasn't explicitly set by the caller. Only apply to anchor tags.\n const isExternal = computed(() => {\n const toStr = String(props.to || '');\n const looksAbsolute = isAbsoluteUrl(toStr);\n return (looksAbsolute || !!props.external) && tagName.value === 'a';\n });\n\n // Inline style from host `style` attribute.\n const inlineStyle = computed(\n () =>\n (hostStyleRef && hostStyleRef.value) || (props.style as string) || '',\n );\n\n const navigate = (e: MouseEvent) => {\n // Respect pre-handled events, non-left clicks, and modifier keys so\n // default browser behaviors (open-in-new-tab, context menu) work.\n if (\n e.defaultPrevented ||\n e.button !== 0 ||\n e.metaKey ||\n e.altKey ||\n e.ctrlKey ||\n e.shiftKey\n )\n return;\n\n if (isDisabled.value) {\n // Prevent navigation and let assistive tech see disabled state\n e.preventDefault();\n return;\n }\n\n // Block dangerous javascript: URIs explicitly to avoid accidental XSS\n const _targetRaw = String(props.to || '');\n if (isDangerousScheme(_targetRaw)) {\n try {\n e.preventDefault();\n } catch {\n /* swallow */\n }\n devWarn('Blocked unsafe javascript: URI in router-link.to');\n return;\n }\n\n // If this is an external anchor, allow default browser behavior\n if (isExternal.value) return;\n\n e.preventDefault();\n if (props.replace) {\n activeRouterProxy.replace(props.to as string);\n } else {\n activeRouterProxy.push(props.to as string);\n }\n };\n\n return html`\n ${match()\n .when(\n isButton.value,\n html`\n <button\n part=\"button\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n disabled=\"${isDisabled.value ? '' : null}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n @click=\"${navigate}\"\n >\n <slot></slot>\n </button>\n `,\n )\n .otherwise(html`\n <a\n part=\"link\"\n href=\"${isDisabled.value ? null : hrefTarget.value}\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n target=\"${isExternal.value ? '_blank' : null}\"\n rel=\"${isExternal.value ? 'noopener noreferrer' : null}\"\n @click=\"${navigate}\"\n ><slot></slot\n ></a>\n `)\n .done()}\n `;\n });\n\n return router;\n}\n\n// Helper functions for SSR-safe active state computation\nfunction computeExactActive(\n currentPath: string,\n targetRaw: string,\n runtimeBase: string,\n): boolean {\n if (isAbsoluteUrl(targetRaw)) return false;\n\n const targetPathOnly = (targetRaw.split('#')[0] || '/').split('?')[0];\n let tgtCandidate = targetPathOnly;\n\n if (runtimeBase && runtimeBase !== '/') {\n const normalizedBase = normalizePathForRoute(runtimeBase);\n const normalizedTarget = normalizePathForRoute(tgtCandidate);\n if (normalizedTarget.startsWith(normalizedBase)) {\n tgtCandidate = normalizedTarget.slice(normalizedBase.length) || '/';\n } else {\n tgtCandidate = normalizedTarget;\n }\n }\n\n const cur = normalizePathForRoute(currentPath);\n const tgt = normalizePathForRoute(tgtCandidate);\n return cur === tgt;\n}\n\nfunction computeActive(\n currentPath: string,\n targetRaw: string,\n runtimeBase: string,\n): boolean {\n if (isAbsoluteUrl(targetRaw)) return false;\n\n const targetPathOnly = (targetRaw.split('#')[0] || '/').split('?')[0];\n let tgtCandidate = targetPathOnly;\n\n if (runtimeBase && runtimeBase !== '/') {\n const normalizedBase = normalizePathForRoute(runtimeBase);\n const normalizedTarget = normalizePathForRoute(tgtCandidate);\n if (normalizedTarget.startsWith(normalizedBase)) {\n tgtCandidate = normalizedTarget.slice(normalizedBase.length) || '/';\n } else {\n tgtCandidate = normalizedTarget;\n }\n }\n\n const cur = normalizePathForRoute(currentPath);\n const tgt = normalizePathForRoute(tgtCandidate);\n\n if (tgt === '/') return cur === '/';\n if (cur === tgt) return true;\n return cur.startsWith(tgt.endsWith('/') ? tgt : tgt + '/');\n}\n"],"names":["DEFAULT_SCROLL_CONFIG","parseQuery","search","serializeQuery","q","isDangerousScheme","s","isAbsoluteUrl","url","safeDecode","value","canonicalizeBase","base","normalized","normalizePathForRoute","compileCache","escapeSeg","seg","p","out","compileRoute","route","raw","routePath","segments","paramNames","regexParts","i","devWarn","name","paramMatch","isSplat","pattern","prefix","e","matchRoute","routes","path","incoming","compiled","regex","m","params","rawValue","findMatchedRoute","r","MAX_COMPONENT_CACHE_SIZE","componentCache","loadingCache","clearComponentCache","evictLRUComponents","entries","toRemove","a","b","resolveRouteComponent","cached","isSSR","loadPromise","mod","component","err","errorMsg","devError","useRouter","config","initialUrl","scrollToFragment","canonicalBase","_scrollConfig","getLocation","initial","store","update","push","replaceFn","back","redirectTracker","MAX_REDIRECT_DEPTH","redirectDepth","runBeforeEnter","to","from","matched","result","redirectKey","runOnEnter","runAfterEnter","matchCache","MATCH_CACHE_SIZE","cachedMatchRoute","entriesToRemove","keys","cleanupScrollState","doScrollToElement","id","offset","element","rect","top","startScrollForNavigation","timeoutMs","resolve","resolved","timeoutId","startTime","safeResolve","attemptScroll","retryScroll","error","isNavigating","navigate","replace","performNavigation","parseNavigationPath","hashIndex","fragment","rawPath","qIndex","pathBeforeQuery","query","stripped","loc","match","beforeEnterResult","onEnterResult","qstr","href","frag","current","fallbackRoute","fallbackMatch","recoveryError","routeList","pathSet","createStore","handlePopState","navigateSSR","matchRouteSSR","activeRouter","_proxyListeners","_proxyInnerUnsub","_rebindProxy","innerCalledSync","listener","activeRouterProxy","cur","flushDOMUpdates","partial","currentState","initRouter","router","html","ref","unsubRouterView","useOnConnected","useOnDisconnected","comp","resolvedComp","props","useProps","stableCurrentPath","targetPath","ssrActiveStates","computeExactActive","computeActive","unsubRouterLink","useStyle","hostClassRef","hostStyleRef","syncCheckInterval","ctx","latestState","host","hc","hs","isExactActive","computed","runtimeBase","targetRaw","isActive","hrefTarget","pathWithQuery","pathOnly","candidate","normalizedBase","normalizedCandidate","norm","userClasses","list","map","c","classObject","classString","k","tagName","isButton","ariaCurrentValue","isDisabled","isExternal","toStr","inlineStyle","_targetRaw","currentPath","tgtCandidate","normalizedTarget","tgt"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./namespace-helpers-BsKQl3aH.cjs"),h=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);function c(r,n){if(typeof r=="string")return i.escapeHTML(r);if(r.tag==="#text")return typeof r.children=="string"?i.escapeHTML(r.children):"";if(r.tag==="#anchor")return(Array.isArray(r.children)?r.children.filter(a=>a!=null):[]).map(a=>c(a,n)).join("");if(r.tag==="#raw")return typeof r.children=="string"?r.children:"";let e={};r.props&&r.props.attrs&&(e={...r.props.attrs});const s=n?.injectSvgNamespace??!0,g=n?.injectKnownNamespaces??s;s&&r.tag==="svg"&&!("xmlns"in e)?e.xmlns=i.SVG_NS:g&&r.tag in i.TAG_NAMESPACE_MAP&&!("xmlns"in e)&&(e.xmlns=i.TAG_NAMESPACE_MAP[r.tag]);const l=Object.entries(e).map(([t,a])=>` ${t}="${i.escapeHTML(String(a))}"`).join("");if(h.has(r.tag))return`<${r.tag}${l}>`;const p=Array.isArray(r.children)?r.children.filter(t=>t!=null).map(t=>c(t,n)).join(""):typeof r.children=="string"?i.escapeHTML(r.children):r.children?c(r.children,n):"";return`<${r.tag}${l}>${p}</${r.tag}>`}exports.renderToString=c;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./namespace-helpers-BCVTzhAO.cjs"),h=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);function c(r,n){if(typeof r=="string")return i.escapeHTML(r);if(r.tag==="#text")return typeof r.children=="string"?i.escapeHTML(r.children):"";if(r.tag==="#anchor")return(Array.isArray(r.children)?r.children.filter(a=>a!=null):[]).map(a=>c(a,n)).join("");if(r.tag==="#raw")return typeof r.children=="string"?r.children:"";let e={};r.props&&r.props.attrs&&(e={...r.props.attrs});const s=n?.injectSvgNamespace??!0,g=n?.injectKnownNamespaces??s;s&&r.tag==="svg"&&!("xmlns"in e)?e.xmlns=i.SVG_NS:g&&r.tag in i.TAG_NAMESPACE_MAP&&!("xmlns"in e)&&(e.xmlns=i.TAG_NAMESPACE_MAP[r.tag]);const l=Object.entries(e).map(([t,a])=>` ${t}="${i.escapeHTML(String(a))}"`).join("");if(h.has(r.tag))return`<${r.tag}${l}>`;const p=Array.isArray(r.children)?r.children.filter(t=>t!=null).map(t=>c(t,n)).join(""):typeof r.children=="string"?i.escapeHTML(r.children):r.children?c(r.children,n):"";return`<${r.tag}${l}>${p}</${r.tag}>`}exports.renderToString=c;
2
2
  //# sourceMappingURL=custom-elements-runtime.ssr.cjs.js.map
@@ -1,4 +1,4 @@
1
- import { e as c, S as p, T as g } from "./namespace-helpers-Dw1mgQab.js";
1
+ import { e as c, S as p, T as g } from "./namespace-helpers-CF28TyaG.js";
2
2
  const m = /* @__PURE__ */ new Set([
3
3
  "area",
4
4
  "base",
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("./custom-elements-runtime.directives.cjs.js");const t=require("./transitions-RXe2brRm.cjs");exports.Transition=t.Transition;exports.TransitionGroup=t.TransitionGroup;exports.createTransitionPreset=t.createTransitionPreset;exports.getTransitionStyleSheet=t.getTransitionStyleSheet;exports.transitionPresets=t.transitionPresets;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("./custom-elements-runtime.directives.cjs.js");const t=require("./transitions-DfcqL-X4.cjs");exports.Transition=t.Transition;exports.TransitionGroup=t.TransitionGroup;exports.createTransitionPreset=t.createTransitionPreset;exports.getTransitionStyleSheet=t.getTransitionStyleSheet;exports.transitionPresets=t.transitionPresets;
2
2
  //# sourceMappingURL=custom-elements-runtime.transitions.cjs.js.map
@@ -1,5 +1,5 @@
1
1
  import "./custom-elements-runtime.directives.es.js";
2
- import { T as r, e as a, f as i, b as n, t as o } from "./transitions-CZ21fzhh.js";
2
+ import { T as r, e as a, f as i, b as n, t as o } from "./transitions-Bx0Nc9zR.js";
3
3
  export {
4
4
  r as Transition,
5
5
  a as TransitionGroup,
package/dist/index.d.ts CHANGED
@@ -5,3 +5,5 @@ export { html } from './runtime/template-compiler';
5
5
  export { css } from './runtime/style';
6
6
  export { unsafeHTML, decodeEntities } from './runtime/helpers';
7
7
  export { setDevMode } from './runtime/logger';
8
+ export { flushDOMUpdates } from './runtime/scheduler';
9
+ export { getHealthMonitor, getHealthStatus, updateHealthMetric, } from './runtime/monitoring/health-monitor';
@@ -0,0 +1,5 @@
1
+ "use strict";const h=require("./logger-DiXdWaF-.cjs");function x(){const n=(()=>{try{return globalThis.process?.env?.NODE_ENV}catch{return}})(),e=(()=>{try{if(typeof window>"u")return{vitest:!1,cypress:!1};const t=window;return{vitest:!!t.__vitest__,cypress:!!t.Cypress}}catch{return{vitest:!1,cypress:!1}}})();return{isTest:n==="test"||e.vitest||e.cypress,isVitest:e.vitest,isCypress:e.cypress}}class D{pendingUpdates=new Map;isFlushScheduled=!1;isFlushing=!1;testEnv;lastCleanup=0;CLEANUP_INTERVAL=300*1e3;MAX_PENDING_SIZE=1e4;constructor(){this.testEnv=x(),this.schedulePeriodicCleanup()}schedule(e,s){const t=s||e;this.pendingUpdates.size>=this.MAX_PENDING_SIZE&&this.performEmergencyCleanup(),this.pendingUpdates.set(t,e),this.isFlushScheduled||this.scheduleFlush()}scheduleFlush(){this.isFlushScheduled=!0,this.testEnv.isTest&&!this.isFlushing?this.flush():queueMicrotask(()=>this.flush())}flush(){if(this.isFlushing)return;this.isFlushing=!0;const e=this.pendingUpdates;this.pendingUpdates=new Map,this.isFlushScheduled=!1;try{for(const s of e.values())try{s()}catch(t){h.devError("Error in batched update:",t)}}finally{this.isFlushing=!1}}flushImmediately(){this.pendingUpdates.size!==0&&(this.isFlushScheduled=!1,this.flush())}get pendingCount(){return this.pendingUpdates.size}get hasPendingUpdates(){return this.pendingUpdates.size>0}get isFlushingUpdates(){return this.isFlushing}schedulePeriodicCleanup(){if(this.testEnv.isTest)return;const e=()=>{this.performPeriodicCleanup(),this.testEnv.isTest||setTimeout(e,this.CLEANUP_INTERVAL)};setTimeout(e,this.CLEANUP_INTERVAL)}performPeriodicCleanup(){const e=Date.now();e-this.lastCleanup<this.CLEANUP_INTERVAL||(this.pendingUpdates.size>100&&h.devWarn(`Scheduler has ${this.pendingUpdates.size} pending updates. Consider investigating.`),this.lastCleanup=e)}performEmergencyCleanup(){h.devWarn("Scheduler emergency cleanup: too many pending updates, clearing oldest entries");const e=Array.from(this.pendingUpdates.entries()),s=Math.floor(e.length/2);for(let t=0;t<s;t++)this.pendingUpdates.delete(e[t][0])}}const A=new D;function b(n,e){A.schedule(n,e)}function H(){A.flushImmediately()}const w=new WeakSet;class P{static cache=new WeakMap;static arrayHandlerCache=new WeakMap;static objectHandlerCache=new WeakMap;static getOrCreateProxy(e,s,t=!1){const r=this.cache.get(e);if(r)return r;const a=t?this.getOrCreateArrayHandler(s):this.getOrCreateObjectHandler(s),i=new Proxy(e,a);try{v.markAsProxy(i)}catch{}return this.cache.set(e,i),i}static getOrCreateArrayHandler(e){if(!this.arrayHandlerCache.has(e)){const s={get:(t,r,a)=>{const i=Reflect.get(t,r,a);return typeof i=="function"&&typeof r=="string"&&["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"].includes(r)?function(...u){const d=i.apply(t,u);return e.triggerUpdate(),d}:i},set:(t,r,a)=>(t[r]=e.makeReactiveValue(a),e.triggerUpdate(),!0),deleteProperty:(t,r)=>(delete t[r],e.triggerUpdate(),!0)};this.arrayHandlerCache.set(e,s)}return this.arrayHandlerCache.get(e)}static getOrCreateObjectHandler(e){if(!this.objectHandlerCache.has(e)){const s={get:(t,r,a)=>Reflect.get(t,r,a),set:(t,r,a)=>(t[r]=e.makeReactiveValue(a),e.triggerUpdate(),!0),deleteProperty:(t,r)=>(delete t[r],e.triggerUpdate(),!0)};this.objectHandlerCache.set(e,s)}return this.objectHandlerCache.get(e)}static hasProxy(e){return this.cache.has(e)}static clear(){this.cache=new WeakMap,this.arrayHandlerCache=new WeakMap,this.objectHandlerCache=new WeakMap}static getStats(){return{hasCachedProxies:this.cache instanceof WeakMap}}}class v{static contextCache=new WeakMap;static createReactiveProxy(e,s,t){try{if(w.has(e))return e}catch{}const r=Array.isArray(e);let a=this.contextCache.get(s);a||(a=new WeakMap,this.contextCache.set(s,a));let i=a.get(t);return i||(i={triggerUpdate:s,makeReactiveValue:t},a.set(t,i)),P.getOrCreateProxy(e,i,r)}static markAsProxy(e){if(e)try{w.add(e)}catch{}}}class U{currentComponentStack=[];componentData=new Map;stateStorage=new Map;trackingDisabled=!1;setCurrentComponent(e,s){if(this.currentComponentStack.push(e),!this.componentData.has(e))this.componentData.set(e,{dependencies:new Set,renderFn:s,stateIndex:0,lastWarnTime:0,watchers:new Map});else{const t=this.componentData.get(e);if(t.watchers&&t.watchers.size){for(const r of t.watchers.values())try{this.cleanup(r)}catch{}t.watchers.clear()}t.renderFn=s,t.stateIndex=0}}clearCurrentComponent(){this.currentComponentStack.pop()}getCurrentComponentId(){return this.currentComponentStack.length?this.currentComponentStack[this.currentComponentStack.length-1]:null}registerWatcher(e,s){const t=this.componentData.get(e);t&&t.watchers.set(s,s)}disableTracking(){this.trackingDisabled=!0}enableTracking(){this.trackingDisabled=!1}isRenderingComponent(){return this.currentComponentStack.length>0}shouldEmitRenderWarning(){const e=this.currentComponentStack.length?this.currentComponentStack[this.currentComponentStack.length-1]:null;if(!e)return!0;const s=this.componentData.get(e);if(!s)return!0;const t=Date.now();return t-s.lastWarnTime<1e3?!1:(s.lastWarnTime=t,!0)}withoutTracking(e){const s=this.trackingDisabled;this.trackingDisabled=!0;try{return e()}finally{this.trackingDisabled=s}}getOrCreateState(e){const s=this.currentComponentStack.length?this.currentComponentStack[this.currentComponentStack.length-1]:null;if(!s)return new y(e);const t=this.componentData.get(s);if(!t)return new y(e);const r=`${s}:${t.stateIndex++}`;let a=this.stateStorage.get(r);return a||(a=new y(e),this.stateStorage.set(r,a)),a}trackDependency(e){if(this.trackingDisabled)return;const s=this.currentComponentStack.length?this.currentComponentStack[this.currentComponentStack.length-1]:null;if(!s)return;const t=this.componentData.get(s);t&&(t.dependencies.add(e),e.addDependent(s))}triggerUpdate(e){const s=e.getDependents();for(const t of s){const r=this.componentData.get(t);r&&b(r.renderFn,t)}}cleanup(e){const s=this.componentData.get(e);if(s){for(const r of s.dependencies)r.removeDependent(e);this.componentData.delete(e)}const t=e+":";for(const r of this.stateStorage.keys())r.startsWith(t)&&this.stateStorage.delete(r)}}const o=new U;class y{_value;dependents=new Set;constructor(e){this._value=this.makeReactive(e);try{const s=Symbol.for("@cer/ReactiveState");Object.defineProperty(this,s,{value:!0,enumerable:!1,configurable:!1})}catch{}}get value(){return o.trackDependency(this),this._value}set value(e){o.isRenderingComponent()&&o.shouldEmitRenderWarning()&&h.devWarn(`🚨 State modification detected during render! This can cause infinite loops.
2
+ • Move state updates to event handlers
3
+ • Use useEffect/watch for side effects
4
+ • Ensure computed properties don't modify state`),this._value=this.makeReactive(e),o.triggerUpdate(this)}addDependent(e){this.dependents.add(e)}removeDependent(e){this.dependents.delete(e)}getDependents(){return this.dependents}makeReactive(e){return e===null||typeof e!="object"||e instanceof Node||e instanceof Element||e instanceof HTMLElement?e:v.createReactiveProxy(e,()=>o.triggerUpdate(this),s=>this.makeReactive(s))}}function R(n){return o.getOrCreateState(n===void 0?null:n)}function p(n){if(!n||typeof n!="object")return!1;try{const e=Symbol.for("@cer/ReactiveState");return Object.prototype.hasOwnProperty.call(n,e)}catch{return!1}}function W(n){const e=new y(n());return{get value(){return o.trackDependency(e),n()}}}function O(n,e,s){let t;const r=p(n)?()=>n.value:n,a=`watch-${Math.random().toString(36).substr(2,9)}`;try{const c=o.getCurrentComponentId();c&&o.registerWatcher(c,a)}catch{}const i=()=>{o.setCurrentComponent(a,i);const c=r();o.clearCurrentComponent(),c!==t&&(e(c,t),t=c)};return o.setCurrentComponent(a,i),t=r(),o.clearCurrentComponent(),s&&s.immediate&&e(t,void 0),()=>{o.cleanup(a)}}const F=n=>{try{n()}catch{}},f=new Map,g=new Map,m=new Map,C=500;let E,T,S=!1,M=!1,_;const I=!!globalThis.process?.versions?.node;function z(n){if(f.has(n))return f.get(n);const e=n.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();return f.size<C&&f.set(n,e),e}function j(n){if(g.has(n))return g.get(n);const e=n.replace(/-([a-z])/g,(s,t)=>t.toUpperCase());return g.size<C&&g.set(n,e),e}function V(n){if(typeof n=="string"){if(m.has(n))return m.get(n);const e=n.replace(/[&<>"']/g,s=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[s]);return e!==n&&m.size<C&&m.set(n,e),e}return n}function l(n){if(!n)return"";const e=String(n);if(typeof document<"u"&&typeof document.createElement=="function"){const c=e.replace(/</g,"").replace(/>/g,""),u=_||(_=document.createElement("div"));try{l._el=u}catch{}return u.innerHTML=c,(u.textContent||"").replace(new RegExp("","g"),"<").replace(new RegExp("","g"),">")}const s={lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "},t=E??l._namedMap;let r=t;if(!r&&I)try{const a=globalThis.require;if(typeof a=="function"){const i=["@jasonshimmy/custom-elements-runtime/entities.json","../../entities.json","../../../entities.json","../entities.json","./entities.json"];for(const c of i)try{const u=a(c);if(u&&typeof u=="object"){r=u;break}}catch{}}}catch{}if(!r){r=s,S=!0;try{l._usedFallback=!0}catch{}const a=l._namedMapLoader??T;a&&a().then(i=>{E=i;try{l._namedMap=i}catch{}}).catch(()=>{})}if((S||l._usedFallback)&&!(M||l._warnedFallback)){M=!0;try{l._warnedFallback=!0}catch{}try{h.devWarn("decodeEntities: using small SSR fallback entity map. Register the full entities.json via registerEntityMap(entities) on the server to enable full HTML5 named-entity decoding.")}catch{}}return e.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g,(a,i)=>{if(i.charCodeAt(0)===35){const d=(i.charAt(1)||"").toLowerCase()==="x"?parseInt(i.slice(2),16):parseInt(i.slice(1),10);return Number.isNaN(d)?`&${i};`:String.fromCodePoint(d)}const c=r[i]??(t&&t[i]);return c!==void 0?c:`&${i};`})}async function k(){const n=["@jasonshimmy","custom-elements-runtime","entities.json"].join("/");try{const e=await import(n);return e&&(e.default||e)}catch{try{const e=[n,"./entities.json","../../entities.json","../../../entities.json"];for(const s of e)try{const t=await import(s);if(t)return t&&(t.default||t)}catch{}return{lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "}}catch{return{lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "}}}}T=k;l._namedMapLoader=k;function G(n){const e=String(n);return{__unsafeHTML:e,__rawHTML:e}}function q(n){return!!n&&(typeof n.__unsafeHTML=="string"||typeof n.__rawHTML=="string")}function $(n,e){if(typeof e=="string"){if(e==="")return;const s=e.split(".");let t=n;for(const r of s){if(t==null||typeof t!="object"){t=void 0;break}t=t[r]}return p(t)?t.value:t}return e}function K(n,e,s){const t=String(e).split("."),r=t.pop();if(!r)return;const a=t.reduce((i,c)=>(i[c]==null&&(i[c]={}),i[c]),n);p(a[r])?a[r].value=s:a[r]=s}function Z(n){try{if(n&&typeof n=="object"){if(p(n))return n.value;if("value"in n){const e=n.value;return e==null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?e:n}}}catch{}return n}function B(n){const e=Z(n);if(e==null)return null;const s=typeof e;return s==="string"||s==="number"||s==="boolean"?String(e):null}function X(n){if(!n||typeof n!="string")return!1;if(n==="class"||n.endsWith("Class"))return!0;if(n.includes("-"))try{if(n.split("-").some(s=>s==="class"))return!0}catch{}return!1}const L={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"};function J(n,e,s){try{if(!e||!e.includes(":")){n.setAttribute(e,s);return}const t=e.indexOf(":"),r=e.substring(0,t),a=e.substring(t+1),i=L[r];i?n.setAttributeNS(i,a,s):n.setAttribute(e,s)}catch{try{n.setAttribute(e,s)}catch{}}}function Q(n,e){try{if(!e||!e.includes(":")){n.removeAttribute(e);return}const s=e.indexOf(":"),t=e.substring(0,s),r=e.substring(s+1),a=L[t];a?n.removeAttributeNS(a,r):n.removeAttribute(e)}catch{try{n.removeAttribute(e)}catch{}}}const N="http://www.w3.org/2000/svg",Y="http://www.w3.org/1998/Math/MathML",ee={svg:N,math:Y};exports.SVG_NS=N;exports.TAG_NAMESPACE_MAP=ee;exports.computed=W;exports.decodeEntities=l;exports.escapeHTML=V;exports.flushDOMUpdates=H;exports.getNestedValue=$;exports.isClassLikeAttr=X;exports.isReactiveState=p;exports.isUnsafeHTML=q;exports.reactiveSystem=o;exports.ref=R;exports.removeAttributeSmart=Q;exports.safe=F;exports.safeSerializeAttr=B;exports.scheduleDOMUpdate=b;exports.setAttributeSmart=J;exports.setNestedValue=K;exports.toCamel=j;exports.toKebab=z;exports.unsafeHTML=G;exports.watch=O;
5
+ //# sourceMappingURL=namespace-helpers-BCVTzhAO.cjs.map