eleva 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -10
- package/dist/{eleva-plugins.cjs.js → eleva-plugins.cjs} +1002 -292
- package/dist/eleva-plugins.cjs.map +1 -0
- package/dist/eleva-plugins.d.cts +1352 -0
- package/dist/eleva-plugins.d.cts.map +1 -0
- package/dist/eleva-plugins.d.ts +1352 -0
- package/dist/eleva-plugins.d.ts.map +1 -0
- package/dist/{eleva-plugins.esm.js → eleva-plugins.js} +1002 -292
- package/dist/eleva-plugins.js.map +1 -0
- package/dist/eleva-plugins.umd.js +1001 -291
- package/dist/eleva-plugins.umd.js.map +1 -1
- package/dist/eleva-plugins.umd.min.js +1 -1
- package/dist/eleva-plugins.umd.min.js.map +1 -1
- package/dist/{eleva.cjs.js → eleva.cjs} +421 -191
- package/dist/eleva.cjs.map +1 -0
- package/dist/eleva.d.cts +1329 -0
- package/dist/eleva.d.cts.map +1 -0
- package/dist/eleva.d.ts +473 -226
- package/dist/eleva.d.ts.map +1 -0
- package/dist/{eleva.esm.js → eleva.js} +422 -192
- package/dist/eleva.js.map +1 -0
- package/dist/eleva.umd.js +420 -190
- package/dist/eleva.umd.js.map +1 -1
- package/dist/eleva.umd.min.js +1 -1
- package/dist/eleva.umd.min.js.map +1 -1
- package/dist/plugins/attr.cjs +279 -0
- package/dist/plugins/attr.cjs.map +1 -0
- package/dist/plugins/attr.d.cts +101 -0
- package/dist/plugins/attr.d.cts.map +1 -0
- package/dist/plugins/attr.d.ts +101 -0
- package/dist/plugins/attr.d.ts.map +1 -0
- package/dist/plugins/attr.js +276 -0
- package/dist/plugins/attr.js.map +1 -0
- package/dist/plugins/attr.umd.js +111 -22
- package/dist/plugins/attr.umd.js.map +1 -1
- package/dist/plugins/attr.umd.min.js +1 -1
- package/dist/plugins/attr.umd.min.js.map +1 -1
- package/dist/plugins/router.cjs +1873 -0
- package/dist/plugins/router.cjs.map +1 -0
- package/dist/plugins/router.d.cts +1296 -0
- package/dist/plugins/router.d.cts.map +1 -0
- package/dist/plugins/router.d.ts +1296 -0
- package/dist/plugins/router.d.ts.map +1 -0
- package/dist/plugins/router.js +1870 -0
- package/dist/plugins/router.js.map +1 -0
- package/dist/plugins/router.umd.js +482 -186
- package/dist/plugins/router.umd.js.map +1 -1
- package/dist/plugins/router.umd.min.js +1 -1
- package/dist/plugins/router.umd.min.js.map +1 -1
- package/dist/plugins/store.cjs +920 -0
- package/dist/plugins/store.cjs.map +1 -0
- package/dist/plugins/store.d.cts +266 -0
- package/dist/plugins/store.d.cts.map +1 -0
- package/dist/plugins/store.d.ts +266 -0
- package/dist/plugins/store.d.ts.map +1 -0
- package/dist/plugins/store.js +917 -0
- package/dist/plugins/store.js.map +1 -0
- package/dist/plugins/store.umd.js +410 -85
- package/dist/plugins/store.umd.js.map +1 -1
- package/dist/plugins/store.umd.min.js +1 -1
- package/dist/plugins/store.umd.min.js.map +1 -1
- package/package.json +112 -68
- package/src/core/Eleva.js +195 -115
- package/src/index.cjs +10 -0
- package/src/index.js +11 -0
- package/src/modules/Emitter.js +68 -20
- package/src/modules/Renderer.js +82 -20
- package/src/modules/Signal.js +43 -15
- package/src/modules/TemplateEngine.js +50 -9
- package/src/plugins/Attr.js +121 -19
- package/src/plugins/Router.js +526 -181
- package/src/plugins/Store.js +448 -69
- package/src/plugins/index.js +1 -0
- package/types/core/Eleva.d.ts +263 -169
- package/types/core/Eleva.d.ts.map +1 -1
- package/types/index.d.cts +3 -0
- package/types/index.d.cts.map +1 -0
- package/types/index.d.ts +5 -0
- package/types/index.d.ts.map +1 -1
- package/types/modules/Emitter.d.ts +73 -30
- package/types/modules/Emitter.d.ts.map +1 -1
- package/types/modules/Renderer.d.ts +48 -18
- package/types/modules/Renderer.d.ts.map +1 -1
- package/types/modules/Signal.d.ts +44 -16
- package/types/modules/Signal.d.ts.map +1 -1
- package/types/modules/TemplateEngine.d.ts +46 -11
- package/types/modules/TemplateEngine.d.ts.map +1 -1
- package/types/plugins/Attr.d.ts +83 -16
- package/types/plugins/Attr.d.ts.map +1 -1
- package/types/plugins/Router.d.ts +498 -207
- package/types/plugins/Router.d.ts.map +1 -1
- package/types/plugins/Store.d.ts +211 -37
- package/types/plugins/Store.d.ts.map +1 -1
- package/dist/eleva-plugins.cjs.js.map +0 -1
- package/dist/eleva-plugins.esm.js.map +0 -1
- package/dist/eleva.cjs.js.map +0 -1
- package/dist/eleva.esm.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Eleva Router Plugin v1.0
|
|
1
|
+
/*! Eleva Router Plugin v1.1.0 | MIT License | https://elevajs.com */
|
|
2
2
|
(function (global, factory) {
|
|
3
3
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
4
4
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
@@ -6,60 +6,176 @@
|
|
|
6
6
|
})(this, (function (exports) { 'use strict';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* @module eleva/plugins/router
|
|
10
|
+
* @fileoverview Client-side router plugin with hash, history, and query modes,
|
|
11
|
+
* navigation guards, and lifecycle hooks.
|
|
12
|
+
*/ // ============================================================================
|
|
13
|
+
// TYPE DEFINITIONS
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
// External Type Imports
|
|
17
|
+
// -----------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Type imports from the Eleva core library.
|
|
9
20
|
* @typedef {import('eleva').Eleva} Eleva
|
|
10
|
-
* @typedef {import('eleva').Signal} Signal
|
|
11
21
|
* @typedef {import('eleva').ComponentDefinition} ComponentDefinition
|
|
12
22
|
* @typedef {import('eleva').Emitter} Emitter
|
|
13
23
|
* @typedef {import('eleva').MountResult} MountResult
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
* @typedef {import('eleva').UnsubscribeFunction} UnsubscribeFunction
|
|
25
|
+
*/ /**
|
|
26
|
+
* Generic type import.
|
|
27
|
+
* @template T
|
|
28
|
+
* @typedef {import('eleva').Signal<T>} Signal
|
|
29
|
+
*/ // -----------------------------------------------------------------------------
|
|
30
|
+
// Router Events
|
|
31
|
+
// -----------------------------------------------------------------------------
|
|
32
|
+
/**
|
|
33
|
+
* Fired when the router initialization completes successfully.
|
|
34
|
+
* @event router:ready
|
|
35
|
+
* @type {Router}
|
|
36
|
+
*/ /**
|
|
37
|
+
* Fired when an error occurs during navigation or route handling.
|
|
38
|
+
* @event router:error
|
|
39
|
+
* @type {Error}
|
|
40
|
+
*/ /**
|
|
41
|
+
* Fired when no matching route is found for the requested path.
|
|
42
|
+
* @event router:notFound
|
|
43
|
+
* @type {{to: RouteLocation, from: RouteLocation | null, path: string}}
|
|
44
|
+
*/ /**
|
|
45
|
+
* Fired before guards run, allowing plugins to block or redirect navigation.
|
|
46
|
+
* @event router:beforeEach
|
|
47
|
+
* @type {NavigationContext}
|
|
48
|
+
*/ /**
|
|
49
|
+
* Fired before component resolution, allowing plugins to modify the resolve context.
|
|
50
|
+
* @event router:beforeResolve
|
|
51
|
+
* @type {ResolveContext}
|
|
52
|
+
*/ /**
|
|
53
|
+
* Fired after components are resolved successfully.
|
|
54
|
+
* @event router:afterResolve
|
|
55
|
+
* @type {ResolveContext}
|
|
56
|
+
*/ /**
|
|
57
|
+
* Fired after leaving the previous route.
|
|
58
|
+
* @event router:afterLeave
|
|
59
|
+
* @type {{to: RouteLocation, from: RouteLocation}}
|
|
60
|
+
*/ /**
|
|
61
|
+
* Fired before DOM rendering begins.
|
|
62
|
+
* @event router:beforeRender
|
|
63
|
+
* @type {RenderContext}
|
|
64
|
+
*/ /**
|
|
65
|
+
* Fired after DOM rendering completes.
|
|
66
|
+
* @event router:afterRender
|
|
67
|
+
* @type {RenderContext}
|
|
68
|
+
*/ /**
|
|
69
|
+
* Fired after render for scroll behavior handling.
|
|
70
|
+
* @event router:scroll
|
|
71
|
+
* @type {ScrollContext}
|
|
72
|
+
*/ /**
|
|
73
|
+
* Fired after entering the new route.
|
|
74
|
+
* @event router:afterEnter
|
|
75
|
+
* @type {{to: RouteLocation, from: RouteLocation | null}}
|
|
76
|
+
*/ /**
|
|
77
|
+
* Fired after navigation completes successfully.
|
|
78
|
+
* @event router:afterEach
|
|
79
|
+
* @type {{to: RouteLocation, from: RouteLocation | null}}
|
|
80
|
+
*/ /**
|
|
81
|
+
* Fired when a route is dynamically added.
|
|
82
|
+
* @event router:routeAdded
|
|
83
|
+
* @type {RouteDefinition}
|
|
84
|
+
*/ /**
|
|
85
|
+
* Fired when a route is dynamically removed.
|
|
86
|
+
* @event router:routeRemoved
|
|
87
|
+
* @type {RouteDefinition}
|
|
88
|
+
*/ // -----------------------------------------------------------------------------
|
|
89
|
+
// Router Data Types
|
|
90
|
+
// -----------------------------------------------------------------------------
|
|
17
91
|
/**
|
|
18
|
-
* @typedef {'hash' | 'history' | 'query'} RouterMode
|
|
19
92
|
* The routing mode determines how the router manages URL state.
|
|
20
93
|
* - `hash`: Uses URL hash (e.g., `/#/path`) - works without server config
|
|
21
94
|
* - `history`: Uses HTML5 History API (e.g., `/path`) - requires server config
|
|
22
95
|
* - `query`: Uses query parameters (e.g., `?view=/path`) - useful for embedded apps
|
|
96
|
+
* @typedef {'hash' | 'history' | 'query'} RouterMode
|
|
97
|
+
*/ /**
|
|
98
|
+
* Route parameters extracted from the URL path.
|
|
99
|
+
* @typedef {Record<string, string>} RouteParams
|
|
100
|
+
* @description Key-value pairs extracted from dynamic route segments (e.g., `/users/:id` → `{ id: '123' }`).
|
|
101
|
+
*/ /**
|
|
102
|
+
* Query parameters from the URL query string.
|
|
103
|
+
* @typedef {Record<string, string>} QueryParams
|
|
104
|
+
* @description Key-value pairs from the URL query string (e.g., `?page=1&sort=name`).
|
|
105
|
+
*/ /**
|
|
106
|
+
* Navigation input parameters supporting multiple value types.
|
|
107
|
+
* @typedef {Record<string, string | number | boolean>} NavigationParams
|
|
108
|
+
* @description Parameters passed to navigation functions, automatically converted to strings in URLs.
|
|
23
109
|
*/ /**
|
|
110
|
+
* Function signature for programmatic navigation.
|
|
111
|
+
* @typedef {(location: string | NavigationTarget, params?: NavigationParams) => Promise<boolean>} NavigateFunction
|
|
112
|
+
* @description Returns true if navigation succeeded, false if blocked by a guard.
|
|
113
|
+
*/ /**
|
|
114
|
+
* Router configuration options.
|
|
24
115
|
* @typedef {Object} RouterOptions
|
|
25
|
-
* @property {RouterMode} [mode='hash']
|
|
26
|
-
*
|
|
27
|
-
* @property {string} [
|
|
28
|
-
*
|
|
29
|
-
* @property {
|
|
30
|
-
*
|
|
31
|
-
* @property {
|
|
116
|
+
* @property {RouterMode} [mode='hash']
|
|
117
|
+
* The routing mode to use.
|
|
118
|
+
* @property {string} [queryParam='view']
|
|
119
|
+
* Query parameter name for 'query' mode.
|
|
120
|
+
* @property {string} [viewSelector='view']
|
|
121
|
+
* Base selector for the view element.
|
|
122
|
+
* @property {string} mount
|
|
123
|
+
* CSS selector for the mount point element.
|
|
124
|
+
* @property {RouteDefinition[]} routes
|
|
125
|
+
* Array of route definitions.
|
|
126
|
+
* @property {RouteComponent} [globalLayout]
|
|
127
|
+
* Default layout for all routes.
|
|
128
|
+
* @property {NavigationGuard} [onBeforeEach]
|
|
129
|
+
* Global navigation guard.
|
|
130
|
+
* @property {boolean} [autoStart=true]
|
|
131
|
+
* Whether to start the router automatically.
|
|
32
132
|
* @description Configuration options for the Router plugin.
|
|
33
133
|
*/ /**
|
|
134
|
+
* Object describing a navigation target for `router.navigate()`.
|
|
34
135
|
* @typedef {Object} NavigationTarget
|
|
35
|
-
* @property {string} path
|
|
36
|
-
*
|
|
37
|
-
* @property {
|
|
38
|
-
*
|
|
39
|
-
* @property {
|
|
136
|
+
* @property {string} path
|
|
137
|
+
* The target path (can include params like '/users/:id').
|
|
138
|
+
* @property {NavigationParams} [params]
|
|
139
|
+
* Route parameters to inject.
|
|
140
|
+
* @property {NavigationParams} [query]
|
|
141
|
+
* Query parameters to append.
|
|
142
|
+
* @property {boolean} [replace=false]
|
|
143
|
+
* Whether to replace current history entry.
|
|
144
|
+
* @property {unknown} [state]
|
|
145
|
+
* History state to pass.
|
|
40
146
|
* @description Object describing a navigation target for `router.navigate()`.
|
|
41
147
|
*/ /**
|
|
148
|
+
* Saved scroll position.
|
|
42
149
|
* @typedef {Object} ScrollPosition
|
|
43
|
-
* @property {number} x
|
|
44
|
-
*
|
|
150
|
+
* @property {number} x
|
|
151
|
+
* Horizontal scroll position.
|
|
152
|
+
* @property {number} y
|
|
153
|
+
* Vertical scroll position.
|
|
45
154
|
* @description Represents a saved scroll position.
|
|
46
155
|
*/ /**
|
|
156
|
+
* Internal representation of a parsed route path segment.
|
|
47
157
|
* @typedef {Object} RouteSegment
|
|
48
|
-
* @property {'static' | 'param'} type
|
|
49
|
-
*
|
|
50
|
-
* @property {string} [
|
|
158
|
+
* @property {'static' | 'param'} type
|
|
159
|
+
* The segment type.
|
|
160
|
+
* @property {string} [value]
|
|
161
|
+
* The segment value (static segments).
|
|
162
|
+
* @property {string} [name]
|
|
163
|
+
* The parameter name (param segments).
|
|
51
164
|
* @description Internal representation of a parsed route path segment.
|
|
52
165
|
* @private
|
|
53
166
|
*/ /**
|
|
167
|
+
* Result of matching a path against route definitions.
|
|
54
168
|
* @typedef {Object} RouteMatch
|
|
55
|
-
* @property {RouteDefinition} route
|
|
56
|
-
*
|
|
169
|
+
* @property {RouteDefinition} route
|
|
170
|
+
* The matched route definition.
|
|
171
|
+
* @property {RouteParams} params
|
|
172
|
+
* The extracted route parameters.
|
|
57
173
|
* @description Result of matching a path against route definitions.
|
|
58
174
|
* @private
|
|
59
175
|
*/ /**
|
|
60
|
-
*
|
|
61
|
-
* @
|
|
62
|
-
* Common properties include:
|
|
176
|
+
* Arbitrary metadata attached to routes for use in guards and components.
|
|
177
|
+
* @typedef {Record<string, unknown>} RouteMeta
|
|
178
|
+
* @description Common properties include:
|
|
63
179
|
* - `requiresAuth: boolean` - Whether the route requires authentication
|
|
64
180
|
* - `title: string` - Page title for the route
|
|
65
181
|
* - `roles: string[]` - Required user roles
|
|
@@ -70,76 +186,119 @@
|
|
|
70
186
|
* meta: { requiresAuth: true, roles: ['admin'], title: 'Admin Dashboard' }
|
|
71
187
|
* }
|
|
72
188
|
*/ /**
|
|
189
|
+
* Interface for the router's error handling system.
|
|
73
190
|
* @typedef {Object} RouterErrorHandler
|
|
74
|
-
* @property {(error: Error, context: string, details?: Record<string,
|
|
75
|
-
*
|
|
76
|
-
* @property {(message: string,
|
|
191
|
+
* @property {(error: Error, context: string, details?: Record<string, unknown>) => void} handle
|
|
192
|
+
* Throws a formatted error.
|
|
193
|
+
* @property {(message: string, details?: Record<string, unknown>) => void} warn
|
|
194
|
+
* Logs a warning.
|
|
195
|
+
* @property {(message: string, error: Error, details?: Record<string, unknown>) => void} log
|
|
196
|
+
* Logs an error without throwing.
|
|
77
197
|
* @description Interface for the router's error handling system.
|
|
78
|
-
*/ //
|
|
79
|
-
// Event Callback
|
|
80
|
-
//
|
|
198
|
+
*/ // -----------------------------------------------------------------------------
|
|
199
|
+
// Event Callback Types
|
|
200
|
+
// -----------------------------------------------------------------------------
|
|
81
201
|
/**
|
|
202
|
+
* Callback for `router:beforeEach` event.
|
|
82
203
|
* @callback NavigationContextCallback
|
|
83
|
-
* @param {NavigationContext} context
|
|
204
|
+
* @param {NavigationContext} context
|
|
205
|
+
* The navigation context (can be modified to block/redirect).
|
|
84
206
|
* @returns {void | Promise<void>}
|
|
85
|
-
* @description
|
|
207
|
+
* @description Modify context to control navigation flow.
|
|
86
208
|
*/ /**
|
|
209
|
+
* Callback for `router:beforeResolve` and `router:afterResolve` events.
|
|
87
210
|
* @callback ResolveContextCallback
|
|
88
|
-
* @param {ResolveContext} context
|
|
211
|
+
* @param {ResolveContext} context
|
|
212
|
+
* The resolve context (can be modified to block/redirect).
|
|
89
213
|
* @returns {void | Promise<void>}
|
|
90
214
|
* @description Callback for `router:beforeResolve` and `router:afterResolve` events.
|
|
91
215
|
*/ /**
|
|
216
|
+
* Callback for `router:beforeRender` and `router:afterRender` events.
|
|
92
217
|
* @callback RenderContextCallback
|
|
93
|
-
* @param {RenderContext} context
|
|
218
|
+
* @param {RenderContext} context
|
|
219
|
+
* The render context.
|
|
94
220
|
* @returns {void | Promise<void>}
|
|
95
221
|
* @description Callback for `router:beforeRender` and `router:afterRender` events.
|
|
96
222
|
*/ /**
|
|
223
|
+
* Callback for `router:scroll` event.
|
|
97
224
|
* @callback ScrollContextCallback
|
|
98
|
-
* @param {ScrollContext} context
|
|
225
|
+
* @param {ScrollContext} context
|
|
226
|
+
* The scroll context with saved position info.
|
|
99
227
|
* @returns {void | Promise<void>}
|
|
100
|
-
* @description
|
|
228
|
+
* @description Use to implement custom scroll behavior.
|
|
101
229
|
*/ /**
|
|
230
|
+
* Callback for `router:afterEnter`, `router:afterLeave`, `router:afterEach` events.
|
|
102
231
|
* @callback RouteChangeCallback
|
|
103
|
-
* @param {RouteLocation} to
|
|
104
|
-
*
|
|
232
|
+
* @param {RouteLocation} to
|
|
233
|
+
* The target route location.
|
|
234
|
+
* @param {RouteLocation | null} from
|
|
235
|
+
* The source route location.
|
|
105
236
|
* @returns {void | Promise<void>}
|
|
106
237
|
* @description Callback for `router:afterEnter`, `router:afterLeave`, `router:afterEach` events.
|
|
107
238
|
*/ /**
|
|
239
|
+
* Router context injected into component setup as `ctx.router`.
|
|
240
|
+
* @typedef {Object} RouterContext
|
|
241
|
+
* @property {NavigateFunction} navigate
|
|
242
|
+
* Programmatic navigation function.
|
|
243
|
+
* @property {Signal<RouteLocation | null>} current
|
|
244
|
+
* Reactive signal for current route.
|
|
245
|
+
* @property {Signal<RouteLocation | null>} previous
|
|
246
|
+
* Reactive signal for previous route.
|
|
247
|
+
* @property {RouteParams} params
|
|
248
|
+
* Current route params (getter).
|
|
249
|
+
* @property {QueryParams} query
|
|
250
|
+
* Current route query (getter).
|
|
251
|
+
* @property {string} path
|
|
252
|
+
* Current route path (getter).
|
|
253
|
+
* @property {string} fullUrl
|
|
254
|
+
* Current routed URL string (getter).
|
|
255
|
+
* @property {RouteMeta} meta
|
|
256
|
+
* Current route meta (getter).
|
|
257
|
+
* @description Injected into component setup as `ctx.router`.
|
|
258
|
+
*/ /**
|
|
259
|
+
* Callback for `router:error` event.
|
|
108
260
|
* @callback RouterErrorCallback
|
|
109
|
-
* @param {Error} error
|
|
110
|
-
*
|
|
111
|
-
* @param {RouteLocation
|
|
261
|
+
* @param {Error} error
|
|
262
|
+
* The error that occurred.
|
|
263
|
+
* @param {RouteLocation} [to]
|
|
264
|
+
* The target route (if available).
|
|
265
|
+
* @param {RouteLocation | null} [from]
|
|
266
|
+
* The source route (if available).
|
|
112
267
|
* @returns {void | Promise<void>}
|
|
113
|
-
* @description Callback for `router:
|
|
268
|
+
* @description Callback for `router:error` event.
|
|
114
269
|
*/ /**
|
|
270
|
+
* Callback for `router:ready` event.
|
|
115
271
|
* @callback RouterReadyCallback
|
|
116
|
-
* @param {Router} router
|
|
272
|
+
* @param {Router} router
|
|
273
|
+
* The router instance.
|
|
117
274
|
* @returns {void | Promise<void>}
|
|
118
275
|
* @description Callback for `router:ready` event.
|
|
119
276
|
*/ /**
|
|
277
|
+
* Callback for `router:routeAdded` event.
|
|
120
278
|
* @callback RouteAddedCallback
|
|
121
|
-
* @param {RouteDefinition} route
|
|
279
|
+
* @param {RouteDefinition} route
|
|
280
|
+
* The added route definition.
|
|
122
281
|
* @returns {void | Promise<void>}
|
|
123
282
|
* @description Callback for `router:routeAdded` event.
|
|
124
283
|
*/ /**
|
|
284
|
+
* Callback for `router:routeRemoved` event.
|
|
125
285
|
* @callback RouteRemovedCallback
|
|
126
|
-
* @param {RouteDefinition} route
|
|
286
|
+
* @param {RouteDefinition} route
|
|
287
|
+
* The removed route definition.
|
|
127
288
|
* @returns {void | Promise<void>}
|
|
128
289
|
* @description Callback for `router:routeRemoved` event.
|
|
129
|
-
*/ //
|
|
130
|
-
//
|
|
131
|
-
//
|
|
290
|
+
*/ // ============================================================================
|
|
291
|
+
// CORE IMPLEMENTATION
|
|
292
|
+
// ============================================================================
|
|
132
293
|
/**
|
|
133
294
|
* Simple error handler for the core router.
|
|
134
|
-
* Can be overridden by error handling plugins.
|
|
135
|
-
* Provides consistent error formatting and logging for router operations.
|
|
136
295
|
* @private
|
|
137
296
|
*/ const CoreErrorHandler = {
|
|
138
297
|
/**
|
|
139
298
|
* Handles router errors with basic formatting.
|
|
140
299
|
* @param {Error} error - The error to handle.
|
|
141
300
|
* @param {string} context - The context where the error occurred.
|
|
142
|
-
* @param {
|
|
301
|
+
* @param {Record<string, unknown>} details - Additional error details.
|
|
143
302
|
* @throws {Error} The formatted error.
|
|
144
303
|
*/ handle (error, context, details = {}) {
|
|
145
304
|
const message = `[ElevaRouter] ${context}: ${error.message}`;
|
|
@@ -158,7 +317,7 @@
|
|
|
158
317
|
/**
|
|
159
318
|
* Logs a warning without throwing an error.
|
|
160
319
|
* @param {string} message - The warning message.
|
|
161
|
-
* @param {
|
|
320
|
+
* @param {Record<string, unknown>} details - Additional warning details.
|
|
162
321
|
*/ warn (message, details = {}) {
|
|
163
322
|
console.warn(`[ElevaRouter] ${message}`, details);
|
|
164
323
|
},
|
|
@@ -166,7 +325,7 @@
|
|
|
166
325
|
* Logs an error without throwing.
|
|
167
326
|
* @param {string} message - The error message.
|
|
168
327
|
* @param {Error} error - The original error.
|
|
169
|
-
* @param {
|
|
328
|
+
* @param {Record<string, unknown>} details - Additional error details.
|
|
170
329
|
*/ log (message, error, details = {}) {
|
|
171
330
|
console.error(`[ElevaRouter] ${message}`, {
|
|
172
331
|
error,
|
|
@@ -175,26 +334,37 @@
|
|
|
175
334
|
}
|
|
176
335
|
};
|
|
177
336
|
/**
|
|
337
|
+
* Represents the current or target location in the router.
|
|
178
338
|
* @typedef {Object} RouteLocation
|
|
179
|
-
* @property {string} path
|
|
180
|
-
*
|
|
181
|
-
* @property {
|
|
182
|
-
*
|
|
183
|
-
* @property {
|
|
184
|
-
*
|
|
185
|
-
* @property {
|
|
339
|
+
* @property {string} path
|
|
340
|
+
* The path of the route (e.g., '/users/123').
|
|
341
|
+
* @property {QueryParams} query
|
|
342
|
+
* Query parameters as key-value pairs.
|
|
343
|
+
* @property {string} fullUrl
|
|
344
|
+
* The routed URL string (path plus query).
|
|
345
|
+
* @property {RouteParams} params
|
|
346
|
+
* Dynamic route parameters.
|
|
347
|
+
* @property {RouteMeta} meta
|
|
348
|
+
* Metadata associated with the matched route.
|
|
349
|
+
* @property {string} [name]
|
|
350
|
+
* The optional name of the matched route.
|
|
351
|
+
* @property {RouteDefinition} matched
|
|
352
|
+
* The raw route definition that was matched.
|
|
186
353
|
* @description Represents the current or target location in the router.
|
|
187
354
|
*/ /**
|
|
188
|
-
*
|
|
189
|
-
* The return value of a navigation guard.
|
|
355
|
+
* Return value of a navigation guard.
|
|
190
356
|
* - `true` or `undefined/void`: Allow navigation
|
|
191
357
|
* - `false`: Abort navigation
|
|
192
358
|
* - `string`: Redirect to path
|
|
193
359
|
* - `NavigationTarget`: Redirect with options
|
|
360
|
+
* @typedef {boolean | string | NavigationTarget | void} NavigationGuardResult
|
|
194
361
|
*/ /**
|
|
362
|
+
* Navigation guard function that controls navigation flow.
|
|
195
363
|
* @callback NavigationGuard
|
|
196
|
-
* @param {RouteLocation} to
|
|
197
|
-
*
|
|
364
|
+
* @param {RouteLocation} to
|
|
365
|
+
* The target route location.
|
|
366
|
+
* @param {RouteLocation | null} from
|
|
367
|
+
* The source route location (null on initial).
|
|
198
368
|
* @returns {NavigationGuardResult | Promise<NavigationGuardResult>}
|
|
199
369
|
* @description A function that controls navigation flow. Runs before navigation is confirmed.
|
|
200
370
|
* @example
|
|
@@ -206,9 +376,12 @@
|
|
|
206
376
|
* // Allow navigation (implicit return undefined)
|
|
207
377
|
* };
|
|
208
378
|
*/ /**
|
|
379
|
+
* Navigation hook for side effects. Does not affect navigation flow.
|
|
209
380
|
* @callback NavigationHook
|
|
210
|
-
* @param {RouteLocation} to
|
|
211
|
-
*
|
|
381
|
+
* @param {RouteLocation} to
|
|
382
|
+
* The target route location.
|
|
383
|
+
* @param {RouteLocation | null} from
|
|
384
|
+
* The source route location.
|
|
212
385
|
* @returns {void | Promise<void>}
|
|
213
386
|
* @description A lifecycle hook for side effects. Does not affect navigation flow.
|
|
214
387
|
* @example
|
|
@@ -217,11 +390,16 @@
|
|
|
217
390
|
* analytics.trackPageView(to.path);
|
|
218
391
|
* };
|
|
219
392
|
*/ /**
|
|
393
|
+
* Interface for router plugins.
|
|
220
394
|
* @typedef {Object} RouterPlugin
|
|
221
|
-
* @property {string} name
|
|
222
|
-
*
|
|
223
|
-
* @property {
|
|
224
|
-
*
|
|
395
|
+
* @property {string} name
|
|
396
|
+
* Unique plugin identifier.
|
|
397
|
+
* @property {string} [version]
|
|
398
|
+
* Plugin version (recommended to match router version).
|
|
399
|
+
* @property {(router: Router, options?: Record<string, unknown>) => void} install
|
|
400
|
+
* Installation function.
|
|
401
|
+
* @property {(router: Router) => void | Promise<void>} [destroy]
|
|
402
|
+
* Cleanup function called on router.destroy().
|
|
225
403
|
* @description Interface for router plugins. Plugins can extend router functionality.
|
|
226
404
|
* @example
|
|
227
405
|
* const AnalyticsPlugin = {
|
|
@@ -234,57 +412,93 @@
|
|
|
234
412
|
* }
|
|
235
413
|
* };
|
|
236
414
|
*/ /**
|
|
415
|
+
* Context object for navigation events that plugins can modify.
|
|
237
416
|
* @typedef {Object} NavigationContext
|
|
238
|
-
* @property {RouteLocation} to
|
|
239
|
-
*
|
|
240
|
-
* @property {
|
|
241
|
-
*
|
|
242
|
-
* @
|
|
417
|
+
* @property {RouteLocation} to
|
|
418
|
+
* The target route location.
|
|
419
|
+
* @property {RouteLocation | null} from
|
|
420
|
+
* The source route location.
|
|
421
|
+
* @property {boolean} cancelled
|
|
422
|
+
* Whether navigation has been cancelled.
|
|
423
|
+
* @property {string | NavigationTarget | null} redirectTo
|
|
424
|
+
* Redirect target if set.
|
|
425
|
+
* @description Passed to navigation events. Plugins can modify to control navigation flow.
|
|
243
426
|
*/ /**
|
|
427
|
+
* Context object for component resolution events.
|
|
244
428
|
* @typedef {Object} ResolveContext
|
|
245
|
-
* @property {RouteLocation} to
|
|
246
|
-
*
|
|
247
|
-
* @property {
|
|
248
|
-
*
|
|
249
|
-
* @property {
|
|
250
|
-
*
|
|
251
|
-
* @property {
|
|
252
|
-
*
|
|
429
|
+
* @property {RouteLocation} to
|
|
430
|
+
* The target route location.
|
|
431
|
+
* @property {RouteLocation | null} from
|
|
432
|
+
* The source route location.
|
|
433
|
+
* @property {RouteDefinition} route
|
|
434
|
+
* The matched route definition.
|
|
435
|
+
* @property {ComponentDefinition | null} layoutComponent
|
|
436
|
+
* The resolved layout component (available in afterResolve).
|
|
437
|
+
* @property {ComponentDefinition | null} pageComponent
|
|
438
|
+
* The resolved page component (available in afterResolve).
|
|
439
|
+
* @property {boolean} cancelled
|
|
440
|
+
* Whether navigation has been cancelled.
|
|
441
|
+
* @property {string | NavigationTarget | null} redirectTo
|
|
442
|
+
* Redirect target if set.
|
|
443
|
+
* @description Passed to component resolution events.
|
|
253
444
|
*/ /**
|
|
445
|
+
* Context object for render events.
|
|
254
446
|
* @typedef {Object} RenderContext
|
|
255
|
-
* @property {RouteLocation} to
|
|
256
|
-
*
|
|
257
|
-
* @property {
|
|
258
|
-
*
|
|
259
|
-
* @
|
|
447
|
+
* @property {RouteLocation} to
|
|
448
|
+
* The target route location.
|
|
449
|
+
* @property {RouteLocation | null} from
|
|
450
|
+
* The source route location.
|
|
451
|
+
* @property {ComponentDefinition | null} layoutComponent
|
|
452
|
+
* The layout component being rendered.
|
|
453
|
+
* @property {ComponentDefinition} pageComponent
|
|
454
|
+
* The page component being rendered.
|
|
455
|
+
* @description Passed to render events.
|
|
260
456
|
*/ /**
|
|
457
|
+
* Context object for scroll events.
|
|
261
458
|
* @typedef {Object} ScrollContext
|
|
262
|
-
* @property {RouteLocation} to
|
|
263
|
-
*
|
|
264
|
-
* @property {
|
|
265
|
-
*
|
|
459
|
+
* @property {RouteLocation} to
|
|
460
|
+
* The target route location.
|
|
461
|
+
* @property {RouteLocation | null} from
|
|
462
|
+
* The source route location.
|
|
463
|
+
* @property {{x: number, y: number} | null} savedPosition
|
|
464
|
+
* Saved position (back/forward nav).
|
|
465
|
+
* @description Passed to scroll events for plugins to handle scroll behavior.
|
|
266
466
|
*/ /**
|
|
267
|
-
* @typedef {string | ComponentDefinition | (() => Promise<{default: ComponentDefinition}>)} RouteComponent
|
|
268
467
|
* A component that can be rendered for a route.
|
|
269
468
|
* - `string`: Name of a registered component
|
|
270
469
|
* - `ComponentDefinition`: Inline component definition
|
|
271
|
-
* - `() =>
|
|
470
|
+
* - `() => ComponentDefinition`: Factory function returning a component
|
|
471
|
+
* - `() => Promise<ComponentDefinition>`: Async factory function
|
|
472
|
+
* - `() => Promise<{default: ComponentDefinition}>`: Lazy-loaded module (e.g., `() => import('./Page.js')`)
|
|
473
|
+
* @typedef {string | ComponentDefinition | (() => ComponentDefinition | Promise<ComponentDefinition | {default: ComponentDefinition}>)} RouteComponent
|
|
272
474
|
*/ /**
|
|
475
|
+
* Defines a route in the application.
|
|
273
476
|
* @typedef {Object} RouteDefinition
|
|
274
|
-
* @property {string} path
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* @property {RouteComponent}
|
|
280
|
-
*
|
|
281
|
-
* @property {
|
|
282
|
-
*
|
|
283
|
-
* @property {
|
|
284
|
-
*
|
|
285
|
-
* @property {
|
|
286
|
-
*
|
|
477
|
+
* @property {string} path
|
|
478
|
+
* URL path pattern. Supports:
|
|
479
|
+
* - Static: '/about'
|
|
480
|
+
* - Dynamic params: '/users/:id'
|
|
481
|
+
* - Wildcard: '*' (catch-all, conventionally last)
|
|
482
|
+
* @property {RouteComponent} component
|
|
483
|
+
* The component to render for this route.
|
|
484
|
+
* @property {RouteComponent} [layout]
|
|
485
|
+
* Optional layout component to wrap the route component.
|
|
486
|
+
* @property {string} [name]
|
|
487
|
+
* Optional route name for programmatic navigation.
|
|
488
|
+
* @property {RouteMeta} [meta]
|
|
489
|
+
* Optional metadata (auth flags, titles, etc.).
|
|
490
|
+
* @property {NavigationGuard} [beforeEnter]
|
|
491
|
+
* Route-specific guard before entering.
|
|
492
|
+
* @property {NavigationHook} [afterEnter]
|
|
493
|
+
* Hook after entering and component is mounted.
|
|
494
|
+
* @property {NavigationGuard} [beforeLeave]
|
|
495
|
+
* Guard before leaving this route.
|
|
496
|
+
* @property {NavigationHook} [afterLeave]
|
|
497
|
+
* Hook after leaving and component is unmounted.
|
|
498
|
+
* @property {RouteSegment[]} [segments]
|
|
499
|
+
* Internal: parsed path segments (added by router).
|
|
287
500
|
* @description Defines a route in the application.
|
|
501
|
+
* @note Nested routes are not supported. Use shared layouts with flat routes instead.
|
|
288
502
|
* @example
|
|
289
503
|
* // Static route
|
|
290
504
|
* { path: '/about', component: AboutPage }
|
|
@@ -300,10 +514,10 @@
|
|
|
300
514
|
* beforeEnter: (to, from) => isLoggedIn() || '/login'
|
|
301
515
|
* }
|
|
302
516
|
*
|
|
303
|
-
* // Catch-all 404 route (
|
|
517
|
+
* // Catch-all 404 route (conventionally last)
|
|
304
518
|
* { path: '*', component: NotFoundPage }
|
|
305
519
|
*/ /**
|
|
306
|
-
* @class Router
|
|
520
|
+
* @class 🛤️ Router
|
|
307
521
|
* @classdesc A powerful, reactive, and flexible Router Plugin for Eleva.
|
|
308
522
|
* This class manages all routing logic, including state, navigation, and rendering.
|
|
309
523
|
*
|
|
@@ -329,15 +543,15 @@
|
|
|
329
543
|
* | `router:scroll` | {@link ScrollContextCallback} | No | For scroll behavior |
|
|
330
544
|
* | `router:afterEnter` | {@link RouteChangeCallback} | No | After entering route |
|
|
331
545
|
* | `router:afterEach` | {@link RouteChangeCallback} | No | Navigation complete |
|
|
332
|
-
* | `router:
|
|
546
|
+
* | `router:error` | {@link RouterErrorCallback} | No | Navigation error |
|
|
333
547
|
* | `router:routeAdded` | {@link RouteAddedCallback} | No | Dynamic route added |
|
|
334
548
|
* | `router:routeRemoved` | {@link RouteRemovedCallback} | No | Dynamic route removed |
|
|
335
549
|
*
|
|
336
550
|
* ## Reactive Signals
|
|
337
551
|
* - `currentRoute: Signal<RouteLocation | null>` - Current route info
|
|
338
552
|
* - `previousRoute: Signal<RouteLocation | null>` - Previous route info
|
|
339
|
-
* - `currentParams: Signal<
|
|
340
|
-
* - `currentQuery: Signal<
|
|
553
|
+
* - `currentParams: Signal<RouteParams>` - Current route params
|
|
554
|
+
* - `currentQuery: Signal<QueryParams>` - Current query params
|
|
341
555
|
* - `currentLayout: Signal<MountResult | null>` - Mounted layout instance
|
|
342
556
|
* - `currentView: Signal<MountResult | null>` - Mounted view instance
|
|
343
557
|
* - `isReady: Signal<boolean>` - Router readiness state
|
|
@@ -412,7 +626,7 @@
|
|
|
412
626
|
* Parses a route path string into an array of static and parameter segments.
|
|
413
627
|
* @private
|
|
414
628
|
* @param {string} path - The path pattern to parse.
|
|
415
|
-
* @returns {
|
|
629
|
+
* @returns {{type: 'static' | 'param', value?: string, name?: string}[]} An array of segment objects.
|
|
416
630
|
* @throws {Error} If the route path is not a valid string.
|
|
417
631
|
*/ _parsePathIntoSegments(path) {
|
|
418
632
|
if (!path || typeof path !== "string") {
|
|
@@ -456,6 +670,11 @@
|
|
|
456
670
|
/**
|
|
457
671
|
* Starts the router, initializes event listeners, and performs the initial navigation.
|
|
458
672
|
* @returns {Promise<Router>} The router instance for method chaining.
|
|
673
|
+
* @listens window:hashchange In hash mode, triggers route changes.
|
|
674
|
+
* @listens window:popstate In history/query mode, triggers route changes.
|
|
675
|
+
* @emits router:ready When initialization completes successfully.
|
|
676
|
+
* @see destroy - Stop the router and clean up listeners.
|
|
677
|
+
* @see navigate - Programmatically navigate to a route.
|
|
459
678
|
*
|
|
460
679
|
* @example
|
|
461
680
|
* // Basic usage
|
|
@@ -500,8 +719,11 @@
|
|
|
500
719
|
return this;
|
|
501
720
|
}
|
|
502
721
|
/**
|
|
503
|
-
* Stops the router and cleans up
|
|
722
|
+
* Stops the router and cleans up event listeners.
|
|
723
|
+
* Unmounts the current layout instance if present.
|
|
724
|
+
* @async
|
|
504
725
|
* @returns {Promise<void>}
|
|
726
|
+
* @see start - Restart the router after destroying.
|
|
505
727
|
*/ async destroy() {
|
|
506
728
|
if (!this.isStarted) return;
|
|
507
729
|
// Clean up plugins
|
|
@@ -525,6 +747,7 @@
|
|
|
525
747
|
/**
|
|
526
748
|
* Alias for destroy(). Stops the router and cleans up all resources.
|
|
527
749
|
* Provided for semantic consistency (start/stop pattern).
|
|
750
|
+
* @async
|
|
528
751
|
* @returns {Promise<void>}
|
|
529
752
|
*
|
|
530
753
|
* @example
|
|
@@ -536,9 +759,13 @@
|
|
|
536
759
|
}
|
|
537
760
|
/**
|
|
538
761
|
* Programmatically navigates to a new route.
|
|
762
|
+
* @async
|
|
539
763
|
* @param {string | NavigationTarget} location - The target location as a path string or navigation target object.
|
|
540
|
-
* @param {
|
|
764
|
+
* @param {NavigationParams} [params] - Route parameters (only used when location is a string).
|
|
541
765
|
* @returns {Promise<boolean>} True if navigation succeeded, false if blocked by guards or failed.
|
|
766
|
+
* @emits router:error When navigation fails due to an exception.
|
|
767
|
+
* @see start - Initialize the router before navigating.
|
|
768
|
+
* @see currentRoute - Access the current route after navigation.
|
|
542
769
|
*
|
|
543
770
|
* @example
|
|
544
771
|
* // Basic navigation
|
|
@@ -601,7 +828,7 @@
|
|
|
601
828
|
return navigationSuccessful;
|
|
602
829
|
} catch (error) {
|
|
603
830
|
this.errorHandler.log("Navigation failed", error);
|
|
604
|
-
await this.emitter.emit("router:
|
|
831
|
+
await this.emitter.emit("router:error", error);
|
|
605
832
|
return false;
|
|
606
833
|
}
|
|
607
834
|
}
|
|
@@ -621,7 +848,7 @@
|
|
|
621
848
|
* @param {string} path - The target path with query string.
|
|
622
849
|
* @param {object} params - The target params.
|
|
623
850
|
* @param {object} query - The target query.
|
|
624
|
-
* @returns {boolean}
|
|
851
|
+
* @returns {boolean} True if the routes are the same.
|
|
625
852
|
*/ _isSameRoute(path, params, query) {
|
|
626
853
|
const current = this.currentRoute.value;
|
|
627
854
|
if (!current) return false;
|
|
@@ -631,7 +858,16 @@
|
|
|
631
858
|
}
|
|
632
859
|
/**
|
|
633
860
|
* Injects dynamic parameters into a path string.
|
|
861
|
+
* Replaces `:param` placeholders with URL-encoded values from the params object.
|
|
862
|
+
*
|
|
634
863
|
* @private
|
|
864
|
+
* @param {string} path - The path pattern containing `:param` placeholders.
|
|
865
|
+
* @param {RouteParams} params - Key-value pairs to inject into the path.
|
|
866
|
+
* @returns {string} The path with all parameters replaced.
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* this._buildPath('/users/:id/posts/:postId', { id: '123', postId: '456' });
|
|
870
|
+
* // Returns: '/users/123/posts/456'
|
|
635
871
|
*/ _buildPath(path, params) {
|
|
636
872
|
let result = path;
|
|
637
873
|
for (const [key, value] of Object.entries(params)){
|
|
@@ -643,8 +879,12 @@
|
|
|
643
879
|
}
|
|
644
880
|
/**
|
|
645
881
|
* The handler for browser-initiated route changes (e.g., back/forward buttons).
|
|
882
|
+
*
|
|
646
883
|
* @private
|
|
884
|
+
* @async
|
|
647
885
|
* @param {boolean} [isPopState=true] - Whether this is a popstate event (back/forward navigation).
|
|
886
|
+
* @returns {Promise<void>}
|
|
887
|
+
* @emits router:error When route change handling fails.
|
|
648
888
|
*/ async _handleRouteChange(isPopState = true) {
|
|
649
889
|
if (this._isNavigating) return;
|
|
650
890
|
try {
|
|
@@ -663,26 +903,30 @@
|
|
|
663
903
|
this.errorHandler.log("Route change handling failed", error, {
|
|
664
904
|
currentUrl: typeof window !== "undefined" ? window.location.href : ""
|
|
665
905
|
});
|
|
666
|
-
await this.emitter.emit("router:
|
|
906
|
+
await this.emitter.emit("router:error", error);
|
|
667
907
|
}
|
|
668
908
|
}
|
|
669
909
|
/**
|
|
670
910
|
* Manages the core navigation lifecycle. Runs guards before committing changes.
|
|
671
|
-
* Emits lifecycle events that plugins can hook into:
|
|
672
|
-
* - router:beforeEach - Before guards run (can block/redirect via context)
|
|
673
|
-
* - router:beforeResolve - Before component resolution (can block/redirect)
|
|
674
|
-
* - router:afterResolve - After components are resolved
|
|
675
|
-
* - router:beforeRender - Before DOM rendering
|
|
676
|
-
* - router:afterRender - After DOM rendering
|
|
677
|
-
* - router:scroll - After render, for scroll behavior
|
|
678
|
-
* - router:afterEnter - After entering a route
|
|
679
|
-
* - router:afterLeave - After leaving a route
|
|
680
|
-
* - router:afterEach - After navigation completes
|
|
681
911
|
*
|
|
682
912
|
* @private
|
|
913
|
+
* @async
|
|
683
914
|
* @param {string} fullPath - The full path (e.g., '/users/123?foo=bar') to navigate to.
|
|
684
915
|
* @param {boolean} [isPopState=false] - Whether this navigation was triggered by popstate (back/forward).
|
|
685
|
-
* @returns {Promise<boolean>}
|
|
916
|
+
* @returns {Promise<boolean>} `true` if navigation succeeded, `false` if aborted.
|
|
917
|
+
* @emits router:notFound When no matching route is found.
|
|
918
|
+
* @emits router:beforeResolve Before component resolution (can block/redirect).
|
|
919
|
+
* @emits router:afterResolve After components are resolved.
|
|
920
|
+
* @emits router:afterLeave After leaving the previous route.
|
|
921
|
+
* @emits router:beforeRender Before DOM rendering.
|
|
922
|
+
* @emits router:afterRender After DOM rendering completes.
|
|
923
|
+
* @emits router:scroll After render, for scroll behavior handling.
|
|
924
|
+
* @emits router:afterEnter After entering the new route.
|
|
925
|
+
* @emits router:afterEach After navigation completes successfully.
|
|
926
|
+
* @emits router:error When an error occurs during navigation.
|
|
927
|
+
* @see _runGuards - Guard execution.
|
|
928
|
+
* @see _resolveComponents - Component resolution.
|
|
929
|
+
* @see _render - DOM rendering.
|
|
686
930
|
*/ async _proceedWithNavigation(fullPath, isPopState = false) {
|
|
687
931
|
const from = this.currentRoute.value;
|
|
688
932
|
const [path, queryString] = (fullPath || "/").split("?");
|
|
@@ -702,7 +946,7 @@
|
|
|
702
946
|
}
|
|
703
947
|
};
|
|
704
948
|
} else {
|
|
705
|
-
await this.emitter.emit("router:
|
|
949
|
+
await this.emitter.emit("router:error", new Error(`Route not found: ${toLocation.path}`), toLocation, from);
|
|
706
950
|
return false;
|
|
707
951
|
}
|
|
708
952
|
}
|
|
@@ -789,7 +1033,7 @@
|
|
|
789
1033
|
};
|
|
790
1034
|
await this.emitter.emit("router:beforeRender", renderContext);
|
|
791
1035
|
// 9. Render the new components.
|
|
792
|
-
await this._render(layoutComponent, pageComponent
|
|
1036
|
+
await this._render(layoutComponent, pageComponent);
|
|
793
1037
|
// 10. Emit afterRender event - plugins can trigger animations
|
|
794
1038
|
await this.emitter.emit("router:afterRender", renderContext);
|
|
795
1039
|
// 11. Emit scroll event - plugins can handle scroll restoration
|
|
@@ -811,7 +1055,7 @@
|
|
|
811
1055
|
to,
|
|
812
1056
|
from
|
|
813
1057
|
});
|
|
814
|
-
await this.emitter.emit("router:
|
|
1058
|
+
await this.emitter.emit("router:error", error, to, from);
|
|
815
1059
|
return false;
|
|
816
1060
|
}
|
|
817
1061
|
}
|
|
@@ -827,7 +1071,8 @@
|
|
|
827
1071
|
* @param {RouteLocation} to - The target route location.
|
|
828
1072
|
* @param {RouteLocation | null} from - The current route location (null on initial navigation).
|
|
829
1073
|
* @param {RouteDefinition} route - The matched route definition.
|
|
830
|
-
* @returns {Promise<boolean>}
|
|
1074
|
+
* @returns {Promise<boolean>} `false` if navigation should be aborted.
|
|
1075
|
+
* @emits router:beforeEach Before guards run (can block/redirect via context).
|
|
831
1076
|
*/ async _runGuards(to, from, route) {
|
|
832
1077
|
// Create navigation context that plugins can modify to block navigation
|
|
833
1078
|
/** @type {NavigationContext} */ const navContext = {
|
|
@@ -888,7 +1133,8 @@
|
|
|
888
1133
|
/**
|
|
889
1134
|
* Resolves a function component definition to a component object.
|
|
890
1135
|
* @private
|
|
891
|
-
* @
|
|
1136
|
+
* @async
|
|
1137
|
+
* @param {() => ComponentDefinition | Promise<ComponentDefinition | { default: ComponentDefinition }>} def - The function to resolve.
|
|
892
1138
|
* @returns {Promise<ComponentDefinition>} The resolved component.
|
|
893
1139
|
* @throws {Error} If the function fails to load the component.
|
|
894
1140
|
*/ async _resolveFunctionComponent(def) {
|
|
@@ -907,7 +1153,7 @@
|
|
|
907
1153
|
/**
|
|
908
1154
|
* Validates a component definition object.
|
|
909
1155
|
* @private
|
|
910
|
-
* @param {
|
|
1156
|
+
* @param {unknown} def - The component definition to validate.
|
|
911
1157
|
* @returns {ComponentDefinition} The validated component.
|
|
912
1158
|
* @throws {Error} If the component definition is invalid.
|
|
913
1159
|
*/ _validateComponentDefinition(def) {
|
|
@@ -926,7 +1172,7 @@
|
|
|
926
1172
|
/**
|
|
927
1173
|
* Resolves a component definition to a component object.
|
|
928
1174
|
* @private
|
|
929
|
-
* @param {
|
|
1175
|
+
* @param {unknown} def - The component definition to resolve.
|
|
930
1176
|
* @returns {Promise<ComponentDefinition | null>} The resolved component or null.
|
|
931
1177
|
*/ async _resolveComponent(def) {
|
|
932
1178
|
if (def === null || def === undefined) {
|
|
@@ -948,8 +1194,10 @@
|
|
|
948
1194
|
/**
|
|
949
1195
|
* Asynchronously resolves the layout and page components for a route.
|
|
950
1196
|
* @private
|
|
1197
|
+
* @async
|
|
951
1198
|
* @param {RouteDefinition} route - The route to resolve components for.
|
|
952
1199
|
* @returns {Promise<{layoutComponent: ComponentDefinition | null, pageComponent: ComponentDefinition}>}
|
|
1200
|
+
* @throws {Error} If page component cannot be resolved.
|
|
953
1201
|
*/ async _resolveComponents(route) {
|
|
954
1202
|
const effectiveLayout = route.layout || this.options.globalLayout;
|
|
955
1203
|
try {
|
|
@@ -975,9 +1223,24 @@
|
|
|
975
1223
|
}
|
|
976
1224
|
/**
|
|
977
1225
|
* Renders the components for the current route into the DOM.
|
|
1226
|
+
*
|
|
1227
|
+
* Rendering algorithm:
|
|
1228
|
+
* 1. Find the mount element using options.mount selector
|
|
1229
|
+
* 2. If layoutComponent exists:
|
|
1230
|
+
* a. Mount layout to mount element
|
|
1231
|
+
* b. Find view element within layout (using viewSelector)
|
|
1232
|
+
* c. Mount page component to view element
|
|
1233
|
+
* 3. If no layoutComponent:
|
|
1234
|
+
* a. Mount page component directly to mount element
|
|
1235
|
+
* b. Set currentLayout to null
|
|
1236
|
+
*
|
|
978
1237
|
* @private
|
|
1238
|
+
* @async
|
|
979
1239
|
* @param {ComponentDefinition | null} layoutComponent - The pre-loaded layout component.
|
|
980
1240
|
* @param {ComponentDefinition} pageComponent - The pre-loaded page component.
|
|
1241
|
+
* @returns {Promise<void>}
|
|
1242
|
+
* @throws {Error} If mount element is not found in the DOM.
|
|
1243
|
+
* @throws {Error} If component mounting fails (propagated from eleva.mount).
|
|
981
1244
|
*/ async _render(layoutComponent, pageComponent) {
|
|
982
1245
|
const mountEl = document.querySelector(this.options.mount);
|
|
983
1246
|
if (!mountEl) {
|
|
@@ -1001,8 +1264,8 @@
|
|
|
1001
1264
|
* Creates a getter function for router context properties.
|
|
1002
1265
|
* @private
|
|
1003
1266
|
* @param {string} property - The property name to access.
|
|
1004
|
-
* @param {
|
|
1005
|
-
* @returns {
|
|
1267
|
+
* @param {unknown} defaultValue - The default value if property is undefined.
|
|
1268
|
+
* @returns {() => unknown} A getter function.
|
|
1006
1269
|
*/ _createRouteGetter(property, defaultValue) {
|
|
1007
1270
|
return ()=>this.currentRoute.value?.[property] ?? defaultValue;
|
|
1008
1271
|
}
|
|
@@ -1017,7 +1280,7 @@
|
|
|
1017
1280
|
return {
|
|
1018
1281
|
...component,
|
|
1019
1282
|
async setup (ctx) {
|
|
1020
|
-
ctx.router = {
|
|
1283
|
+
/** @type {RouterContext} */ ctx.router = {
|
|
1021
1284
|
navigate: self.navigate.bind(self),
|
|
1022
1285
|
current: self.currentRoute,
|
|
1023
1286
|
previous: self.previousRoute,
|
|
@@ -1044,9 +1307,13 @@
|
|
|
1044
1307
|
}
|
|
1045
1308
|
/**
|
|
1046
1309
|
* Recursively wraps all child components to ensure they have access to router context.
|
|
1310
|
+
* String component references are returned as-is (context injected during mount).
|
|
1311
|
+
* Objects are wrapped with router context and their children are recursively wrapped.
|
|
1312
|
+
*
|
|
1047
1313
|
* @private
|
|
1048
1314
|
* @param {ComponentDefinition | string} component - The component to wrap (can be a definition object or a registered component name).
|
|
1049
1315
|
* @returns {ComponentDefinition | string} The wrapped component definition or the original string reference.
|
|
1316
|
+
* @see _wrapComponent - Single component wrapping.
|
|
1050
1317
|
*/ _wrapComponentWithChildren(component) {
|
|
1051
1318
|
// If the component is a string (registered component name), return as-is
|
|
1052
1319
|
// The router context will be injected when the component is resolved during mounting
|
|
@@ -1103,7 +1370,15 @@
|
|
|
1103
1370
|
}
|
|
1104
1371
|
/**
|
|
1105
1372
|
* Parses a query string into a key-value object.
|
|
1373
|
+
* Uses URLSearchParams for robust parsing of encoded values.
|
|
1374
|
+
*
|
|
1106
1375
|
* @private
|
|
1376
|
+
* @param {string} queryString - The query string to parse (without leading '?').
|
|
1377
|
+
* @returns {QueryParams} Key-value pairs from the query string.
|
|
1378
|
+
*
|
|
1379
|
+
* @example
|
|
1380
|
+
* this._parseQuery('foo=bar&baz=qux');
|
|
1381
|
+
* // Returns: { foo: 'bar', baz: 'qux' }
|
|
1107
1382
|
*/ _parseQuery(queryString) {
|
|
1108
1383
|
const query = {};
|
|
1109
1384
|
if (queryString) {
|
|
@@ -1155,10 +1430,12 @@
|
|
|
1155
1430
|
/**
|
|
1156
1431
|
* Adds a new route dynamically at runtime.
|
|
1157
1432
|
* The route will be processed and available for navigation immediately.
|
|
1433
|
+
* Routes are inserted before the wildcard (*) route if one exists.
|
|
1158
1434
|
*
|
|
1159
1435
|
* @param {RouteDefinition} route - The route definition to add.
|
|
1160
1436
|
* @param {RouteDefinition} [parentRoute] - Optional parent route to add as a child (not yet implemented).
|
|
1161
|
-
* @returns {() => void} A function to remove the added route.
|
|
1437
|
+
* @returns {() => void} A function to remove the added route (returns no-op if route was invalid).
|
|
1438
|
+
* @emits router:routeAdded When a route is successfully added.
|
|
1162
1439
|
*
|
|
1163
1440
|
* @example
|
|
1164
1441
|
* // Add a route dynamically
|
|
@@ -1206,6 +1483,7 @@
|
|
|
1206
1483
|
*
|
|
1207
1484
|
* @param {string} path - The path of the route to remove.
|
|
1208
1485
|
* @returns {boolean} True if the route was removed, false if not found.
|
|
1486
|
+
* @emits router:routeRemoved When a route is successfully removed.
|
|
1209
1487
|
*
|
|
1210
1488
|
* @example
|
|
1211
1489
|
* router.removeRoute('/dynamic');
|
|
@@ -1293,6 +1571,7 @@
|
|
|
1293
1571
|
* Registers a global hook that runs after a new route component has been mounted.
|
|
1294
1572
|
* @param {NavigationHook} hook - The hook function to register.
|
|
1295
1573
|
* @returns {() => void} A function to unregister the hook.
|
|
1574
|
+
* @listens router:afterEnter
|
|
1296
1575
|
*/ onAfterEnter(hook) {
|
|
1297
1576
|
return this.emitter.on("router:afterEnter", hook);
|
|
1298
1577
|
}
|
|
@@ -1300,6 +1579,7 @@
|
|
|
1300
1579
|
* Registers a global hook that runs after a route component has been unmounted.
|
|
1301
1580
|
* @param {NavigationHook} hook - The hook function to register.
|
|
1302
1581
|
* @returns {() => void} A function to unregister the hook.
|
|
1582
|
+
* @listens router:afterLeave
|
|
1303
1583
|
*/ onAfterLeave(hook) {
|
|
1304
1584
|
return this.emitter.on("router:afterLeave", hook);
|
|
1305
1585
|
}
|
|
@@ -1307,6 +1587,7 @@
|
|
|
1307
1587
|
* Registers a global hook that runs after a navigation has been confirmed and all hooks have completed.
|
|
1308
1588
|
* @param {NavigationHook} hook - The hook function to register.
|
|
1309
1589
|
* @returns {() => void} A function to unregister the hook.
|
|
1590
|
+
* @listens router:afterEach
|
|
1310
1591
|
*/ onAfterEach(hook) {
|
|
1311
1592
|
return this.emitter.on("router:afterEach", hook);
|
|
1312
1593
|
}
|
|
@@ -1314,12 +1595,18 @@
|
|
|
1314
1595
|
* Registers a global error handler for navigation errors.
|
|
1315
1596
|
* @param {(error: Error, to?: RouteLocation, from?: RouteLocation) => void} handler - The error handler function.
|
|
1316
1597
|
* @returns {() => void} A function to unregister the handler.
|
|
1598
|
+
* @listens router:error
|
|
1317
1599
|
*/ onError(handler) {
|
|
1318
|
-
return this.emitter.on("router:
|
|
1600
|
+
return this.emitter.on("router:error", handler);
|
|
1319
1601
|
}
|
|
1320
1602
|
/**
|
|
1321
1603
|
* Registers a plugin with the router.
|
|
1322
|
-
*
|
|
1604
|
+
* Logs a warning if the plugin is already registered.
|
|
1605
|
+
*
|
|
1606
|
+
* @param {RouterPlugin} plugin - The plugin to register (must have install method).
|
|
1607
|
+
* @param {Record<string, unknown>} [options={}] - Options to pass to plugin.install().
|
|
1608
|
+
* @returns {void}
|
|
1609
|
+
* @throws {Error} If plugin does not have an install method.
|
|
1323
1610
|
*/ use(plugin, options = {}) {
|
|
1324
1611
|
if (typeof plugin.install !== "function") {
|
|
1325
1612
|
this.errorHandler.handle(new Error("Plugin must have an install method"), "Plugin registration failed", {
|
|
@@ -1368,7 +1655,9 @@
|
|
|
1368
1655
|
}
|
|
1369
1656
|
/**
|
|
1370
1657
|
* Sets a custom error handler. Used by error handling plugins.
|
|
1371
|
-
*
|
|
1658
|
+
* Logs a warning if the provided handler is invalid (missing required methods).
|
|
1659
|
+
* @param {RouterErrorHandler} errorHandler - The error handler object with handle, warn, and log methods.
|
|
1660
|
+
* @returns {void}
|
|
1372
1661
|
*/ setErrorHandler(errorHandler) {
|
|
1373
1662
|
if (errorHandler && typeof errorHandler.handle === "function" && typeof errorHandler.warn === "function" && typeof errorHandler.log === "function") {
|
|
1374
1663
|
this.errorHandler = errorHandler;
|
|
@@ -1380,6 +1669,7 @@
|
|
|
1380
1669
|
* Creates an instance of the Router.
|
|
1381
1670
|
* @param {Eleva} eleva - The Eleva framework instance.
|
|
1382
1671
|
* @param {RouterOptions} options - The configuration options for the router.
|
|
1672
|
+
* @throws {Error} If the routing mode is invalid.
|
|
1383
1673
|
*/ constructor(eleva, options = {}){
|
|
1384
1674
|
/** @type {Eleva} The Eleva framework instance. */ this.eleva = eleva;
|
|
1385
1675
|
/** @type {RouterOptions} The merged router options. */ this.options = {
|
|
@@ -1389,40 +1679,30 @@
|
|
|
1389
1679
|
...options
|
|
1390
1680
|
};
|
|
1391
1681
|
/** @private @type {RouteDefinition[]} The processed list of route definitions. */ this.routes = this._processRoutes(options.routes || []);
|
|
1392
|
-
/** @private @type {
|
|
1682
|
+
/** @private @type {Emitter} The shared Eleva event emitter for global hooks. */ this.emitter = this.eleva.emitter;
|
|
1393
1683
|
/** @private @type {boolean} A flag indicating if the router has been started. */ this.isStarted = false;
|
|
1394
1684
|
/** @private @type {boolean} A flag to prevent navigation loops from history events. */ this._isNavigating = false;
|
|
1395
1685
|
/** @private @type {number} Counter for tracking navigation operations to prevent race conditions. */ this._navigationId = 0;
|
|
1396
|
-
/** @private @type {
|
|
1686
|
+
/** @private @type {UnsubscribeFunction[]} A collection of cleanup functions for event listeners. */ this.eventListeners = [];
|
|
1397
1687
|
/** @type {Signal<RouteLocation | null>} A reactive signal holding the current route's information. */ this.currentRoute = new this.eleva.signal(null);
|
|
1398
1688
|
/** @type {Signal<RouteLocation | null>} A reactive signal holding the previous route's information. */ this.previousRoute = new this.eleva.signal(null);
|
|
1399
|
-
/** @type {Signal<
|
|
1400
|
-
/** @type {Signal<
|
|
1401
|
-
/** @type {Signal<
|
|
1402
|
-
/** @type {Signal<
|
|
1689
|
+
/** @type {Signal<RouteParams>} A reactive signal holding the current route's parameters. */ this.currentParams = new this.eleva.signal({});
|
|
1690
|
+
/** @type {Signal<QueryParams>} A reactive signal holding the current route's query parameters. */ this.currentQuery = new this.eleva.signal({});
|
|
1691
|
+
/** @type {Signal<MountResult | null>} A reactive signal for the currently mounted layout instance. */ this.currentLayout = new this.eleva.signal(null);
|
|
1692
|
+
/** @type {Signal<MountResult | null>} A reactive signal for the currently mounted view (page) instance. */ this.currentView = new this.eleva.signal(null);
|
|
1403
1693
|
/** @type {Signal<boolean>} A reactive signal indicating if the router is ready (started and initial navigation complete). */ this.isReady = new this.eleva.signal(false);
|
|
1404
1694
|
/** @private @type {Map<string, RouterPlugin>} Map of registered plugins by name. */ this.plugins = new Map();
|
|
1405
|
-
/** @private @type {
|
|
1695
|
+
/** @private @type {NavigationGuard[]} Array of global before-each navigation guards. */ this._beforeEachGuards = [];
|
|
1406
1696
|
// If onBeforeEach was provided in options, add it to the guards array
|
|
1407
1697
|
if (options.onBeforeEach) {
|
|
1408
1698
|
this._beforeEachGuards.push(options.onBeforeEach);
|
|
1409
1699
|
}
|
|
1410
|
-
/** @type {
|
|
1700
|
+
/** @type {RouterErrorHandler} The error handler instance. Can be overridden by plugins. */ this.errorHandler = CoreErrorHandler;
|
|
1411
1701
|
/** @private @type {Map<string, {x: number, y: number}>} Saved scroll positions by route path. */ this._scrollPositions = new Map();
|
|
1412
1702
|
this._validateOptions();
|
|
1413
1703
|
}
|
|
1414
1704
|
}
|
|
1415
1705
|
/**
|
|
1416
|
-
* @typedef {Object} RouterOptions
|
|
1417
|
-
* @property {string} mount - A CSS selector for the main element where the app is mounted.
|
|
1418
|
-
* @property {RouteDefinition[]} routes - An array of route definitions.
|
|
1419
|
-
* @property {'hash' | 'query' | 'history'} [mode='hash'] - The routing mode.
|
|
1420
|
-
* @property {string} [queryParam='page'] - The query parameter to use in 'query' mode.
|
|
1421
|
-
* @property {string} [viewSelector='view'] - The selector for the view element within a layout.
|
|
1422
|
-
* @property {boolean} [autoStart=true] - Whether to start the router automatically.
|
|
1423
|
-
* @property {NavigationGuard} [onBeforeEach] - A global guard executed before every navigation.
|
|
1424
|
-
* @property {string | ComponentDefinition | (() => Promise<{default: ComponentDefinition}>)} [globalLayout] - A global layout for all routes. Can be overridden by a route's specific layout.
|
|
1425
|
-
*/ /**
|
|
1426
1706
|
* @class 🚀 RouterPlugin
|
|
1427
1707
|
* @classdesc A powerful, reactive, and flexible Router Plugin for Eleva applications.
|
|
1428
1708
|
* This plugin provides comprehensive client-side routing functionality including:
|
|
@@ -1461,7 +1741,7 @@
|
|
|
1461
1741
|
/**
|
|
1462
1742
|
* Plugin version
|
|
1463
1743
|
* @type {string}
|
|
1464
|
-
*/ version: "1.0
|
|
1744
|
+
*/ version: "1.1.0",
|
|
1465
1745
|
/**
|
|
1466
1746
|
* Plugin description
|
|
1467
1747
|
* @type {string}
|
|
@@ -1469,16 +1749,25 @@
|
|
|
1469
1749
|
/**
|
|
1470
1750
|
* Installs the RouterPlugin into an Eleva instance.
|
|
1471
1751
|
*
|
|
1472
|
-
* @
|
|
1473
|
-
* @param {
|
|
1474
|
-
* @param {
|
|
1475
|
-
* @param {
|
|
1476
|
-
* @param {
|
|
1477
|
-
* @param {
|
|
1478
|
-
* @param {string} [options.
|
|
1479
|
-
* @param {
|
|
1480
|
-
* @param {
|
|
1481
|
-
* @param {
|
|
1752
|
+
* @public
|
|
1753
|
+
* @param {Eleva} eleva - The Eleva instance.
|
|
1754
|
+
* @param {RouterOptions} options - Router configuration options.
|
|
1755
|
+
* @param {string} options.mount - A CSS selector for the main element where the app is mounted.
|
|
1756
|
+
* @param {RouteDefinition[]} options.routes - An array of route definitions.
|
|
1757
|
+
* @param {'hash' | 'query' | 'history'} [options.mode='hash'] - The routing mode.
|
|
1758
|
+
* @param {string} [options.queryParam='view'] - The query parameter to use in 'query' mode.
|
|
1759
|
+
* @param {string} [options.viewSelector='view'] - Base selector for the view element (matched as #id, .class, [data-*], or raw selector).
|
|
1760
|
+
* @param {boolean} [options.autoStart=true] - Whether to start the router automatically.
|
|
1761
|
+
* @param {NavigationGuard} [options.onBeforeEach] - A global guard executed before every navigation.
|
|
1762
|
+
* @param {RouteComponent} [options.globalLayout] - A global layout for all routes.
|
|
1763
|
+
* @returns {Router} The created router instance.
|
|
1764
|
+
* @throws {Error} If 'mount' option is not provided.
|
|
1765
|
+
* @throws {Error} If 'routes' option is not an array.
|
|
1766
|
+
* @throws {Error} If component registration fails during route processing.
|
|
1767
|
+
* @description
|
|
1768
|
+
* Registers route/layout components, sets `eleva.router`, and adds helpers
|
|
1769
|
+
* (`eleva.navigate`, `eleva.getCurrentRoute`, `eleva.getRouteParams`, `eleva.getRouteQuery`).
|
|
1770
|
+
* When `autoStart` is enabled, startup is scheduled via microtask.
|
|
1482
1771
|
*
|
|
1483
1772
|
* @example
|
|
1484
1773
|
* // main.js
|
|
@@ -1508,9 +1797,10 @@
|
|
|
1508
1797
|
* Registers a component definition with the Eleva instance.
|
|
1509
1798
|
* This method handles both inline component objects and pre-registered component names.
|
|
1510
1799
|
*
|
|
1511
|
-
* @
|
|
1512
|
-
* @param {
|
|
1513
|
-
* @
|
|
1800
|
+
* @inner
|
|
1801
|
+
* @param {unknown} def - The component definition to register.
|
|
1802
|
+
* @param {string} type - The type of component for naming (e.g., "Route", "Layout").
|
|
1803
|
+
* @returns {string | null} The registered component name or null if no definition provided.
|
|
1514
1804
|
*/ const register = (def, type)=>{
|
|
1515
1805
|
if (!def) return null;
|
|
1516
1806
|
if (typeof def === "object" && def !== null && !def.name) {
|
|
@@ -1534,7 +1824,7 @@
|
|
|
1534
1824
|
}
|
|
1535
1825
|
});
|
|
1536
1826
|
const router = new Router(eleva, options);
|
|
1537
|
-
eleva.router = router;
|
|
1827
|
+
/** @type {Router} */ eleva.router = router;
|
|
1538
1828
|
if (options.autoStart !== false) {
|
|
1539
1829
|
queueMicrotask(()=>router.start());
|
|
1540
1830
|
}
|
|
@@ -1549,16 +1839,22 @@
|
|
|
1549
1839
|
options
|
|
1550
1840
|
});
|
|
1551
1841
|
// Add utility methods for manual router access
|
|
1552
|
-
eleva.navigate = router.navigate.bind(router);
|
|
1553
|
-
eleva.getCurrentRoute = ()=>router.currentRoute.value;
|
|
1554
|
-
eleva.getRouteParams = ()=>router.currentParams.value;
|
|
1555
|
-
eleva.getRouteQuery = ()=>router.currentQuery.value;
|
|
1842
|
+
/** @type {NavigateFunction} */ eleva.navigate = router.navigate.bind(router);
|
|
1843
|
+
/** @type {() => RouteLocation | null} */ eleva.getCurrentRoute = ()=>router.currentRoute.value;
|
|
1844
|
+
/** @type {() => RouteParams} */ eleva.getRouteParams = ()=>router.currentParams.value;
|
|
1845
|
+
/** @type {() => QueryParams} */ eleva.getRouteQuery = ()=>router.currentQuery.value;
|
|
1556
1846
|
return router;
|
|
1557
1847
|
},
|
|
1558
1848
|
/**
|
|
1559
|
-
* Uninstalls the plugin from the Eleva instance
|
|
1849
|
+
* Uninstalls the plugin from the Eleva instance.
|
|
1560
1850
|
*
|
|
1561
|
-
* @
|
|
1851
|
+
* @public
|
|
1852
|
+
* @async
|
|
1853
|
+
* @param {Eleva} eleva - The Eleva instance.
|
|
1854
|
+
* @returns {Promise<void>}
|
|
1855
|
+
* @description
|
|
1856
|
+
* Destroys the router instance, removes `eleva.router`, and deletes helper methods
|
|
1857
|
+
* (`eleva.navigate`, `eleva.getCurrentRoute`, `eleva.getRouteParams`, `eleva.getRouteQuery`).
|
|
1562
1858
|
*/ async uninstall (eleva) {
|
|
1563
1859
|
if (eleva.router) {
|
|
1564
1860
|
await eleva.router.destroy();
|