@vielzeug/wayfinder 3.0.0 → 3.1.0

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.
package/dist/compile.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs");require("./_dev.cjs");const t=require("./path.cjs");function n(n){let r=[],i=(n,a,o,s,c)=>{if(a.index&&a.path!==void 0)throw new e.WayfinderRouteError(`Route "${n}" cannot define both index and path`);if(!a.index&&a.path===void 0)throw new e.WayfinderRouteError(`Route "${n}" must define path or set index: true`);let l=a.index?o:t.normalizePath(a.path?t.joinPaths(o,a.path):o),u=[...s,{dataFn:a.data,name:n,onError:a.onError}],d=[...c,...a.middleware??[]];if(a.children)for(let[e,t]of Object.entries(a.children))i(`${n}.${e}`,t,l,u,d);if(a.redirect!==void 0||!a.children||a.data!==void 0){let e=u[u.length-1];r.push({branchDefs:u,coerceSearch:a.coerceSearch,leaf:e,matcher:t.compilePathMatcher(l),ownMiddleware:d,path:l,redirect:a.redirect})}};for(let[e,t]of Object.entries(n.routes))i(e,t,`/`,[],[]);let a=new Set;for(let t of r){if(a.has(t.leaf.name))throw new e.WayfinderRouteError(`Duplicate route name: "${t.leaf.name}". A top-level route key must not coincide with a nested route's dot-notation name.`);a.add(t.leaf.name)}let o=!1;for(let e of r){let t=e.path===`/*`||e.path.endsWith(`/*`)||e.path.includes(`:`)&&e.path.endsWith(`*`);o&&!t&&`${e.leaf.name}${e.path}`,t&&(o=!0)}return{records:r,routesByName:new Map(r.map(e=>[e.leaf.name,e]))}}exports.compileRoutes=n;
1
+ const e=require("./errors.cjs"),t=require("./path.cjs");require("./_dev.cjs");function n(n){let r=[],i=(n,a,o,s,c)=>{if(a.index&&a.path!==void 0)throw new e.WayfinderRouteError(`Route "${n}" cannot define both index and path`);if(!a.index&&a.path===void 0)throw new e.WayfinderRouteError(`Route "${n}" must define path or set index: true`);let l=a.index?o:t.normalizePath(a.path?t.joinPaths(o,a.path):o),u=[...s,{dataFn:a.data,name:n,onError:a.onError}],d=[...c,...a.middleware??[]];if(a.children)for(let[e,t]of Object.entries(a.children))i(`${n}.${e}`,t,l,u,d);if(a.redirect!==void 0||!a.children||a.data!==void 0){let e=u[u.length-1];r.push({branchDefs:u,coerceSearch:a.coerceSearch,leaf:e,matcher:t.compilePathMatcher(l),ownMiddleware:d,path:l,redirect:a.redirect})}};for(let[e,t]of Object.entries(n.routes))i(e,t,`/`,[],[]);let a=new Set;for(let t of r){if(a.has(t.leaf.name))throw new e.WayfinderRouteError(`Duplicate route name: "${t.leaf.name}". A top-level route key must not coincide with a nested route's dot-notation name.`);a.add(t.leaf.name)}let o=!1;for(let e of r){let t=e.path===`/*`||e.path.endsWith(`/*`)||e.path.includes(`:`)&&e.path.endsWith(`*`);o&&!t&&`${e.leaf.name}${e.path}`,t&&(o=!0)}return{records:r,routesByName:new Map(r.map(e=>[e.leaf.name,e]))}}exports.compileRoutes=n;
2
2
  //# sourceMappingURL=compile.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compile.cjs","names":[],"sources":["../src/compile.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { WayfinderRouteError } from './errors';\nimport { compilePathMatcher, joinPaths, normalizePath } from './path';\nimport type { Middleware, RouteBranchDef, RouteDefinition, RouteRecord, RouterOptions, RouteTable } from './types';\n\nexport type CompiledRoutes = {\n records: readonly RouteRecord[];\n routesByName: ReadonlyMap<string, RouteRecord>;\n};\n\nexport function compileRoutes<TRoutes extends RouteTable>(options: RouterOptions<TRoutes>): CompiledRoutes {\n const records: RouteRecord[] = [];\n\n const compile = (\n name: string,\n route: RouteDefinition,\n ancestorPath: string,\n ancestorBranchDefs: RouteBranchDef[],\n ancestorMiddleware: RouteRecord['ownMiddleware'],\n ): void => {\n if (route.index && route.path !== undefined) {\n throw new WayfinderRouteError(`Route \"${name}\" cannot define both index and path`);\n }\n\n if (!route.index && route.path === undefined) {\n throw new WayfinderRouteError(`Route \"${name}\" must define path or set index: true`);\n }\n\n const ownPath = route.index\n ? ancestorPath\n : normalizePath(route.path ? joinPaths(ancestorPath, route.path) : ancestorPath);\n\n const branchDefs: RouteBranchDef[] = [\n ...ancestorBranchDefs,\n {\n dataFn: route.data,\n name,\n onError: route.onError as RouteBranchDef['onError'],\n },\n ];\n\n const ownMiddleware: Middleware[] = [\n ...ancestorMiddleware,\n ...((route.middleware ?? []) as unknown as Middleware[]),\n ];\n\n if (route.children) {\n for (const [childName, childRoute] of Object.entries(route.children)) {\n compile(`${name}.${childName}`, childRoute, ownPath, branchDefs, ownMiddleware);\n }\n }\n\n // Emit a record for leaf routes (no children) and routes with data or redirect.\n // A bare parent-only route (children but no data/redirect) is not emitted as a leaf.\n if (route.redirect !== undefined || !route.children || route.data !== undefined) {\n const leaf = branchDefs[branchDefs.length - 1]!;\n\n records.push({\n branchDefs,\n coerceSearch: route.coerceSearch,\n leaf,\n matcher: compilePathMatcher(ownPath),\n ownMiddleware,\n path: ownPath,\n redirect: route.redirect,\n });\n }\n };\n\n for (const [name, route] of Object.entries(options.routes)) {\n compile(name, route, '/', [], []);\n }\n\n // Validate duplicate names.\n const namesSeen = new Set<string>();\n\n for (const record of records) {\n if (namesSeen.has(record.leaf.name)) {\n throw new WayfinderRouteError(\n `Duplicate route name: \"${record.leaf.name}\". A top-level route key must not coincide with a nested route's dot-notation name.`,\n );\n }\n\n namesSeen.add(record.leaf.name);\n }\n\n // Warn when a catch-all or wildcard-param route precedes more specific routes.\n // Routes match in array order (object key order), so a wildcard placed too early silently shadows later routes.\n let wildcardSeen = false;\n\n for (const record of records) {\n const isCatchAll =\n record.path === '/*' || record.path.endsWith('/*') || (record.path.includes(':') && record.path.endsWith('*'));\n\n if (wildcardSeen && !isCatchAll) {\n warn(\n `Route \"${record.leaf.name}\" (${record.path}) is defined after a wildcard/catch-all route and will never match. Move specific routes before wildcards.`,\n );\n }\n\n if (isCatchAll) wildcardSeen = true;\n }\n\n return {\n records,\n routesByName: new Map(records.map((r) => [r.leaf.name, r])),\n };\n}\n"],"mappings":"oFAUA,SAAgB,EAA0C,EAAiD,CACzG,IAAM,EAAyB,CAAC,EAE1B,GACJ,EACA,EACA,EACA,EACA,IACS,CACT,GAAI,EAAM,OAAS,EAAM,OAAS,IAAA,GAChC,MAAM,IAAI,EAAA,oBAAoB,UAAU,EAAK,oCAAoC,EAGnF,GAAI,CAAC,EAAM,OAAS,EAAM,OAAS,IAAA,GACjC,MAAM,IAAI,EAAA,oBAAoB,UAAU,EAAK,sCAAsC,EAGrF,IAAM,EAAU,EAAM,MAClB,EACA,EAAA,cAAc,EAAM,KAAO,EAAA,UAAU,EAAc,EAAM,IAAI,EAAI,CAAY,EAE3E,EAA+B,CACnC,GAAG,EACH,CACE,OAAQ,EAAM,KACd,OACA,QAAS,EAAM,OACjB,CACF,EAEM,EAA8B,CAClC,GAAG,EACH,GAAK,EAAM,YAAc,CAAC,CAC5B,EAEA,GAAI,EAAM,SACR,IAAK,GAAM,CAAC,EAAW,KAAe,OAAO,QAAQ,EAAM,QAAQ,EACjE,EAAQ,GAAG,EAAK,GAAG,IAAa,EAAY,EAAS,EAAY,CAAa,EAMlF,GAAI,EAAM,WAAa,IAAA,IAAa,CAAC,EAAM,UAAY,EAAM,OAAS,IAAA,GAAW,CAC/E,IAAM,EAAO,EAAW,EAAW,OAAS,GAE5C,EAAQ,KAAK,CACX,aACA,aAAc,EAAM,aACpB,OACA,QAAS,EAAA,mBAAmB,CAAO,EACnC,gBACA,KAAM,EACN,SAAU,EAAM,QAClB,CAAC,CACH,CACF,EAEA,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,MAAM,EACvD,EAAQ,EAAM,EAAO,IAAK,CAAC,EAAG,CAAC,CAAC,EAIlC,IAAM,EAAY,IAAI,IAEtB,IAAK,IAAM,KAAU,EAAS,CAC5B,GAAI,EAAU,IAAI,EAAO,KAAK,IAAI,EAChC,MAAM,IAAI,EAAA,oBACR,0BAA0B,EAAO,KAAK,KAAK,oFAC7C,EAGF,EAAU,IAAI,EAAO,KAAK,IAAI,CAChC,CAIA,IAAI,EAAe,GAEnB,IAAK,IAAM,KAAU,EAAS,CAC5B,IAAM,EACJ,EAAO,OAAS,MAAQ,EAAO,KAAK,SAAS,IAAI,GAAM,EAAO,KAAK,SAAS,GAAG,GAAK,EAAO,KAAK,SAAS,GAAG,EAE1G,GAAgB,CAAC,GAEjB,GAAU,EAAO,KAAK,KAAtB,EAAgC,EAAO,KAAvC,EAIA,IAAY,EAAe,GACjC,CAEA,MAAO,CACL,UACA,aAAc,IAAI,IAAI,EAAQ,IAAK,GAAM,CAAC,EAAE,KAAK,KAAM,CAAC,CAAC,CAAC,CAC5D,CACF"}
1
+ {"version":3,"file":"compile.cjs","names":[],"sources":["../src/compile.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { WayfinderRouteError } from './errors';\nimport { compilePathMatcher, joinPaths, normalizePath } from './path';\nimport type { Middleware, RouteBranchDef, RouteDefinition, RouteRecord, RouterOptions, RouteTable } from './types';\n\nexport type CompiledRoutes = {\n records: readonly RouteRecord[];\n routesByName: ReadonlyMap<string, RouteRecord>;\n};\n\nexport function compileRoutes<TRoutes extends RouteTable>(options: RouterOptions<TRoutes>): CompiledRoutes {\n const records: RouteRecord[] = [];\n\n const compile = (\n name: string,\n route: RouteDefinition,\n ancestorPath: string,\n ancestorBranchDefs: RouteBranchDef[],\n ancestorMiddleware: RouteRecord['ownMiddleware'],\n ): void => {\n if (route.index && route.path !== undefined) {\n throw new WayfinderRouteError(`Route \"${name}\" cannot define both index and path`);\n }\n\n if (!route.index && route.path === undefined) {\n throw new WayfinderRouteError(`Route \"${name}\" must define path or set index: true`);\n }\n\n const ownPath = route.index\n ? ancestorPath\n : normalizePath(route.path ? joinPaths(ancestorPath, route.path) : ancestorPath);\n\n const branchDefs: RouteBranchDef[] = [\n ...ancestorBranchDefs,\n {\n dataFn: route.data,\n name,\n onError: route.onError as RouteBranchDef['onError'],\n },\n ];\n\n const ownMiddleware: Middleware[] = [\n ...ancestorMiddleware,\n ...((route.middleware ?? []) as unknown as Middleware[]),\n ];\n\n if (route.children) {\n for (const [childName, childRoute] of Object.entries(route.children)) {\n compile(`${name}.${childName}`, childRoute, ownPath, branchDefs, ownMiddleware);\n }\n }\n\n // Emit a record for leaf routes (no children) and routes with data or redirect.\n // A bare parent-only route (children but no data/redirect) is not emitted as a leaf.\n if (route.redirect !== undefined || !route.children || route.data !== undefined) {\n const leaf = branchDefs[branchDefs.length - 1]!;\n\n records.push({\n branchDefs,\n coerceSearch: route.coerceSearch,\n leaf,\n matcher: compilePathMatcher(ownPath),\n ownMiddleware,\n path: ownPath,\n redirect: route.redirect,\n });\n }\n };\n\n for (const [name, route] of Object.entries(options.routes)) {\n compile(name, route, '/', [], []);\n }\n\n // Validate duplicate names.\n const namesSeen = new Set<string>();\n\n for (const record of records) {\n if (namesSeen.has(record.leaf.name)) {\n throw new WayfinderRouteError(\n `Duplicate route name: \"${record.leaf.name}\". A top-level route key must not coincide with a nested route's dot-notation name.`,\n );\n }\n\n namesSeen.add(record.leaf.name);\n }\n\n // Warn when a catch-all or wildcard-param route precedes more specific routes.\n // Routes match in array order (object key order), so a wildcard placed too early silently shadows later routes.\n let wildcardSeen = false;\n\n for (const record of records) {\n const isCatchAll =\n record.path === '/*' || record.path.endsWith('/*') || (record.path.includes(':') && record.path.endsWith('*'));\n\n if (wildcardSeen && !isCatchAll) {\n warn(\n `Route \"${record.leaf.name}\" (${record.path}) is defined after a wildcard/catch-all route and will never match. Move specific routes before wildcards.`,\n );\n }\n\n if (isCatchAll) wildcardSeen = true;\n }\n\n return {\n records,\n routesByName: new Map(records.map((r) => [r.leaf.name, r])),\n };\n}\n"],"mappings":"8EAUA,SAAgB,EAA0C,EAAiD,CACzG,IAAM,EAAyB,CAAC,EAE1B,GACJ,EACA,EACA,EACA,EACA,IACS,CACT,GAAI,EAAM,OAAS,EAAM,OAAS,IAAA,GAChC,MAAM,IAAI,EAAA,oBAAoB,UAAU,EAAK,oCAAoC,EAGnF,GAAI,CAAC,EAAM,OAAS,EAAM,OAAS,IAAA,GACjC,MAAM,IAAI,EAAA,oBAAoB,UAAU,EAAK,sCAAsC,EAGrF,IAAM,EAAU,EAAM,MAClB,EACA,EAAA,cAAc,EAAM,KAAO,EAAA,UAAU,EAAc,EAAM,IAAI,EAAI,CAAY,EAE3E,EAA+B,CACnC,GAAG,EACH,CACE,OAAQ,EAAM,KACd,OACA,QAAS,EAAM,OACjB,CACF,EAEM,EAA8B,CAClC,GAAG,EACH,GAAK,EAAM,YAAc,CAAC,CAC5B,EAEA,GAAI,EAAM,SACR,IAAK,GAAM,CAAC,EAAW,KAAe,OAAO,QAAQ,EAAM,QAAQ,EACjE,EAAQ,GAAG,EAAK,GAAG,IAAa,EAAY,EAAS,EAAY,CAAa,EAMlF,GAAI,EAAM,WAAa,IAAA,IAAa,CAAC,EAAM,UAAY,EAAM,OAAS,IAAA,GAAW,CAC/E,IAAM,EAAO,EAAW,EAAW,OAAS,GAE5C,EAAQ,KAAK,CACX,aACA,aAAc,EAAM,aACpB,OACA,QAAS,EAAA,mBAAmB,CAAO,EACnC,gBACA,KAAM,EACN,SAAU,EAAM,QAClB,CAAC,CACH,CACF,EAEA,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,EAAQ,MAAM,EACvD,EAAQ,EAAM,EAAO,IAAK,CAAC,EAAG,CAAC,CAAC,EAIlC,IAAM,EAAY,IAAI,IAEtB,IAAK,IAAM,KAAU,EAAS,CAC5B,GAAI,EAAU,IAAI,EAAO,KAAK,IAAI,EAChC,MAAM,IAAI,EAAA,oBACR,0BAA0B,EAAO,KAAK,KAAK,oFAC7C,EAGF,EAAU,IAAI,EAAO,KAAK,IAAI,CAChC,CAIA,IAAI,EAAe,GAEnB,IAAK,IAAM,KAAU,EAAS,CAC5B,IAAM,EACJ,EAAO,OAAS,MAAQ,EAAO,KAAK,SAAS,IAAI,GAAM,EAAO,KAAK,SAAS,GAAG,GAAK,EAAO,KAAK,SAAS,GAAG,EAE1G,GAAgB,CAAC,GAEjB,GAAU,EAAO,KAAK,KAAtB,EAAgC,EAAO,KAAvC,EAIA,IAAY,EAAe,GACjC,CAEA,MAAO,CACL,UACA,aAAc,IAAI,IAAI,EAAQ,IAAK,GAAM,CAAC,EAAE,KAAK,KAAM,CAAC,CAAC,CAAC,CAC5D,CACF"}
package/dist/compile.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { WayfinderRouteError as e } from "./errors.js";
2
- import "./_dev.js";
3
2
  import { compilePathMatcher as t, joinPaths as n, normalizePath as r } from "./path.js";
3
+ import "./_dev.js";
4
4
  //#region src/compile.ts
5
5
  function i(i) {
6
6
  let a = [], o = (i, s, c, l, u) => {
package/dist/history.cjs CHANGED
@@ -1,2 +1,2 @@
1
- function e(){return{back(){window.history.back()},get location(){return{hash:window.location.hash,pathname:window.location.pathname,search:window.location.search,state:window.history.state}},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,e)},replace(e,t){window.history.replaceState(t,``,e)}}}function t(e=`/`){let t=new URL(e,`http://localhost`),n=[{hash:t.hash,pathname:t.pathname,search:t.search,state:null}],r=0,i=new Set;return{back(){r<=0||(--r,i.forEach(e=>{e()}))},get location(){return n[r]},onPopstate(e){return i.add(e),()=>i.delete(e)},push(e,t=null){let i=new URL(e,`http://localhost`);n.splice(r+1),n.push({hash:i.hash,pathname:i.pathname,search:i.search,state:t}),r=n.length-1},replace(e,t=null){let i=new URL(e,`http://localhost`);n[r]={hash:i.hash,pathname:i.pathname,search:i.search,state:t}}}}exports.createBrowserHistory=e,exports.createMemoryHistory=t;
1
+ const e=require("./path.cjs");function t(){return{back(){window.history.back()},get location(){return{hash:window.location.hash,pathname:window.location.pathname,search:window.location.search,state:window.history.state}},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,e)},replace(e,t){window.history.replaceState(t,``,e)}}}function n(t={}){let n=e.normalizePath(t.base??`/`),r=n===`/`?`/`:`${n}/`,i=()=>{let t=new URL(window.location.hash.slice(1)||`/`,`http://localhost`);return{hash:t.hash,pathname:e.joinPaths(n,t.pathname),search:t.search,state:window.history.state}},a=t=>{let i=new URL(t,`http://localhost`),a=e.stripBase(i.pathname,n);return`${r}#${a}${i.search}${i.hash}`};return{back(){window.history.back()},get location(){return i()},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,a(e))},replace(e,t){window.history.replaceState(t,``,a(e))}}}function r(e=`/`){let t=new URL(e,`http://localhost`),n=[{hash:t.hash,pathname:t.pathname,search:t.search,state:null}],r=0,i=new Set;return{back(){r<=0||(--r,i.forEach(e=>{e()}))},get location(){return n[r]},onPopstate(e){return i.add(e),()=>i.delete(e)},push(e,t=null){let i=new URL(e,`http://localhost`);n.splice(r+1),n.push({hash:i.hash,pathname:i.pathname,search:i.search,state:t}),r=n.length-1},replace(e,t=null){let i=new URL(e,`http://localhost`);n[r]={hash:i.hash,pathname:i.pathname,search:i.search,state:t}}}}exports.createBrowserHistory=t,exports.createHashHistory=n,exports.createMemoryHistory=r;
2
2
  //# sourceMappingURL=history.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"history.cjs","names":[],"sources":["../src/history.ts"],"sourcesContent":["import type { HistoryDriver } from './types';\n\n/** Creates a history driver backed by the browser History API. */\nexport function createBrowserHistory(): HistoryDriver {\n return {\n back() {\n window.history.back();\n },\n get location() {\n return {\n hash: window.location.hash,\n pathname: window.location.pathname,\n search: window.location.search,\n // State lives on window.history.state, not window.location.\n state: window.history.state,\n };\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', url);\n },\n replace(url, state) {\n window.history.replaceState(state, '', url);\n },\n };\n}\n\ntype MemoryLocation = { hash: string; pathname: string; search: string; state: unknown };\n\n/**\n * Creates an in-memory history driver. Suitable for SSR, tests, and non-browser environments.\n *\n * Semantics mirror the browser History API:\n * - `push()` and `replace()` update the location silently (no listener notification),\n * matching `pushState`/`replaceState` which do not fire `popstate`.\n * - `back()` moves one entry back and notifies subscribers, matching a browser back-button press.\n */\nexport function createMemoryHistory(initialPath = '/'): HistoryDriver {\n const parsed = new URL(initialPath, 'http://localhost');\n const stack: MemoryLocation[] = [\n { hash: parsed.hash, pathname: parsed.pathname, search: parsed.search, state: null },\n ];\n let cursor = 0;\n const listeners = new Set<() => void>();\n\n return {\n back() {\n if (cursor <= 0) return;\n\n cursor -= 1;\n listeners.forEach((l) => {\n l();\n });\n },\n get location(): MemoryLocation {\n return stack[cursor]!;\n },\n onPopstate(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n push(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack.splice(cursor + 1);\n stack.push({ hash: p.hash, pathname: p.pathname, search: p.search, state });\n cursor = stack.length - 1;\n // Silent — mirrors browser pushState semantics. Router drives navigation via #handleRoute directly.\n },\n replace(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack[cursor] = { hash: p.hash, pathname: p.pathname, search: p.search, state };\n // Silent — mirrors browser replaceState semantics.\n },\n };\n}\n"],"mappings":"AAGA,SAAgB,GAAsC,CACpD,MAAO,CACL,MAAO,CACL,OAAO,QAAQ,KAAK,CACtB,EACA,IAAI,UAAW,CACb,MAAO,CACL,KAAM,OAAO,SAAS,KACtB,SAAU,OAAO,SAAS,SAC1B,OAAQ,OAAO,SAAS,OAExB,MAAO,OAAO,QAAQ,KACxB,CACF,EACA,WAAW,EAAU,CAGnB,OAFA,OAAO,iBAAiB,WAAY,CAAQ,MAE/B,OAAO,oBAAoB,WAAY,CAAQ,CAC9D,EACA,KAAK,EAAK,EAAO,CACf,OAAO,QAAQ,UAAU,EAAO,GAAI,CAAG,CACzC,EACA,QAAQ,EAAK,EAAO,CAClB,OAAO,QAAQ,aAAa,EAAO,GAAI,CAAG,CAC5C,CACF,CACF,CAYA,SAAgB,EAAoB,EAAc,IAAoB,CACpE,IAAM,EAAS,IAAI,IAAI,EAAa,kBAAkB,EAChD,EAA0B,CAC9B,CAAE,KAAM,EAAO,KAAM,SAAU,EAAO,SAAU,OAAQ,EAAO,OAAQ,MAAO,IAAK,CACrF,EACI,EAAS,EACP,EAAY,IAAI,IAEtB,MAAO,CACL,MAAO,CACD,GAAU,IAEd,IACA,EAAU,QAAS,GAAM,CACvB,EAAE,CACJ,CAAC,EACH,EACA,IAAI,UAA2B,CAC7B,OAAO,EAAM,EACf,EACA,WAAW,EAAU,CAGnB,OAFA,EAAU,IAAI,CAAQ,MAET,EAAU,OAAO,CAAQ,CACxC,EACA,KAAK,EAAK,EAAQ,KAAM,CACtB,IAAM,EAAI,IAAI,IAAI,EAAK,kBAAkB,EAEzC,EAAM,OAAO,EAAS,CAAC,EACvB,EAAM,KAAK,CAAE,KAAM,EAAE,KAAM,SAAU,EAAE,SAAU,OAAQ,EAAE,OAAQ,OAAM,CAAC,EAC1E,EAAS,EAAM,OAAS,CAE1B,EACA,QAAQ,EAAK,EAAQ,KAAM,CACzB,IAAM,EAAI,IAAI,IAAI,EAAK,kBAAkB,EAEzC,EAAM,GAAU,CAAE,KAAM,EAAE,KAAM,SAAU,EAAE,SAAU,OAAQ,EAAE,OAAQ,OAAM,CAEhF,CACF,CACF"}
1
+ {"version":3,"file":"history.cjs","names":[],"sources":["../src/history.ts"],"sourcesContent":["import { joinPaths, normalizePath, stripBase } from './path';\nimport type { HistoryDriver } from './types';\n\n/** Creates a history driver backed by the browser History API. */\nexport function createBrowserHistory(): HistoryDriver {\n return {\n back() {\n window.history.back();\n },\n get location() {\n return {\n hash: window.location.hash,\n pathname: window.location.pathname,\n search: window.location.search,\n // State lives on window.history.state, not window.location.\n state: window.history.state,\n };\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', url);\n },\n replace(url, state) {\n window.history.replaceState(state, '', url);\n },\n };\n}\n\nexport type HashHistoryOptions = { base?: string };\n\nexport function createHashHistory(options: HashHistoryOptions = {}): HistoryDriver {\n const base = normalizePath(options.base ?? '/');\n const baseRoot = base === '/' ? '/' : `${base}/`;\n const location = () => {\n const parsed = new URL(window.location.hash.slice(1) || '/', 'http://localhost');\n\n return {\n hash: parsed.hash,\n pathname: joinPaths(base, parsed.pathname),\n search: parsed.search,\n state: window.history.state,\n };\n };\n const destination = (url: string) => {\n const parsed = new URL(url, 'http://localhost');\n const pathname = stripBase(parsed.pathname, base);\n\n return `${baseRoot}#${pathname}${parsed.search}${parsed.hash}`;\n };\n\n return {\n back() {\n window.history.back();\n },\n get location() {\n return location();\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', destination(url));\n },\n replace(url, state) {\n window.history.replaceState(state, '', destination(url));\n },\n };\n}\n\ntype MemoryLocation = { hash: string; pathname: string; search: string; state: unknown };\n\n/**\n * Creates an in-memory history driver. Suitable for SSR, tests, and non-browser environments.\n *\n * Semantics mirror the browser History API:\n * - `push()` and `replace()` update the location silently (no listener notification),\n * matching `pushState`/`replaceState` which do not fire `popstate`.\n * - `back()` moves one entry back and notifies subscribers, matching a browser back-button press.\n */\nexport function createMemoryHistory(initialPath = '/'): HistoryDriver {\n const parsed = new URL(initialPath, 'http://localhost');\n const stack: MemoryLocation[] = [\n { hash: parsed.hash, pathname: parsed.pathname, search: parsed.search, state: null },\n ];\n let cursor = 0;\n const listeners = new Set<() => void>();\n\n return {\n back() {\n if (cursor <= 0) return;\n\n cursor -= 1;\n listeners.forEach((l) => {\n l();\n });\n },\n get location(): MemoryLocation {\n return stack[cursor]!;\n },\n onPopstate(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n push(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack.splice(cursor + 1);\n stack.push({ hash: p.hash, pathname: p.pathname, search: p.search, state });\n cursor = stack.length - 1;\n // Silent — mirrors browser pushState semantics. Router drives navigation via #handleRoute directly.\n },\n replace(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack[cursor] = { hash: p.hash, pathname: p.pathname, search: p.search, state };\n // Silent — mirrors browser replaceState semantics.\n },\n };\n}\n"],"mappings":"8BAIA,SAAgB,GAAsC,CACpD,MAAO,CACL,MAAO,CACL,OAAO,QAAQ,KAAK,CACtB,EACA,IAAI,UAAW,CACb,MAAO,CACL,KAAM,OAAO,SAAS,KACtB,SAAU,OAAO,SAAS,SAC1B,OAAQ,OAAO,SAAS,OAExB,MAAO,OAAO,QAAQ,KACxB,CACF,EACA,WAAW,EAAU,CAGnB,OAFA,OAAO,iBAAiB,WAAY,CAAQ,MAE/B,OAAO,oBAAoB,WAAY,CAAQ,CAC9D,EACA,KAAK,EAAK,EAAO,CACf,OAAO,QAAQ,UAAU,EAAO,GAAI,CAAG,CACzC,EACA,QAAQ,EAAK,EAAO,CAClB,OAAO,QAAQ,aAAa,EAAO,GAAI,CAAG,CAC5C,CACF,CACF,CAIA,SAAgB,EAAkB,EAA8B,CAAC,EAAkB,CACjF,IAAM,EAAO,EAAA,cAAc,EAAQ,MAAQ,GAAG,EACxC,EAAW,IAAS,IAAM,IAAM,GAAG,EAAK,GACxC,MAAiB,CACrB,IAAM,EAAS,IAAI,IAAI,OAAO,SAAS,KAAK,MAAM,CAAC,GAAK,IAAK,kBAAkB,EAE/E,MAAO,CACL,KAAM,EAAO,KACb,SAAU,EAAA,UAAU,EAAM,EAAO,QAAQ,EACzC,OAAQ,EAAO,OACf,MAAO,OAAO,QAAQ,KACxB,CACF,EACM,EAAe,GAAgB,CACnC,IAAM,EAAS,IAAI,IAAI,EAAK,kBAAkB,EACxC,EAAW,EAAA,UAAU,EAAO,SAAU,CAAI,EAEhD,MAAO,GAAG,EAAS,GAAG,IAAW,EAAO,SAAS,EAAO,MAC1D,EAEA,MAAO,CACL,MAAO,CACL,OAAO,QAAQ,KAAK,CACtB,EACA,IAAI,UAAW,CACb,OAAO,EAAS,CAClB,EACA,WAAW,EAAU,CAGnB,OAFA,OAAO,iBAAiB,WAAY,CAAQ,MAE/B,OAAO,oBAAoB,WAAY,CAAQ,CAC9D,EACA,KAAK,EAAK,EAAO,CACf,OAAO,QAAQ,UAAU,EAAO,GAAI,EAAY,CAAG,CAAC,CACtD,EACA,QAAQ,EAAK,EAAO,CAClB,OAAO,QAAQ,aAAa,EAAO,GAAI,EAAY,CAAG,CAAC,CACzD,CACF,CACF,CAYA,SAAgB,EAAoB,EAAc,IAAoB,CACpE,IAAM,EAAS,IAAI,IAAI,EAAa,kBAAkB,EAChD,EAA0B,CAC9B,CAAE,KAAM,EAAO,KAAM,SAAU,EAAO,SAAU,OAAQ,EAAO,OAAQ,MAAO,IAAK,CACrF,EACI,EAAS,EACP,EAAY,IAAI,IAEtB,MAAO,CACL,MAAO,CACD,GAAU,IAEd,IACA,EAAU,QAAS,GAAM,CACvB,EAAE,CACJ,CAAC,EACH,EACA,IAAI,UAA2B,CAC7B,OAAO,EAAM,EACf,EACA,WAAW,EAAU,CAGnB,OAFA,EAAU,IAAI,CAAQ,MAET,EAAU,OAAO,CAAQ,CACxC,EACA,KAAK,EAAK,EAAQ,KAAM,CACtB,IAAM,EAAI,IAAI,IAAI,EAAK,kBAAkB,EAEzC,EAAM,OAAO,EAAS,CAAC,EACvB,EAAM,KAAK,CAAE,KAAM,EAAE,KAAM,SAAU,EAAE,SAAU,OAAQ,EAAE,OAAQ,OAAM,CAAC,EAC1E,EAAS,EAAM,OAAS,CAE1B,EACA,QAAQ,EAAK,EAAQ,KAAM,CACzB,IAAM,EAAI,IAAI,IAAI,EAAK,kBAAkB,EAEzC,EAAM,GAAU,CAAE,KAAM,EAAE,KAAM,SAAU,EAAE,SAAU,OAAQ,EAAE,OAAQ,OAAM,CAEhF,CACF,CACF"}
package/dist/history.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import type { HistoryDriver } from './types';
2
2
  /** Creates a history driver backed by the browser History API. */
3
3
  export declare function createBrowserHistory(): HistoryDriver;
4
+ export type HashHistoryOptions = {
5
+ base?: string;
6
+ };
7
+ export declare function createHashHistory(options?: HashHistoryOptions): HistoryDriver;
4
8
  /**
5
9
  * Creates an in-memory history driver. Suitable for SSR, tests, and non-browser environments.
6
10
  *
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,kEAAkE;AAClE,wBAAgB,oBAAoB,IAAI,aAAa,CA0BpD;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAM,GAAG,aAAa,CAwCpE"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,kEAAkE;AAClE,wBAAgB,oBAAoB,IAAI,aAAa,CA0BpD;AAED,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,aAAa,CAuCjF;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAM,GAAG,aAAa,CAwCpE"}
package/dist/history.js CHANGED
@@ -1,5 +1,6 @@
1
+ import { joinPaths as e, normalizePath as t, stripBase as n } from "./path.js";
1
2
  //#region src/history.ts
2
- function e() {
3
+ function r() {
3
4
  return {
4
5
  back() {
5
6
  window.history.back();
@@ -23,7 +24,38 @@ function e() {
23
24
  }
24
25
  };
25
26
  }
26
- function t(e = "/") {
27
+ function i(r = {}) {
28
+ let i = t(r.base ?? "/"), a = i === "/" ? "/" : `${i}/`, o = () => {
29
+ let t = new URL(window.location.hash.slice(1) || "/", "http://localhost");
30
+ return {
31
+ hash: t.hash,
32
+ pathname: e(i, t.pathname),
33
+ search: t.search,
34
+ state: window.history.state
35
+ };
36
+ }, s = (e) => {
37
+ let t = new URL(e, "http://localhost"), r = n(t.pathname, i);
38
+ return `${a}#${r}${t.search}${t.hash}`;
39
+ };
40
+ return {
41
+ back() {
42
+ window.history.back();
43
+ },
44
+ get location() {
45
+ return o();
46
+ },
47
+ onPopstate(e) {
48
+ return window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
49
+ },
50
+ push(e, t) {
51
+ window.history.pushState(t, "", s(e));
52
+ },
53
+ replace(e, t) {
54
+ window.history.replaceState(t, "", s(e));
55
+ }
56
+ };
57
+ }
58
+ function a(e = "/") {
27
59
  let t = new URL(e, "http://localhost"), n = [{
28
60
  hash: t.hash,
29
61
  pathname: t.pathname,
@@ -63,6 +95,6 @@ function t(e = "/") {
63
95
  };
64
96
  }
65
97
  //#endregion
66
- export { e as createBrowserHistory, t as createMemoryHistory };
98
+ export { r as createBrowserHistory, i as createHashHistory, a as createMemoryHistory };
67
99
 
68
100
  //# sourceMappingURL=history.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","names":[],"sources":["../src/history.ts"],"sourcesContent":["import type { HistoryDriver } from './types';\n\n/** Creates a history driver backed by the browser History API. */\nexport function createBrowserHistory(): HistoryDriver {\n return {\n back() {\n window.history.back();\n },\n get location() {\n return {\n hash: window.location.hash,\n pathname: window.location.pathname,\n search: window.location.search,\n // State lives on window.history.state, not window.location.\n state: window.history.state,\n };\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', url);\n },\n replace(url, state) {\n window.history.replaceState(state, '', url);\n },\n };\n}\n\ntype MemoryLocation = { hash: string; pathname: string; search: string; state: unknown };\n\n/**\n * Creates an in-memory history driver. Suitable for SSR, tests, and non-browser environments.\n *\n * Semantics mirror the browser History API:\n * - `push()` and `replace()` update the location silently (no listener notification),\n * matching `pushState`/`replaceState` which do not fire `popstate`.\n * - `back()` moves one entry back and notifies subscribers, matching a browser back-button press.\n */\nexport function createMemoryHistory(initialPath = '/'): HistoryDriver {\n const parsed = new URL(initialPath, 'http://localhost');\n const stack: MemoryLocation[] = [\n { hash: parsed.hash, pathname: parsed.pathname, search: parsed.search, state: null },\n ];\n let cursor = 0;\n const listeners = new Set<() => void>();\n\n return {\n back() {\n if (cursor <= 0) return;\n\n cursor -= 1;\n listeners.forEach((l) => {\n l();\n });\n },\n get location(): MemoryLocation {\n return stack[cursor]!;\n },\n onPopstate(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n push(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack.splice(cursor + 1);\n stack.push({ hash: p.hash, pathname: p.pathname, search: p.search, state });\n cursor = stack.length - 1;\n // Silent — mirrors browser pushState semantics. Router drives navigation via #handleRoute directly.\n },\n replace(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack[cursor] = { hash: p.hash, pathname: p.pathname, search: p.search, state };\n // Silent — mirrors browser replaceState semantics.\n },\n };\n}\n"],"mappings":";AAGA,SAAgB,IAAsC;CACpD,OAAO;EACL,OAAO;GACL,OAAO,QAAQ,KAAK;EACtB;EACA,IAAI,WAAW;GACb,OAAO;IACL,MAAM,OAAO,SAAS;IACtB,UAAU,OAAO,SAAS;IAC1B,QAAQ,OAAO,SAAS;IAExB,OAAO,OAAO,QAAQ;GACxB;EACF;EACA,WAAW,GAAU;GAGnB,OAFA,OAAO,iBAAiB,YAAY,CAAQ,SAE/B,OAAO,oBAAoB,YAAY,CAAQ;EAC9D;EACA,KAAK,GAAK,GAAO;GACf,OAAO,QAAQ,UAAU,GAAO,IAAI,CAAG;EACzC;EACA,QAAQ,GAAK,GAAO;GAClB,OAAO,QAAQ,aAAa,GAAO,IAAI,CAAG;EAC5C;CACF;AACF;AAYA,SAAgB,EAAoB,IAAc,KAAoB;CACpE,IAAM,IAAS,IAAI,IAAI,GAAa,kBAAkB,GAChD,IAA0B,CAC9B;EAAE,MAAM,EAAO;EAAM,UAAU,EAAO;EAAU,QAAQ,EAAO;EAAQ,OAAO;CAAK,CACrF,GACI,IAAS,GACP,oBAAY,IAAI,IAAgB;CAEtC,OAAO;EACL,OAAO;GACD,KAAU,MAEd,KACA,EAAU,SAAS,MAAM;IACvB,EAAE;GACJ,CAAC;EACH;EACA,IAAI,WAA2B;GAC7B,OAAO,EAAM;EACf;EACA,WAAW,GAAU;GAGnB,OAFA,EAAU,IAAI,CAAQ,SAET,EAAU,OAAO,CAAQ;EACxC;EACA,KAAK,GAAK,IAAQ,MAAM;GACtB,IAAM,IAAI,IAAI,IAAI,GAAK,kBAAkB;GAIzC,AAFA,EAAM,OAAO,IAAS,CAAC,GACvB,EAAM,KAAK;IAAE,MAAM,EAAE;IAAM,UAAU,EAAE;IAAU,QAAQ,EAAE;IAAQ;GAAM,CAAC,GAC1E,IAAS,EAAM,SAAS;EAE1B;EACA,QAAQ,GAAK,IAAQ,MAAM;GACzB,IAAM,IAAI,IAAI,IAAI,GAAK,kBAAkB;GAEzC,EAAM,KAAU;IAAE,MAAM,EAAE;IAAM,UAAU,EAAE;IAAU,QAAQ,EAAE;IAAQ;GAAM;EAEhF;CACF;AACF"}
1
+ {"version":3,"file":"history.js","names":[],"sources":["../src/history.ts"],"sourcesContent":["import { joinPaths, normalizePath, stripBase } from './path';\nimport type { HistoryDriver } from './types';\n\n/** Creates a history driver backed by the browser History API. */\nexport function createBrowserHistory(): HistoryDriver {\n return {\n back() {\n window.history.back();\n },\n get location() {\n return {\n hash: window.location.hash,\n pathname: window.location.pathname,\n search: window.location.search,\n // State lives on window.history.state, not window.location.\n state: window.history.state,\n };\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', url);\n },\n replace(url, state) {\n window.history.replaceState(state, '', url);\n },\n };\n}\n\nexport type HashHistoryOptions = { base?: string };\n\nexport function createHashHistory(options: HashHistoryOptions = {}): HistoryDriver {\n const base = normalizePath(options.base ?? '/');\n const baseRoot = base === '/' ? '/' : `${base}/`;\n const location = () => {\n const parsed = new URL(window.location.hash.slice(1) || '/', 'http://localhost');\n\n return {\n hash: parsed.hash,\n pathname: joinPaths(base, parsed.pathname),\n search: parsed.search,\n state: window.history.state,\n };\n };\n const destination = (url: string) => {\n const parsed = new URL(url, 'http://localhost');\n const pathname = stripBase(parsed.pathname, base);\n\n return `${baseRoot}#${pathname}${parsed.search}${parsed.hash}`;\n };\n\n return {\n back() {\n window.history.back();\n },\n get location() {\n return location();\n },\n onPopstate(listener) {\n window.addEventListener('popstate', listener);\n\n return () => window.removeEventListener('popstate', listener);\n },\n push(url, state) {\n window.history.pushState(state, '', destination(url));\n },\n replace(url, state) {\n window.history.replaceState(state, '', destination(url));\n },\n };\n}\n\ntype MemoryLocation = { hash: string; pathname: string; search: string; state: unknown };\n\n/**\n * Creates an in-memory history driver. Suitable for SSR, tests, and non-browser environments.\n *\n * Semantics mirror the browser History API:\n * - `push()` and `replace()` update the location silently (no listener notification),\n * matching `pushState`/`replaceState` which do not fire `popstate`.\n * - `back()` moves one entry back and notifies subscribers, matching a browser back-button press.\n */\nexport function createMemoryHistory(initialPath = '/'): HistoryDriver {\n const parsed = new URL(initialPath, 'http://localhost');\n const stack: MemoryLocation[] = [\n { hash: parsed.hash, pathname: parsed.pathname, search: parsed.search, state: null },\n ];\n let cursor = 0;\n const listeners = new Set<() => void>();\n\n return {\n back() {\n if (cursor <= 0) return;\n\n cursor -= 1;\n listeners.forEach((l) => {\n l();\n });\n },\n get location(): MemoryLocation {\n return stack[cursor]!;\n },\n onPopstate(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n push(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack.splice(cursor + 1);\n stack.push({ hash: p.hash, pathname: p.pathname, search: p.search, state });\n cursor = stack.length - 1;\n // Silent — mirrors browser pushState semantics. Router drives navigation via #handleRoute directly.\n },\n replace(url, state = null) {\n const p = new URL(url, 'http://localhost');\n\n stack[cursor] = { hash: p.hash, pathname: p.pathname, search: p.search, state };\n // Silent — mirrors browser replaceState semantics.\n },\n };\n}\n"],"mappings":";;AAIA,SAAgB,IAAsC;CACpD,OAAO;EACL,OAAO;GACL,OAAO,QAAQ,KAAK;EACtB;EACA,IAAI,WAAW;GACb,OAAO;IACL,MAAM,OAAO,SAAS;IACtB,UAAU,OAAO,SAAS;IAC1B,QAAQ,OAAO,SAAS;IAExB,OAAO,OAAO,QAAQ;GACxB;EACF;EACA,WAAW,GAAU;GAGnB,OAFA,OAAO,iBAAiB,YAAY,CAAQ,SAE/B,OAAO,oBAAoB,YAAY,CAAQ;EAC9D;EACA,KAAK,GAAK,GAAO;GACf,OAAO,QAAQ,UAAU,GAAO,IAAI,CAAG;EACzC;EACA,QAAQ,GAAK,GAAO;GAClB,OAAO,QAAQ,aAAa,GAAO,IAAI,CAAG;EAC5C;CACF;AACF;AAIA,SAAgB,EAAkB,IAA8B,CAAC,GAAkB;CACjF,IAAM,IAAO,EAAc,EAAQ,QAAQ,GAAG,GACxC,IAAW,MAAS,MAAM,MAAM,GAAG,EAAK,IACxC,UAAiB;EACrB,IAAM,IAAS,IAAI,IAAI,OAAO,SAAS,KAAK,MAAM,CAAC,KAAK,KAAK,kBAAkB;EAE/E,OAAO;GACL,MAAM,EAAO;GACb,UAAU,EAAU,GAAM,EAAO,QAAQ;GACzC,QAAQ,EAAO;GACf,OAAO,OAAO,QAAQ;EACxB;CACF,GACM,KAAe,MAAgB;EACnC,IAAM,IAAS,IAAI,IAAI,GAAK,kBAAkB,GACxC,IAAW,EAAU,EAAO,UAAU,CAAI;EAEhD,OAAO,GAAG,EAAS,GAAG,IAAW,EAAO,SAAS,EAAO;CAC1D;CAEA,OAAO;EACL,OAAO;GACL,OAAO,QAAQ,KAAK;EACtB;EACA,IAAI,WAAW;GACb,OAAO,EAAS;EAClB;EACA,WAAW,GAAU;GAGnB,OAFA,OAAO,iBAAiB,YAAY,CAAQ,SAE/B,OAAO,oBAAoB,YAAY,CAAQ;EAC9D;EACA,KAAK,GAAK,GAAO;GACf,OAAO,QAAQ,UAAU,GAAO,IAAI,EAAY,CAAG,CAAC;EACtD;EACA,QAAQ,GAAK,GAAO;GAClB,OAAO,QAAQ,aAAa,GAAO,IAAI,EAAY,CAAG,CAAC;EACzD;CACF;AACF;AAYA,SAAgB,EAAoB,IAAc,KAAoB;CACpE,IAAM,IAAS,IAAI,IAAI,GAAa,kBAAkB,GAChD,IAA0B,CAC9B;EAAE,MAAM,EAAO;EAAM,UAAU,EAAO;EAAU,QAAQ,EAAO;EAAQ,OAAO;CAAK,CACrF,GACI,IAAS,GACP,oBAAY,IAAI,IAAgB;CAEtC,OAAO;EACL,OAAO;GACD,KAAU,MAEd,KACA,EAAU,SAAS,MAAM;IACvB,EAAE;GACJ,CAAC;EACH;EACA,IAAI,WAA2B;GAC7B,OAAO,EAAM;EACf;EACA,WAAW,GAAU;GAGnB,OAFA,EAAU,IAAI,CAAQ,SAET,EAAU,OAAO,CAAQ;EACxC;EACA,KAAK,GAAK,IAAQ,MAAM;GACtB,IAAM,IAAI,IAAI,IAAI,GAAK,kBAAkB;GAIzC,AAFA,EAAM,OAAO,IAAS,CAAC,GACvB,EAAM,KAAK;IAAE,MAAM,EAAE;IAAM,UAAU,EAAE;IAAU,QAAQ,EAAE;IAAQ;GAAM,CAAC,GAC1E,IAAS,EAAM,SAAS;EAE1B;EACA,QAAQ,GAAK,IAAQ,MAAM;GACzB,IAAM,IAAI,IAAI,IAAI,GAAK,kBAAkB;GAEzC,EAAM,KAAU;IAAE,MAAM,EAAE;IAAM,UAAU,EAAE;IAAU,QAAQ,EAAE;IAAQ;GAAM;EAEhF;CACF;AACF"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./history.cjs"),n=require("./middleware.cjs"),r=require("./router.cjs");exports.WayfinderApiError=e.WayfinderApiError,exports.WayfinderDisposedError=e.WayfinderDisposedError,exports.WayfinderError=e.WayfinderError,exports.WayfinderRedirectLoopError=e.WayfinderRedirectLoopError,exports.WayfinderRouteError=e.WayfinderRouteError,exports.createBrowserHistory=t.createBrowserHistory,exports.createMemoryHistory=t.createMemoryHistory,exports.createRouter=r.createRouter,exports.redirectTo=n.redirectTo;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./history.cjs"),n=require("./middleware.cjs"),r=require("./router.cjs");exports.WayfinderApiError=e.WayfinderApiError,exports.WayfinderDisposedError=e.WayfinderDisposedError,exports.WayfinderError=e.WayfinderError,exports.WayfinderRedirectLoopError=e.WayfinderRedirectLoopError,exports.WayfinderRouteError=e.WayfinderRouteError,exports.createBrowserHistory=t.createBrowserHistory,exports.createHashHistory=t.createHashHistory,exports.createMemoryHistory=t.createMemoryHistory,exports.createRouter=r.createRouter,exports.redirectTo=n.redirectTo;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { WayfinderApiError, WayfinderDisposedError, WayfinderError, WayfinderRedirectLoopError, WayfinderRouteError, } from './errors';
2
- export { createBrowserHistory, createMemoryHistory } from './history';
2
+ export { createBrowserHistory, createHashHistory, createMemoryHistory, type HashHistoryOptions } from './history';
3
3
  export { redirectTo } from './middleware';
4
4
  export type { Router } from './router';
5
5
  export { createRouter } from './router';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,EACd,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,MAAM,EACN,aAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,WAAW,EACX,4BAA4B,GAC7B,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,EACd,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAClH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,MAAM,EACN,aAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,WAAW,EACX,4BAA4B,GAC7B,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WayfinderApiError as e, WayfinderDisposedError as t, WayfinderError as n, WayfinderRedirectLoopError as r, WayfinderRouteError as i } from "./errors.js";
2
- import { createBrowserHistory as a, createMemoryHistory as o } from "./history.js";
3
- import { redirectTo as s } from "./middleware.js";
4
- import { createRouter as c } from "./router.js";
5
- export { e as WayfinderApiError, t as WayfinderDisposedError, n as WayfinderError, r as WayfinderRedirectLoopError, i as WayfinderRouteError, a as createBrowserHistory, o as createMemoryHistory, c as createRouter, s as redirectTo };
2
+ import { createBrowserHistory as a, createHashHistory as o, createMemoryHistory as s } from "./history.js";
3
+ import { redirectTo as c } from "./middleware.js";
4
+ import { createRouter as l } from "./router.js";
5
+ export { e as WayfinderApiError, t as WayfinderDisposedError, n as WayfinderError, r as WayfinderRedirectLoopError, i as WayfinderRouteError, a as createBrowserHistory, o as createHashHistory, s as createMemoryHistory, l as createRouter, c as redirectTo };
package/dist/router.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./history.cjs"),n=require("./_navigation.cjs"),r=require("./path.cjs"),i=require("./compile.cjs"),a=require("./context.cjs"),o=require("./guards.cjs");function s(t,n){let r=n.get(t);if(r)return r;let i=[...n.keys()].join(`, `);throw new e.WayfinderRouteError(i?`Unknown route name: ${t}. Available routes: ${i}`:`Unknown route name: ${t}`)}function c(e,t,n=`/`){if(`path`in e)return e.path;let i=s(e.name,t),a=r.buildUrl(n,i.path,e.params,e.query);return e.hash?`${a}#${e.hash}`:a}var l=Symbol(`wayfinder.routerError`);function u(e,t){return{[l]:!0,context:t,error:e}}function d(e){return typeof e==`object`&&!!e&&l in e}function f(e){throw d(e)?e.error:e}var p=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l=new Set;#u=n.createNavigationCoordinator();#d;#f=!1;#p=new AbortController;#m=`/`;#h=new Set;#g=new Map;#_=new Map;#v;#y;ready;constructor(e){let n=i.compileRoutes(e);if(this.#e=r.normalizePath(e.base??`/`),this.#t=e.middleware??[],this.#n=e.coerceSearch,this.#r=e.history??t.createBrowserHistory(),this.#o=e.onError,this.#s=e.scroll,this.#c=e.viewTransition??!1,this.#i=n.records,this.#a=n.routesByName,this.#d=a.createRouteState({location:{hash:``,historyState:null,pathname:`/`,query:{}},matches:[],status:`idle`}),e.notFound){let t=e.notFound,n={dataFn:t.data,name:`__notFound__`};this.#v={branchDefs:[n],leaf:n,matcher:{paramNames:[],pattern:/(?:)/,prefixPattern:/(?:)/},ownMiddleware:t.middleware??[],path:`/*`}}else this.#v=null;this.#y=this.#x();let{hash:o,pathname:s,search:c}=this.#r.location;this.#m=`${s}${c}${o}`;let l=this.#u.begin(),u=this.#A(l,r.readLocation(this.#e,this.#r),(e,t)=>{if(!l.isCurrent())return;let n=this.#F(e);t&&this.#r.replace(n,e.historyState),this.#m=n},void 0,0,!1).then(()=>void 0);this.ready=u.catch(f),this.ready.catch(()=>{}),this.#w(u,{source:`initial-navigation`}),this.beforeLeave=this.beforeLeave.bind(this),this.createViewRegistry=this.createViewRegistry.bind(this),this.dispose=this.dispose.bind(this),this.getSnapshot=this.getSnapshot.bind(this),this.isActive=this.isActive.bind(this),this.load=this.load.bind(this),this.match=this.match.bind(this),this.navigate=this.navigate.bind(this),this.preload=this.preload.bind(this),this.subscribe=this.subscribe.bind(this),this.url=this.url.bind(this),this.waitFor=this.waitFor.bind(this)}getSnapshot(){return this.#d}createViewRegistry(e,t){return{resolve:n=>{let r=n.matches.at(-1)?.name;return r===`__notFound__`?t?.notFound:r?e[r]:void 0}}}subscribe(e){return this.#b(),this.#h.add(e),()=>{this.#h.delete(e)}}navigate(e,t){let n=c(typeof e==`string`?{path:e}:e,this.#a);return this.#L(n,t)}url(e,t,n){let i=s(e,this.#a);return r.buildUrl(this.#e,i.path,t,n)}isActive(e,t={}){let n=s(e,this.#a),i=this.#d.location.pathname;return t.exact??!1?r.matchRouteFor(i,[n]).record!=null:r.matchesPrefix(i,n)}match(e){let t=r.stripBase(r.normalizePath(e),this.#e),{params:n,record:i}=r.matchRouteFor(t,this.#i);if(!i||i.redirect)return null;let o=a.buildMatchBranch(i.branchDefs,n,t,i.branchDefs.map(()=>void 0));return o.length?o:null}async load(e,t){let n=await this.#D(e);if(n.type!==`matched`)return null;let{location:r,params:i,record:o,resolvedQuery:s}=n,c=o.branchDefs,l=c.some(e=>e.dataFn!=null),u=c.map(()=>void 0),d,f=`idle`;if(l){let e=t?.signal??new AbortController().signal,n=a.buildMatchBranch(c,i,r.pathname,u),o=a.createRouteContext(r,s,i,n,()=>Promise.resolve());try{u=await this.#E(c,o,e)}catch(e){d=e,f=`error`}}return a.createRouteState({error:d,location:r,matches:a.buildMatchBranch(c,i,r.pathname,u),status:f})}async preload(e){this.#b();let t=this.#N(c(e,this.#a,this.#e)),n=this.#_.get(t);if(n)return n;let r=this.load(t,{signal:this.#p.signal}).then(e=>{if(this.#f)throw this.#p.signal.reason;if(e?.status===`error`)throw e.error;if(e){let t=this.#F(e.location);this.#g.size>=20&&this.#g.delete(this.#g.keys().next().value),this.#g.set(t,e.matches.map(e=>e.data))}return e}).catch(e=>{throw this.#o&&this.#C(e,{source:`preload`}),e}).finally(()=>{this.#_.delete(t)});return this.#_.set(t,r),r}waitFor(e){return this.#b(),new Promise((t,n)=>{let r=t=>t.status===`idle`&&t.matches.some(t=>t.name===e);if(this.#d.status===`error`){n(this.#d.error);return}if(r(this.#d)){t(this.#d);return}let i=this.subscribe(e=>{r(e)?(i(),t(e)):e.status===`error`&&(i(),n(e.error))});this.#p.signal.addEventListener(`abort`,()=>{i(),n(this.#p.signal.reason)},{once:!0})})}beforeLeave(e,t){this.#b();let n={handler:e,routes:t?.routes};return this.#l.add(n),()=>{this.#l.delete(n)}}get disposalSignal(){return this.#p.signal}get disposed(){return this.#f}dispose(){this.#f||(this.#f=!0,this.#l.clear(),this.#h.clear(),this.#g.clear(),this.#_.clear(),this.#u.invalidate(new e.WayfinderDisposedError),this.#y(),this.#p.abort(new e.WayfinderDisposedError))}[Symbol.dispose](){this.dispose()}#b(){if(this.#f)throw new e.WayfinderDisposedError}#x(){return this.#r.onPopstate(()=>{let{hash:e,pathname:t,search:n}=this.#r.location,r=`${t}${n}${e}`,i=this.#m;r!==i&&this.#w(this.#S(r,i),{source:`history-listener`})})}async#S(e,t){let n=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=this.#I(e),s=await o.runLeaveBlockers(this.#l,i,a);if(!n.isCurrent())return;if(!s){this.#r.replace(t,this.#d.location.historyState);return}let c=await this.#A(n,r.readLocation(this.#e,this.#r),(e,t)=>{if(!n.isCurrent())return;let r=this.#F(e);t&&this.#r.replace(r,e.historyState),this.#m=r},void 0,0,!1);n.isCurrent()&&!c&&this.#r.replace(t,this.#d.location.historyState)}#C(e,t){a.reportError(e,t,this.#o)}#w(e,t){e.catch(e=>{d(e)?this.#C(e.error,e.context):this.#C(e,t)})}#T(){this.#h.forEach(e=>{e(this.#d)})}async#E(e,t,n){return Promise.all(e.map(async e=>{if(!e.dataFn)return;let r=e.dataFn;try{return await r({...t,signal:n})}catch(r){if(e.onError)return e.onError(r,{...t,signal:n});throw r}}))}async#D(t){let n=t;for(let e=0;e<5;e+=1){let e=new URL(n,`http://localhost`),t={hash:e.hash.replace(/^#/,``),historyState:null,pathname:r.stripBase(e.pathname,this.#e),query:r.parseQuery(e.search)},i=await this.#O(t);if(i.type!==`redirect`)return i;n=this.#N(i.redirectTo)}throw new e.WayfinderRedirectLoopError}async#O(e){let{params:t,record:n}=r.matchRouteFor(e.pathname,this.#i);if(!n)return{location:e,params:t,type:`unmatched`};if(n.redirect)return{location:e,params:t,redirectTo:c(n.redirect,this.#a,this.#e),type:`redirect`};let i=e.query,o=n.coerceSearch??this.#n;if(o)try{i=o(e.query)}catch(t){this.#C(t,{source:`coerce-search`}),i=e.query}return{branch:a.buildMatchBranch(n.branchDefs,t,e.pathname,n.branchDefs.map(()=>void 0)),location:e,params:t,record:n,resolvedQuery:i,type:`matched`}}async#k(e,t,n,r,i,o,s){if(!o())return;let c=e.branchDefs,l=c.some(e=>e.dataFn!=null),u=c.map(()=>void 0);if(l){let e=this.#F(n),l=this.#_.get(e);if(l&&(await l.catch(()=>void 0),!o()))return;let d=this.#g.get(e);if(d)this.#g.delete(e),u=d;else{this.#d=a.createRouteState({location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`loading`}),this.#T();try{u=await this.#E(c,t,i)}catch(e){if(!o())return;throw this.#d=a.createRouteState({error:e,location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`error`}),s?.(e),e}}}o()&&(this.#d=a.createRouteState({location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`idle`}))}async#A(t,n,r,i,o=0,s=!1){let c=this.#d,l=()=>t.isCurrent()&&!this.#f,f=await this.#O(n);if(!l())return!1;if(f.type===`redirect`){if(o>=5)throw new e.WayfinderRedirectLoopError;return this.#A(t,this.#P(f.redirectTo,n.historyState),r,i,o+1,!0)}if(f.type===`unmatched`){if(this.#v){let e=[this.#v.leaf],o=a.buildMatchBranch(e,{},n.pathname,[void 0]),f=!1,p,m=!1,h=!1,g=n.query;if(this.#n)try{g=this.#n(n.query)}catch(e){this.#C(e,{source:`coerce-search`})}let _=async()=>{if(!l())return;let e=a.createRouteContext(n,g,{},o,(e,t)=>this.navigate(e,t));h=await a.executeMiddlewarePipeline(e,[...this.#t,...this.#v.ownMiddleware],async()=>{l()&&(f=!0,r(n,s),l()&&await this.#k(this.#v,e,n,{},t.signal,l,e=>{p=e,m=!0}))},e=>d(e)||m&&e===p?e:u(e,{routeName:`__notFound__`,source:`middleware`}))};try{await this.#j(_,i)}catch(e){throw m&&e===p?u(e,{routeName:`__notFound__`,source:`data-loader`}):e}finally{l()&&f&&(this.#T(),this.#M(this.#d,c))}return h&&f}return!l()||(r(f.location,s),!l())?!1:(this.#d=a.createRouteState({location:f.location,matches:[],status:`idle`}),this.#T(),this.#M(this.#d,c),!0)}let{branch:p,location:m,params:h,record:g,resolvedQuery:_}=f,v=!1,y,b=!1,x=!1,S=async()=>{if(!l())return;let e=a.createRouteContext(m,_,h,p,(e,t)=>this.navigate(e,t));x=await a.executeMiddlewarePipeline(e,[...this.#t,...g.ownMiddleware],async()=>{l()&&(v=!0,r(m,s),l()&&await this.#k(g,e,m,h,t.signal,l,e=>{y=e,b=!0}))},e=>d(e)||b&&e===y?e:u(e,{routeName:g.leaf.name,source:`middleware`}))};try{await this.#j(S,i)}catch(e){throw b&&e===y?u(e,{routeName:g.leaf.name,source:`data-loader`}):e}finally{l()&&v&&(this.#T(),this.#M(this.#d,c))}return x&&v}async#j(e,t){if((t??this.#c)&&typeof document<`u`){let t=document.startViewTransition;if(t){await t.call(document,e).finished;return}}await e()}#M(e,t){if(!this.#s||typeof window>`u`)return;let n=this.#s(e,t);if(n!==`preserve`){if(n===`top`){window.scrollTo(0,0);return}window.scrollTo(n.x,n.y)}}#N(e){let t=new URL(e,`http://localhost`),n=r.stripBase(t.pathname,this.#e);return`${r.joinPaths(this.#e,n)}${t.search}${t.hash}`}#P(e,t){let n=new URL(this.#N(e),`http://localhost`);return{hash:n.hash.replace(/^#/,``),historyState:t,pathname:r.stripBase(n.pathname,this.#e),query:r.parseQuery(n.search)}}#F(e){let t=new URLSearchParams;for(let[n,r]of Object.entries(e.query))Array.isArray(r)?r.forEach(e=>{t.append(n,e)}):t.set(n,r);let n=t.toString(),i=e.hash?`#${e.hash}`:``;return`${r.joinPaths(this.#e,e.pathname)}${n?`?${n}`:``}${i}`}#I(e){let t=new URL(e,`http://localhost`),n=r.stripBase(t.pathname,this.#e),{params:i,record:a}=r.matchRouteFor(n,this.#i);return{name:a?.leaf.name,params:i,pathname:n,query:r.parseQuery(t.search)}}async#L(e,t={}){this.#b();let n=this.#N(e);if(!t.force&&n===this.#m)return;let r=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=await o.runLeaveBlockers(this.#l,i,this.#I(n));if(r.isCurrent()&&a)try{await this.#A(r,this.#P(n,t.state),(e,t)=>{if(!r.isCurrent())return;let n=this.#F(e);t?this.#r.replace(n,e.historyState):this.#r.push(n,e.historyState),this.#m=n},t.viewTransition,0,t.replace??!1)}catch(e){throw d(e)?e.error:e}}};function m(e){return new p(e)}exports.createRouter=m;
1
+ const e=require("./errors.cjs"),t=require("./path.cjs"),n=require("./history.cjs"),r=require("./_navigation.cjs"),i=require("./compile.cjs"),a=require("./context.cjs"),o=require("./guards.cjs");function s(t,n){let r=n.get(t);if(r)return r;let i=[...n.keys()].join(`, `);throw new e.WayfinderRouteError(i?`Unknown route name: ${t}. Available routes: ${i}`:`Unknown route name: ${t}`)}function c(e,n,r=`/`){if(`path`in e)return e.path;let i=s(e.name,n),a=t.buildUrl(r,i.path,e.params,e.query);return e.hash?`${a}#${e.hash}`:a}var l=Symbol(`wayfinder.routerError`);function u(e,t){return{[l]:!0,context:t,error:e}}function d(e){return typeof e==`object`&&!!e&&l in e}function f(e){throw d(e)?e.error:e}var p=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l=new Set;#u=r.createNavigationCoordinator();#d;#f=!1;#p=new AbortController;#m=`/`;#h=new Set;#g=new Map;#_=new Map;#v;#y;ready;constructor(e){let r=i.compileRoutes(e);if(this.#e=t.normalizePath(e.base??`/`),this.#t=e.middleware??[],this.#n=e.coerceSearch,this.#r=e.history??n.createBrowserHistory(),this.#o=e.onError,this.#s=e.scroll,this.#c=e.viewTransition??!1,this.#i=r.records,this.#a=r.routesByName,this.#d=a.createRouteState({location:{hash:``,historyState:null,pathname:`/`,query:{}},matches:[],status:`idle`}),e.notFound){let t=e.notFound,n={dataFn:t.data,name:`__notFound__`};this.#v={branchDefs:[n],leaf:n,matcher:{paramNames:[],pattern:/(?:)/,prefixPattern:/(?:)/},ownMiddleware:t.middleware??[],path:`/*`}}else this.#v=null;this.#y=this.#x();let{hash:o,pathname:s,search:c}=this.#r.location;this.#m=`${s}${c}${o}`;let l=this.#u.begin(),u=this.#A(l,t.readLocation(this.#e,this.#r),(e,t)=>{if(!l.isCurrent())return;let n=this.#F(e);t&&this.#r.replace(n,e.historyState),this.#m=n},void 0,0,!1).then(()=>void 0);this.ready=u.catch(f),this.ready.catch(()=>{}),this.#w(u,{source:`initial-navigation`}),this.beforeLeave=this.beforeLeave.bind(this),this.createViewRegistry=this.createViewRegistry.bind(this),this.dispose=this.dispose.bind(this),this.getSnapshot=this.getSnapshot.bind(this),this.isActive=this.isActive.bind(this),this.load=this.load.bind(this),this.match=this.match.bind(this),this.navigate=this.navigate.bind(this),this.preload=this.preload.bind(this),this.subscribe=this.subscribe.bind(this),this.url=this.url.bind(this),this.waitFor=this.waitFor.bind(this)}getSnapshot(){return this.#d}createViewRegistry(e,t){return{resolve:n=>{let r=n.matches.at(-1)?.name;return r===`__notFound__`?t?.notFound:r?e[r]:void 0}}}subscribe(e){return this.#b(),this.#h.add(e),()=>{this.#h.delete(e)}}navigate(e,t){let n=c(typeof e==`string`?{path:e}:e,this.#a);return this.#L(n,t)}url(e,n,r){let i=s(e,this.#a);return t.buildUrl(this.#e,i.path,n,r)}isActive(e,n={}){let r=s(e,this.#a),i=this.#d.location.pathname;return n.exact??!1?t.matchRouteFor(i,[r]).record!=null:t.matchesPrefix(i,r)}match(e){let n=t.stripBase(t.normalizePath(e),this.#e),{params:r,record:i}=t.matchRouteFor(n,this.#i);if(!i||i.redirect)return null;let o=a.buildMatchBranch(i.branchDefs,r,n,i.branchDefs.map(()=>void 0));return o.length?o:null}async load(e,t){let n=await this.#D(e);if(n.type!==`matched`)return null;let{location:r,params:i,record:o,resolvedQuery:s}=n,c=o.branchDefs,l=c.some(e=>e.dataFn!=null),u=c.map(()=>void 0),d,f=`idle`;if(l){let e=t?.signal??new AbortController().signal,n=a.buildMatchBranch(c,i,r.pathname,u),o=a.createRouteContext(r,s,i,n,()=>Promise.resolve());try{u=await this.#E(c,o,e)}catch(e){d=e,f=`error`}}return a.createRouteState({error:d,location:r,matches:a.buildMatchBranch(c,i,r.pathname,u),status:f})}async preload(e){this.#b();let t=this.#N(c(e,this.#a,this.#e)),n=this.#_.get(t);if(n)return n;let r=this.load(t,{signal:this.#p.signal}).then(e=>{if(this.#f)throw this.#p.signal.reason;if(e?.status===`error`)throw e.error;if(e){let t=this.#F(e.location);this.#g.size>=20&&this.#g.delete(this.#g.keys().next().value),this.#g.set(t,e.matches.map(e=>e.data))}return e}).catch(e=>{throw this.#o&&this.#C(e,{source:`preload`}),e}).finally(()=>{this.#_.delete(t)});return this.#_.set(t,r),r}waitFor(e){return this.#b(),new Promise((t,n)=>{let r=t=>t.status===`idle`&&t.matches.some(t=>t.name===e);if(this.#d.status===`error`){n(this.#d.error);return}if(r(this.#d)){t(this.#d);return}let i=this.subscribe(e=>{r(e)?(i(),t(e)):e.status===`error`&&(i(),n(e.error))});this.#p.signal.addEventListener(`abort`,()=>{i(),n(this.#p.signal.reason)},{once:!0})})}beforeLeave(e,t){this.#b();let n={handler:e,routes:t?.routes};return this.#l.add(n),()=>{this.#l.delete(n)}}get disposalSignal(){return this.#p.signal}get disposed(){return this.#f}dispose(){this.#f||(this.#f=!0,this.#l.clear(),this.#h.clear(),this.#g.clear(),this.#_.clear(),this.#u.invalidate(new e.WayfinderDisposedError),this.#y(),this.#p.abort(new e.WayfinderDisposedError))}[Symbol.dispose](){this.dispose()}#b(){if(this.#f)throw new e.WayfinderDisposedError}#x(){return this.#r.onPopstate(()=>{let{hash:e,pathname:t,search:n}=this.#r.location,r=`${t}${n}${e}`,i=this.#m;r!==i&&this.#w(this.#S(r,i),{source:`history-listener`})})}async#S(e,n){let r=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=this.#I(e),s=await o.runLeaveBlockers(this.#l,i,a);if(!r.isCurrent())return;if(!s){this.#r.replace(n,this.#d.location.historyState);return}let c=await this.#A(r,t.readLocation(this.#e,this.#r),(e,t)=>{if(!r.isCurrent())return;let n=this.#F(e);t&&this.#r.replace(n,e.historyState),this.#m=n},void 0,0,!1);r.isCurrent()&&!c&&this.#r.replace(n,this.#d.location.historyState)}#C(e,t){a.reportError(e,t,this.#o)}#w(e,t){e.catch(e=>{d(e)?this.#C(e.error,e.context):this.#C(e,t)})}#T(){this.#h.forEach(e=>{e(this.#d)})}async#E(e,t,n){return Promise.all(e.map(async e=>{if(!e.dataFn)return;let r=e.dataFn;try{return await r({...t,signal:n})}catch(r){if(e.onError)return e.onError(r,{...t,signal:n});throw r}}))}async#D(n){let r=n;for(let e=0;e<5;e+=1){let e=new URL(r,`http://localhost`),n={hash:e.hash.replace(/^#/,``),historyState:null,pathname:t.stripBase(e.pathname,this.#e),query:t.parseQuery(e.search)},i=await this.#O(n);if(i.type!==`redirect`)return i;r=this.#N(i.redirectTo)}throw new e.WayfinderRedirectLoopError}async#O(e){let{params:n,record:r}=t.matchRouteFor(e.pathname,this.#i);if(!r)return{location:e,params:n,type:`unmatched`};if(r.redirect)return{location:e,params:n,redirectTo:c(r.redirect,this.#a,this.#e),type:`redirect`};let i=e.query,o=r.coerceSearch??this.#n;if(o)try{i=o(e.query)}catch(t){this.#C(t,{source:`coerce-search`}),i=e.query}return{branch:a.buildMatchBranch(r.branchDefs,n,e.pathname,r.branchDefs.map(()=>void 0)),location:e,params:n,record:r,resolvedQuery:i,type:`matched`}}async#k(e,t,n,r,i,o,s){if(!o())return;let c=e.branchDefs,l=c.some(e=>e.dataFn!=null),u=c.map(()=>void 0);if(l){let e=this.#F(n),l=this.#_.get(e);if(l&&(await l.catch(()=>void 0),!o()))return;let d=this.#g.get(e);if(d)this.#g.delete(e),u=d;else{this.#d=a.createRouteState({location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`loading`}),this.#T();try{u=await this.#E(c,t,i)}catch(e){if(!o())return;throw this.#d=a.createRouteState({error:e,location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`error`}),s?.(e),e}}}o()&&(this.#d=a.createRouteState({location:n,matches:a.buildMatchBranch(c,r,n.pathname,u),status:`idle`}))}async#A(t,n,r,i,o=0,s=!1){let c=this.#d,l=()=>t.isCurrent()&&!this.#f,f=await this.#O(n);if(!l())return!1;if(f.type===`redirect`){if(o>=5)throw new e.WayfinderRedirectLoopError;return this.#A(t,this.#P(f.redirectTo,n.historyState),r,i,o+1,!0)}if(f.type===`unmatched`){if(this.#v){let e=[this.#v.leaf],o=a.buildMatchBranch(e,{},n.pathname,[void 0]),f=!1,p,m=!1,h=!1,g=n.query;if(this.#n)try{g=this.#n(n.query)}catch(e){this.#C(e,{source:`coerce-search`})}let _=async()=>{if(!l())return;let e=a.createRouteContext(n,g,{},o,(e,t)=>this.navigate(e,t));h=await a.executeMiddlewarePipeline(e,[...this.#t,...this.#v.ownMiddleware],async()=>{l()&&(f=!0,r(n,s),l()&&await this.#k(this.#v,e,n,{},t.signal,l,e=>{p=e,m=!0}))},e=>d(e)||m&&e===p?e:u(e,{routeName:`__notFound__`,source:`middleware`}))};try{await this.#j(_,i)}catch(e){throw m&&e===p?u(e,{routeName:`__notFound__`,source:`data-loader`}):e}finally{l()&&f&&(this.#T(),this.#M(this.#d,c))}return h&&f}return!l()||(r(f.location,s),!l())?!1:(this.#d=a.createRouteState({location:f.location,matches:[],status:`idle`}),this.#T(),this.#M(this.#d,c),!0)}let{branch:p,location:m,params:h,record:g,resolvedQuery:_}=f,v=!1,y,b=!1,x=!1,S=async()=>{if(!l())return;let e=a.createRouteContext(m,_,h,p,(e,t)=>this.navigate(e,t));x=await a.executeMiddlewarePipeline(e,[...this.#t,...g.ownMiddleware],async()=>{l()&&(v=!0,r(m,s),l()&&await this.#k(g,e,m,h,t.signal,l,e=>{y=e,b=!0}))},e=>d(e)||b&&e===y?e:u(e,{routeName:g.leaf.name,source:`middleware`}))};try{await this.#j(S,i)}catch(e){throw b&&e===y?u(e,{routeName:g.leaf.name,source:`data-loader`}):e}finally{l()&&v&&(this.#T(),this.#M(this.#d,c))}return x&&v}async#j(e,t){if((t??this.#c)&&typeof document<`u`){let t=document.startViewTransition;if(t){await t.call(document,e).finished;return}}await e()}#M(e,t){if(!this.#s||typeof window>`u`)return;let n=this.#s(e,t);if(n!==`preserve`){if(n===`top`){window.scrollTo(0,0);return}window.scrollTo(n.x,n.y)}}#N(e){let n=new URL(e,`http://localhost`),r=t.stripBase(n.pathname,this.#e);return`${t.joinPaths(this.#e,r)}${n.search}${n.hash}`}#P(e,n){let r=new URL(this.#N(e),`http://localhost`);return{hash:r.hash.replace(/^#/,``),historyState:n,pathname:t.stripBase(r.pathname,this.#e),query:t.parseQuery(r.search)}}#F(e){let n=new URLSearchParams;for(let[t,r]of Object.entries(e.query))Array.isArray(r)?r.forEach(e=>{n.append(t,e)}):n.set(t,r);let r=n.toString(),i=e.hash?`#${e.hash}`:``;return`${t.joinPaths(this.#e,e.pathname)}${r?`?${r}`:``}${i}`}#I(e){let n=new URL(e,`http://localhost`),r=t.stripBase(n.pathname,this.#e),{params:i,record:a}=t.matchRouteFor(r,this.#i);return{name:a?.leaf.name,params:i,pathname:r,query:t.parseQuery(n.search)}}async#L(e,t={}){this.#b();let n=this.#N(e);if(!t.force&&n===this.#m)return;let r=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=await o.runLeaveBlockers(this.#l,i,this.#I(n));if(r.isCurrent()&&a)try{await this.#A(r,this.#P(n,t.state),(e,t)=>{if(!r.isCurrent())return;let n=this.#F(e);t?this.#r.replace(n,e.historyState):this.#r.push(n,e.historyState),this.#m=n},t.viewTransition,0,t.replace??!1)}catch(e){throw d(e)?e.error:e}}};function m(e){return new p(e)}exports.createRouter=m;
2
2
  //# sourceMappingURL=router.cjs.map
package/dist/router.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { WayfinderDisposedError as e, WayfinderRedirectLoopError as t, WayfinderRouteError as n } from "./errors.js";
2
- import { createBrowserHistory as r } from "./history.js";
3
- import { createNavigationCoordinator as i } from "./_navigation.js";
4
- import { buildUrl as a, joinPaths as o, matchRouteFor as s, matchesPrefix as c, normalizePath as l, parseQuery as u, readLocation as d, stripBase as f } from "./path.js";
2
+ import { buildUrl as r, joinPaths as i, matchRouteFor as a, matchesPrefix as o, normalizePath as s, parseQuery as c, readLocation as l, stripBase as u } from "./path.js";
3
+ import { createBrowserHistory as d } from "./history.js";
4
+ import { createNavigationCoordinator as f } from "./_navigation.js";
5
5
  import { compileRoutes as p } from "./compile.js";
6
6
  import { buildMatchBranch as m, createRouteContext as h, createRouteState as g, executeMiddlewarePipeline as _, reportError as v } from "./context.js";
7
7
  import { runLeaveBlockers as y } from "./guards.js";
@@ -14,8 +14,8 @@ function b(e, t) {
14
14
  }
15
15
  function x(e, t, n = "/") {
16
16
  if ("path" in e) return e.path;
17
- let r = b(e.name, t), i = a(n, r.path, e.params, e.query);
18
- return e.hash ? `${i}#${e.hash}` : i;
17
+ let i = b(e.name, t), a = r(n, i.path, e.params, e.query);
18
+ return e.hash ? `${a}#${e.hash}` : a;
19
19
  }
20
20
  var S = Symbol("wayfinder.routerError");
21
21
  function C(e, t) {
@@ -42,7 +42,7 @@ var E = class {
42
42
  #s;
43
43
  #c;
44
44
  #l = /* @__PURE__ */ new Set();
45
- #u = i();
45
+ #u = f();
46
46
  #d;
47
47
  #f = !1;
48
48
  #p = new AbortController();
@@ -55,7 +55,7 @@ var E = class {
55
55
  ready;
56
56
  constructor(e) {
57
57
  let t = p(e);
58
- if (this.#e = l(e.base ?? "/"), this.#t = e.middleware ?? [], this.#n = e.coerceSearch, this.#r = e.history ?? r(), this.#o = e.onError, this.#s = e.scroll, this.#c = e.viewTransition ?? !1, this.#i = t.records, this.#a = t.routesByName, this.#d = g({
58
+ if (this.#e = s(e.base ?? "/"), this.#t = e.middleware ?? [], this.#n = e.coerceSearch, this.#r = e.history ?? d(), this.#o = e.onError, this.#s = e.scroll, this.#c = e.viewTransition ?? !1, this.#i = t.records, this.#a = t.routesByName, this.#d = g({
59
59
  location: {
60
60
  hash: "",
61
61
  historyState: null,
@@ -82,14 +82,14 @@ var E = class {
82
82
  };
83
83
  } else this.#v = null;
84
84
  this.#y = this.#x();
85
- let { hash: n, pathname: i, search: a } = this.#r.location;
86
- this.#m = `${i}${a}${n}`;
87
- let o = this.#u.begin(), s = this.#A(o, d(this.#e, this.#r), (e, t) => {
88
- if (!o.isCurrent()) return;
85
+ let { hash: n, pathname: r, search: i } = this.#r.location;
86
+ this.#m = `${r}${i}${n}`;
87
+ let a = this.#u.begin(), o = this.#A(a, l(this.#e, this.#r), (e, t) => {
88
+ if (!a.isCurrent()) return;
89
89
  let n = this.#F(e);
90
90
  t && this.#r.replace(n, e.historyState), this.#m = n;
91
91
  }, void 0, 0, !1).then(() => void 0);
92
- this.ready = s.catch(T), this.ready.catch(() => {}), this.#w(s, { source: "initial-navigation" }), this.beforeLeave = this.beforeLeave.bind(this), this.createViewRegistry = this.createViewRegistry.bind(this), this.dispose = this.dispose.bind(this), this.getSnapshot = this.getSnapshot.bind(this), this.isActive = this.isActive.bind(this), this.load = this.load.bind(this), this.match = this.match.bind(this), this.navigate = this.navigate.bind(this), this.preload = this.preload.bind(this), this.subscribe = this.subscribe.bind(this), this.url = this.url.bind(this), this.waitFor = this.waitFor.bind(this);
92
+ this.ready = o.catch(T), this.ready.catch(() => {}), this.#w(o, { source: "initial-navigation" }), this.beforeLeave = this.beforeLeave.bind(this), this.createViewRegistry = this.createViewRegistry.bind(this), this.dispose = this.dispose.bind(this), this.getSnapshot = this.getSnapshot.bind(this), this.isActive = this.isActive.bind(this), this.load = this.load.bind(this), this.match = this.match.bind(this), this.navigate = this.navigate.bind(this), this.preload = this.preload.bind(this), this.subscribe = this.subscribe.bind(this), this.url = this.url.bind(this), this.waitFor = this.waitFor.bind(this);
93
93
  }
94
94
  getSnapshot() {
95
95
  return this.#d;
@@ -110,15 +110,15 @@ var E = class {
110
110
  return this.#L(n, t);
111
111
  }
112
112
  url(e, t, n) {
113
- let r = b(e, this.#a);
114
- return a(this.#e, r.path, t, n);
113
+ let i = b(e, this.#a);
114
+ return r(this.#e, i.path, t, n);
115
115
  }
116
116
  isActive(e, t = {}) {
117
117
  let n = b(e, this.#a), r = this.#d.location.pathname;
118
- return t.exact ?? !1 ? s(r, [n]).record != null : c(r, n);
118
+ return t.exact ?? !1 ? a(r, [n]).record != null : o(r, n);
119
119
  }
120
120
  match(e) {
121
- let t = f(l(e), this.#e), { params: n, record: r } = s(t, this.#i);
121
+ let t = u(s(e), this.#e), { params: n, record: r } = a(t, this.#i);
122
122
  if (!r || r.redirect) return null;
123
123
  let i = m(r.branchDefs, n, t, r.branchDefs.map(() => void 0));
124
124
  return i.length ? i : null;
@@ -218,7 +218,7 @@ var E = class {
218
218
  this.#r.replace(t, this.#d.location.historyState);
219
219
  return;
220
220
  }
221
- let o = await this.#A(n, d(this.#e, this.#r), (e, t) => {
221
+ let o = await this.#A(n, l(this.#e, this.#r), (e, t) => {
222
222
  if (!n.isCurrent()) return;
223
223
  let r = this.#F(e);
224
224
  t && this.#r.replace(r, e.historyState), this.#m = r;
@@ -262,8 +262,8 @@ var E = class {
262
262
  let e = new URL(n, "http://localhost"), t = {
263
263
  hash: e.hash.replace(/^#/, ""),
264
264
  historyState: null,
265
- pathname: f(e.pathname, this.#e),
266
- query: u(e.search)
265
+ pathname: u(e.pathname, this.#e),
266
+ query: c(e.search)
267
267
  }, r = await this.#O(t);
268
268
  if (r.type !== "redirect") return r;
269
269
  n = this.#N(r.redirectTo);
@@ -271,7 +271,7 @@ var E = class {
271
271
  throw new t();
272
272
  }
273
273
  async #O(e) {
274
- let { params: t, record: n } = s(e.pathname, this.#i);
274
+ let { params: t, record: n } = a(e.pathname, this.#i);
275
275
  if (!n) return {
276
276
  location: e,
277
277
  params: t,
@@ -422,16 +422,16 @@ var E = class {
422
422
  }
423
423
  }
424
424
  #N(e) {
425
- let t = new URL(e, "http://localhost"), n = f(t.pathname, this.#e);
426
- return `${o(this.#e, n)}${t.search}${t.hash}`;
425
+ let t = new URL(e, "http://localhost"), n = u(t.pathname, this.#e);
426
+ return `${i(this.#e, n)}${t.search}${t.hash}`;
427
427
  }
428
428
  #P(e, t) {
429
429
  let n = new URL(this.#N(e), "http://localhost");
430
430
  return {
431
431
  hash: n.hash.replace(/^#/, ""),
432
432
  historyState: t,
433
- pathname: f(n.pathname, this.#e),
434
- query: u(n.search)
433
+ pathname: u(n.pathname, this.#e),
434
+ query: c(n.search)
435
435
  };
436
436
  }
437
437
  #F(e) {
@@ -440,15 +440,15 @@ var E = class {
440
440
  t.append(n, e);
441
441
  }) : t.set(n, r);
442
442
  let n = t.toString(), r = e.hash ? `#${e.hash}` : "";
443
- return `${o(this.#e, e.pathname)}${n ? `?${n}` : ""}${r}`;
443
+ return `${i(this.#e, e.pathname)}${n ? `?${n}` : ""}${r}`;
444
444
  }
445
445
  #I(e) {
446
- let t = new URL(e, "http://localhost"), n = f(t.pathname, this.#e), { params: r, record: i } = s(n, this.#i);
446
+ let t = new URL(e, "http://localhost"), n = u(t.pathname, this.#e), { params: r, record: i } = a(n, this.#i);
447
447
  return {
448
448
  name: i?.leaf.name,
449
449
  params: r,
450
450
  pathname: n,
451
- query: u(t.search)
451
+ query: c(t.search)
452
452
  };
453
453
  }
454
454
  async #L(e, t = {}) {
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(){super(`Router is disposed`)}},n=class extends e{},r=class extends e{constructor(){super(`Redirect loop detected`)}},i=class extends e{};function a(){return{back(){window.history.back()},get location(){return{hash:window.location.hash,pathname:window.location.pathname,search:window.location.search,state:window.history.state}},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,e)},replace(e,t){window.history.replaceState(t,``,e)}}}function o(e=`/`){let t=new URL(e,`http://localhost`),n=[{hash:t.hash,pathname:t.pathname,search:t.search,state:null}],r=0,i=new Set;return{back(){r<=0||(--r,i.forEach(e=>{e()}))},get location(){return n[r]},onPopstate(e){return i.add(e),()=>i.delete(e)},push(e,t=null){let i=new URL(e,`http://localhost`);n.splice(r+1),n.push({hash:i.hash,pathname:i.pathname,search:i.search,state:t}),r=n.length-1},replace(e,t=null){let i=new URL(e,`http://localhost`);n[r]={hash:i.hash,pathname:i.pathname,search:i.search,state:t}}}}function s(e,t){return async n=>{await n.navigate(e,t)}}function c(){let e;return{begin(){e?.abort();let t=new AbortController;return e=t,{isCurrent:()=>e===t&&!t.signal.aborted,signal:t.signal}},invalidate(t){e?.abort(t),e=void 0}}}function l(e){let t=`/${e}`.replace(/\/+/g,`/`);return t!==`/`&&t.endsWith(`/`)?t.slice(0,-1):t}function u(e,t){return l(`${e}/${t}`)}function d(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function f(e){let t=l(e);if(t===`/`)return{paramNames:[],pattern:/^\/$/,prefixPattern:/^\/$/};let r=[],i=t.slice(1).split(`/`),a=[`^`],o=[`^`];for(let t=0;t<i.length;t+=1){let s=i[t];if(s===`*`){if(t!==i.length-1)throw new n(`Wildcard "*" must be the final segment in path: ${e}`);a.push(`(?:/.*)?`);break}if(s.startsWith(`:`)&&s.endsWith(`*`)){if(t!==i.length-1)throw new n(`Wildcard param must be final segment in path: ${e}`);let c=s.slice(1,-1);if(!/^\w+$/.test(c))throw new n(`Invalid param name ":${c}" in path "${e}". Param names must only contain word characters (a–z, A–Z, 0–9, _).`);r.push(c),a.push(t===i.length-1?`(?:/(.*))?`:`/(.*)`),o.push(`/.*`);break}if(s.startsWith(`:`)){let t=s.slice(1);if(!/^\w+$/.test(t))throw new n(`Invalid param name ":${t}" in path "${e}". Param names must only contain word characters (a–z, A–Z, 0–9, _).`);r.push(t),a.push(`/([^/]+)`),o.push(`/[^/]+`);continue}let c=d(s);a.push(`/${c}`),o.push(`/${c}`)}return a.push(`$`),o.push(`(?:/.*)?$`),{paramNames:r,pattern:new RegExp(a.join(``)),prefixPattern:new RegExp(o.join(``))}}function p(e,t){let n=t.matcher.pattern.exec(e);if(!n)return null;let r={};return t.matcher.paramNames.forEach((e,t)=>{let i=n[t+1]??``;try{r[e]=decodeURIComponent(i)}catch{r[e]=i}}),r}function m(e,t){for(let n of t){let t=p(e,n);if(t)return{params:t,record:n}}return{params:{}}}function h(e,t){return t.matcher.prefixPattern.test(e)}function g(e){let t=new URLSearchParams(e),n={},r=(e,t)=>{Object.defineProperty(n,e,{configurable:!0,enumerable:!0,value:t,writable:!0})};for(let[e,i]of t.entries()){let t=Object.hasOwn(n,e)?n[e]:void 0;if(t===void 0){r(e,i);continue}if(Array.isArray(t)){t.push(i);continue}r(e,[t,i])}return n}function _(e,t,r={},i){let a=t.replace(/:(\w+)(\*)?/g,(e,t,i)=>{let a=r[t];if(a==null)throw new n(`Missing path param: ${t}`);return i?a.split(`/`).map(e=>encodeURIComponent(e)).join(`/`):encodeURIComponent(a)});if(i&&Object.keys(i).length){let e=new URLSearchParams;Object.entries(i).forEach(([t,n])=>{Array.isArray(n)?n.forEach(n=>{e.append(t,String(n))}):e.set(t,String(n))}),a+=`?${e.toString()}`}return u(e,a)}function v(e,t=`/`){let n=l(e),r=l(t);if(r===`/`)return n;if(n===r)return`/`;let i=`${r}/`;return n.startsWith(i)?l(n.slice(r.length)):n}function y(e,t){return{hash:t.location.hash.replace(/^#/,``),historyState:t.location.state,pathname:v(t.location.pathname||`/`,e),query:g(t.location.search||``)}}function b(e){let t=[],r=(e,i,a,o,s)=>{if(i.index&&i.path!==void 0)throw new n(`Route "${e}" cannot define both index and path`);if(!i.index&&i.path===void 0)throw new n(`Route "${e}" must define path or set index: true`);let c=i.index?a:l(i.path?u(a,i.path):a),d=[...o,{dataFn:i.data,name:e,onError:i.onError}],p=[...s,...i.middleware??[]];if(i.children)for(let[t,n]of Object.entries(i.children))r(`${e}.${t}`,n,c,d,p);if(i.redirect!==void 0||!i.children||i.data!==void 0){let e=d[d.length-1];t.push({branchDefs:d,coerceSearch:i.coerceSearch,leaf:e,matcher:f(c),ownMiddleware:p,path:c,redirect:i.redirect})}};for(let[t,n]of Object.entries(e.routes))r(t,n,`/`,[],[]);let i=new Set;for(let e of t){if(i.has(e.leaf.name))throw new n(`Duplicate route name: "${e.leaf.name}". A top-level route key must not coincide with a nested route's dot-notation name.`);i.add(e.leaf.name)}let a=!1;for(let e of t){let t=e.path===`/*`||e.path.endsWith(`/*`)||e.path.includes(`:`)&&e.path.endsWith(`*`);a&&!t&&`${e.leaf.name}${e.path}`,t&&(a=!0)}return{records:t,routesByName:new Map(t.map(e=>[e.leaf.name,e]))}}function x(e){return{error:e.error,location:e.location,matches:e.matches,status:e.status}}function S(e,t,n,r){return e.map((e,i)=>({data:r[i],name:e.name,params:{...t},pathname:n}))}function C(e,t,n,r,i){return{hash:e.hash,historyState:e.historyState,locals:{},matches:r,navigate:i,params:n,pathname:e.pathname,query:t}}async function w(e,t,n,r){let a=!1;async function o(s){if(s<t.length){let n=!1;try{await t[s]?.(e,async()=>{if(n)throw new i(`next() called multiple times`);n=!0,await o(s+1)})}catch(e){throw r?.(e)??e}return}a=!0,await n()}return await o(0),a}function T(e,t,n){if(n){n(e,t);return}}async function E(e,t,n){let r=new Set(t),i=[...e];for(let{handler:e,routes:t}of i)if((t===void 0||t.some(e=>r.has(e)))&&!await e(n))return!1;return!0}function D(e,t){let r=t.get(e);if(r)return r;let i=[...t.keys()].join(`, `);throw new n(i?`Unknown route name: ${e}. Available routes: ${i}`:`Unknown route name: ${e}`)}function O(e,t,n=`/`){if(`path`in e)return e.path;let r=_(n,D(e.name,t).path,e.params,e.query);return e.hash?`${r}#${e.hash}`:r}var k=Symbol(`wayfinder.routerError`);function A(e,t){return{[k]:!0,context:t,error:e}}function j(e){return typeof e==`object`&&!!e&&k in e}function M(e){throw j(e)?e.error:e}var N=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l=new Set;#u=c();#d;#f=!1;#p=new AbortController;#m=`/`;#h=new Set;#g=new Map;#_=new Map;#v;#y;ready;constructor(e){let t=b(e);if(this.#e=l(e.base??`/`),this.#t=e.middleware??[],this.#n=e.coerceSearch,this.#r=e.history??a(),this.#o=e.onError,this.#s=e.scroll,this.#c=e.viewTransition??!1,this.#i=t.records,this.#a=t.routesByName,this.#d=x({location:{hash:``,historyState:null,pathname:`/`,query:{}},matches:[],status:`idle`}),e.notFound){let t=e.notFound,n={dataFn:t.data,name:`__notFound__`};this.#v={branchDefs:[n],leaf:n,matcher:{paramNames:[],pattern:/(?:)/,prefixPattern:/(?:)/},ownMiddleware:t.middleware??[],path:`/*`}}else this.#v=null;this.#y=this.#x();let{hash:n,pathname:r,search:i}=this.#r.location;this.#m=`${r}${i}${n}`;let o=this.#u.begin(),s=this.#A(o,y(this.#e,this.#r),(e,t)=>{if(!o.isCurrent())return;let n=this.#F(e);t&&this.#r.replace(n,e.historyState),this.#m=n},void 0,0,!1).then(()=>void 0);this.ready=s.catch(M),this.ready.catch(()=>{}),this.#w(s,{source:`initial-navigation`}),this.beforeLeave=this.beforeLeave.bind(this),this.createViewRegistry=this.createViewRegistry.bind(this),this.dispose=this.dispose.bind(this),this.getSnapshot=this.getSnapshot.bind(this),this.isActive=this.isActive.bind(this),this.load=this.load.bind(this),this.match=this.match.bind(this),this.navigate=this.navigate.bind(this),this.preload=this.preload.bind(this),this.subscribe=this.subscribe.bind(this),this.url=this.url.bind(this),this.waitFor=this.waitFor.bind(this)}getSnapshot(){return this.#d}createViewRegistry(e,t){return{resolve:n=>{let r=n.matches.at(-1)?.name;return r===`__notFound__`?t?.notFound:r?e[r]:void 0}}}subscribe(e){return this.#b(),this.#h.add(e),()=>{this.#h.delete(e)}}navigate(e,t){let n=O(typeof e==`string`?{path:e}:e,this.#a);return this.#L(n,t)}url(e,t,n){let r=D(e,this.#a);return _(this.#e,r.path,t,n)}isActive(e,t={}){let n=D(e,this.#a),r=this.#d.location.pathname;return t.exact??!1?m(r,[n]).record!=null:h(r,n)}match(e){let t=v(l(e),this.#e),{params:n,record:r}=m(t,this.#i);if(!r||r.redirect)return null;let i=S(r.branchDefs,n,t,r.branchDefs.map(()=>void 0));return i.length?i:null}async load(e,t){let n=await this.#D(e);if(n.type!==`matched`)return null;let{location:r,params:i,record:a,resolvedQuery:o}=n,s=a.branchDefs,c=s.some(e=>e.dataFn!=null),l=s.map(()=>void 0),u,d=`idle`;if(c){let e=t?.signal??new AbortController().signal,n=C(r,o,i,S(s,i,r.pathname,l),()=>Promise.resolve());try{l=await this.#E(s,n,e)}catch(e){u=e,d=`error`}}return x({error:u,location:r,matches:S(s,i,r.pathname,l),status:d})}async preload(e){this.#b();let t=this.#N(O(e,this.#a,this.#e)),n=this.#_.get(t);if(n)return n;let r=this.load(t,{signal:this.#p.signal}).then(e=>{if(this.#f)throw this.#p.signal.reason;if(e?.status===`error`)throw e.error;if(e){let t=this.#F(e.location);this.#g.size>=20&&this.#g.delete(this.#g.keys().next().value),this.#g.set(t,e.matches.map(e=>e.data))}return e}).catch(e=>{throw this.#o&&this.#C(e,{source:`preload`}),e}).finally(()=>{this.#_.delete(t)});return this.#_.set(t,r),r}waitFor(e){return this.#b(),new Promise((t,n)=>{let r=t=>t.status===`idle`&&t.matches.some(t=>t.name===e);if(this.#d.status===`error`){n(this.#d.error);return}if(r(this.#d)){t(this.#d);return}let i=this.subscribe(e=>{r(e)?(i(),t(e)):e.status===`error`&&(i(),n(e.error))});this.#p.signal.addEventListener(`abort`,()=>{i(),n(this.#p.signal.reason)},{once:!0})})}beforeLeave(e,t){this.#b();let n={handler:e,routes:t?.routes};return this.#l.add(n),()=>{this.#l.delete(n)}}get disposalSignal(){return this.#p.signal}get disposed(){return this.#f}dispose(){this.#f||(this.#f=!0,this.#l.clear(),this.#h.clear(),this.#g.clear(),this.#_.clear(),this.#u.invalidate(new t),this.#y(),this.#p.abort(new t))}[Symbol.dispose](){this.dispose()}#b(){if(this.#f)throw new t}#x(){return this.#r.onPopstate(()=>{let{hash:e,pathname:t,search:n}=this.#r.location,r=`${t}${n}${e}`,i=this.#m;r!==i&&this.#w(this.#S(r,i),{source:`history-listener`})})}async#S(e,t){let n=this.#u.begin(),r=this.#d.matches.map(e=>e.name),i=this.#I(e),a=await E(this.#l,r,i);if(!n.isCurrent())return;if(!a){this.#r.replace(t,this.#d.location.historyState);return}let o=await this.#A(n,y(this.#e,this.#r),(e,t)=>{if(!n.isCurrent())return;let r=this.#F(e);t&&this.#r.replace(r,e.historyState),this.#m=r},void 0,0,!1);n.isCurrent()&&!o&&this.#r.replace(t,this.#d.location.historyState)}#C(e,t){T(e,t,this.#o)}#w(e,t){e.catch(e=>{j(e)?this.#C(e.error,e.context):this.#C(e,t)})}#T(){this.#h.forEach(e=>{e(this.#d)})}async#E(e,t,n){return Promise.all(e.map(async e=>{if(!e.dataFn)return;let r=e.dataFn;try{return await r({...t,signal:n})}catch(r){if(e.onError)return e.onError(r,{...t,signal:n});throw r}}))}async#D(e){let t=e;for(let e=0;e<5;e+=1){let e=new URL(t,`http://localhost`),n={hash:e.hash.replace(/^#/,``),historyState:null,pathname:v(e.pathname,this.#e),query:g(e.search)},r=await this.#O(n);if(r.type!==`redirect`)return r;t=this.#N(r.redirectTo)}throw new r}async#O(e){let{params:t,record:n}=m(e.pathname,this.#i);if(!n)return{location:e,params:t,type:`unmatched`};if(n.redirect)return{location:e,params:t,redirectTo:O(n.redirect,this.#a,this.#e),type:`redirect`};let r=e.query,i=n.coerceSearch??this.#n;if(i)try{r=i(e.query)}catch(t){this.#C(t,{source:`coerce-search`}),r=e.query}return{branch:S(n.branchDefs,t,e.pathname,n.branchDefs.map(()=>void 0)),location:e,params:t,record:n,resolvedQuery:r,type:`matched`}}async#k(e,t,n,r,i,a,o){if(!a())return;let s=e.branchDefs,c=s.some(e=>e.dataFn!=null),l=s.map(()=>void 0);if(c){let e=this.#F(n),c=this.#_.get(e);if(c&&(await c.catch(()=>void 0),!a()))return;let u=this.#g.get(e);if(u)this.#g.delete(e),l=u;else{this.#d=x({location:n,matches:S(s,r,n.pathname,l),status:`loading`}),this.#T();try{l=await this.#E(s,t,i)}catch(e){if(!a())return;throw this.#d=x({error:e,location:n,matches:S(s,r,n.pathname,l),status:`error`}),o?.(e),e}}}a()&&(this.#d=x({location:n,matches:S(s,r,n.pathname,l),status:`idle`}))}async#A(e,t,n,i,a=0,o=!1){let s=this.#d,c=()=>e.isCurrent()&&!this.#f,l=await this.#O(t);if(!c())return!1;if(l.type===`redirect`){if(a>=5)throw new r;return this.#A(e,this.#P(l.redirectTo,t.historyState),n,i,a+1,!0)}if(l.type===`unmatched`){if(this.#v){let r=S([this.#v.leaf],{},t.pathname,[void 0]),a=!1,l,u=!1,d=!1,f=t.query;if(this.#n)try{f=this.#n(t.query)}catch(e){this.#C(e,{source:`coerce-search`})}let p=async()=>{if(!c())return;let i=C(t,f,{},r,(e,t)=>this.navigate(e,t));d=await w(i,[...this.#t,...this.#v.ownMiddleware],async()=>{c()&&(a=!0,n(t,o),c()&&await this.#k(this.#v,i,t,{},e.signal,c,e=>{l=e,u=!0}))},e=>j(e)||u&&e===l?e:A(e,{routeName:`__notFound__`,source:`middleware`}))};try{await this.#j(p,i)}catch(e){throw u&&e===l?A(e,{routeName:`__notFound__`,source:`data-loader`}):e}finally{c()&&a&&(this.#T(),this.#M(this.#d,s))}return d&&a}return!c()||(n(l.location,o),!c())?!1:(this.#d=x({location:l.location,matches:[],status:`idle`}),this.#T(),this.#M(this.#d,s),!0)}let{branch:u,location:d,params:f,record:p,resolvedQuery:m}=l,h=!1,g,_=!1,v=!1,y=async()=>{if(!c())return;let t=C(d,m,f,u,(e,t)=>this.navigate(e,t));v=await w(t,[...this.#t,...p.ownMiddleware],async()=>{c()&&(h=!0,n(d,o),c()&&await this.#k(p,t,d,f,e.signal,c,e=>{g=e,_=!0}))},e=>j(e)||_&&e===g?e:A(e,{routeName:p.leaf.name,source:`middleware`}))};try{await this.#j(y,i)}catch(e){throw _&&e===g?A(e,{routeName:p.leaf.name,source:`data-loader`}):e}finally{c()&&h&&(this.#T(),this.#M(this.#d,s))}return v&&h}async#j(e,t){if((t??this.#c)&&typeof document<`u`){let t=document.startViewTransition;if(t){await t.call(document,e).finished;return}}await e()}#M(e,t){if(!this.#s||typeof window>`u`)return;let n=this.#s(e,t);if(n!==`preserve`){if(n===`top`){window.scrollTo(0,0);return}window.scrollTo(n.x,n.y)}}#N(e){let t=new URL(e,`http://localhost`),n=v(t.pathname,this.#e);return`${u(this.#e,n)}${t.search}${t.hash}`}#P(e,t){let n=new URL(this.#N(e),`http://localhost`);return{hash:n.hash.replace(/^#/,``),historyState:t,pathname:v(n.pathname,this.#e),query:g(n.search)}}#F(e){let t=new URLSearchParams;for(let[n,r]of Object.entries(e.query))Array.isArray(r)?r.forEach(e=>{t.append(n,e)}):t.set(n,r);let n=t.toString(),r=e.hash?`#${e.hash}`:``;return`${u(this.#e,e.pathname)}${n?`?${n}`:``}${r}`}#I(e){let t=new URL(e,`http://localhost`),n=v(t.pathname,this.#e),{params:r,record:i}=m(n,this.#i);return{name:i?.leaf.name,params:r,pathname:n,query:g(t.search)}}async#L(e,t={}){this.#b();let n=this.#N(e);if(!t.force&&n===this.#m)return;let r=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=await E(this.#l,i,this.#I(n));if(r.isCurrent()&&a)try{await this.#A(r,this.#P(n,t.state),(e,t)=>{if(!r.isCurrent())return;let n=this.#F(e);t?this.#r.replace(n,e.historyState):this.#r.push(n,e.historyState),this.#m=n},t.viewTransition,0,t.replace??!1)}catch(e){throw j(e)?e.error:e}}};function P(e){return new N(e)}exports.WayfinderApiError=i,exports.WayfinderDisposedError=t,exports.WayfinderError=e,exports.WayfinderRedirectLoopError=r,exports.WayfinderRouteError=n,exports.createBrowserHistory=a,exports.createMemoryHistory=o,exports.createRouter=P,exports.redirectTo=s;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(){super(`Router is disposed`)}},n=class extends e{},r=class extends e{constructor(){super(`Redirect loop detected`)}},i=class extends e{};function a(e){let t=`/${e}`.replace(/\/+/g,`/`);return t!==`/`&&t.endsWith(`/`)?t.slice(0,-1):t}function o(e,t){return a(`${e}/${t}`)}function s(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function c(e){let t=a(e);if(t===`/`)return{paramNames:[],pattern:/^\/$/,prefixPattern:/^\/$/};let r=[],i=t.slice(1).split(`/`),o=[`^`],c=[`^`];for(let t=0;t<i.length;t+=1){let a=i[t];if(a===`*`){if(t!==i.length-1)throw new n(`Wildcard "*" must be the final segment in path: ${e}`);o.push(`(?:/.*)?`);break}if(a.startsWith(`:`)&&a.endsWith(`*`)){if(t!==i.length-1)throw new n(`Wildcard param must be final segment in path: ${e}`);let s=a.slice(1,-1);if(!/^\w+$/.test(s))throw new n(`Invalid param name ":${s}" in path "${e}". Param names must only contain word characters (a–z, A–Z, 0–9, _).`);r.push(s),o.push(t===i.length-1?`(?:/(.*))?`:`/(.*)`),c.push(`/.*`);break}if(a.startsWith(`:`)){let t=a.slice(1);if(!/^\w+$/.test(t))throw new n(`Invalid param name ":${t}" in path "${e}". Param names must only contain word characters (a–z, A–Z, 0–9, _).`);r.push(t),o.push(`/([^/]+)`),c.push(`/[^/]+`);continue}let l=s(a);o.push(`/${l}`),c.push(`/${l}`)}return o.push(`$`),c.push(`(?:/.*)?$`),{paramNames:r,pattern:new RegExp(o.join(``)),prefixPattern:new RegExp(c.join(``))}}function l(e,t){let n=t.matcher.pattern.exec(e);if(!n)return null;let r={};return t.matcher.paramNames.forEach((e,t)=>{let i=n[t+1]??``;try{r[e]=decodeURIComponent(i)}catch{r[e]=i}}),r}function u(e,t){for(let n of t){let t=l(e,n);if(t)return{params:t,record:n}}return{params:{}}}function d(e,t){return t.matcher.prefixPattern.test(e)}function f(e){let t=new URLSearchParams(e),n={},r=(e,t)=>{Object.defineProperty(n,e,{configurable:!0,enumerable:!0,value:t,writable:!0})};for(let[e,i]of t.entries()){let t=Object.hasOwn(n,e)?n[e]:void 0;if(t===void 0){r(e,i);continue}if(Array.isArray(t)){t.push(i);continue}r(e,[t,i])}return n}function p(e,t,r={},i){let a=t.replace(/:(\w+)(\*)?/g,(e,t,i)=>{let a=r[t];if(a==null)throw new n(`Missing path param: ${t}`);return i?a.split(`/`).map(e=>encodeURIComponent(e)).join(`/`):encodeURIComponent(a)});if(i&&Object.keys(i).length){let e=new URLSearchParams;Object.entries(i).forEach(([t,n])=>{Array.isArray(n)?n.forEach(n=>{e.append(t,String(n))}):e.set(t,String(n))}),a+=`?${e.toString()}`}return o(e,a)}function m(e,t=`/`){let n=a(e),r=a(t);if(r===`/`)return n;if(n===r)return`/`;let i=`${r}/`;return n.startsWith(i)?a(n.slice(r.length)):n}function h(e,t){return{hash:t.location.hash.replace(/^#/,``),historyState:t.location.state,pathname:m(t.location.pathname||`/`,e),query:f(t.location.search||``)}}function g(){return{back(){window.history.back()},get location(){return{hash:window.location.hash,pathname:window.location.pathname,search:window.location.search,state:window.history.state}},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,e)},replace(e,t){window.history.replaceState(t,``,e)}}}function _(e={}){let t=a(e.base??`/`),n=t===`/`?`/`:`${t}/`,r=()=>{let e=new URL(window.location.hash.slice(1)||`/`,`http://localhost`);return{hash:e.hash,pathname:o(t,e.pathname),search:e.search,state:window.history.state}},i=e=>{let r=new URL(e,`http://localhost`),i=m(r.pathname,t);return`${n}#${i}${r.search}${r.hash}`};return{back(){window.history.back()},get location(){return r()},onPopstate(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},push(e,t){window.history.pushState(t,``,i(e))},replace(e,t){window.history.replaceState(t,``,i(e))}}}function v(e=`/`){let t=new URL(e,`http://localhost`),n=[{hash:t.hash,pathname:t.pathname,search:t.search,state:null}],r=0,i=new Set;return{back(){r<=0||(--r,i.forEach(e=>{e()}))},get location(){return n[r]},onPopstate(e){return i.add(e),()=>i.delete(e)},push(e,t=null){let i=new URL(e,`http://localhost`);n.splice(r+1),n.push({hash:i.hash,pathname:i.pathname,search:i.search,state:t}),r=n.length-1},replace(e,t=null){let i=new URL(e,`http://localhost`);n[r]={hash:i.hash,pathname:i.pathname,search:i.search,state:t}}}}function y(e,t){return async n=>{await n.navigate(e,t)}}function b(){let e;return{begin(){e?.abort();let t=new AbortController;return e=t,{isCurrent:()=>e===t&&!t.signal.aborted,signal:t.signal}},invalidate(t){e?.abort(t),e=void 0}}}function x(e){let t=[],r=(e,i,s,l,u)=>{if(i.index&&i.path!==void 0)throw new n(`Route "${e}" cannot define both index and path`);if(!i.index&&i.path===void 0)throw new n(`Route "${e}" must define path or set index: true`);let d=i.index?s:a(i.path?o(s,i.path):s),f=[...l,{dataFn:i.data,name:e,onError:i.onError}],p=[...u,...i.middleware??[]];if(i.children)for(let[t,n]of Object.entries(i.children))r(`${e}.${t}`,n,d,f,p);if(i.redirect!==void 0||!i.children||i.data!==void 0){let e=f[f.length-1];t.push({branchDefs:f,coerceSearch:i.coerceSearch,leaf:e,matcher:c(d),ownMiddleware:p,path:d,redirect:i.redirect})}};for(let[t,n]of Object.entries(e.routes))r(t,n,`/`,[],[]);let i=new Set;for(let e of t){if(i.has(e.leaf.name))throw new n(`Duplicate route name: "${e.leaf.name}". A top-level route key must not coincide with a nested route's dot-notation name.`);i.add(e.leaf.name)}let s=!1;for(let e of t){let t=e.path===`/*`||e.path.endsWith(`/*`)||e.path.includes(`:`)&&e.path.endsWith(`*`);s&&!t&&`${e.leaf.name}${e.path}`,t&&(s=!0)}return{records:t,routesByName:new Map(t.map(e=>[e.leaf.name,e]))}}function S(e){return{error:e.error,location:e.location,matches:e.matches,status:e.status}}function C(e,t,n,r){return e.map((e,i)=>({data:r[i],name:e.name,params:{...t},pathname:n}))}function w(e,t,n,r,i){return{hash:e.hash,historyState:e.historyState,locals:{},matches:r,navigate:i,params:n,pathname:e.pathname,query:t}}async function T(e,t,n,r){let a=!1;async function o(s){if(s<t.length){let n=!1;try{await t[s]?.(e,async()=>{if(n)throw new i(`next() called multiple times`);n=!0,await o(s+1)})}catch(e){throw r?.(e)??e}return}a=!0,await n()}return await o(0),a}function E(e,t,n){if(n){n(e,t);return}}async function D(e,t,n){let r=new Set(t),i=[...e];for(let{handler:e,routes:t}of i)if((t===void 0||t.some(e=>r.has(e)))&&!await e(n))return!1;return!0}function O(e,t){let r=t.get(e);if(r)return r;let i=[...t.keys()].join(`, `);throw new n(i?`Unknown route name: ${e}. Available routes: ${i}`:`Unknown route name: ${e}`)}function k(e,t,n=`/`){if(`path`in e)return e.path;let r=p(n,O(e.name,t).path,e.params,e.query);return e.hash?`${r}#${e.hash}`:r}var A=Symbol(`wayfinder.routerError`);function j(e,t){return{[A]:!0,context:t,error:e}}function M(e){return typeof e==`object`&&!!e&&A in e}function N(e){throw M(e)?e.error:e}var P=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l=new Set;#u=b();#d;#f=!1;#p=new AbortController;#m=`/`;#h=new Set;#g=new Map;#_=new Map;#v;#y;ready;constructor(e){let t=x(e);if(this.#e=a(e.base??`/`),this.#t=e.middleware??[],this.#n=e.coerceSearch,this.#r=e.history??g(),this.#o=e.onError,this.#s=e.scroll,this.#c=e.viewTransition??!1,this.#i=t.records,this.#a=t.routesByName,this.#d=S({location:{hash:``,historyState:null,pathname:`/`,query:{}},matches:[],status:`idle`}),e.notFound){let t=e.notFound,n={dataFn:t.data,name:`__notFound__`};this.#v={branchDefs:[n],leaf:n,matcher:{paramNames:[],pattern:/(?:)/,prefixPattern:/(?:)/},ownMiddleware:t.middleware??[],path:`/*`}}else this.#v=null;this.#y=this.#x();let{hash:n,pathname:r,search:i}=this.#r.location;this.#m=`${r}${i}${n}`;let o=this.#u.begin(),s=this.#A(o,h(this.#e,this.#r),(e,t)=>{if(!o.isCurrent())return;let n=this.#F(e);t&&this.#r.replace(n,e.historyState),this.#m=n},void 0,0,!1).then(()=>void 0);this.ready=s.catch(N),this.ready.catch(()=>{}),this.#w(s,{source:`initial-navigation`}),this.beforeLeave=this.beforeLeave.bind(this),this.createViewRegistry=this.createViewRegistry.bind(this),this.dispose=this.dispose.bind(this),this.getSnapshot=this.getSnapshot.bind(this),this.isActive=this.isActive.bind(this),this.load=this.load.bind(this),this.match=this.match.bind(this),this.navigate=this.navigate.bind(this),this.preload=this.preload.bind(this),this.subscribe=this.subscribe.bind(this),this.url=this.url.bind(this),this.waitFor=this.waitFor.bind(this)}getSnapshot(){return this.#d}createViewRegistry(e,t){return{resolve:n=>{let r=n.matches.at(-1)?.name;return r===`__notFound__`?t?.notFound:r?e[r]:void 0}}}subscribe(e){return this.#b(),this.#h.add(e),()=>{this.#h.delete(e)}}navigate(e,t){let n=k(typeof e==`string`?{path:e}:e,this.#a);return this.#L(n,t)}url(e,t,n){let r=O(e,this.#a);return p(this.#e,r.path,t,n)}isActive(e,t={}){let n=O(e,this.#a),r=this.#d.location.pathname;return t.exact??!1?u(r,[n]).record!=null:d(r,n)}match(e){let t=m(a(e),this.#e),{params:n,record:r}=u(t,this.#i);if(!r||r.redirect)return null;let i=C(r.branchDefs,n,t,r.branchDefs.map(()=>void 0));return i.length?i:null}async load(e,t){let n=await this.#D(e);if(n.type!==`matched`)return null;let{location:r,params:i,record:a,resolvedQuery:o}=n,s=a.branchDefs,c=s.some(e=>e.dataFn!=null),l=s.map(()=>void 0),u,d=`idle`;if(c){let e=t?.signal??new AbortController().signal,n=w(r,o,i,C(s,i,r.pathname,l),()=>Promise.resolve());try{l=await this.#E(s,n,e)}catch(e){u=e,d=`error`}}return S({error:u,location:r,matches:C(s,i,r.pathname,l),status:d})}async preload(e){this.#b();let t=this.#N(k(e,this.#a,this.#e)),n=this.#_.get(t);if(n)return n;let r=this.load(t,{signal:this.#p.signal}).then(e=>{if(this.#f)throw this.#p.signal.reason;if(e?.status===`error`)throw e.error;if(e){let t=this.#F(e.location);this.#g.size>=20&&this.#g.delete(this.#g.keys().next().value),this.#g.set(t,e.matches.map(e=>e.data))}return e}).catch(e=>{throw this.#o&&this.#C(e,{source:`preload`}),e}).finally(()=>{this.#_.delete(t)});return this.#_.set(t,r),r}waitFor(e){return this.#b(),new Promise((t,n)=>{let r=t=>t.status===`idle`&&t.matches.some(t=>t.name===e);if(this.#d.status===`error`){n(this.#d.error);return}if(r(this.#d)){t(this.#d);return}let i=this.subscribe(e=>{r(e)?(i(),t(e)):e.status===`error`&&(i(),n(e.error))});this.#p.signal.addEventListener(`abort`,()=>{i(),n(this.#p.signal.reason)},{once:!0})})}beforeLeave(e,t){this.#b();let n={handler:e,routes:t?.routes};return this.#l.add(n),()=>{this.#l.delete(n)}}get disposalSignal(){return this.#p.signal}get disposed(){return this.#f}dispose(){this.#f||(this.#f=!0,this.#l.clear(),this.#h.clear(),this.#g.clear(),this.#_.clear(),this.#u.invalidate(new t),this.#y(),this.#p.abort(new t))}[Symbol.dispose](){this.dispose()}#b(){if(this.#f)throw new t}#x(){return this.#r.onPopstate(()=>{let{hash:e,pathname:t,search:n}=this.#r.location,r=`${t}${n}${e}`,i=this.#m;r!==i&&this.#w(this.#S(r,i),{source:`history-listener`})})}async#S(e,t){let n=this.#u.begin(),r=this.#d.matches.map(e=>e.name),i=this.#I(e),a=await D(this.#l,r,i);if(!n.isCurrent())return;if(!a){this.#r.replace(t,this.#d.location.historyState);return}let o=await this.#A(n,h(this.#e,this.#r),(e,t)=>{if(!n.isCurrent())return;let r=this.#F(e);t&&this.#r.replace(r,e.historyState),this.#m=r},void 0,0,!1);n.isCurrent()&&!o&&this.#r.replace(t,this.#d.location.historyState)}#C(e,t){E(e,t,this.#o)}#w(e,t){e.catch(e=>{M(e)?this.#C(e.error,e.context):this.#C(e,t)})}#T(){this.#h.forEach(e=>{e(this.#d)})}async#E(e,t,n){return Promise.all(e.map(async e=>{if(!e.dataFn)return;let r=e.dataFn;try{return await r({...t,signal:n})}catch(r){if(e.onError)return e.onError(r,{...t,signal:n});throw r}}))}async#D(e){let t=e;for(let e=0;e<5;e+=1){let e=new URL(t,`http://localhost`),n={hash:e.hash.replace(/^#/,``),historyState:null,pathname:m(e.pathname,this.#e),query:f(e.search)},r=await this.#O(n);if(r.type!==`redirect`)return r;t=this.#N(r.redirectTo)}throw new r}async#O(e){let{params:t,record:n}=u(e.pathname,this.#i);if(!n)return{location:e,params:t,type:`unmatched`};if(n.redirect)return{location:e,params:t,redirectTo:k(n.redirect,this.#a,this.#e),type:`redirect`};let r=e.query,i=n.coerceSearch??this.#n;if(i)try{r=i(e.query)}catch(t){this.#C(t,{source:`coerce-search`}),r=e.query}return{branch:C(n.branchDefs,t,e.pathname,n.branchDefs.map(()=>void 0)),location:e,params:t,record:n,resolvedQuery:r,type:`matched`}}async#k(e,t,n,r,i,a,o){if(!a())return;let s=e.branchDefs,c=s.some(e=>e.dataFn!=null),l=s.map(()=>void 0);if(c){let e=this.#F(n),c=this.#_.get(e);if(c&&(await c.catch(()=>void 0),!a()))return;let u=this.#g.get(e);if(u)this.#g.delete(e),l=u;else{this.#d=S({location:n,matches:C(s,r,n.pathname,l),status:`loading`}),this.#T();try{l=await this.#E(s,t,i)}catch(e){if(!a())return;throw this.#d=S({error:e,location:n,matches:C(s,r,n.pathname,l),status:`error`}),o?.(e),e}}}a()&&(this.#d=S({location:n,matches:C(s,r,n.pathname,l),status:`idle`}))}async#A(e,t,n,i,a=0,o=!1){let s=this.#d,c=()=>e.isCurrent()&&!this.#f,l=await this.#O(t);if(!c())return!1;if(l.type===`redirect`){if(a>=5)throw new r;return this.#A(e,this.#P(l.redirectTo,t.historyState),n,i,a+1,!0)}if(l.type===`unmatched`){if(this.#v){let r=C([this.#v.leaf],{},t.pathname,[void 0]),a=!1,l,u=!1,d=!1,f=t.query;if(this.#n)try{f=this.#n(t.query)}catch(e){this.#C(e,{source:`coerce-search`})}let p=async()=>{if(!c())return;let i=w(t,f,{},r,(e,t)=>this.navigate(e,t));d=await T(i,[...this.#t,...this.#v.ownMiddleware],async()=>{c()&&(a=!0,n(t,o),c()&&await this.#k(this.#v,i,t,{},e.signal,c,e=>{l=e,u=!0}))},e=>M(e)||u&&e===l?e:j(e,{routeName:`__notFound__`,source:`middleware`}))};try{await this.#j(p,i)}catch(e){throw u&&e===l?j(e,{routeName:`__notFound__`,source:`data-loader`}):e}finally{c()&&a&&(this.#T(),this.#M(this.#d,s))}return d&&a}return!c()||(n(l.location,o),!c())?!1:(this.#d=S({location:l.location,matches:[],status:`idle`}),this.#T(),this.#M(this.#d,s),!0)}let{branch:u,location:d,params:f,record:p,resolvedQuery:m}=l,h=!1,g,_=!1,v=!1,y=async()=>{if(!c())return;let t=w(d,m,f,u,(e,t)=>this.navigate(e,t));v=await T(t,[...this.#t,...p.ownMiddleware],async()=>{c()&&(h=!0,n(d,o),c()&&await this.#k(p,t,d,f,e.signal,c,e=>{g=e,_=!0}))},e=>M(e)||_&&e===g?e:j(e,{routeName:p.leaf.name,source:`middleware`}))};try{await this.#j(y,i)}catch(e){throw _&&e===g?j(e,{routeName:p.leaf.name,source:`data-loader`}):e}finally{c()&&h&&(this.#T(),this.#M(this.#d,s))}return v&&h}async#j(e,t){if((t??this.#c)&&typeof document<`u`){let t=document.startViewTransition;if(t){await t.call(document,e).finished;return}}await e()}#M(e,t){if(!this.#s||typeof window>`u`)return;let n=this.#s(e,t);if(n!==`preserve`){if(n===`top`){window.scrollTo(0,0);return}window.scrollTo(n.x,n.y)}}#N(e){let t=new URL(e,`http://localhost`),n=m(t.pathname,this.#e);return`${o(this.#e,n)}${t.search}${t.hash}`}#P(e,t){let n=new URL(this.#N(e),`http://localhost`);return{hash:n.hash.replace(/^#/,``),historyState:t,pathname:m(n.pathname,this.#e),query:f(n.search)}}#F(e){let t=new URLSearchParams;for(let[n,r]of Object.entries(e.query))Array.isArray(r)?r.forEach(e=>{t.append(n,e)}):t.set(n,r);let n=t.toString(),r=e.hash?`#${e.hash}`:``;return`${o(this.#e,e.pathname)}${n?`?${n}`:``}${r}`}#I(e){let t=new URL(e,`http://localhost`),n=m(t.pathname,this.#e),{params:r,record:i}=u(n,this.#i);return{name:i?.leaf.name,params:r,pathname:n,query:f(t.search)}}async#L(e,t={}){this.#b();let n=this.#N(e);if(!t.force&&n===this.#m)return;let r=this.#u.begin(),i=this.#d.matches.map(e=>e.name),a=await D(this.#l,i,this.#I(n));if(r.isCurrent()&&a)try{await this.#A(r,this.#P(n,t.state),(e,t)=>{if(!r.isCurrent())return;let n=this.#F(e);t?this.#r.replace(n,e.historyState):this.#r.push(n,e.historyState),this.#m=n},t.viewTransition,0,t.replace??!1)}catch(e){throw M(e)?e.error:e}}};function F(e){return new P(e)}exports.WayfinderApiError=i,exports.WayfinderDisposedError=t,exports.WayfinderError=e,exports.WayfinderRedirectLoopError=r,exports.WayfinderRouteError=n,exports.createBrowserHistory=g,exports.createHashHistory=_,exports.createMemoryHistory=v,exports.createRouter=F,exports.redirectTo=y;
2
2
  //# sourceMappingURL=wayfinder.cjs.map