@bromscandium/router 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.js ADDED
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Router hooks for components.
3
+ * @module
4
+ */
5
+ import { computed } from '@bromscandium/core';
6
+ import { getRouter } from './router.js';
7
+ /**
8
+ * Returns the router instance.
9
+ * Must be called within a component where a router has been created.
10
+ *
11
+ * @returns The router instance
12
+ * @throws Error if called outside of router context
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * function MyComponent() {
17
+ * const router = useRouter();
18
+ *
19
+ * function handleClick() {
20
+ * router.push('/dashboard');
21
+ * }
22
+ *
23
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
24
+ * }
25
+ * ```
26
+ */
27
+ export function useRouter() {
28
+ const router = getRouter();
29
+ if (!router) {
30
+ throw new Error('useRouter() called outside of router context. ' +
31
+ 'Make sure you have created a router with createRouter() and mounted it.');
32
+ }
33
+ return router;
34
+ }
35
+ /**
36
+ * Returns a reactive reference to the current route location.
37
+ *
38
+ * @returns A ref containing the current RouteLocation
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * function Breadcrumb() {
43
+ * const route = useRoute();
44
+ *
45
+ * return <span>Current path: {route.value.path}</span>;
46
+ * }
47
+ * ```
48
+ */
49
+ export function useRoute() {
50
+ const router = useRouter();
51
+ return router.currentRoute;
52
+ }
53
+ /**
54
+ * Returns a computed ref of the current route parameters.
55
+ *
56
+ * @returns A computed ref containing route params
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * // For route /users/:id
61
+ * function UserProfile() {
62
+ * const params = useParams();
63
+ *
64
+ * return <div>User ID: {params.value.id}</div>;
65
+ * }
66
+ * ```
67
+ */
68
+ export function useParams() {
69
+ const route = useRoute();
70
+ return computed(() => route.value.params);
71
+ }
72
+ /**
73
+ * Returns a computed ref of the current query string parameters.
74
+ *
75
+ * @returns A computed ref containing query params
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * // For URL /search?q=hello
80
+ * function SearchResults() {
81
+ * const query = useQuery();
82
+ *
83
+ * return <div>Searching for: {query.value.q}</div>;
84
+ * }
85
+ * ```
86
+ */
87
+ export function useQuery() {
88
+ const route = useRoute();
89
+ return computed(() => route.value.query);
90
+ }
91
+ /**
92
+ * Returns a computed ref of the merged metadata from all matched routes.
93
+ *
94
+ * @returns A computed ref containing route metadata
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * function PageTitle() {
99
+ * const meta = useRouteMeta();
100
+ *
101
+ * return <title>{meta.value.title || 'My App'}</title>;
102
+ * }
103
+ * ```
104
+ */
105
+ export function useRouteMeta() {
106
+ const route = useRoute();
107
+ return computed(() => route.value.meta);
108
+ }
109
+ /**
110
+ * Returns navigation helper functions from the router.
111
+ *
112
+ * @returns An object with push, replace, back, forward, and go methods
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * function Navigation() {
117
+ * const { push, back } = useNavigate();
118
+ *
119
+ * return (
120
+ * <>
121
+ * <button onClick={back}>Back</button>
122
+ * <button onClick={() => push('/home')}>Home</button>
123
+ * </>
124
+ * );
125
+ * }
126
+ * ```
127
+ */
128
+ export function useNavigate() {
129
+ const router = useRouter();
130
+ return {
131
+ push: router.push,
132
+ replace: router.replace,
133
+ back: router.back,
134
+ forward: router.forward,
135
+ go: router.go,
136
+ };
137
+ }
138
+ /**
139
+ * Returns a computed boolean indicating if the current route matches a path.
140
+ *
141
+ * @param path - A string path or RegExp to match against
142
+ * @returns A computed ref that is true when the route matches
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * function NavLink({ to, children }) {
147
+ * const isActive = useRouteMatch(to);
148
+ *
149
+ * return (
150
+ * <a href={to} className={isActive.value ? 'active' : ''}>
151
+ * {children}
152
+ * </a>
153
+ * );
154
+ * }
155
+ * ```
156
+ */
157
+ export function useRouteMatch(path) {
158
+ const route = useRoute();
159
+ return computed(() => {
160
+ const currentPath = route.value.path;
161
+ if (typeof path === 'string') {
162
+ return currentPath === path || currentPath.startsWith(path + '/');
163
+ }
164
+ return path.test(currentPath);
165
+ });
166
+ }
167
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAoB,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAyB,MAAM,aAAa,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,gDAAgD;YAChD,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,MAAM,CAAC,YAAY,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,EAAE,EAAE,MAAM,CAAC,EAAE;KACd,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAAC,IAAqB;IACjD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,OAAO,QAAQ,CAAC,GAAG,EAAE;QACnB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;QAErC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,WAAW,KAAK,IAAI,IAAI,WAAW,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;QACpE,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { createRouter, getRouter, setRouter, type Router, type Route, type RouteLocation, type MatchedRoute, type NavigationTarget, type NavigationGuard, type NavigationHook, } from './router.js';
2
+ export { useRouter, useRoute, useParams, useQuery, useRouteMeta, useNavigate, useRouteMatch, } from './hooks.js';
3
+ export { Link, RouterView, Redirect, Navigate, } from './components.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // Router package exports
2
+ export { createRouter, getRouter, setRouter, } from './router.js';
3
+ export { useRouter, useRoute, useParams, useQuery, useRouteMeta, useNavigate, useRouteMatch, } from './hooks.js';
4
+ export { Link, RouterView, Redirect, Navigate, } from './components.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yBAAyB;AAEzB,OAAO,EACL,YAAY,EACZ,SAAS,EACT,SAAS,GAQV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,QAAQ,GACT,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Router implementation with file-based routing support.
3
+ * @module
4
+ */
5
+ import { Ref } from '@bromscandium/core';
6
+ /**
7
+ * A route configuration object.
8
+ */
9
+ export interface Route {
10
+ /** The path pattern to match (supports `:param` and `[param]` syntax) */
11
+ path: string;
12
+ /** The component to render, can be async for lazy loading */
13
+ component: () => Promise<{
14
+ default: any;
15
+ }> | {
16
+ default: any;
17
+ };
18
+ /** Optional layout component to wrap the page */
19
+ layout?: () => Promise<{
20
+ default: any;
21
+ }> | {
22
+ default: any;
23
+ };
24
+ /** Child routes for nested routing */
25
+ children?: Route[];
26
+ /** Arbitrary metadata attached to the route */
27
+ meta?: Record<string, any>;
28
+ /** Named route identifier for programmatic navigation */
29
+ name?: string;
30
+ }
31
+ /**
32
+ * The current location state.
33
+ */
34
+ export interface RouteLocation {
35
+ /** The current path without query or hash */
36
+ path: string;
37
+ /** Dynamic route parameters extracted from the path */
38
+ params: Record<string, string>;
39
+ /** Query string parameters */
40
+ query: Record<string, string>;
41
+ /** Hash fragment (without #) */
42
+ hash: string;
43
+ /** All matched route records for the current location */
44
+ matched: MatchedRoute[];
45
+ /** Full path including query and hash */
46
+ fullPath: string;
47
+ /** Name of the matched route if defined */
48
+ name?: string;
49
+ /** Merged metadata from all matched routes */
50
+ meta: Record<string, any>;
51
+ }
52
+ /**
53
+ * A matched route record with extracted parameters.
54
+ */
55
+ export interface MatchedRoute {
56
+ /** The route configuration */
57
+ route: Route;
58
+ /** Parameters extracted from the path */
59
+ params: Record<string, string>;
60
+ /** The resolved path for this route */
61
+ path: string;
62
+ }
63
+ /**
64
+ * The router instance providing navigation and route state.
65
+ */
66
+ export interface Router {
67
+ /** Reactive reference to the current route location */
68
+ currentRoute: Ref<RouteLocation>;
69
+ /** Navigate to a new location, adding to history */
70
+ push(to: string | NavigationTarget): Promise<void>;
71
+ /** Navigate to a new location, replacing current history entry */
72
+ replace(to: string | NavigationTarget): Promise<void>;
73
+ /** Navigate back in history */
74
+ back(): void;
75
+ /** Navigate forward in history */
76
+ forward(): void;
77
+ /** Navigate by a relative history position */
78
+ go(delta: number): void;
79
+ /** Register a navigation guard called before navigation */
80
+ beforeEach(guard: NavigationGuard): () => void;
81
+ /** Register a hook called after navigation completes */
82
+ afterEach(hook: NavigationHook): () => void;
83
+ /** Returns a promise that resolves when router is ready */
84
+ isReady(): Promise<void>;
85
+ /** The configured routes */
86
+ routes: Route[];
87
+ /** The base path for all routes */
88
+ base: string;
89
+ }
90
+ /**
91
+ * A navigation target for programmatic navigation.
92
+ */
93
+ export interface NavigationTarget {
94
+ /** Target path */
95
+ path?: string;
96
+ /** Named route to navigate to */
97
+ name?: string;
98
+ /** Route parameters for dynamic segments */
99
+ params?: Record<string, string>;
100
+ /** Query parameters */
101
+ query?: Record<string, string>;
102
+ /** Hash fragment */
103
+ hash?: string;
104
+ }
105
+ /**
106
+ * A navigation guard function that can block or redirect navigation.
107
+ * Return false to cancel, string/NavigationTarget to redirect, or true to proceed.
108
+ */
109
+ export type NavigationGuard = (to: RouteLocation, from: RouteLocation) => boolean | string | NavigationTarget | Promise<boolean | string | NavigationTarget>;
110
+ /**
111
+ * A hook called after navigation completes.
112
+ */
113
+ export type NavigationHook = (to: RouteLocation, from: RouteLocation) => void;
114
+ interface RouterOptions {
115
+ /** Route configurations */
116
+ routes: Route[];
117
+ /** Base path prepended to all routes */
118
+ base?: string;
119
+ }
120
+ /**
121
+ * Sets the current router instance for global access.
122
+ *
123
+ * @param router - The router instance or null to clear
124
+ */
125
+ export declare function setRouter(router: Router | null): void;
126
+ /**
127
+ * Gets the current router instance.
128
+ *
129
+ * @returns The current router or null if not set
130
+ */
131
+ export declare function getRouter(): Router | null;
132
+ /**
133
+ * Creates a new router instance with the given configuration.
134
+ *
135
+ * @param options - Router configuration including routes and optional base path
136
+ * @returns A configured router instance
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * const router = createRouter({
141
+ * base: '/app',
142
+ * routes: [
143
+ * { path: '/', component: () => import('./pages/Home') },
144
+ * { path: '/users/:id', component: () => import('./pages/User') },
145
+ * ]
146
+ * });
147
+ *
148
+ * // Use navigation guards
149
+ * router.beforeEach((to, from) => {
150
+ * if (!isAuthenticated && to.path !== '/login') {
151
+ * return '/login';
152
+ * }
153
+ * return true;
154
+ * });
155
+ * ```
156
+ */
157
+ export declare function createRouter(options: RouterOptions): Router;
158
+ export {};
159
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
package/dist/router.js ADDED
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Router implementation with file-based routing support.
3
+ * @module
4
+ */
5
+ import { ref } from '@bromscandium/core';
6
+ let currentRouter = null;
7
+ /**
8
+ * Sets the current router instance for global access.
9
+ *
10
+ * @param router - The router instance or null to clear
11
+ */
12
+ export function setRouter(router) {
13
+ currentRouter = router;
14
+ }
15
+ /**
16
+ * Gets the current router instance.
17
+ *
18
+ * @returns The current router or null if not set
19
+ */
20
+ export function getRouter() {
21
+ return currentRouter;
22
+ }
23
+ /**
24
+ * Creates a new router instance with the given configuration.
25
+ *
26
+ * @param options - Router configuration including routes and optional base path
27
+ * @returns A configured router instance
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const router = createRouter({
32
+ * base: '/app',
33
+ * routes: [
34
+ * { path: '/', component: () => import('./pages/Home') },
35
+ * { path: '/users/:id', component: () => import('./pages/User') },
36
+ * ]
37
+ * });
38
+ *
39
+ * // Use navigation guards
40
+ * router.beforeEach((to, from) => {
41
+ * if (!isAuthenticated && to.path !== '/login') {
42
+ * return '/login';
43
+ * }
44
+ * return true;
45
+ * });
46
+ * ```
47
+ */
48
+ export function createRouter(options) {
49
+ const { routes, base = '' } = options;
50
+ const currentRoute = ref(createEmptyLocation());
51
+ const beforeGuards = [];
52
+ const afterHooks = [];
53
+ let isReady = false;
54
+ let readyResolve = null;
55
+ const readyPromise = new Promise((resolve) => {
56
+ readyResolve = resolve;
57
+ });
58
+ function createEmptyLocation() {
59
+ return {
60
+ path: '/',
61
+ params: {},
62
+ query: {},
63
+ hash: '',
64
+ matched: [],
65
+ fullPath: '/',
66
+ meta: {},
67
+ };
68
+ }
69
+ function parseQuery(search) {
70
+ const query = {};
71
+ if (!search)
72
+ return query;
73
+ const searchParams = new URLSearchParams(search);
74
+ searchParams.forEach((value, key) => {
75
+ query[key] = value;
76
+ });
77
+ return query;
78
+ }
79
+ function stringifyQuery(query) {
80
+ const params = new URLSearchParams();
81
+ for (const [key, value] of Object.entries(query)) {
82
+ if (value != null && value !== '') {
83
+ params.set(key, value);
84
+ }
85
+ }
86
+ const str = params.toString();
87
+ return str ? `?${str}` : '';
88
+ }
89
+ function matchRoute(path, routes, basePath = '') {
90
+ const matched = [];
91
+ const segments = path.split('/').filter(Boolean);
92
+ function match(routes, segmentIndex, parentPath) {
93
+ for (const route of routes) {
94
+ const routePath = route.path.startsWith('/')
95
+ ? route.path
96
+ : `${parentPath}/${route.path}`.replace(/\/+/g, '/');
97
+ const routeSegments = routePath.split('/').filter(Boolean);
98
+ const params = {};
99
+ let matches = true;
100
+ let i = 0;
101
+ for (const routeSeg of routeSegments) {
102
+ const pathSeg = segments[segmentIndex + i];
103
+ if (routeSeg.startsWith(':')) {
104
+ const paramName = routeSeg.slice(1);
105
+ if (pathSeg) {
106
+ params[paramName] = decodeURIComponent(pathSeg);
107
+ }
108
+ else {
109
+ matches = false;
110
+ break;
111
+ }
112
+ }
113
+ else if (routeSeg.startsWith('[') && routeSeg.endsWith(']')) {
114
+ const paramName = routeSeg.slice(1, -1).replace('...', '');
115
+ if (routeSeg.startsWith('[...')) {
116
+ const remaining = segments.slice(segmentIndex + i);
117
+ params[paramName] = remaining.join('/');
118
+ i += remaining.length;
119
+ break;
120
+ }
121
+ else if (pathSeg) {
122
+ params[paramName] = decodeURIComponent(pathSeg);
123
+ }
124
+ else {
125
+ matches = false;
126
+ break;
127
+ }
128
+ }
129
+ else if (routeSeg !== pathSeg) {
130
+ matches = false;
131
+ break;
132
+ }
133
+ i++;
134
+ }
135
+ const totalSegments = segmentIndex + i;
136
+ const isExactMatch = totalSegments === segments.length;
137
+ const hasChildren = route.children && route.children.length > 0;
138
+ if (matches && (isExactMatch || hasChildren)) {
139
+ matched.push({
140
+ route,
141
+ params,
142
+ path: routePath,
143
+ });
144
+ if (hasChildren && !isExactMatch) {
145
+ match(route.children, totalSegments, routePath);
146
+ }
147
+ return true;
148
+ }
149
+ }
150
+ return false;
151
+ }
152
+ match(routes, 0, basePath);
153
+ return matched;
154
+ }
155
+ function parseLocation(location) {
156
+ const urlPath = location.pathname;
157
+ const path = urlPath.replace(base, '') || '/';
158
+ const query = parseQuery(location.search);
159
+ const hash = location.hash.slice(1);
160
+ const matched = matchRoute(path, routes, '');
161
+ const params = {};
162
+ const meta = {};
163
+ matched.forEach(m => {
164
+ Object.assign(params, m.params);
165
+ Object.assign(meta, m.route.meta || {});
166
+ });
167
+ const fullPath = path + stringifyQuery(query) + (hash ? `#${hash}` : '');
168
+ const name = matched[matched.length - 1]?.route.name;
169
+ return { path, params, query, hash, matched, fullPath, name, meta };
170
+ }
171
+ function resolveTarget(target) {
172
+ if (typeof target === 'string') {
173
+ return target;
174
+ }
175
+ let path = target.path || '/';
176
+ if (target.name) {
177
+ const findRoute = (routes, name) => {
178
+ for (const route of routes) {
179
+ if (route.name === name)
180
+ return route;
181
+ if (route.children) {
182
+ const found = findRoute(route.children, name);
183
+ if (found)
184
+ return found;
185
+ }
186
+ }
187
+ return null;
188
+ };
189
+ const route = findRoute(routes, target.name);
190
+ if (route) {
191
+ path = route.path;
192
+ if (target.params) {
193
+ for (const [key, value] of Object.entries(target.params)) {
194
+ path = path.replace(`:${key}`, encodeURIComponent(value));
195
+ path = path.replace(`[${key}]`, encodeURIComponent(value));
196
+ }
197
+ }
198
+ }
199
+ }
200
+ if (target.query) {
201
+ path += stringifyQuery(target.query);
202
+ }
203
+ if (target.hash) {
204
+ path += target.hash.startsWith('#') ? target.hash : `#${target.hash}`;
205
+ }
206
+ return path;
207
+ }
208
+ async function navigate(to, replace = false) {
209
+ const resolvedPath = resolveTarget(to);
210
+ const url = new URL(resolvedPath, window.location.origin);
211
+ if (base && !url.pathname.startsWith(base)) {
212
+ url.pathname = base + url.pathname;
213
+ }
214
+ const newLocation = parseLocation({
215
+ pathname: url.pathname,
216
+ search: url.search,
217
+ hash: url.hash,
218
+ });
219
+ const from = currentRoute.value;
220
+ for (const guard of beforeGuards) {
221
+ const result = await guard(newLocation, from);
222
+ if (result === false) {
223
+ return;
224
+ }
225
+ if (typeof result === 'string' || (typeof result === 'object' && result !== null)) {
226
+ await navigate(result, replace);
227
+ return;
228
+ }
229
+ }
230
+ if (replace) {
231
+ window.history.replaceState(null, '', url.href);
232
+ }
233
+ else {
234
+ window.history.pushState(null, '', url.href);
235
+ }
236
+ currentRoute.value = newLocation;
237
+ afterHooks.forEach(hook => hook(newLocation, from));
238
+ }
239
+ window.addEventListener('popstate', () => {
240
+ const newLocation = parseLocation(window.location);
241
+ const from = currentRoute.value;
242
+ currentRoute.value = newLocation;
243
+ afterHooks.forEach(hook => hook(newLocation, from));
244
+ });
245
+ const router = {
246
+ currentRoute,
247
+ routes,
248
+ base,
249
+ push: (to) => navigate(to, false),
250
+ replace: (to) => navigate(to, true),
251
+ back: () => window.history.back(),
252
+ forward: () => window.history.forward(),
253
+ go: (delta) => window.history.go(delta),
254
+ beforeEach(guard) {
255
+ beforeGuards.push(guard);
256
+ return () => {
257
+ const index = beforeGuards.indexOf(guard);
258
+ if (index > -1)
259
+ beforeGuards.splice(index, 1);
260
+ };
261
+ },
262
+ afterEach(hook) {
263
+ afterHooks.push(hook);
264
+ return () => {
265
+ const index = afterHooks.indexOf(hook);
266
+ if (index > -1)
267
+ afterHooks.splice(index, 1);
268
+ };
269
+ },
270
+ isReady() {
271
+ if (isReady)
272
+ return Promise.resolve();
273
+ return readyPromise;
274
+ },
275
+ };
276
+ currentRoute.value = parseLocation(window.location);
277
+ isReady = true;
278
+ readyResolve?.();
279
+ setRouter(router);
280
+ return router;
281
+ }
282
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}