@ktjs/router 0.37.1 → 0.38.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/README.md CHANGED
@@ -17,17 +17,20 @@
17
17
 
18
18
  ## Recent Updates
19
19
 
20
- 1. 0.37.x - fixes and refactors
20
+ 1. 0.38.x - reactive helper additions
21
+ 1. `reactive.is(target)`: create a boolean computed based on `Object.is` comparison.
22
+ 2. `reactive.match(pattern)`: create a boolean computed using deep object/array pattern matching.
23
+ 2. 0.37.x - fixes and refactors
21
24
  1. fix schedulers clear issue. Which would occur when some handler throws an error.
22
25
  2. `Fragment` is refactored. Fixes memory leak issues and makes it more robust.
23
- 2. 0.36.x - override 0.35.x. Now refs and computeds have 2 new apis:
26
+ 3. 0.36.x - override 0.35.x. Now refs and computeds have 2 new apis:
24
27
  1. `get(...keys)`: create a `KTSubComputed` object. It is a light version of computed, used to bind values
25
28
  2. `subref(...keys)`: create a `KTSubRef` object. It is a light version of ref, used to bind values and also support two-way binding with `k-model`.
26
- 3. 0.34.x - `ref.notify()` no-longer has an optional argument.
27
- 4. 0.33.x - `ref.value` remains the standard read API, and it can also replace the whole outer value with `ref.value = nextValue`.
28
- 5. 0.33.x - `ref.draft` is the deep-mutation entry for literally any objects. Just use `someRef.draft.a = someValue`, and kt.js will add it to microqueue and redraw it on the next tick. Works for `Map`, `Set`, `Array`, `Date` and your custom objects.
29
+ 4. 0.34.x - `ref.notify()` no-longer has an optional argument.
30
+ 5. 0.33.x - `ref.value` remains the standard read API, and it can also replace the whole outer value with `ref.value = nextValue`.
31
+ 6. 0.33.x - `ref.draft` is the deep-mutation entry for literally any objects. Just use `someRef.draft.a = someValue`, and kt.js will add it to microqueue and redraw it on the next tick. Works for `Map`, `Set`, `Array`, `Date` and your custom objects.
29
32
  1. `ref.draft` itself is **not assignable**.
30
- 6. `addOnChange((newValue, oldValue) => ...)` keeps `oldValue` as the previous reference, not a deep snapshot.
33
+ 7. `addOnChange((newValue, oldValue) => ...)` keeps `oldValue` as the previous reference, not a deep snapshot.
31
34
 
32
35
  ## Community
33
36
 
package/dist/index.mjs CHANGED
@@ -71,10 +71,10 @@ const createRouter = ({beforeEach: beforeEach = $emptyFn, afterEach: afterEach =
71
71
  let targetPath;
72
72
  if (options.name) {
73
73
  const targetRoute = findByName(options.name);
74
- if (!targetRoute) throw new Error(`[@ktjs/router error] Route not found: ${options.name}`);
74
+ if (!targetRoute) throw new Error(`[kt.js error] Route not found: ${options.name}`);
75
75
  targetPath = targetRoute.path;
76
76
  } else {
77
- if (!options.path) throw new Error("[@ktjs/router error] Either path or name must be provided");
77
+ if (!options.path) throw new Error("[kt.js error] Either path or name must be provided");
78
78
  targetPath = normalizePath(options.path), prefixPath && targetPath !== prefixPath && !targetPath.startsWith(prefixPath + "/") && (targetPath = normalizePath(prefixPath, targetPath));
79
79
  }
80
80
  options.params && (targetPath = emplaceParams(targetPath, options.params));
@@ -139,7 +139,7 @@ const createRouter = ({beforeEach: beforeEach = $emptyFn, afterEach: afterEach =
139
139
  for (let i = 0; i < routes.length; i++) {
140
140
  const route = routes[i];
141
141
  if (void 0 !== route.name) {
142
- if (route.name in nameMap) throw new Error(`[@ktjs/router error] Duplicate route name detected: '${route.name}'`);
142
+ if (route.name in nameMap) throw new Error(`[kt.js error] Duplicate route name detected: '${route.name}'`);
143
143
  nameMap[route.name] = route;
144
144
  }
145
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/core/kt-router.ts","../src/core/index.ts","../src/core/matcher.ts"],"sourcesContent":["import type { JSX } from '@ktjs/core/jsx-runtime';\nimport type { Router } from '../types/router.js';\n\n/**\n * Create a router view container that automatically renders route components\n */\nexport function KTRouter({ router }: { router: Router }): JSX.Element {\n const view = document.createElement('kt-router-view');\n router.setRouterView(view);\n return view as JSX.Element;\n}\n","import { $emptyFn, buildQuery, normalizePath, parseQuery, emplaceParams } from '@ktjs/shared';\n\nimport type { Router, RouterConfig, RouteContext, NavOptions, RawRouteConfig, RouteConfig } from '../types/router.js';\nimport { GuardLevel } from './consts.js';\nimport { createMatcher } from './matcher.js';\n\n/**\n * Create a new router instance\n */\nexport const createRouter = ({\n beforeEach = $emptyFn,\n afterEach = $emptyFn,\n onNotFound = $emptyFn,\n onError = $emptyFn,\n prefix = '',\n routes: rawRoutes,\n}: RouterConfig): Router => {\n // # private values\n const routes: RouteConfig[] = [];\n const matchedMap = new Map<RouteConfig, RouteConfig[]>();\n const history: RouteContext[] = [];\n const prefixPath = prefix ? normalizePath(prefix) : '';\n let routerView: HTMLElement | null = null;\n let current: RouteContext | null = null;\n let ignoreNextHashChange = false;\n\n // # methods\n const normalize = (rawRoutes: RawRouteConfig[], parentPath: string, parentMatched: RouteConfig[]): RouteConfig[] =>\n rawRoutes.map((route) => {\n const path = normalizePath(parentPath, route.path);\n const normalized: RouteConfig = {\n path: prefixPath ? normalizePath(prefixPath, path) : path,\n name: route.name,\n meta: route.meta ?? {},\n beforeEnter: route.beforeEnter ?? $emptyFn,\n after: route.after ?? $emptyFn,\n children: [],\n component: route.component,\n };\n const matched = parentMatched.concat(normalized);\n matchedMap.set(normalized, matched);\n normalized.children = route.children ? normalize(route.children, path, matched) : [];\n\n // directly push the normalized route to the list\n // avoid flatten them again\n routes.push(normalized);\n return normalized;\n });\n\n normalize(rawRoutes, '/', []);\n\n const guard = async (\n to: RouteContext,\n from: RouteContext | null,\n guardLevel: GuardLevel,\n ): Promise<{ continue: boolean; redirectTo?: NavOptions }> => {\n try {\n if (guardLevel === GuardLevel.None) {\n return { continue: true };\n }\n\n if (guardLevel & GuardLevel.Global) {\n const result = await beforeEach(to, from);\n if (result === false) {\n return { continue: false };\n }\n if (typeof result === 'string') {\n return { continue: false, redirectTo: { path: result } };\n }\n if (result && typeof result === 'object') {\n return { continue: false, redirectTo: result };\n }\n }\n\n if (guardLevel & GuardLevel.Route) {\n const targetRoute = to.matched[to.matched.length - 1];\n const result = await targetRoute.beforeEnter(to);\n if (result === false) {\n return { continue: false };\n }\n if (typeof result === 'string') {\n return { continue: false, redirectTo: { path: result } };\n }\n if (result && typeof result === 'object') {\n return { continue: false, redirectTo: result };\n }\n }\n\n return { continue: true };\n } catch (error) {\n onError(error as Error);\n return { continue: false };\n }\n };\n\n const navigatePrepare = (options: NavOptions) => {\n // Resolve target route\n let targetPath: string;\n\n if (options.name) {\n const targetRoute = findByName(options.name);\n if (!targetRoute) {\n $throw(`Route not found: ${options.name}`);\n }\n targetPath = targetRoute.path;\n } else if (options.path) {\n targetPath = normalizePath(options.path);\n if (prefixPath && targetPath !== prefixPath && !targetPath.startsWith(prefixPath + '/')) {\n targetPath = normalizePath(prefixPath, targetPath);\n }\n } else {\n $throw(`Either path or name must be provided`);\n }\n\n // Substitute params\n if (options.params) {\n targetPath = emplaceParams(targetPath, options.params);\n }\n\n // Match final path\n const matched = match(targetPath);\n if (!matched) {\n onNotFound(targetPath);\n return null;\n }\n\n // Build route context\n const queryString = options.query ? buildQuery(options.query) : '';\n const fullPath = targetPath + queryString;\n\n const to: RouteContext = {\n path: targetPath,\n name: matched.route.name ?? '',\n params: { ...matched.params, ...(options.params ?? {}) },\n query: options.query ?? {},\n meta: matched.route.meta ?? {},\n matched: matched.result,\n };\n\n return {\n guardLevel: options.guardLevel ?? GuardLevel.Default,\n replace: options.replace ?? false,\n to,\n fullPath,\n };\n };\n\n const commit = async (\n to: RouteContext,\n fullPath: string,\n replaceHistory: boolean,\n hashMode: 'push' | 'replace' | null,\n ): Promise<void> => {\n if (hashMode && window.location.hash.slice(1) !== fullPath) {\n ignoreNextHashChange = true;\n const hashUrl = '#' + fullPath;\n if (hashMode === 'replace') {\n window.location.replace(hashUrl);\n } else {\n window.location.hash = fullPath;\n }\n }\n\n const from = current;\n current = to;\n if (replaceHistory) {\n if (history.length > 0) {\n history[history.length - 1] = to;\n } else {\n history.push(to);\n }\n } else {\n history.push(to);\n }\n\n if (routerView && to.matched.length > 0) {\n const route = to.matched[to.matched.length - 1];\n const element = await route.component();\n routerView.innerHTML = '';\n routerView.appendChild(element);\n }\n\n void executeAfterHooks(to, from).catch((error) => {\n onError(error as Error, to.matched[to.matched.length - 1]);\n });\n };\n\n const navigate = async (options: NavOptions, redirectCount = 0): Promise<boolean> => {\n try {\n // Prevent infinite redirect loop\n if (redirectCount > 10) {\n onError(new Error('Maximum redirect count exceeded'));\n return false;\n }\n\n const prep = navigatePrepare(options);\n if (!prep) {\n return false;\n }\n\n const { guardLevel, replace, to, fullPath } = prep;\n\n const guardResult = await guard(to, current, guardLevel);\n if (!guardResult.continue) {\n // Check if there's a redirect\n if (guardResult.redirectTo) {\n return await navigate(guardResult.redirectTo, redirectCount + 1);\n }\n return false;\n }\n\n // ---- Guards passed ----\n await commit(to, fullPath, replace, replace ? 'replace' : 'push');\n return true;\n } catch (error) {\n onError(error as Error);\n return false;\n }\n };\n\n const executeAfterHooks = async (to: RouteContext, from: RouteContext | null): Promise<void> => {\n const targetRoute = to.matched[to.matched.length - 1];\n await targetRoute.after(to);\n await afterEach(to, from);\n };\n\n /**\n * Normalize navigation argument\n */\n const normalizeLocation = (loc: string | NavOptions): NavOptions => {\n if (typeof loc !== 'string') {\n return loc;\n }\n\n const [path, queryString] = loc.split('?');\n return {\n path,\n query: queryString ? parseQuery(queryString) : undefined,\n };\n };\n\n const { findByName, match } = createMatcher(routes, matchedMap);\n\n const handleHashChange = async () => {\n if (ignoreNextHashChange) {\n ignoreNextHashChange = false;\n return;\n }\n\n const hash = window.location.hash.slice(1);\n if (!hash) {\n return;\n }\n\n const prep = navigatePrepare(normalizeLocation(hash));\n if (!prep) {\n return;\n }\n\n const { guardLevel, to, fullPath } = prep;\n const guardResult = await guard(to, current, guardLevel);\n if (!guardResult.continue) {\n if (guardResult.redirectTo) {\n await navigate({ ...guardResult.redirectTo, replace: true });\n return;\n }\n\n ignoreNextHashChange = true;\n if (current) {\n window.location.replace('#' + current.path + buildQuery(current.query));\n } else {\n window.location.replace(window.location.pathname + window.location.search);\n }\n return;\n }\n\n await commit(to, fullPath, false, fullPath === hash ? null : 'replace');\n };\n\n // # register events\n window.addEventListener('hashchange', () => {\n void handleHashChange();\n });\n\n // # initialize\n const instance: Router = {\n get current() {\n return current;\n },\n\n get history() {\n return history.concat();\n },\n\n setRouterView(view: HTMLElement) {\n routerView = view;\n },\n\n push(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate(options);\n },\n\n silentPush(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate({ ...options, guardLevel: GuardLevel.Route });\n },\n\n replace(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate({ ...options, replace: true });\n },\n\n back() {\n window.history.back();\n },\n\n forward() {\n window.history.forward();\n },\n };\n const currentHash = window.location.hash.slice(1);\n if (currentHash) {\n void handleHashChange();\n }\n\n return instance;\n};\n\nexport { GuardLevel };\nexport { KTRouter } from './kt-router.js';\n","import type { RouteConfig, RouteMatch } from '../types/router.js';\nimport { extractParams, normalizePath } from '@ktjs/shared';\n\n/**\n * Route matcher for finding matching routes and extracting params\n */\nexport const createMatcher = (routes: RouteConfig[], matchedMap: Map<RouteConfig, RouteConfig[]>) => {\n const nameMap: Record<string, RouteConfig> = {};\n\n for (let i = 0; i < routes.length; i++) {\n const route = routes[i];\n if (route.name !== undefined) {\n if (route.name in nameMap) {\n $throw(`Duplicate route name detected: '${route.name}'`);\n }\n nameMap[route.name] = route;\n }\n }\n\n /**\n * Find route by name\n */\n const findByName = (name: string): RouteConfig | null => {\n return nameMap[name] ?? null;\n };\n\n /**\n * Match path against all routes\n */\n const match = (path: string): RouteMatch | null => {\n const normalizedPath = normalizePath(path);\n\n // Try exact match first\n for (const route of routes) {\n if (route.path === normalizedPath) {\n return {\n route,\n params: {},\n result: matchedMap.get(route) ?? [route],\n };\n }\n }\n\n // Try dynamic routes\n for (const route of routes) {\n if (route.path.includes(':')) {\n const params = extractParams(route.path, normalizedPath);\n if (params) {\n return {\n route,\n params,\n result: matchedMap.get(route) ?? [route],\n };\n }\n }\n }\n\n return null;\n };\n\n return {\n findByName,\n match,\n };\n};\n"],"names":["KTRouter","router","view","document","createElement","setRouterView","createRouter","beforeEach","$emptyFn","afterEach","onNotFound","onError","prefix","routes","rawRoutes","matchedMap","Map","history","prefixPath","normalizePath","routerView","current","ignoreNextHashChange","normalize","parentPath","parentMatched","map","route","path","normalized","name","meta","beforeEnter","after","children","component","matched","concat","set","push","guard","async","to","from","guardLevel","continue","result","redirectTo","targetRoute","length","error","navigatePrepare","options","targetPath","findByName","Error","startsWith","params","emplaceParams","match","fullPath","query","buildQuery","replace","commit","replaceHistory","hashMode","window","location","hash","slice","hashUrl","element","innerHTML","appendChild","executeAfterHooks","catch","navigate","redirectCount","prep","guardResult","normalizeLocation","loc","queryString","split","parseQuery","undefined","nameMap","i","normalizedPath","get","includes","extractParams","createMatcher","handleHashChange","pathname","search","addEventListener","instance","silentPush","back","forward"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/core/kt-router.ts","../src/core/index.ts","../src/core/matcher.ts"],"sourcesContent":["import type { JSX } from '@ktjs/core/jsx-runtime';\nimport type { Router } from '../types/router.js';\n\n/**\n * Create a router view container that automatically renders route components\n */\nexport function KTRouter({ router }: { router: Router }): JSX.Element {\n const view = document.createElement('kt-router-view');\n router.setRouterView(view);\n return view as JSX.Element;\n}\n","import { $emptyFn, buildQuery, normalizePath, parseQuery, emplaceParams } from '@ktjs/shared';\n\nimport type { Router, RouterConfig, RouteContext, NavOptions, RawRouteConfig, RouteConfig } from '../types/router.js';\nimport { GuardLevel } from './consts.js';\nimport { createMatcher } from './matcher.js';\n\n/**\n * Create a new router instance\n */\nexport const createRouter = ({\n beforeEach = $emptyFn,\n afterEach = $emptyFn,\n onNotFound = $emptyFn,\n onError = $emptyFn,\n prefix = '',\n routes: rawRoutes,\n}: RouterConfig): Router => {\n // # private values\n const routes: RouteConfig[] = [];\n const matchedMap = new Map<RouteConfig, RouteConfig[]>();\n const history: RouteContext[] = [];\n const prefixPath = prefix ? normalizePath(prefix) : '';\n let routerView: HTMLElement | null = null;\n let current: RouteContext | null = null;\n let ignoreNextHashChange = false;\n\n // # methods\n const normalize = (rawRoutes: RawRouteConfig[], parentPath: string, parentMatched: RouteConfig[]): RouteConfig[] =>\n rawRoutes.map((route) => {\n const path = normalizePath(parentPath, route.path);\n const normalized: RouteConfig = {\n path: prefixPath ? normalizePath(prefixPath, path) : path,\n name: route.name,\n meta: route.meta ?? {},\n beforeEnter: route.beforeEnter ?? $emptyFn,\n after: route.after ?? $emptyFn,\n children: [],\n component: route.component,\n };\n const matched = parentMatched.concat(normalized);\n matchedMap.set(normalized, matched);\n normalized.children = route.children ? normalize(route.children, path, matched) : [];\n\n // directly push the normalized route to the list\n // avoid flatten them again\n routes.push(normalized);\n return normalized;\n });\n\n normalize(rawRoutes, '/', []);\n\n const guard = async (\n to: RouteContext,\n from: RouteContext | null,\n guardLevel: GuardLevel,\n ): Promise<{ continue: boolean; redirectTo?: NavOptions }> => {\n try {\n if (guardLevel === GuardLevel.None) {\n return { continue: true };\n }\n\n if (guardLevel & GuardLevel.Global) {\n const result = await beforeEach(to, from);\n if (result === false) {\n return { continue: false };\n }\n if (typeof result === 'string') {\n return { continue: false, redirectTo: { path: result } };\n }\n if (result && typeof result === 'object') {\n return { continue: false, redirectTo: result };\n }\n }\n\n if (guardLevel & GuardLevel.Route) {\n const targetRoute = to.matched[to.matched.length - 1];\n const result = await targetRoute.beforeEnter(to);\n if (result === false) {\n return { continue: false };\n }\n if (typeof result === 'string') {\n return { continue: false, redirectTo: { path: result } };\n }\n if (result && typeof result === 'object') {\n return { continue: false, redirectTo: result };\n }\n }\n\n return { continue: true };\n } catch (error) {\n onError(error as Error);\n return { continue: false };\n }\n };\n\n const navigatePrepare = (options: NavOptions) => {\n // Resolve target route\n let targetPath: string;\n\n if (options.name) {\n const targetRoute = findByName(options.name);\n if (!targetRoute) {\n $throw(`Route not found: ${options.name}`);\n }\n targetPath = targetRoute.path;\n } else if (options.path) {\n targetPath = normalizePath(options.path);\n if (prefixPath && targetPath !== prefixPath && !targetPath.startsWith(prefixPath + '/')) {\n targetPath = normalizePath(prefixPath, targetPath);\n }\n } else {\n $throw(`Either path or name must be provided`);\n }\n\n // Substitute params\n if (options.params) {\n targetPath = emplaceParams(targetPath, options.params);\n }\n\n // Match final path\n const matched = match(targetPath);\n if (!matched) {\n onNotFound(targetPath);\n return null;\n }\n\n // Build route context\n const queryString = options.query ? buildQuery(options.query) : '';\n const fullPath = targetPath + queryString;\n\n const to: RouteContext = {\n path: targetPath,\n name: matched.route.name ?? '',\n params: { ...matched.params, ...(options.params ?? {}) },\n query: options.query ?? {},\n meta: matched.route.meta ?? {},\n matched: matched.result,\n };\n\n return {\n guardLevel: options.guardLevel ?? GuardLevel.Default,\n replace: options.replace ?? false,\n to,\n fullPath,\n };\n };\n\n const commit = async (\n to: RouteContext,\n fullPath: string,\n replaceHistory: boolean,\n hashMode: 'push' | 'replace' | null,\n ): Promise<void> => {\n if (hashMode && window.location.hash.slice(1) !== fullPath) {\n ignoreNextHashChange = true;\n const hashUrl = '#' + fullPath;\n if (hashMode === 'replace') {\n window.location.replace(hashUrl);\n } else {\n window.location.hash = fullPath;\n }\n }\n\n const from = current;\n current = to;\n if (replaceHistory) {\n if (history.length > 0) {\n history[history.length - 1] = to;\n } else {\n history.push(to);\n }\n } else {\n history.push(to);\n }\n\n if (routerView && to.matched.length > 0) {\n const route = to.matched[to.matched.length - 1];\n const element = await route.component();\n routerView.innerHTML = '';\n routerView.appendChild(element);\n }\n\n void executeAfterHooks(to, from).catch((error) => {\n onError(error as Error, to.matched[to.matched.length - 1]);\n });\n };\n\n const navigate = async (options: NavOptions, redirectCount = 0): Promise<boolean> => {\n try {\n // Prevent infinite redirect loop\n if (redirectCount > 10) {\n onError(new Error('Maximum redirect count exceeded'));\n return false;\n }\n\n const prep = navigatePrepare(options);\n if (!prep) {\n return false;\n }\n\n const { guardLevel, replace, to, fullPath } = prep;\n\n const guardResult = await guard(to, current, guardLevel);\n if (!guardResult.continue) {\n // Check if there's a redirect\n if (guardResult.redirectTo) {\n return await navigate(guardResult.redirectTo, redirectCount + 1);\n }\n return false;\n }\n\n // ---- Guards passed ----\n await commit(to, fullPath, replace, replace ? 'replace' : 'push');\n return true;\n } catch (error) {\n onError(error as Error);\n return false;\n }\n };\n\n const executeAfterHooks = async (to: RouteContext, from: RouteContext | null): Promise<void> => {\n const targetRoute = to.matched[to.matched.length - 1];\n await targetRoute.after(to);\n await afterEach(to, from);\n };\n\n /**\n * Normalize navigation argument\n */\n const normalizeLocation = (loc: string | NavOptions): NavOptions => {\n if (typeof loc !== 'string') {\n return loc;\n }\n\n const [path, queryString] = loc.split('?');\n return {\n path,\n query: queryString ? parseQuery(queryString) : undefined,\n };\n };\n\n const { findByName, match } = createMatcher(routes, matchedMap);\n\n const handleHashChange = async () => {\n if (ignoreNextHashChange) {\n ignoreNextHashChange = false;\n return;\n }\n\n const hash = window.location.hash.slice(1);\n if (!hash) {\n return;\n }\n\n const prep = navigatePrepare(normalizeLocation(hash));\n if (!prep) {\n return;\n }\n\n const { guardLevel, to, fullPath } = prep;\n const guardResult = await guard(to, current, guardLevel);\n if (!guardResult.continue) {\n if (guardResult.redirectTo) {\n await navigate({ ...guardResult.redirectTo, replace: true });\n return;\n }\n\n ignoreNextHashChange = true;\n if (current) {\n window.location.replace('#' + current.path + buildQuery(current.query));\n } else {\n window.location.replace(window.location.pathname + window.location.search);\n }\n return;\n }\n\n await commit(to, fullPath, false, fullPath === hash ? null : 'replace');\n };\n\n // # register events\n window.addEventListener('hashchange', () => {\n void handleHashChange();\n });\n\n // # initialize\n const instance: Router = {\n get current() {\n return current;\n },\n\n get history() {\n return history.concat();\n },\n\n setRouterView(view: HTMLElement) {\n routerView = view;\n },\n\n push(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate(options);\n },\n\n silentPush(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate({ ...options, guardLevel: GuardLevel.Route });\n },\n\n replace(location: string | NavOptions): boolean | Promise<boolean> {\n const options = normalizeLocation(location);\n return navigate({ ...options, replace: true });\n },\n\n back() {\n window.history.back();\n },\n\n forward() {\n window.history.forward();\n },\n };\n const currentHash = window.location.hash.slice(1);\n if (currentHash) {\n void handleHashChange();\n }\n\n return instance;\n};\n\nexport { GuardLevel };\nexport { KTRouter } from './kt-router.js';\n","import type { RouteConfig, RouteMatch } from '../types/router.js';\nimport { extractParams, normalizePath } from '@ktjs/shared';\n\n/**\n * Route matcher for finding matching routes and extracting params\n */\nexport const createMatcher = (routes: RouteConfig[], matchedMap: Map<RouteConfig, RouteConfig[]>) => {\n const nameMap: Record<string, RouteConfig> = {};\n\n for (let i = 0; i < routes.length; i++) {\n const route = routes[i];\n if (route.name !== undefined) {\n if (route.name in nameMap) {\n $throw(`Duplicate route name detected: '${route.name}'`);\n }\n nameMap[route.name] = route;\n }\n }\n\n /**\n * Find route by name\n */\n const findByName = (name: string): RouteConfig | null => {\n return nameMap[name] ?? null;\n };\n\n /**\n * Match path against all routes\n */\n const match = (path: string): RouteMatch | null => {\n const normalizedPath = normalizePath(path);\n\n // Try exact match first\n for (const route of routes) {\n if (route.path === normalizedPath) {\n return {\n route,\n params: {},\n result: matchedMap.get(route) ?? [route],\n };\n }\n }\n\n // Try dynamic routes\n for (const route of routes) {\n if (route.path.includes(':')) {\n const params = extractParams(route.path, normalizedPath);\n if (params) {\n return {\n route,\n params,\n result: matchedMap.get(route) ?? [route],\n };\n }\n }\n }\n\n return null;\n };\n\n return {\n findByName,\n match,\n };\n};\n"],"names":["KTRouter","router","view","document","createElement","setRouterView","createRouter","beforeEach","$emptyFn","afterEach","onNotFound","onError","prefix","routes","rawRoutes","matchedMap","Map","history","prefixPath","normalizePath","routerView","current","ignoreNextHashChange","normalize","parentPath","parentMatched","map","route","path","normalized","name","meta","beforeEnter","after","children","component","matched","concat","set","push","guard","async","to","from","guardLevel","continue","result","redirectTo","targetRoute","length","error","navigatePrepare","options","targetPath","findByName","Error","startsWith","params","emplaceParams","match","fullPath","query","buildQuery","replace","commit","replaceHistory","hashMode","window","location","hash","slice","hashUrl","element","innerHTML","appendChild","executeAfterHooks","catch","navigate","redirectCount","prep","guardResult","normalizeLocation","loc","queryString","split","parseQuery","undefined","nameMap","i","normalizedPath","get","includes","extractParams","createMatcher","handleHashChange","pathname","search","addEventListener","instance","silentPush","back","forward"],"mappings":";;AAMM,SAAUA,UAASC,QAAEA;IACzB,MAAMC,OAAOC,SAASC,cAAc;IAEpC,OADAH,OAAOI,cAAcH,OACdA;AACT;;ACDO,MAAMI,eAAe,EAC1BC,yBAAaC,UACbC,uBAAYD,UACZE,yBAAaF,UACbG,mBAAUH,UACVI,iBAAS,IACTC,QAAQC;IAGR,MAAMD,SAAwB,IACxBE,aAAa,IAAIC,KACjBC,UAA0B,IAC1BC,aAAaN,SAASO,cAAcP,UAAU;IACpD,IAAIQ,aAAiC,MACjCC,UAA+B,MAC/BC,wBAAuB;IAG3B,MAAMC,YAAY,CAACT,WAA6BU,YAAoBC,kBAClEX,UAAUY,IAAKC;QACb,MAAMC,OAAOT,cAAcK,YAAYG,MAAMC,OACvCC,aAA0B;YAC9BD,MAAMV,aAAaC,cAAcD,YAAYU,QAAQA;YACrDE,MAAMH,MAAMG;YACZC,MAAMJ,MAAMI,QAAQ,CAAA;YACpBC,aAAaL,MAAMK,eAAexB;YAClCyB,OAAON,MAAMM,SAASzB;YACtB0B,UAAU;YACVC,WAAWR,MAAMQ;WAEbC,UAAUX,cAAcY,OAAOR;QAOrC,OANAd,WAAWuB,IAAIT,YAAYO,UAC3BP,WAAWK,WAAWP,MAAMO,WAAWX,UAAUI,MAAMO,UAAUN,MAAMQ,WAAW;QAIlFvB,OAAO0B,KAAKV,aACLA;;IAGXN,UAAUT,WAAW,KAAK;IAE1B,MAAM0B,QAAQC,OACZC,IACAC,MACAC;QAEA;YACE,IAAc,MAAVA,YACF,OAAO;gBAAEC,WAAU;;YAGrB,IAAc,IAAVD,YAAgC;gBAClC,MAAME,eAAevC,WAAWmC,IAAIC;gBACpC,KAAe,MAAXG,QACF,OAAO;oBAAED,WAAU;;gBAErB,IAAsB,mBAAXC,QACT,OAAO;oBAAED,WAAU;oBAAOE,YAAY;wBAAEnB,MAAMkB;;;gBAEhD,IAAIA,UAA4B,mBAAXA,QACnB,OAAO;oBAAED,WAAU;oBAAOE,YAAYD;;AAE1C;YAEA,IAAc,IAAVF,YAA+B;gBACjC,MAAMI,cAAcN,GAAGN,QAAQM,GAAGN,QAAQa,SAAS,IAC7CH,eAAeE,YAAYhB,YAAYU;gBAC7C,KAAe,MAAXI,QACF,OAAO;oBAAED,WAAU;;gBAErB,IAAsB,mBAAXC,QACT,OAAO;oBAAED,WAAU;oBAAOE,YAAY;wBAAEnB,MAAMkB;;;gBAEhD,IAAIA,UAA4B,mBAAXA,QACnB,OAAO;oBAAED,WAAU;oBAAOE,YAAYD;;AAE1C;YAEA,OAAO;gBAAED,WAAU;;AACrB,UAAE,OAAOK;YAEP,OADAvC,QAAQuC,QACD;gBAAEL,WAAU;;AACrB;OAGIM,kBAAmBC;QAEvB,IAAIC;QAEJ,IAAID,QAAQtB,MAAM;YAChB,MAAMkB,cAAcM,WAAWF,QAAQtB;YACvC,KAAKkB,aACH,MAAA,IAAAO,MAAA,kCAA2BH,QAAQtB;YAErCuB,aAAaL,YAAYpB;AAC3B,eAAO;YAAA,KAAIwB,QAAQxB,MAMjB;YALAyB,aAAalC,cAAciC,QAAQxB,OAC/BV,cAAcmC,eAAenC,eAAemC,WAAWG,WAAWtC,aAAa,SACjFmC,aAAalC,cAAcD,YAAYmC;AAI3C;QAGID,QAAQK,WACVJ,aAAaK,cAAcL,YAAYD,QAAQK;QAIjD,MAAMrB,UAAUuB,MAAMN;QACtB,KAAKjB,SAEH,OADA1B,WAAW2C,aACJ;QAIT,MACMO,WAAWP,cADGD,QAAQS,QAAQC,WAAWV,QAAQS,SAAS,KAG1DnB,KAAmB;YACvBd,MAAMyB;YACNvB,MAAMM,QAAQT,MAAMG,QAAQ;YAC5B2B,QAAQ;mBAAKrB,QAAQqB;mBAAYL,QAAQK,UAAU,CAAA;;YACnDI,OAAOT,QAAQS,SAAS,CAAA;YACxB9B,MAAMK,QAAQT,MAAMI,QAAQ,CAAA;YAC5BK,SAASA,QAAQU;;QAGnB,OAAO;YACLF,YAAYQ,QAAQR,cAAU;YAC9BmB,SAASX,QAAQW,YAAW;YAC5BrB;YACAkB;;OAIEI,SAASvB,OACbC,IACAkB,UACAK,gBACAC;QAEA,IAAIA,YAAYC,OAAOC,SAASC,KAAKC,MAAM,OAAOV,UAAU;YAC1DtC,wBAAuB;YACvB,MAAMiD,UAAU,MAAMX;YACL,cAAbM,WACFC,OAAOC,SAASL,QAAQQ,WAExBJ,OAAOC,SAASC,OAAOT;AAE3B;QAEA,MAAMjB,OAAOtB;QAYb,IAXAA,UAAUqB,IACNuB,kBACEhD,QAAQgC,SAAS,IACnBhC,QAAQA,QAAQgC,SAAS,KAAKP,KAKhCzB,QAAQsB,KAAKG;QAGXtB,cAAcsB,GAAGN,QAAQa,SAAS,GAAG;YACvC,MAAMtB,QAAQe,GAAGN,QAAQM,GAAGN,QAAQa,SAAS,IACvCuB,gBAAgB7C,MAAMQ;YAC5Bf,WAAWqD,YAAY,IACvBrD,WAAWsD,YAAYF;AACzB;QAEKG,kBAAkBjC,IAAIC,MAAMiC,MAAO1B;YACtCvC,QAAQuC,OAAgBR,GAAGN,QAAQM,GAAGN,QAAQa,SAAS;;OAIrD4B,WAAWpC,OAAOW,SAAqB0B,gBAAgB;QAC3D;YAEE,IAAIA,gBAAgB,IAElB,OADAnE,QAAQ,IAAI4C,MAAM;aACX;YAGT,MAAMwB,OAAO5B,gBAAgBC;YAC7B,KAAK2B,MACH,QAAO;YAGT,OAAMnC,YAAEA,YAAUmB,SAAEA,SAAOrB,IAAEA,IAAEkB,UAAEA,YAAamB,MAExCC,oBAAoBxC,MAAME,IAAIrB,SAASuB;YAC7C,OAAKoC,YAAYnC,kBASXmB,OAAOtB,IAAIkB,UAAUG,SAASA,UAAU,YAAY;aACnD,OARDiB,YAAYjC,oBACD8B,SAASG,YAAYjC,YAAY+B,gBAAgB;AAQpE,UAAE,OAAO5B;YAEP,OADAvC,QAAQuC,SACD;AACT;OAGIyB,oBAAoBlC,OAAOC,IAAkBC;QACjD,MAAMK,cAAcN,GAAGN,QAAQM,GAAGN,QAAQa,SAAS;cAC7CD,YAAYf,MAAMS,WAClBjC,UAAUiC,IAAIC;OAMhBsC,oBAAqBC;QACzB,IAAmB,mBAARA,KACT,OAAOA;QAGT,OAAOtD,MAAMuD,eAAeD,IAAIE,MAAM;QACtC,OAAO;YACLxD;YACAiC,OAAOsB,cAAcE,WAAWF,oBAAeG;;QAI7ChC,YAAEA,YAAUK,OAAEA,SC3OO,EAAC9C,QAAuBE;QACnD,MAAMwE,UAAuC,CAAA;QAE7C,KAAK,IAAIC,IAAI,GAAGA,IAAI3E,OAAOoC,QAAQuC,KAAK;YACtC,MAAM7D,QAAQd,OAAO2E;YACrB,SAAmBF,MAAf3D,MAAMG,MAAoB;gBAC5B,IAAIH,MAAMG,QAAQyD,SAChB,MAAA,IAAAhC,MAAA,iDAA0C5B,MAAMG;gBAElDyD,QAAQ5D,MAAMG,QAAQH;AACxB;AACF;QA2CA,OAAO;YACL2B,YAvCkBxB,QACXyD,QAAQzD,SAAS;YAuCxB6B,OAjCa/B;gBACb,MAAM6D,iBAAiBtE,cAAcS;gBAGrC,KAAK,MAAMD,SAASd,QAClB,IAAIc,MAAMC,SAAS6D,gBACjB,OAAO;oBACL9D;oBACA8B,QAAQ,CAAA;oBACRX,QAAQ/B,WAAW2E,IAAI/D,UAAU,EAACA;;gBAMxC,KAAK,MAAMA,SAASd,QAClB,IAAIc,MAAMC,KAAK+D,SAAS,MAAM;oBAC5B,MAAMlC,SAASmC,cAAcjE,MAAMC,MAAM6D;oBACzC,IAAIhC,QACF,OAAO;wBACL9B;wBACA8B;wBACAX,QAAQ/B,WAAW2E,IAAI/D,UAAU,EAACA;;AAGxC;gBAGF,OAAO;;;MDwLqBkE,CAAchF,QAAQE,aAE9C+E,mBAAmBrD;QACvB,IAAInB,sBAEF,aADAA,wBAAuB;QAIzB,MAAM+C,OAAOF,OAAOC,SAASC,KAAKC,MAAM;QACxC,KAAKD,MACH;QAGF,MAAMU,OAAO5B,gBAAgB8B,kBAAkBZ;QAC/C,KAAKU,MACH;QAGF,OAAMnC,YAAEA,YAAUF,IAAEA,IAAEkB,UAAEA,YAAamB,MAC/BC,oBAAoBxC,MAAME,IAAIrB,SAASuB;QAC7C,KAAKoC,YAAYnC,UACf,OAAImC,YAAYjC,wBACR8B,SAAS;eAAKG,YAAYjC;YAAYgB,UAAS;cAIvDzC,wBAAuB,SACnBD,UACF8C,OAAOC,SAASL,QAAQ,MAAM1C,QAAQO,OAAOkC,WAAWzC,QAAQwC,UAEhEM,OAAOC,SAASL,QAAQI,OAAOC,SAAS2B,WAAW5B,OAAOC,SAAS4B;cAKjEhC,OAAOtB,IAAIkB,WAAU,GAAOA,aAAaS,OAAO,OAAO;;IAI/DF,OAAO8B,iBAAiB,cAAc;QAC/BH;;IAIP,MAAMI,WAAmB;QACvB,WAAI7E;YACF,OAAOA;AACT;QAEA,WAAIJ;YACF,OAAOA,QAAQoB;AACjB;QAEA,aAAAhC,CAAcH;YACZkB,aAAalB;AACf;QAEA,IAAAqC,CAAK6B;YACH,MAAMhB,UAAU6B,kBAAkBb;YAClC,OAAOS,SAASzB;AAClB;QAEA,UAAA+C,CAAW/B;YACT,MAAMhB,UAAU6B,kBAAkBb;YAClC,OAAOS,SAAS;mBAAKzB;gBAASR,YAAU;;AAC1C;QAEA,OAAAmB,CAAQK;YACN,MAAMhB,UAAU6B,kBAAkBb;YAClC,OAAOS,SAAS;mBAAKzB;gBAASW,UAAS;;AACzC;QAEA,IAAAqC;YACEjC,OAAOlD,QAAQmF;AACjB;QAEA,OAAAC;YACElC,OAAOlD,QAAQoF;AACjB;;IAOF,OALoBlC,OAAOC,SAASC,KAAKC,MAAM,MAExCwB,oBAGAI;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/router",
3
- "version": "0.37.1",
3
+ "version": "0.38.0",
4
4
  "description": "Router for kt.js - client-side routing with navigation guards",
5
5
  "description_zh": "kt.js 的路由库,支持前端路由与导航守卫。",
6
6
  "type": "module",