@real-router/helpers 0.1.4 → 0.1.6
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/cjs/index.d.ts +13 -234
- package/dist/esm/index.d.mts +13 -234
- package/package.json +2 -2
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,238 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { State } from '@real-router/core';
|
|
2
2
|
|
|
3
|
-
export interface State<P extends Params = Params, MP extends Params = Params> {
|
|
4
|
-
name: string;
|
|
5
|
-
params: P;
|
|
6
|
-
path: string;
|
|
7
|
-
meta?: StateMeta<MP> | undefined;
|
|
8
|
-
}
|
|
9
|
-
export interface StateMeta<P extends Params = Params> {
|
|
10
|
-
id: number;
|
|
11
|
-
params: P;
|
|
12
|
-
options: NavigationOptions;
|
|
13
|
-
redirected: boolean;
|
|
14
|
-
source?: string | undefined;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Configuration options that control navigation transition behavior.
|
|
18
|
-
*
|
|
19
|
-
* @description
|
|
20
|
-
* NavigationOptions provides fine-grained control over how the router performs navigation
|
|
21
|
-
* transitions. These options affect history management, transition lifecycle execution,
|
|
22
|
-
* guard enforcement, and state comparison logic.
|
|
23
|
-
*
|
|
24
|
-
* All options are optional and have sensible defaults. Options can be combined to achieve
|
|
25
|
-
* complex navigation behaviors. The options object is stored in state.meta.options and is
|
|
26
|
-
* available to middleware, guards, and event listeners.
|
|
27
|
-
*
|
|
28
|
-
* @see {@link Router.navigate} for navigation method that accepts these options
|
|
29
|
-
* @see {@link State.meta} for where options are stored after navigation
|
|
30
|
-
*/
|
|
31
|
-
export interface NavigationOptions {
|
|
32
|
-
[key: string]: string | number | boolean | Record<string, unknown> | undefined;
|
|
33
|
-
/**
|
|
34
|
-
* Replace the current history entry instead of pushing a new one.
|
|
35
|
-
*
|
|
36
|
-
* @description
|
|
37
|
-
* When `true`, the navigation will replace the current entry in browser history instead
|
|
38
|
-
* of adding a new entry. This is typically used by history plugins (browser plugin) to
|
|
39
|
-
* control how navigation affects the browser's back/forward buttons.
|
|
40
|
-
*
|
|
41
|
-
* @default false
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* // Redirect after login - prevent back button to login page
|
|
45
|
-
* router.navigate('dashboard', {}, { replace: true });
|
|
46
|
-
*
|
|
47
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState}
|
|
48
|
-
*/
|
|
49
|
-
replace?: boolean | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Force reload of the current route even if states are equal.
|
|
52
|
-
*
|
|
53
|
-
* @description
|
|
54
|
-
* When `true`, bypasses the "same state" check that normally prevents navigation when
|
|
55
|
-
* the target state equals the current state. This forces a full transition lifecycle
|
|
56
|
-
* execution, allowing route components to reload with the same parameters.
|
|
57
|
-
*
|
|
58
|
-
* Without `reload`:
|
|
59
|
-
* - Navigation to current route throws SAME_STATES error
|
|
60
|
-
* - No lifecycle hooks or middleware execute
|
|
61
|
-
* - No events are fired
|
|
62
|
-
*
|
|
63
|
-
* With `reload`:
|
|
64
|
-
* - Full transition executes (deactivate → activate → middleware)
|
|
65
|
-
* - All lifecycle hooks run again
|
|
66
|
-
* - TRANSITION_SUCCESS event fires with same state
|
|
67
|
-
* - State object is recreated (new reference)
|
|
68
|
-
*
|
|
69
|
-
* @default false
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* // Refresh current page data
|
|
73
|
-
* router.navigate(currentRoute.name, currentRoute.params, { reload: true });
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* // Force re-fetch on same route with different query params
|
|
77
|
-
* // Note: query params are in path, not checked for equality
|
|
78
|
-
* router.navigate('search', { term: 'react' }, { reload: true });
|
|
79
|
-
*
|
|
80
|
-
* @see {@link force} for alternative that forces transition
|
|
81
|
-
* @see {@link Router.areStatesEqual} for state comparison logic
|
|
82
|
-
*/
|
|
83
|
-
reload?: boolean | undefined;
|
|
84
|
-
/**
|
|
85
|
-
* Preview navigation without any side effects (dry-run mode).
|
|
86
|
-
*
|
|
87
|
-
* @description
|
|
88
|
-
* When `true`, returns the would-be target state via callback WITHOUT:
|
|
89
|
-
* - Executing canDeactivate/canActivate guards
|
|
90
|
-
* - Executing middleware
|
|
91
|
-
* - Updating router state (`router.getState()` remains unchanged)
|
|
92
|
-
* - Emitting any transition events (TRANSITION_START, TRANSITION_SUCCESS, etc.)
|
|
93
|
-
*
|
|
94
|
-
* The callback receives `(undefined, toState)` where `toState` is the computed
|
|
95
|
-
* target state that WOULD result from this navigation.
|
|
96
|
-
*
|
|
97
|
-
* @default false
|
|
98
|
-
*
|
|
99
|
-
* @remarks
|
|
100
|
-
* This option is useful for:
|
|
101
|
-
* - Validating that a route exists and params are correct
|
|
102
|
-
* - SSR: previewing state for pre-rendering without side effects
|
|
103
|
-
* - Dry-run before actual navigation
|
|
104
|
-
*
|
|
105
|
-
* @deprecated Consider using `router.buildState()` + `router.makeState()` instead
|
|
106
|
-
* for clearer intent. This option may be removed in a future major version.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* // Preview navigation - router.getState() is NOT changed
|
|
110
|
-
* router.navigate('users.view', { id: 123 }, { skipTransition: true }, (err, previewState) => {
|
|
111
|
-
* console.log(previewState); // { name: 'users.view', params: { id: 123 }, path: '/users/view/123', ... }
|
|
112
|
-
* console.log(router.getState()); // Still the previous state!
|
|
113
|
-
* });
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* // Recommended alternative (clearer intent)
|
|
117
|
-
* const route = router.buildState('users.view', { id: 123 });
|
|
118
|
-
* if (route) {
|
|
119
|
-
* const path = router.buildPath(route.name, route.params);
|
|
120
|
-
* const previewState = router.makeState(route.name, route.params, path, { params: route.meta });
|
|
121
|
-
* }
|
|
122
|
-
*
|
|
123
|
-
* @see {@link forceDeactivate} for skipping only canDeactivate guards
|
|
124
|
-
* @see {@link force} for forcing navigation while preserving lifecycle
|
|
125
|
-
*/
|
|
126
|
-
skipTransition?: boolean | undefined;
|
|
127
|
-
/**
|
|
128
|
-
* Force navigation even if target state equals current state.
|
|
129
|
-
*
|
|
130
|
-
* @description
|
|
131
|
-
* When `true`, bypasses the "same state" equality check but still executes the full
|
|
132
|
-
* transition lifecycle (unlike `skipTransition`). Similar to `reload` but can be used
|
|
133
|
-
* for any forced navigation scenario.
|
|
134
|
-
*
|
|
135
|
-
* Difference from `reload`:
|
|
136
|
-
* - `reload`: semantic meaning is "refresh current route"
|
|
137
|
-
* - `force`: general-purpose bypass of equality check
|
|
138
|
-
* - Both have identical implementation effect
|
|
139
|
-
*
|
|
140
|
-
* The equality check compares:
|
|
141
|
-
* - state.name (route name)
|
|
142
|
-
* - state.params (route parameters, shallow comparison)
|
|
143
|
-
*
|
|
144
|
-
* @default false
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* // Force transition for tracking even if params didn't change
|
|
148
|
-
* router.navigate('analytics', { event: 'pageview' }, { force: true });
|
|
149
|
-
*
|
|
150
|
-
* @see {@link reload} for semantic equivalent (preferred for refresh scenarios)
|
|
151
|
-
* @see {@link skipTransition} for bypassing entire lifecycle
|
|
152
|
-
*/
|
|
153
|
-
force?: boolean | undefined;
|
|
154
|
-
/**
|
|
155
|
-
* Skip canDeactivate guards during transition.
|
|
156
|
-
*
|
|
157
|
-
* @description
|
|
158
|
-
* When `true`, bypasses only the canDeactivate lifecycle hooks for segments being
|
|
159
|
-
* deactivated. canActivate guards and middleware still execute normally. This allows
|
|
160
|
-
* forcing navigation away from routes with confirmation dialogs or unsaved changes.
|
|
161
|
-
*
|
|
162
|
-
* Skipped vs executed:
|
|
163
|
-
* ```
|
|
164
|
-
* // Normal transition
|
|
165
|
-
* deactivate(fromSegments) → activate(toSegments) → middleware → success
|
|
166
|
-
*
|
|
167
|
-
* // With forceDeactivate: true
|
|
168
|
-
* [skip deactivate] → activate(toSegments) → middleware → success
|
|
169
|
-
* ```
|
|
170
|
-
*
|
|
171
|
-
* ⚠️ Data loss risk: Bypassing canDeactivate means unsaved changes will be lost
|
|
172
|
-
*
|
|
173
|
-
* @default false
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* // Force logout even with unsaved changes
|
|
177
|
-
* function forceLogout() {
|
|
178
|
-
* router.navigate('login', {}, {
|
|
179
|
-
* forceDeactivate: true,
|
|
180
|
-
* replace: true
|
|
181
|
-
* });
|
|
182
|
-
* }
|
|
183
|
-
*
|
|
184
|
-
* @see {@link skipTransition} for bypassing all guards and middleware
|
|
185
|
-
* @see {@link Router.clearCanDeactivate} for programmatically clearing guards
|
|
186
|
-
*/
|
|
187
|
-
forceDeactivate?: boolean | undefined;
|
|
188
|
-
/**
|
|
189
|
-
* Internal flag indicating navigation is result of a redirect.
|
|
190
|
-
*
|
|
191
|
-
* @internal
|
|
192
|
-
*
|
|
193
|
-
* @description
|
|
194
|
-
* Automatically set by the router when a navigation is triggered by a redirect from
|
|
195
|
-
* middleware or lifecycle hooks. This flag is used internally to track redirect chains
|
|
196
|
-
* and is stored in state.meta.redirected.
|
|
197
|
-
*
|
|
198
|
-
* @default false (auto-set by router during redirects)
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* // Middleware triggers automatic redirect
|
|
202
|
-
* router.useMiddleware((toState, fromState, opts) => {
|
|
203
|
-
* if (!isAuthenticated && toState.name !== 'login') {
|
|
204
|
-
* // Router will automatically set redirected: true
|
|
205
|
-
* return { name: 'login', params: { next: toState.path } };
|
|
206
|
-
* }
|
|
207
|
-
* });
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* // Accessing redirect flag in lifecycle
|
|
211
|
-
* router.canActivate('dashboard', (toState, fromState) => {
|
|
212
|
-
* if (toState.meta?.redirected) {
|
|
213
|
-
* console.log('This navigation is from a redirect');
|
|
214
|
-
* }
|
|
215
|
-
* return true;
|
|
216
|
-
* });
|
|
217
|
-
*
|
|
218
|
-
* @see {@link Router.navigate} for redirect handling implementation
|
|
219
|
-
* @see {@link State.meta.redirected} for redirect flag in state
|
|
220
|
-
*/
|
|
221
|
-
redirected?: boolean | undefined;
|
|
222
|
-
}
|
|
223
|
-
export interface Params {
|
|
224
|
-
[key: string]: string | string[] | number | number[] | boolean | boolean[] | Params | Params[] | Record<string, string | number | boolean> | null | undefined;
|
|
225
|
-
}
|
|
226
3
|
/**
|
|
227
4
|
* Type definition for segment test functions.
|
|
228
5
|
* These functions can be called directly with a segment, or curried for later use.
|
|
229
6
|
*/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
7
|
+
interface SegmentTestFunction {
|
|
8
|
+
(route: State | string): (segment: string) => boolean;
|
|
9
|
+
(route: State | string, segment: string): boolean;
|
|
10
|
+
(route: State | string, segment: null): false;
|
|
11
|
+
(route: State | string, segment?: string | null): boolean | ((segment: string) => boolean);
|
|
235
12
|
}
|
|
13
|
+
|
|
236
14
|
/**
|
|
237
15
|
* Tests if a route name starts with the given segment.
|
|
238
16
|
*
|
|
@@ -292,7 +70,7 @@ export interface SegmentTestFunction {
|
|
|
292
70
|
* @see endsWithSegment for suffix matching
|
|
293
71
|
* @see includesSegment for anywhere matching
|
|
294
72
|
*/
|
|
295
|
-
|
|
73
|
+
declare const startsWithSegment: SegmentTestFunction;
|
|
296
74
|
/**
|
|
297
75
|
* Tests if a route name ends with the given segment.
|
|
298
76
|
*
|
|
@@ -333,7 +111,7 @@ export declare const startsWithSegment: SegmentTestFunction;
|
|
|
333
111
|
* @see startsWithSegment for prefix matching
|
|
334
112
|
* @see includesSegment for anywhere matching
|
|
335
113
|
*/
|
|
336
|
-
|
|
114
|
+
declare const endsWithSegment: SegmentTestFunction;
|
|
337
115
|
/**
|
|
338
116
|
* Tests if a route name includes the given segment anywhere in its path.
|
|
339
117
|
*
|
|
@@ -378,7 +156,8 @@ export declare const endsWithSegment: SegmentTestFunction;
|
|
|
378
156
|
* @see startsWithSegment for prefix matching
|
|
379
157
|
* @see endsWithSegment for suffix matching
|
|
380
158
|
*/
|
|
381
|
-
|
|
159
|
+
declare const includesSegment: SegmentTestFunction;
|
|
160
|
+
|
|
382
161
|
/**
|
|
383
162
|
* Checks if two routes are related in the hierarchy.
|
|
384
163
|
*
|
|
@@ -398,6 +177,6 @@ export declare const includesSegment: SegmentTestFunction;
|
|
|
398
177
|
* areRoutesRelated("users", "admin"); // false (different branches)
|
|
399
178
|
* areRoutesRelated("users.list", "users.view"); // false (siblings)
|
|
400
179
|
*/
|
|
401
|
-
|
|
180
|
+
declare function areRoutesRelated(route1: string, route2: string): boolean;
|
|
402
181
|
|
|
403
|
-
export {};
|
|
182
|
+
export { type SegmentTestFunction, areRoutesRelated, endsWithSegment, includesSegment, startsWithSegment };
|
package/dist/esm/index.d.mts
CHANGED
|
@@ -1,238 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { State } from '@real-router/core';
|
|
2
2
|
|
|
3
|
-
export interface State<P extends Params = Params, MP extends Params = Params> {
|
|
4
|
-
name: string;
|
|
5
|
-
params: P;
|
|
6
|
-
path: string;
|
|
7
|
-
meta?: StateMeta<MP> | undefined;
|
|
8
|
-
}
|
|
9
|
-
export interface StateMeta<P extends Params = Params> {
|
|
10
|
-
id: number;
|
|
11
|
-
params: P;
|
|
12
|
-
options: NavigationOptions;
|
|
13
|
-
redirected: boolean;
|
|
14
|
-
source?: string | undefined;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Configuration options that control navigation transition behavior.
|
|
18
|
-
*
|
|
19
|
-
* @description
|
|
20
|
-
* NavigationOptions provides fine-grained control over how the router performs navigation
|
|
21
|
-
* transitions. These options affect history management, transition lifecycle execution,
|
|
22
|
-
* guard enforcement, and state comparison logic.
|
|
23
|
-
*
|
|
24
|
-
* All options are optional and have sensible defaults. Options can be combined to achieve
|
|
25
|
-
* complex navigation behaviors. The options object is stored in state.meta.options and is
|
|
26
|
-
* available to middleware, guards, and event listeners.
|
|
27
|
-
*
|
|
28
|
-
* @see {@link Router.navigate} for navigation method that accepts these options
|
|
29
|
-
* @see {@link State.meta} for where options are stored after navigation
|
|
30
|
-
*/
|
|
31
|
-
export interface NavigationOptions {
|
|
32
|
-
[key: string]: string | number | boolean | Record<string, unknown> | undefined;
|
|
33
|
-
/**
|
|
34
|
-
* Replace the current history entry instead of pushing a new one.
|
|
35
|
-
*
|
|
36
|
-
* @description
|
|
37
|
-
* When `true`, the navigation will replace the current entry in browser history instead
|
|
38
|
-
* of adding a new entry. This is typically used by history plugins (browser plugin) to
|
|
39
|
-
* control how navigation affects the browser's back/forward buttons.
|
|
40
|
-
*
|
|
41
|
-
* @default false
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* // Redirect after login - prevent back button to login page
|
|
45
|
-
* router.navigate('dashboard', {}, { replace: true });
|
|
46
|
-
*
|
|
47
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/History/replaceState}
|
|
48
|
-
*/
|
|
49
|
-
replace?: boolean | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Force reload of the current route even if states are equal.
|
|
52
|
-
*
|
|
53
|
-
* @description
|
|
54
|
-
* When `true`, bypasses the "same state" check that normally prevents navigation when
|
|
55
|
-
* the target state equals the current state. This forces a full transition lifecycle
|
|
56
|
-
* execution, allowing route components to reload with the same parameters.
|
|
57
|
-
*
|
|
58
|
-
* Without `reload`:
|
|
59
|
-
* - Navigation to current route throws SAME_STATES error
|
|
60
|
-
* - No lifecycle hooks or middleware execute
|
|
61
|
-
* - No events are fired
|
|
62
|
-
*
|
|
63
|
-
* With `reload`:
|
|
64
|
-
* - Full transition executes (deactivate → activate → middleware)
|
|
65
|
-
* - All lifecycle hooks run again
|
|
66
|
-
* - TRANSITION_SUCCESS event fires with same state
|
|
67
|
-
* - State object is recreated (new reference)
|
|
68
|
-
*
|
|
69
|
-
* @default false
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* // Refresh current page data
|
|
73
|
-
* router.navigate(currentRoute.name, currentRoute.params, { reload: true });
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* // Force re-fetch on same route with different query params
|
|
77
|
-
* // Note: query params are in path, not checked for equality
|
|
78
|
-
* router.navigate('search', { term: 'react' }, { reload: true });
|
|
79
|
-
*
|
|
80
|
-
* @see {@link force} for alternative that forces transition
|
|
81
|
-
* @see {@link Router.areStatesEqual} for state comparison logic
|
|
82
|
-
*/
|
|
83
|
-
reload?: boolean | undefined;
|
|
84
|
-
/**
|
|
85
|
-
* Preview navigation without any side effects (dry-run mode).
|
|
86
|
-
*
|
|
87
|
-
* @description
|
|
88
|
-
* When `true`, returns the would-be target state via callback WITHOUT:
|
|
89
|
-
* - Executing canDeactivate/canActivate guards
|
|
90
|
-
* - Executing middleware
|
|
91
|
-
* - Updating router state (`router.getState()` remains unchanged)
|
|
92
|
-
* - Emitting any transition events (TRANSITION_START, TRANSITION_SUCCESS, etc.)
|
|
93
|
-
*
|
|
94
|
-
* The callback receives `(undefined, toState)` where `toState` is the computed
|
|
95
|
-
* target state that WOULD result from this navigation.
|
|
96
|
-
*
|
|
97
|
-
* @default false
|
|
98
|
-
*
|
|
99
|
-
* @remarks
|
|
100
|
-
* This option is useful for:
|
|
101
|
-
* - Validating that a route exists and params are correct
|
|
102
|
-
* - SSR: previewing state for pre-rendering without side effects
|
|
103
|
-
* - Dry-run before actual navigation
|
|
104
|
-
*
|
|
105
|
-
* @deprecated Consider using `router.buildState()` + `router.makeState()` instead
|
|
106
|
-
* for clearer intent. This option may be removed in a future major version.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* // Preview navigation - router.getState() is NOT changed
|
|
110
|
-
* router.navigate('users.view', { id: 123 }, { skipTransition: true }, (err, previewState) => {
|
|
111
|
-
* console.log(previewState); // { name: 'users.view', params: { id: 123 }, path: '/users/view/123', ... }
|
|
112
|
-
* console.log(router.getState()); // Still the previous state!
|
|
113
|
-
* });
|
|
114
|
-
*
|
|
115
|
-
* @example
|
|
116
|
-
* // Recommended alternative (clearer intent)
|
|
117
|
-
* const route = router.buildState('users.view', { id: 123 });
|
|
118
|
-
* if (route) {
|
|
119
|
-
* const path = router.buildPath(route.name, route.params);
|
|
120
|
-
* const previewState = router.makeState(route.name, route.params, path, { params: route.meta });
|
|
121
|
-
* }
|
|
122
|
-
*
|
|
123
|
-
* @see {@link forceDeactivate} for skipping only canDeactivate guards
|
|
124
|
-
* @see {@link force} for forcing navigation while preserving lifecycle
|
|
125
|
-
*/
|
|
126
|
-
skipTransition?: boolean | undefined;
|
|
127
|
-
/**
|
|
128
|
-
* Force navigation even if target state equals current state.
|
|
129
|
-
*
|
|
130
|
-
* @description
|
|
131
|
-
* When `true`, bypasses the "same state" equality check but still executes the full
|
|
132
|
-
* transition lifecycle (unlike `skipTransition`). Similar to `reload` but can be used
|
|
133
|
-
* for any forced navigation scenario.
|
|
134
|
-
*
|
|
135
|
-
* Difference from `reload`:
|
|
136
|
-
* - `reload`: semantic meaning is "refresh current route"
|
|
137
|
-
* - `force`: general-purpose bypass of equality check
|
|
138
|
-
* - Both have identical implementation effect
|
|
139
|
-
*
|
|
140
|
-
* The equality check compares:
|
|
141
|
-
* - state.name (route name)
|
|
142
|
-
* - state.params (route parameters, shallow comparison)
|
|
143
|
-
*
|
|
144
|
-
* @default false
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* // Force transition for tracking even if params didn't change
|
|
148
|
-
* router.navigate('analytics', { event: 'pageview' }, { force: true });
|
|
149
|
-
*
|
|
150
|
-
* @see {@link reload} for semantic equivalent (preferred for refresh scenarios)
|
|
151
|
-
* @see {@link skipTransition} for bypassing entire lifecycle
|
|
152
|
-
*/
|
|
153
|
-
force?: boolean | undefined;
|
|
154
|
-
/**
|
|
155
|
-
* Skip canDeactivate guards during transition.
|
|
156
|
-
*
|
|
157
|
-
* @description
|
|
158
|
-
* When `true`, bypasses only the canDeactivate lifecycle hooks for segments being
|
|
159
|
-
* deactivated. canActivate guards and middleware still execute normally. This allows
|
|
160
|
-
* forcing navigation away from routes with confirmation dialogs or unsaved changes.
|
|
161
|
-
*
|
|
162
|
-
* Skipped vs executed:
|
|
163
|
-
* ```
|
|
164
|
-
* // Normal transition
|
|
165
|
-
* deactivate(fromSegments) → activate(toSegments) → middleware → success
|
|
166
|
-
*
|
|
167
|
-
* // With forceDeactivate: true
|
|
168
|
-
* [skip deactivate] → activate(toSegments) → middleware → success
|
|
169
|
-
* ```
|
|
170
|
-
*
|
|
171
|
-
* ⚠️ Data loss risk: Bypassing canDeactivate means unsaved changes will be lost
|
|
172
|
-
*
|
|
173
|
-
* @default false
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* // Force logout even with unsaved changes
|
|
177
|
-
* function forceLogout() {
|
|
178
|
-
* router.navigate('login', {}, {
|
|
179
|
-
* forceDeactivate: true,
|
|
180
|
-
* replace: true
|
|
181
|
-
* });
|
|
182
|
-
* }
|
|
183
|
-
*
|
|
184
|
-
* @see {@link skipTransition} for bypassing all guards and middleware
|
|
185
|
-
* @see {@link Router.clearCanDeactivate} for programmatically clearing guards
|
|
186
|
-
*/
|
|
187
|
-
forceDeactivate?: boolean | undefined;
|
|
188
|
-
/**
|
|
189
|
-
* Internal flag indicating navigation is result of a redirect.
|
|
190
|
-
*
|
|
191
|
-
* @internal
|
|
192
|
-
*
|
|
193
|
-
* @description
|
|
194
|
-
* Automatically set by the router when a navigation is triggered by a redirect from
|
|
195
|
-
* middleware or lifecycle hooks. This flag is used internally to track redirect chains
|
|
196
|
-
* and is stored in state.meta.redirected.
|
|
197
|
-
*
|
|
198
|
-
* @default false (auto-set by router during redirects)
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* // Middleware triggers automatic redirect
|
|
202
|
-
* router.useMiddleware((toState, fromState, opts) => {
|
|
203
|
-
* if (!isAuthenticated && toState.name !== 'login') {
|
|
204
|
-
* // Router will automatically set redirected: true
|
|
205
|
-
* return { name: 'login', params: { next: toState.path } };
|
|
206
|
-
* }
|
|
207
|
-
* });
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* // Accessing redirect flag in lifecycle
|
|
211
|
-
* router.canActivate('dashboard', (toState, fromState) => {
|
|
212
|
-
* if (toState.meta?.redirected) {
|
|
213
|
-
* console.log('This navigation is from a redirect');
|
|
214
|
-
* }
|
|
215
|
-
* return true;
|
|
216
|
-
* });
|
|
217
|
-
*
|
|
218
|
-
* @see {@link Router.navigate} for redirect handling implementation
|
|
219
|
-
* @see {@link State.meta.redirected} for redirect flag in state
|
|
220
|
-
*/
|
|
221
|
-
redirected?: boolean | undefined;
|
|
222
|
-
}
|
|
223
|
-
export interface Params {
|
|
224
|
-
[key: string]: string | string[] | number | number[] | boolean | boolean[] | Params | Params[] | Record<string, string | number | boolean> | null | undefined;
|
|
225
|
-
}
|
|
226
3
|
/**
|
|
227
4
|
* Type definition for segment test functions.
|
|
228
5
|
* These functions can be called directly with a segment, or curried for later use.
|
|
229
6
|
*/
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
7
|
+
interface SegmentTestFunction {
|
|
8
|
+
(route: State | string): (segment: string) => boolean;
|
|
9
|
+
(route: State | string, segment: string): boolean;
|
|
10
|
+
(route: State | string, segment: null): false;
|
|
11
|
+
(route: State | string, segment?: string | null): boolean | ((segment: string) => boolean);
|
|
235
12
|
}
|
|
13
|
+
|
|
236
14
|
/**
|
|
237
15
|
* Tests if a route name starts with the given segment.
|
|
238
16
|
*
|
|
@@ -292,7 +70,7 @@ export interface SegmentTestFunction {
|
|
|
292
70
|
* @see endsWithSegment for suffix matching
|
|
293
71
|
* @see includesSegment for anywhere matching
|
|
294
72
|
*/
|
|
295
|
-
|
|
73
|
+
declare const startsWithSegment: SegmentTestFunction;
|
|
296
74
|
/**
|
|
297
75
|
* Tests if a route name ends with the given segment.
|
|
298
76
|
*
|
|
@@ -333,7 +111,7 @@ export declare const startsWithSegment: SegmentTestFunction;
|
|
|
333
111
|
* @see startsWithSegment for prefix matching
|
|
334
112
|
* @see includesSegment for anywhere matching
|
|
335
113
|
*/
|
|
336
|
-
|
|
114
|
+
declare const endsWithSegment: SegmentTestFunction;
|
|
337
115
|
/**
|
|
338
116
|
* Tests if a route name includes the given segment anywhere in its path.
|
|
339
117
|
*
|
|
@@ -378,7 +156,8 @@ export declare const endsWithSegment: SegmentTestFunction;
|
|
|
378
156
|
* @see startsWithSegment for prefix matching
|
|
379
157
|
* @see endsWithSegment for suffix matching
|
|
380
158
|
*/
|
|
381
|
-
|
|
159
|
+
declare const includesSegment: SegmentTestFunction;
|
|
160
|
+
|
|
382
161
|
/**
|
|
383
162
|
* Checks if two routes are related in the hierarchy.
|
|
384
163
|
*
|
|
@@ -398,6 +177,6 @@ export declare const includesSegment: SegmentTestFunction;
|
|
|
398
177
|
* areRoutesRelated("users", "admin"); // false (different branches)
|
|
399
178
|
* areRoutesRelated("users.list", "users.view"); // false (siblings)
|
|
400
179
|
*/
|
|
401
|
-
|
|
180
|
+
declare function areRoutesRelated(route1: string, route2: string): boolean;
|
|
402
181
|
|
|
403
|
-
export {};
|
|
182
|
+
export { type SegmentTestFunction, areRoutesRelated, endsWithSegment, includesSegment, startsWithSegment };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@real-router/helpers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"description": "Helper utilities for comparing and checking routes",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"homepage": "https://github.com/greydragon888/real-router",
|
|
40
40
|
"sideEffects": false,
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@real-router/core": "^0.
|
|
42
|
+
"@real-router/core": "^0.3.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"test": "vitest",
|