@ktjs/router 0.20.0 → 0.31.9

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
@@ -40,6 +40,14 @@ Client-side router with navigation guards for KT.js.
40
40
 
41
41
  ## Installation
42
42
 
43
+ ### Create a KT.js project
44
+
45
+ ```bash
46
+ pnpm create kt.js my-app
47
+ ```
48
+
49
+ ### Add router to an existing project
50
+
43
51
  ```bash
44
52
  pnpm add @ktjs/router @ktjs/core
45
53
  ```
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { JSX } from '@ktjs/core/jsx-runtime';
2
+
1
3
  /**
2
4
  * Guard level that determines which guards to apply during navigation
3
5
  * - there are global and route-level guards
package/dist/index.mjs CHANGED
@@ -1,93 +1,4 @@
1
- // Cached native methods for performance optimization
2
-
3
- // Error handling utilities
4
- const $throw = (message) => {
5
- throw new Error('@ktjs/shared: ' + message);
6
- };
7
-
8
- // String manipulation utilities
9
- /**
10
- * Default empty function
11
- */
12
- const $emptyFn = (() => true);
13
- const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
14
-
15
- /**
16
- * Normalize path by joining parts and ensuring leading slash
17
- */
18
- const normalizePath = (...paths) => {
19
- const p = paths
20
- .map((p) => p.split('/'))
21
- .flat()
22
- .filter(Boolean);
23
- return '/' + p.join('/');
24
- };
25
- /**
26
- * Parse query string into object
27
- */
28
- const parseQuery = (queryString) => {
29
- const query = {};
30
- if (!queryString || queryString === '?') {
31
- return query;
32
- }
33
- const params = queryString.replace(/^\?/, '').split('&');
34
- for (const param of params) {
35
- const [key, value] = param.split('=');
36
- if (key) {
37
- query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
38
- }
39
- }
40
- return query;
41
- };
42
- /**
43
- * Build query string from object
44
- */
45
- const buildQuery = (query) => {
46
- const keys = Object.keys(query);
47
- if (keys.length === 0)
48
- return '';
49
- const params = keys.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`).join('&');
50
- return `?${params}`;
51
- };
52
- /**
53
- * Substitute params into path pattern
54
- * @example '/user/:id' + {id: '123'} => '/user/123'
55
- */
56
- const emplaceParams = (path, params) => {
57
- let result = path;
58
- for (const key in params) {
59
- result = result.replace(`:${key}`, params[key]);
60
- }
61
- return result;
62
- };
63
- /**
64
- * Extract dynamic params from path using pattern
65
- * @example pattern: '/user/:id', path: '/user/123' => {id: '123'}
66
- */
67
- const extractParams = (pattern, path) => {
68
- const params = {};
69
- const patternParts = pattern.split('/');
70
- const pathParts = path.split('/');
71
- if (patternParts.length !== pathParts.length) {
72
- return null;
73
- }
74
- for (let i = 0; i < patternParts.length; i++) {
75
- const patternPart = patternParts[i];
76
- const pathPart = pathParts[i];
77
- if (patternPart.startsWith(':')) {
78
- const paramName = patternPart.slice(1);
79
- params[paramName] = pathPart;
80
- }
81
- else if (patternPart !== pathPart) {
82
- return null;
83
- }
84
- }
85
- return params;
86
- };
87
-
88
- // Shared utilities and cached native methods for kt.js framework
89
- // Re-export all utilities
90
- Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
1
+ import { normalizePath, extractParams, $emptyFn, parseQuery, emplaceParams, buildQuery } from '@ktjs/shared';
91
2
 
92
3
  /**
93
4
  * Route matcher for finding matching routes and extracting params
@@ -98,7 +9,7 @@ const createMatcher = (routes) => {
98
9
  const route = routes[i];
99
10
  if (route.name !== undefined) {
100
11
  if (route.name in nameMap) {
101
- $throw(`Duplicate route name detected: '${route.name}'`);
12
+ throw new Error(`[@ktjs/router error] Duplicate route name detected: '${route.name}'`);
102
13
  }
103
14
  nameMap[route.name] = route;
104
15
  }
@@ -240,7 +151,7 @@ const createRouter = ({ beforeEach = $emptyFn, afterEach = $emptyFn, onNotFound
240
151
  if (options.name) {
241
152
  targetRoute = findByName(options.name);
242
153
  if (!targetRoute) {
243
- $throw(`Route not found: ${options.name}`);
154
+ throw new Error(`[@ktjs/router error] Route not found: ${options.name}`);
244
155
  }
245
156
  targetPath = targetRoute.path;
246
157
  }
@@ -249,7 +160,7 @@ const createRouter = ({ beforeEach = $emptyFn, afterEach = $emptyFn, onNotFound
249
160
  targetRoute = match(targetPath)?.route;
250
161
  }
251
162
  else {
252
- $throw(`Either path or name must be provided`);
163
+ throw new Error(`[@ktjs/router error] Either path or name must be provided`);
253
164
  }
254
165
  // Substitute params
255
166
  if (options.params) {
@@ -438,3 +349,4 @@ const createRouter = ({ beforeEach = $emptyFn, afterEach = $emptyFn, onNotFound
438
349
  };
439
350
 
440
351
  export { KTRouter, createRouter };
352
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/core/matcher.ts","../src/core/kt-router.ts","../src/core/index.ts"],"sourcesContent":["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[]) => {\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: getMatchedChain(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: getMatchedChain(route),\n };\n }\n }\n }\n\n return null;\n };\n\n /**\n * Get chain of matched routes (for nested routes)\n * - parent roots ahead\n */\n const getMatchedChain = (route: RouteConfig): RouteConfig[] => {\n const matched: RouteConfig[] = [route];\n const path = route.path;\n\n // Find parent routes by path prefix matching\n for (let i = 0; i < routes.length; i++) {\n const r = routes[i];\n if (r !== route && path.startsWith(r.path) && path !== r.path) {\n matched.push(r);\n }\n }\n\n return matched.reverse();\n };\n\n return {\n findByName,\n match,\n };\n};\n","import { 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 history: RouteContext[] = [];\n let routerView: HTMLElement | null = null;\n let current: RouteContext | null = null;\n\n // # methods\n const normalize = (rawRoutes: RawRouteConfig[], parentPath: string): RouteConfig[] =>\n rawRoutes.map((route) => {\n const path = normalizePath(parentPath, route.path);\n const normalized = {\n path: prefix + path,\n name: route.name ?? '',\n meta: route.meta ?? {},\n beforeEnter: route.beforeEnter ?? $emptyFn,\n after: route.after ?? $emptyFn,\n children: route.children ? normalize(route.children, path) : [],\n component: route.component,\n };\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 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 let targetRoute;\n\n if (options.name) {\n 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 targetRoute = match(targetPath)?.route;\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 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\n const hashUrl = '#' + fullPath;\n if (replace) {\n window.location.replace(hashUrl);\n } else {\n window.location.hash = fullPath;\n }\n\n current = to;\n if (replace) {\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 // Render component if routerView exists\n if (routerView && to.matched.length > 0) {\n const route = to.matched[to.matched.length - 1];\n if (route.component) {\n const element = await route.component();\n routerView.innerHTML = '';\n routerView.appendChild(element);\n }\n }\n\n executeAfterHooks(to, history[history.length - 2] ?? null);\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 // # register events\n window.addEventListener('hashchange', () => {\n const hash = window.location.hash.slice(1);\n const [path] = hash.split('?');\n const normalizedPath = normalizePath(path);\n if (current && current.path === normalizedPath) {\n return;\n }\n // render route for new hash without adding extra history entry\n const matched = match(normalizedPath);\n if (!matched) {\n onNotFound(normalizedPath);\n return;\n }\n const queryString = window.location.hash.slice(1).split('?')[1];\n const to: RouteContext = {\n path: normalizedPath,\n name: matched.route.name,\n params: matched.params,\n query: queryString ? parseQuery(queryString) : {},\n meta: matched.route.meta ?? {},\n matched: matched.result,\n };\n\n // apply without modifying browser history\n current = to;\n history.push(to);\n\n if (routerView && to.matched.length > 0) {\n const route = to.matched[to.matched.length - 1];\n if (route.component) {\n const element = route.component();\n if (element instanceof Promise) {\n element.then((el) => {\n routerView!.innerHTML = '';\n routerView!.appendChild(el);\n });\n } else {\n routerView.innerHTML = '';\n routerView.appendChild(element);\n }\n }\n }\n\n executeAfterHooks(to, history[history.length - 2] ?? null);\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 normalize(rawRoutes, '/');\n const { findByName, match } = createMatcher(routes);\n const currentHash = window.location.hash.slice(1);\n if (currentHash) {\n instance.push(currentHash);\n }\n\n return instance;\n};\n\nexport { GuardLevel };\nexport { KTRouter } from './kt-router.js';\n"],"names":[],"mappings":";;AAGA;;AAEG;AACI,MAAM,aAAa,GAAG,CAAC,MAAqB,KAAI;IACrD,MAAM,OAAO,GAAgC,EAAE;AAE/C,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACtC,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;AACvB,QAAA,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE;AAC5B,YAAA,IAAI,KAAK,CAAC,IAAI,IAAI,OAAO,EAAE;AACzB,gBAAA,MAAA,IAAA,KAAA,CAAA,CAAA,qDAAO,EAAmC,KAAK,CAAC,IAAI,CAAA,CAAA,CAAG,CAAC;YAC1D;AACA,YAAA,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK;QAC7B;IACF;AAEA;;AAEG;AACH,IAAA,MAAM,UAAU,GAAG,CAAC,IAAY,KAAwB;AACtD,QAAA,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI;AAC9B,IAAA,CAAC;AAED;;AAEG;AACH,IAAA,MAAM,KAAK,GAAG,CAAC,IAAY,KAAuB;AAChD,QAAA,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC;;AAG1C,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,YAAA,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE;gBACjC,OAAO;oBACL,KAAK;AACL,oBAAA,MAAM,EAAE,EAAE;AACV,oBAAA,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC;iBAC/B;YACH;QACF;;AAGA,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gBAC5B,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC;gBACxD,IAAI,MAAM,EAAE;oBACV,OAAO;wBACL,KAAK;wBACL,MAAM;AACN,wBAAA,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC;qBAC/B;gBACH;YACF;QACF;AAEA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC;AAED;;;AAGG;AACH,IAAA,MAAM,eAAe,GAAG,CAAC,KAAkB,KAAmB;AAC5D,QAAA,MAAM,OAAO,GAAkB,CAAC,KAAK,CAAC;AACtC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI;;AAGvB,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACtC,YAAA,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AACnB,YAAA,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE;AAC7D,gBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACjB;QACF;AAEA,QAAA,OAAO,OAAO,CAAC,OAAO,EAAE;AAC1B,IAAA,CAAC;IAED,OAAO;QACL,UAAU;QACV,KAAK;KACN;AACH,CAAC;;AChFD;;AAEG;AACG,SAAU,QAAQ,CAAC,EAAE,MAAM,EAAsB,EAAA;IACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC;AACrD,IAAA,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;AAC1B,IAAA,OAAO,IAAmB;AAC5B;;ACJA;;AAEG;AACI,MAAM,YAAY,GAAG,CAAC,EAC3B,UAAU,GAAG,QAAQ,EACrB,SAAS,GAAG,QAAQ,EACpB,UAAU,GAAG,QAAQ,EACrB,OAAO,GAAG,QAAQ,EAClB,MAAM,GAAG,EAAE,EACX,MAAM,EAAE,SAAS,GACJ,KAAY;;IAEzB,MAAM,MAAM,GAAkB,EAAE;IAChC,MAAM,OAAO,GAAmB,EAAE;IAClC,IAAI,UAAU,GAAuB,IAAI;IACzC,IAAI,OAAO,GAAwB,IAAI;;AAGvC,IAAA,MAAM,SAAS,GAAG,CAAC,SAA2B,EAAE,UAAkB,KAChE,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;QACtB,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC;AAClD,QAAA,MAAM,UAAU,GAAG;YACjB,IAAI,EAAE,MAAM,GAAG,IAAI;AACnB,YAAA,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;AACtB,YAAA,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;AACtB,YAAA,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,QAAQ;AAC1C,YAAA,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ;AAC9B,YAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;YAC/D,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;;;AAID,QAAA,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;AACvB,QAAA,OAAO,UAAU;AACnB,IAAA,CAAC,CAAC;IAEJ,MAAM,KAAK,GAAG,OACZ,EAAgB,EAChB,IAAyB,EACzB,UAAsB,KACqC;AAC3D,QAAA,IAAI;YACF,IAAI,UAAU,KAAA,CAAA,wBAAsB;AAClC,gBAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC3B;YAEA,IAAI,UAAU,GAAA,CAAA,0BAAsB;gBAClC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC;AACzC,gBAAA,IAAI,MAAM,KAAK,KAAK,EAAE;AACpB,oBAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC5B;AACA,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;gBAC1D;AACA,gBAAA,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;oBACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE;gBAChD;YACF;YAEA,IAAI,UAAU,GAAA,CAAA,yBAAqB;AACjC,gBAAA,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;AAChD,gBAAA,IAAI,MAAM,KAAK,KAAK,EAAE;AACpB,oBAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;gBAC5B;AACA,gBAAA,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC9B,oBAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;gBAC1D;AACA,gBAAA,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;oBACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE;gBAChD;YACF;AAEA,YAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC3B;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAc,CAAC;AACvB,YAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5B;AACF,IAAA,CAAC;AAED,IAAA,MAAM,eAAe,GAAG,CAAC,OAAmB,KAAI;;AAE9C,QAAA,IAAI,UAAkB;AACtB,QAAA,IAAI,WAAW;AAEf,QAAA,IAAI,OAAO,CAAC,IAAI,EAAE;AAChB,YAAA,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;YACtC,IAAI,CAAC,WAAW,EAAE;AAChB,gBAAA,MAAA,IAAA,KAAA,CAAA,CAAA,sCAAO,EAAoB,OAAO,CAAC,IAAI,CAAA,CAAE,CAAC;YAC5C;AACA,YAAA,UAAU,GAAG,WAAW,CAAC,IAAI;QAC/B;AAAO,aAAA,IAAI,OAAO,CAAC,IAAI,EAAE;AACvB,YAAA,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC;AACxC,YAAA,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK;QACxC;aAAO;YACL,0EAAO,CAAsC,CAAC;QAChD;;AAGA,QAAA,IAAI,OAAO,CAAC,MAAM,EAAE;YAClB,UAAU,GAAG,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;QACxD;;AAGA,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE;YACZ,UAAU,CAAC,UAAU,CAAC;AACtB,YAAA,OAAO,IAAI;QACb;;AAGA,QAAA,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;AAClE,QAAA,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW;AAEzC,QAAA,MAAM,EAAE,GAAiB;AACvB,YAAA,IAAI,EAAE,UAAU;AAChB,YAAA,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;AACxB,YAAA,MAAM,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE;AACxD,YAAA,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;AAC1B,YAAA,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE;YAC9B,OAAO,EAAE,OAAO,CAAC,MAAM;SACxB;QAED,OAAO;AACL,YAAA,UAAU,EAAE,OAAO,CAAC,UAAU,IAAA,EAAA;AAC9B,YAAA,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK;YACjC,EAAE;YACF,QAAQ;SACT;AACH,IAAA,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,OAAmB,EAAE,aAAa,GAAG,CAAC,KAAsB;AAClF,QAAA,IAAI;;AAEF,YAAA,IAAI,aAAa,GAAG,EAAE,EAAE;AACtB,gBAAA,OAAO,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;AACrD,gBAAA,OAAO,KAAK;YACd;AAEA,YAAA,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC;YACrC,IAAI,CAAC,IAAI,EAAE;AACT,gBAAA,OAAO,KAAK;YACd;YAEA,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,IAAI;YAElD,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC;AACxD,YAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;;AAEzB,gBAAA,IAAI,WAAW,CAAC,UAAU,EAAE;oBAC1B,OAAO,MAAM,QAAQ,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,GAAG,CAAC,CAAC;gBAClE;AACA,gBAAA,OAAO,KAAK;YACd;;AAIA,YAAA,MAAM,OAAO,GAAG,GAAG,GAAG,QAAQ;YAC9B,IAAI,OAAO,EAAE;AACX,gBAAA,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;YAClC;iBAAO;AACL,gBAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,QAAQ;YACjC;YAEA,OAAO,GAAG,EAAE;YACZ,IAAI,OAAO,EAAE;AACX,gBAAA,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;oBACtB,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE;gBAClC;qBAAO;AACL,oBAAA,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB;YACF;iBAAO;AACL,gBAAA,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAClB;;YAGA,IAAI,UAAU,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AACvC,gBAAA,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAC/C,gBAAA,IAAI,KAAK,CAAC,SAAS,EAAE;AACnB,oBAAA,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;AACvC,oBAAA,UAAU,CAAC,SAAS,GAAG,EAAE;AACzB,oBAAA,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC;gBACjC;YACF;AAEA,YAAA,iBAAiB,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AAC1D,YAAA,OAAO,IAAI;QACb;QAAE,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAc,CAAC;AACvB,YAAA,OAAO,KAAK;QACd;AACF,IAAA,CAAC;IAED,MAAM,iBAAiB,GAAG,OAAO,EAAgB,EAAE,IAAyB,KAAmB;AAC7F,QAAA,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AACrD,QAAA,MAAM,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3B,QAAA,MAAM,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC;AAC3B,IAAA,CAAC;AAED;;AAEG;AACH,IAAA,MAAM,iBAAiB,GAAG,CAAC,GAAwB,KAAgB;AACjE,QAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC3B,YAAA,OAAO,GAAG;QACZ;AAEA,QAAA,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;QAC1C,OAAO;YACL,IAAI;AACJ,YAAA,KAAK,EAAE,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,SAAS;SACzD;AACH,IAAA,CAAC;;AAGD,IAAA,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,MAAK;AACzC,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC9B,QAAA,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC;QAC1C,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE;YAC9C;QACF;;AAEA,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC;QACrC,IAAI,CAAC,OAAO,EAAE;YACZ,UAAU,CAAC,cAAc,CAAC;YAC1B;QACF;QACA,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/D,QAAA,MAAM,EAAE,GAAiB;AACvB,YAAA,IAAI,EAAE,cAAc;AACpB,YAAA,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;AACtB,YAAA,KAAK,EAAE,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE;AACjD,YAAA,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE;YAC9B,OAAO,EAAE,OAAO,CAAC,MAAM;SACxB;;QAGD,OAAO,GAAG,EAAE;AACZ,QAAA,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAEhB,IAAI,UAAU,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AACvC,YAAA,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;AAC/C,YAAA,IAAI,KAAK,CAAC,SAAS,EAAE;AACnB,gBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,EAAE;AACjC,gBAAA,IAAI,OAAO,YAAY,OAAO,EAAE;AAC9B,oBAAA,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAI;AAClB,wBAAA,UAAW,CAAC,SAAS,GAAG,EAAE;AAC1B,wBAAA,UAAW,CAAC,WAAW,CAAC,EAAE,CAAC;AAC7B,oBAAA,CAAC,CAAC;gBACJ;qBAAO;AACL,oBAAA,UAAU,CAAC,SAAS,GAAG,EAAE;AACzB,oBAAA,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC;gBACjC;YACF;QACF;AAEA,QAAA,iBAAiB,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5D,IAAA,CAAC,CAAC;;AAGF,IAAA,MAAM,QAAQ,GAAW;AACvB,QAAA,IAAI,OAAO,GAAA;AACT,YAAA,OAAO,OAAO;QAChB,CAAC;AAED,QAAA,IAAI,OAAO,GAAA;AACT,YAAA,OAAO,OAAO,CAAC,MAAM,EAAE;QACzB,CAAC;AAED,QAAA,aAAa,CAAC,IAAiB,EAAA;YAC7B,UAAU,GAAG,IAAI;QACnB,CAAC;AAED,QAAA,IAAI,CAAC,QAA6B,EAAA;AAChC,YAAA,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC;AAC3C,YAAA,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC;AAED,QAAA,UAAU,CAAC,QAA6B,EAAA;AACtC,YAAA,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC;YAC3C,OAAO,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAA,CAAA,yBAAoB,CAAC;QAC/D,CAAC;AAED,QAAA,OAAO,CAAC,QAA6B,EAAA;AACnC,YAAA,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC;YAC3C,OAAO,QAAQ,CAAC,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAChD,CAAC;QAED,IAAI,GAAA;AACF,YAAA,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;QACvB,CAAC;QAED,OAAO,GAAA;AACL,YAAA,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;QAC1B,CAAC;KACF;AACD,IAAA,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC;IACzB,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC;AACnD,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,IAAI,WAAW,EAAE;AACf,QAAA,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;IAC5B;AAEA,IAAA,OAAO,QAAQ;AACjB;;;;"}
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@ktjs/router",
3
- "version": "0.20.0",
3
+ "version": "0.31.9",
4
4
  "description": "Router for kt.js - client-side routing with navigation guards",
5
+ "description_zh": "kt.js 的路由库,支持前端路由与导航守卫。",
5
6
  "type": "module",
6
7
  "module": "./dist/index.mjs",
7
8
  "types": "./dist/index.d.ts",
@@ -31,11 +32,12 @@
31
32
  "directory": "packages/router"
32
33
  },
33
34
  "dependencies": {
34
- "@ktjs/core": "0.20.0",
35
- "@ktjs/shared": "0.20.0"
35
+ "@ktjs/core": "^*",
36
+ "@ktjs/shared": "^*"
36
37
  },
37
38
  "scripts": {
38
39
  "build": "rollup -c rollup.config.mjs",
39
- "dev": "rollup -c rollup.config.mjs -w"
40
+ "dev": "rollup -c rollup.config.mjs -w",
41
+ "test": "vitest run"
40
42
  }
41
43
  }
@@ -1,448 +0,0 @@
1
- var __ktjs_router__ = (function (exports) {
2
- 'use strict';
3
-
4
- // Cached native methods for performance optimization
5
-
6
- // Error handling utilities
7
- const $throw = (message) => {
8
- throw new Error('@ktjs/shared: ' + message);
9
- };
10
-
11
- // String manipulation utilities
12
- /**
13
- * Default empty function
14
- */
15
- const $emptyFn = (() => true);
16
- const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
17
-
18
- /**
19
- * Normalize path by joining parts and ensuring leading slash
20
- */
21
- const normalizePath = (...paths) => {
22
- const p = paths
23
- .map((p) => p.split('/'))
24
- .flat()
25
- .filter(Boolean);
26
- return '/' + p.join('/');
27
- };
28
- /**
29
- * Parse query string into object
30
- */
31
- const parseQuery = (queryString) => {
32
- const query = {};
33
- if (!queryString || queryString === '?') {
34
- return query;
35
- }
36
- const params = queryString.replace(/^\?/, '').split('&');
37
- for (const param of params) {
38
- const [key, value] = param.split('=');
39
- if (key) {
40
- query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
41
- }
42
- }
43
- return query;
44
- };
45
- /**
46
- * Build query string from object
47
- */
48
- const buildQuery = (query) => {
49
- const keys = Object.keys(query);
50
- if (keys.length === 0)
51
- return '';
52
- const params = keys.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`).join('&');
53
- return `?${params}`;
54
- };
55
- /**
56
- * Substitute params into path pattern
57
- * @example '/user/:id' + {id: '123'} => '/user/123'
58
- */
59
- const emplaceParams = (path, params) => {
60
- let result = path;
61
- for (const key in params) {
62
- result = result.replace(`:${key}`, params[key]);
63
- }
64
- return result;
65
- };
66
- /**
67
- * Extract dynamic params from path using pattern
68
- * @example pattern: '/user/:id', path: '/user/123' => {id: '123'}
69
- */
70
- const extractParams = (pattern, path) => {
71
- const params = {};
72
- const patternParts = pattern.split('/');
73
- const pathParts = path.split('/');
74
- if (patternParts.length !== pathParts.length) {
75
- return null;
76
- }
77
- for (let i = 0; i < patternParts.length; i++) {
78
- const patternPart = patternParts[i];
79
- const pathPart = pathParts[i];
80
- if (patternPart.startsWith(':')) {
81
- const paramName = patternPart.slice(1);
82
- params[paramName] = pathPart;
83
- }
84
- else if (patternPart !== pathPart) {
85
- return null;
86
- }
87
- }
88
- return params;
89
- };
90
-
91
- // Shared utilities and cached native methods for kt.js framework
92
- // Re-export all utilities
93
- Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
94
-
95
- /**
96
- * Route matcher for finding matching routes and extracting params
97
- */
98
- const createMatcher = (routes) => {
99
- const nameMap = {};
100
- for (let i = 0; i < routes.length; i++) {
101
- const route = routes[i];
102
- if (route.name !== undefined) {
103
- if (route.name in nameMap) {
104
- $throw(`Duplicate route name detected: '${route.name}'`);
105
- }
106
- nameMap[route.name] = route;
107
- }
108
- }
109
- /**
110
- * Find route by name
111
- */
112
- const findByName = (name) => {
113
- return nameMap[name] ?? null;
114
- };
115
- /**
116
- * Match path against all routes
117
- */
118
- const match = (path) => {
119
- const normalizedPath = normalizePath(path);
120
- // Try exact match first
121
- for (const route of routes) {
122
- if (route.path === normalizedPath) {
123
- return {
124
- route,
125
- params: {},
126
- result: getMatchedChain(route),
127
- };
128
- }
129
- }
130
- // Try dynamic routes
131
- for (const route of routes) {
132
- if (route.path.includes(':')) {
133
- const params = extractParams(route.path, normalizedPath);
134
- if (params) {
135
- return {
136
- route,
137
- params,
138
- result: getMatchedChain(route),
139
- };
140
- }
141
- }
142
- }
143
- return null;
144
- };
145
- /**
146
- * Get chain of matched routes (for nested routes)
147
- * - parent roots ahead
148
- */
149
- const getMatchedChain = (route) => {
150
- const matched = [route];
151
- const path = route.path;
152
- // Find parent routes by path prefix matching
153
- for (let i = 0; i < routes.length; i++) {
154
- const r = routes[i];
155
- if (r !== route && path.startsWith(r.path) && path !== r.path) {
156
- matched.push(r);
157
- }
158
- }
159
- return matched.reverse();
160
- };
161
- return {
162
- findByName,
163
- match,
164
- };
165
- };
166
-
167
- /**
168
- * Create a router view container that automatically renders route components
169
- */
170
- function KTRouter({ router }) {
171
- const view = document.createElement('kt-router-view');
172
- router.setRouterView(view);
173
- return view;
174
- }
175
-
176
- /**
177
- * Create a new router instance
178
- */
179
- const createRouter = ({ beforeEach = $emptyFn, afterEach = $emptyFn, onNotFound = $emptyFn, onError = $emptyFn, prefix = '', routes: rawRoutes, }) => {
180
- // # private values
181
- const routes = [];
182
- const history = [];
183
- let routerView = null;
184
- let current = null;
185
- // # methods
186
- const normalize = (rawRoutes, parentPath) => rawRoutes.map((route) => {
187
- const path = normalizePath(parentPath, route.path);
188
- const normalized = {
189
- path: prefix + path,
190
- name: route.name ?? '',
191
- meta: route.meta ?? {},
192
- beforeEnter: route.beforeEnter ?? $emptyFn,
193
- after: route.after ?? $emptyFn,
194
- children: route.children ? normalize(route.children, path) : [],
195
- component: route.component,
196
- };
197
- // directly push the normalized route to the list
198
- // avoid flatten them again
199
- routes.push(normalized);
200
- return normalized;
201
- });
202
- const guard = async (to, from, guardLevel) => {
203
- try {
204
- if (guardLevel === 0 /* GuardLevel.None */) {
205
- return { continue: true };
206
- }
207
- if (guardLevel & 1 /* GuardLevel.Global */) {
208
- const result = await beforeEach(to, from);
209
- if (result === false) {
210
- return { continue: false };
211
- }
212
- if (typeof result === 'string') {
213
- return { continue: false, redirectTo: { path: result } };
214
- }
215
- if (result && typeof result === 'object') {
216
- return { continue: false, redirectTo: result };
217
- }
218
- }
219
- if (guardLevel & 2 /* GuardLevel.Route */) {
220
- const targetRoute = to.matched[to.matched.length - 1];
221
- const result = await targetRoute.beforeEnter(to);
222
- if (result === false) {
223
- return { continue: false };
224
- }
225
- if (typeof result === 'string') {
226
- return { continue: false, redirectTo: { path: result } };
227
- }
228
- if (result && typeof result === 'object') {
229
- return { continue: false, redirectTo: result };
230
- }
231
- }
232
- return { continue: true };
233
- }
234
- catch (error) {
235
- onError(error);
236
- return { continue: false };
237
- }
238
- };
239
- const navigatePrepare = (options) => {
240
- // Resolve target route
241
- let targetPath;
242
- let targetRoute;
243
- if (options.name) {
244
- targetRoute = findByName(options.name);
245
- if (!targetRoute) {
246
- $throw(`Route not found: ${options.name}`);
247
- }
248
- targetPath = targetRoute.path;
249
- }
250
- else if (options.path) {
251
- targetPath = normalizePath(options.path);
252
- targetRoute = match(targetPath)?.route;
253
- }
254
- else {
255
- $throw(`Either path or name must be provided`);
256
- }
257
- // Substitute params
258
- if (options.params) {
259
- targetPath = emplaceParams(targetPath, options.params);
260
- }
261
- // Match final path
262
- const matched = match(targetPath);
263
- if (!matched) {
264
- onNotFound(targetPath);
265
- return null;
266
- }
267
- // Build route context
268
- const queryString = options.query ? buildQuery(options.query) : '';
269
- const fullPath = targetPath + queryString;
270
- const to = {
271
- path: targetPath,
272
- name: matched.route.name,
273
- params: { ...matched.params, ...(options.params ?? {}) },
274
- query: options.query ?? {},
275
- meta: matched.route.meta ?? {},
276
- matched: matched.result,
277
- };
278
- return {
279
- guardLevel: options.guardLevel ?? 15 /* GuardLevel.Default */,
280
- replace: options.replace ?? false,
281
- to,
282
- fullPath,
283
- };
284
- };
285
- const navigate = async (options, redirectCount = 0) => {
286
- try {
287
- // Prevent infinite redirect loop
288
- if (redirectCount > 10) {
289
- onError(new Error('Maximum redirect count exceeded'));
290
- return false;
291
- }
292
- const prep = navigatePrepare(options);
293
- if (!prep) {
294
- return false;
295
- }
296
- const { guardLevel, replace, to, fullPath } = prep;
297
- const guardResult = await guard(to, current, guardLevel);
298
- if (!guardResult.continue) {
299
- // Check if there's a redirect
300
- if (guardResult.redirectTo) {
301
- return await navigate(guardResult.redirectTo, redirectCount + 1);
302
- }
303
- return false;
304
- }
305
- // ---- Guards passed ----
306
- const hashUrl = '#' + fullPath;
307
- if (replace) {
308
- window.location.replace(hashUrl);
309
- }
310
- else {
311
- window.location.hash = fullPath;
312
- }
313
- current = to;
314
- if (replace) {
315
- if (history.length > 0) {
316
- history[history.length - 1] = to;
317
- }
318
- else {
319
- history.push(to);
320
- }
321
- }
322
- else {
323
- history.push(to);
324
- }
325
- // Render component if routerView exists
326
- if (routerView && to.matched.length > 0) {
327
- const route = to.matched[to.matched.length - 1];
328
- if (route.component) {
329
- const element = await route.component();
330
- routerView.innerHTML = '';
331
- routerView.appendChild(element);
332
- }
333
- }
334
- executeAfterHooks(to, history[history.length - 2] ?? null);
335
- return true;
336
- }
337
- catch (error) {
338
- onError(error);
339
- return false;
340
- }
341
- };
342
- const executeAfterHooks = async (to, from) => {
343
- const targetRoute = to.matched[to.matched.length - 1];
344
- await targetRoute.after(to);
345
- await afterEach(to, from);
346
- };
347
- /**
348
- * Normalize navigation argument
349
- */
350
- const normalizeLocation = (loc) => {
351
- if (typeof loc !== 'string') {
352
- return loc;
353
- }
354
- const [path, queryString] = loc.split('?');
355
- return {
356
- path,
357
- query: queryString ? parseQuery(queryString) : undefined,
358
- };
359
- };
360
- // # register events
361
- window.addEventListener('hashchange', () => {
362
- const hash = window.location.hash.slice(1);
363
- const [path] = hash.split('?');
364
- const normalizedPath = normalizePath(path);
365
- if (current && current.path === normalizedPath) {
366
- return;
367
- }
368
- // render route for new hash without adding extra history entry
369
- const matched = match(normalizedPath);
370
- if (!matched) {
371
- onNotFound(normalizedPath);
372
- return;
373
- }
374
- const queryString = window.location.hash.slice(1).split('?')[1];
375
- const to = {
376
- path: normalizedPath,
377
- name: matched.route.name,
378
- params: matched.params,
379
- query: queryString ? parseQuery(queryString) : {},
380
- meta: matched.route.meta ?? {},
381
- matched: matched.result,
382
- };
383
- // apply without modifying browser history
384
- current = to;
385
- history.push(to);
386
- if (routerView && to.matched.length > 0) {
387
- const route = to.matched[to.matched.length - 1];
388
- if (route.component) {
389
- const element = route.component();
390
- if (element instanceof Promise) {
391
- element.then((el) => {
392
- routerView.innerHTML = '';
393
- routerView.appendChild(el);
394
- });
395
- }
396
- else {
397
- routerView.innerHTML = '';
398
- routerView.appendChild(element);
399
- }
400
- }
401
- }
402
- executeAfterHooks(to, history[history.length - 2] ?? null);
403
- });
404
- // # initialize
405
- const instance = {
406
- get current() {
407
- return current;
408
- },
409
- get history() {
410
- return history.concat();
411
- },
412
- setRouterView(view) {
413
- routerView = view;
414
- },
415
- push(location) {
416
- const options = normalizeLocation(location);
417
- return navigate(options);
418
- },
419
- silentPush(location) {
420
- const options = normalizeLocation(location);
421
- return navigate({ ...options, guardLevel: 2 /* GuardLevel.Route */ });
422
- },
423
- replace(location) {
424
- const options = normalizeLocation(location);
425
- return navigate({ ...options, replace: true });
426
- },
427
- back() {
428
- window.history.back();
429
- },
430
- forward() {
431
- window.history.forward();
432
- },
433
- };
434
- normalize(rawRoutes, '/');
435
- const { findByName, match } = createMatcher(routes);
436
- const currentHash = window.location.hash.slice(1);
437
- if (currentHash) {
438
- instance.push(currentHash);
439
- }
440
- return instance;
441
- };
442
-
443
- exports.KTRouter = KTRouter;
444
- exports.createRouter = createRouter;
445
-
446
- return exports;
447
-
448
- })({});
@@ -1,576 +0,0 @@
1
- var __ktjs_router__ = (function (exports) {
2
- 'use strict';
3
-
4
- /******************************************************************************
5
- Copyright (c) Microsoft Corporation.
6
-
7
- Permission to use, copy, modify, and/or distribute this software for any
8
- purpose with or without fee is hereby granted.
9
-
10
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16
- PERFORMANCE OF THIS SOFTWARE.
17
- ***************************************************************************** */
18
- /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
19
-
20
-
21
- var __assign = function() {
22
- __assign = Object.assign || function __assign(t) {
23
- for (var s, i = 1, n = arguments.length; i < n; i++) {
24
- s = arguments[i];
25
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
26
- }
27
- return t;
28
- };
29
- return __assign.apply(this, arguments);
30
- };
31
-
32
- function __awaiter(thisArg, _arguments, P, generator) {
33
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
34
- return new (P || (P = Promise))(function (resolve, reject) {
35
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
36
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
37
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
38
- step((generator = generator.apply(thisArg, _arguments || [])).next());
39
- });
40
- }
41
-
42
- function __generator(thisArg, body) {
43
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
44
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
45
- function verb(n) { return function (v) { return step([n, v]); }; }
46
- function step(op) {
47
- if (f) throw new TypeError("Generator is already executing.");
48
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
49
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
50
- if (y = 0, t) op = [op[0] & 2, t.value];
51
- switch (op[0]) {
52
- case 0: case 1: t = op; break;
53
- case 4: _.label++; return { value: op[1], done: false };
54
- case 5: _.label++; y = op[1]; op = [0]; continue;
55
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
56
- default:
57
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
58
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
59
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
60
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
61
- if (t[2]) _.ops.pop();
62
- _.trys.pop(); continue;
63
- }
64
- op = body.call(thisArg, _);
65
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
66
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
67
- }
68
- }
69
-
70
- function __spreadArray(to, from, pack) {
71
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
72
- if (ar || !(i in from)) {
73
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
74
- ar[i] = from[i];
75
- }
76
- }
77
- return to.concat(ar || Array.prototype.slice.call(from));
78
- }
79
-
80
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
81
- var e = new Error(message);
82
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
83
- };
84
-
85
- // Cached native methods for performance optimization
86
-
87
- // Error handling utilities
88
- const $throw = (message) => {
89
- throw new Error('@ktjs/shared: ' + message);
90
- };
91
-
92
- // String manipulation utilities
93
- /**
94
- * Default empty function
95
- */
96
- const $emptyFn = (() => true);
97
- const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
98
-
99
- /**
100
- * Normalize path by joining parts and ensuring leading slash
101
- */
102
- const normalizePath = (...paths) => {
103
- const p = paths
104
- .map((p) => p.split('/'))
105
- .flat()
106
- .filter(Boolean);
107
- return '/' + p.join('/');
108
- };
109
- /**
110
- * Parse query string into object
111
- */
112
- const parseQuery = (queryString) => {
113
- const query = {};
114
- if (!queryString || queryString === '?') {
115
- return query;
116
- }
117
- const params = queryString.replace(/^\?/, '').split('&');
118
- for (const param of params) {
119
- const [key, value] = param.split('=');
120
- if (key) {
121
- query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
122
- }
123
- }
124
- return query;
125
- };
126
- /**
127
- * Build query string from object
128
- */
129
- const buildQuery = (query) => {
130
- const keys = Object.keys(query);
131
- if (keys.length === 0)
132
- return '';
133
- const params = keys.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`).join('&');
134
- return `?${params}`;
135
- };
136
- /**
137
- * Substitute params into path pattern
138
- * @example '/user/:id' + {id: '123'} => '/user/123'
139
- */
140
- const emplaceParams = (path, params) => {
141
- let result = path;
142
- for (const key in params) {
143
- result = result.replace(`:${key}`, params[key]);
144
- }
145
- return result;
146
- };
147
- /**
148
- * Extract dynamic params from path using pattern
149
- * @example pattern: '/user/:id', path: '/user/123' => {id: '123'}
150
- */
151
- const extractParams = (pattern, path) => {
152
- const params = {};
153
- const patternParts = pattern.split('/');
154
- const pathParts = path.split('/');
155
- if (patternParts.length !== pathParts.length) {
156
- return null;
157
- }
158
- for (let i = 0; i < patternParts.length; i++) {
159
- const patternPart = patternParts[i];
160
- const pathPart = pathParts[i];
161
- if (patternPart.startsWith(':')) {
162
- const paramName = patternPart.slice(1);
163
- params[paramName] = pathPart;
164
- }
165
- else if (patternPart !== pathPart) {
166
- return null;
167
- }
168
- }
169
- return params;
170
- };
171
-
172
- // Shared utilities and cached native methods for kt.js framework
173
- // Re-export all utilities
174
- Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
175
-
176
- /**
177
- * Route matcher for finding matching routes and extracting params
178
- */
179
- var createMatcher = function (routes) {
180
- var nameMap = {};
181
- for (var i = 0; i < routes.length; i++) {
182
- var route = routes[i];
183
- if (route.name !== undefined) {
184
- if (route.name in nameMap) {
185
- $throw("Duplicate route name detected: '".concat(route.name, "'"));
186
- }
187
- nameMap[route.name] = route;
188
- }
189
- }
190
- /**
191
- * Find route by name
192
- */
193
- var findByName = function (name) {
194
- var _a;
195
- return (_a = nameMap[name]) !== null && _a !== void 0 ? _a : null;
196
- };
197
- /**
198
- * Match path against all routes
199
- */
200
- var match = function (path) {
201
- var normalizedPath = normalizePath(path);
202
- // Try exact match first
203
- for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
204
- var route = routes_1[_i];
205
- if (route.path === normalizedPath) {
206
- return {
207
- route: route,
208
- params: {},
209
- result: getMatchedChain(route),
210
- };
211
- }
212
- }
213
- // Try dynamic routes
214
- for (var _a = 0, routes_2 = routes; _a < routes_2.length; _a++) {
215
- var route = routes_2[_a];
216
- if (route.path.includes(':')) {
217
- var params = extractParams(route.path, normalizedPath);
218
- if (params) {
219
- return {
220
- route: route,
221
- params: params,
222
- result: getMatchedChain(route),
223
- };
224
- }
225
- }
226
- }
227
- return null;
228
- };
229
- /**
230
- * Get chain of matched routes (for nested routes)
231
- * - parent roots ahead
232
- */
233
- var getMatchedChain = function (route) {
234
- var matched = [route];
235
- var path = route.path;
236
- // Find parent routes by path prefix matching
237
- for (var i = 0; i < routes.length; i++) {
238
- var r = routes[i];
239
- if (r !== route && path.startsWith(r.path) && path !== r.path) {
240
- matched.push(r);
241
- }
242
- }
243
- return matched.reverse();
244
- };
245
- return {
246
- findByName: findByName,
247
- match: match,
248
- };
249
- };
250
-
251
- /**
252
- * Create a router view container that automatically renders route components
253
- */
254
- function KTRouter(_a) {
255
- var router = _a.router;
256
- var view = document.createElement('kt-router-view');
257
- router.setRouterView(view);
258
- return view;
259
- }
260
-
261
- /**
262
- * Create a new router instance
263
- */
264
- var createRouter = function (_a) {
265
- var _b = _a.beforeEach, beforeEach = _b === void 0 ? $emptyFn : _b, _c = _a.afterEach, afterEach = _c === void 0 ? $emptyFn : _c, _d = _a.onNotFound, onNotFound = _d === void 0 ? $emptyFn : _d, _e = _a.onError, onError = _e === void 0 ? $emptyFn : _e, _f = _a.prefix, prefix = _f === void 0 ? '' : _f, rawRoutes = _a.routes;
266
- // # private values
267
- var routes = [];
268
- var history = [];
269
- var routerView = null;
270
- var current = null;
271
- // # methods
272
- var normalize = function (rawRoutes, parentPath) {
273
- return rawRoutes.map(function (route) {
274
- var _a, _b, _c, _d;
275
- var path = normalizePath(parentPath, route.path);
276
- var normalized = {
277
- path: prefix + path,
278
- name: (_a = route.name) !== null && _a !== void 0 ? _a : '',
279
- meta: (_b = route.meta) !== null && _b !== void 0 ? _b : {},
280
- beforeEnter: (_c = route.beforeEnter) !== null && _c !== void 0 ? _c : $emptyFn,
281
- after: (_d = route.after) !== null && _d !== void 0 ? _d : $emptyFn,
282
- children: route.children ? normalize(route.children, path) : [],
283
- component: route.component,
284
- };
285
- // directly push the normalized route to the list
286
- // avoid flatten them again
287
- routes.push(normalized);
288
- return normalized;
289
- });
290
- };
291
- var guard = function (to, from, guardLevel) { return __awaiter(void 0, void 0, void 0, function () {
292
- var result, targetRoute, result, error_1;
293
- return __generator(this, function (_a) {
294
- switch (_a.label) {
295
- case 0:
296
- _a.trys.push([0, 5, , 6]);
297
- if (guardLevel === 0 /* GuardLevel.None */) {
298
- return [2 /*return*/, { continue: true }];
299
- }
300
- if (!(guardLevel & 1 /* GuardLevel.Global */)) return [3 /*break*/, 2];
301
- return [4 /*yield*/, beforeEach(to, from)];
302
- case 1:
303
- result = _a.sent();
304
- if (result === false) {
305
- return [2 /*return*/, { continue: false }];
306
- }
307
- if (typeof result === 'string') {
308
- return [2 /*return*/, { continue: false, redirectTo: { path: result } }];
309
- }
310
- if (result && typeof result === 'object') {
311
- return [2 /*return*/, { continue: false, redirectTo: result }];
312
- }
313
- _a.label = 2;
314
- case 2:
315
- if (!(guardLevel & 2 /* GuardLevel.Route */)) return [3 /*break*/, 4];
316
- targetRoute = to.matched[to.matched.length - 1];
317
- return [4 /*yield*/, targetRoute.beforeEnter(to)];
318
- case 3:
319
- result = _a.sent();
320
- if (result === false) {
321
- return [2 /*return*/, { continue: false }];
322
- }
323
- if (typeof result === 'string') {
324
- return [2 /*return*/, { continue: false, redirectTo: { path: result } }];
325
- }
326
- if (result && typeof result === 'object') {
327
- return [2 /*return*/, { continue: false, redirectTo: result }];
328
- }
329
- _a.label = 4;
330
- case 4: return [2 /*return*/, { continue: true }];
331
- case 5:
332
- error_1 = _a.sent();
333
- onError(error_1);
334
- return [2 /*return*/, { continue: false }];
335
- case 6: return [2 /*return*/];
336
- }
337
- });
338
- }); };
339
- var navigatePrepare = function (options) {
340
- var _a, _b, _c, _d, _e, _f;
341
- // Resolve target route
342
- var targetPath;
343
- var targetRoute;
344
- if (options.name) {
345
- targetRoute = findByName(options.name);
346
- if (!targetRoute) {
347
- $throw("Route not found: ".concat(options.name));
348
- }
349
- targetPath = targetRoute.path;
350
- }
351
- else if (options.path) {
352
- targetPath = normalizePath(options.path);
353
- targetRoute = (_a = match(targetPath)) === null || _a === void 0 ? void 0 : _a.route;
354
- }
355
- else {
356
- $throw("Either path or name must be provided");
357
- }
358
- // Substitute params
359
- if (options.params) {
360
- targetPath = emplaceParams(targetPath, options.params);
361
- }
362
- // Match final path
363
- var matched = match(targetPath);
364
- if (!matched) {
365
- onNotFound(targetPath);
366
- return null;
367
- }
368
- // Build route context
369
- var queryString = options.query ? buildQuery(options.query) : '';
370
- var fullPath = targetPath + queryString;
371
- var to = {
372
- path: targetPath,
373
- name: matched.route.name,
374
- params: __assign(__assign({}, matched.params), ((_b = options.params) !== null && _b !== void 0 ? _b : {})),
375
- query: (_c = options.query) !== null && _c !== void 0 ? _c : {},
376
- meta: (_d = matched.route.meta) !== null && _d !== void 0 ? _d : {},
377
- matched: matched.result,
378
- };
379
- return {
380
- guardLevel: (_e = options.guardLevel) !== null && _e !== void 0 ? _e : 15 /* GuardLevel.Default */,
381
- replace: (_f = options.replace) !== null && _f !== void 0 ? _f : false,
382
- to: to,
383
- fullPath: fullPath,
384
- };
385
- };
386
- var navigate = function (options_1) {
387
- var args_1 = [];
388
- for (var _i = 1; _i < arguments.length; _i++) {
389
- args_1[_i - 1] = arguments[_i];
390
- }
391
- return __awaiter(void 0, __spreadArray([options_1], args_1, true), void 0, function (options, redirectCount) {
392
- var prep, guardLevel, replace, to, fullPath, guardResult, hashUrl, route, element, error_2;
393
- var _a;
394
- if (redirectCount === void 0) { redirectCount = 0; }
395
- return __generator(this, function (_b) {
396
- switch (_b.label) {
397
- case 0:
398
- _b.trys.push([0, 7, , 8]);
399
- // Prevent infinite redirect loop
400
- if (redirectCount > 10) {
401
- onError(new Error('Maximum redirect count exceeded'));
402
- return [2 /*return*/, false];
403
- }
404
- prep = navigatePrepare(options);
405
- if (!prep) {
406
- return [2 /*return*/, false];
407
- }
408
- guardLevel = prep.guardLevel, replace = prep.replace, to = prep.to, fullPath = prep.fullPath;
409
- return [4 /*yield*/, guard(to, current, guardLevel)];
410
- case 1:
411
- guardResult = _b.sent();
412
- if (!!guardResult.continue) return [3 /*break*/, 4];
413
- if (!guardResult.redirectTo) return [3 /*break*/, 3];
414
- return [4 /*yield*/, navigate(guardResult.redirectTo, redirectCount + 1)];
415
- case 2: return [2 /*return*/, _b.sent()];
416
- case 3: return [2 /*return*/, false];
417
- case 4:
418
- hashUrl = '#' + fullPath;
419
- if (replace) {
420
- window.location.replace(hashUrl);
421
- }
422
- else {
423
- window.location.hash = fullPath;
424
- }
425
- current = to;
426
- if (replace) {
427
- if (history.length > 0) {
428
- history[history.length - 1] = to;
429
- }
430
- else {
431
- history.push(to);
432
- }
433
- }
434
- else {
435
- history.push(to);
436
- }
437
- if (!(routerView && to.matched.length > 0)) return [3 /*break*/, 6];
438
- route = to.matched[to.matched.length - 1];
439
- if (!route.component) return [3 /*break*/, 6];
440
- return [4 /*yield*/, route.component()];
441
- case 5:
442
- element = _b.sent();
443
- routerView.innerHTML = '';
444
- routerView.appendChild(element);
445
- _b.label = 6;
446
- case 6:
447
- executeAfterHooks(to, (_a = history[history.length - 2]) !== null && _a !== void 0 ? _a : null);
448
- return [2 /*return*/, true];
449
- case 7:
450
- error_2 = _b.sent();
451
- onError(error_2);
452
- return [2 /*return*/, false];
453
- case 8: return [2 /*return*/];
454
- }
455
- });
456
- });
457
- };
458
- var executeAfterHooks = function (to, from) { return __awaiter(void 0, void 0, void 0, function () {
459
- var targetRoute;
460
- return __generator(this, function (_a) {
461
- switch (_a.label) {
462
- case 0:
463
- targetRoute = to.matched[to.matched.length - 1];
464
- return [4 /*yield*/, targetRoute.after(to)];
465
- case 1:
466
- _a.sent();
467
- return [4 /*yield*/, afterEach(to, from)];
468
- case 2:
469
- _a.sent();
470
- return [2 /*return*/];
471
- }
472
- });
473
- }); };
474
- /**
475
- * Normalize navigation argument
476
- */
477
- var normalizeLocation = function (loc) {
478
- if (typeof loc !== 'string') {
479
- return loc;
480
- }
481
- var _a = loc.split('?'), path = _a[0], queryString = _a[1];
482
- return {
483
- path: path,
484
- query: queryString ? parseQuery(queryString) : undefined,
485
- };
486
- };
487
- // # register events
488
- window.addEventListener('hashchange', function () {
489
- var _a, _b;
490
- var hash = window.location.hash.slice(1);
491
- var path = hash.split('?')[0];
492
- var normalizedPath = normalizePath(path);
493
- if (current && current.path === normalizedPath) {
494
- return;
495
- }
496
- // render route for new hash without adding extra history entry
497
- var matched = match(normalizedPath);
498
- if (!matched) {
499
- onNotFound(normalizedPath);
500
- return;
501
- }
502
- var queryString = window.location.hash.slice(1).split('?')[1];
503
- var to = {
504
- path: normalizedPath,
505
- name: matched.route.name,
506
- params: matched.params,
507
- query: queryString ? parseQuery(queryString) : {},
508
- meta: (_a = matched.route.meta) !== null && _a !== void 0 ? _a : {},
509
- matched: matched.result,
510
- };
511
- // apply without modifying browser history
512
- current = to;
513
- history.push(to);
514
- if (routerView && to.matched.length > 0) {
515
- var route = to.matched[to.matched.length - 1];
516
- if (route.component) {
517
- var element = route.component();
518
- if (element instanceof Promise) {
519
- element.then(function (el) {
520
- routerView.innerHTML = '';
521
- routerView.appendChild(el);
522
- });
523
- }
524
- else {
525
- routerView.innerHTML = '';
526
- routerView.appendChild(element);
527
- }
528
- }
529
- }
530
- executeAfterHooks(to, (_b = history[history.length - 2]) !== null && _b !== void 0 ? _b : null);
531
- });
532
- // # initialize
533
- var instance = {
534
- get current() {
535
- return current;
536
- },
537
- get history() {
538
- return history.concat();
539
- },
540
- setRouterView: function (view) {
541
- routerView = view;
542
- },
543
- push: function (location) {
544
- var options = normalizeLocation(location);
545
- return navigate(options);
546
- },
547
- silentPush: function (location) {
548
- var options = normalizeLocation(location);
549
- return navigate(__assign(__assign({}, options), { guardLevel: 2 /* GuardLevel.Route */ }));
550
- },
551
- replace: function (location) {
552
- var options = normalizeLocation(location);
553
- return navigate(__assign(__assign({}, options), { replace: true }));
554
- },
555
- back: function () {
556
- window.history.back();
557
- },
558
- forward: function () {
559
- window.history.forward();
560
- },
561
- };
562
- normalize(rawRoutes, '/');
563
- var _g = createMatcher(routes), findByName = _g.findByName, match = _g.match;
564
- var currentHash = window.location.hash.slice(1);
565
- if (currentHash) {
566
- instance.push(currentHash);
567
- }
568
- return instance;
569
- };
570
-
571
- exports.KTRouter = KTRouter;
572
- exports.createRouter = createRouter;
573
-
574
- return exports;
575
-
576
- })({});