@mmstack/router-core 21.0.3 → 21.0.4
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 +352 -201
- package/fesm2022/mmstack-router-core.mjs +331 -60
- package/fesm2022/mmstack-router-core.mjs.map +1 -1
- package/package.json +1 -1
- package/types/mmstack-router-core.d.ts +217 -32
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
import * as i1 from '@angular/router';
|
|
2
|
+
import { ActivatedRouteSnapshot, ResolveFn, Params, ActivatedRoute, UrlTree, IsActiveMatchOptions, PreloadingStrategy, Route, Router } from '@angular/router';
|
|
1
3
|
import * as _angular_core from '@angular/core';
|
|
2
4
|
import { Signal, InjectionToken, Provider, WritableSignal } from '@angular/core';
|
|
3
|
-
import * as i1 from '@angular/router';
|
|
4
|
-
import { ActivatedRouteSnapshot, ResolveFn, Params, ActivatedRoute, UrlTree, PreloadingStrategy, Route } from '@angular/router';
|
|
5
5
|
import { Observable } from 'rxjs';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
type ResolvedLeafRoute = {
|
|
11
|
+
route: ActivatedRouteSnapshot;
|
|
12
|
+
segment: {
|
|
13
|
+
path: string;
|
|
14
|
+
resolved: string;
|
|
15
|
+
};
|
|
16
|
+
path: string;
|
|
17
|
+
link: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
7
20
|
/**
|
|
8
21
|
* Represents a single breadcrumb item within the navigation path.
|
|
9
22
|
* All dynamic properties are represented as Angular Signals to enable reactivity.
|
|
@@ -32,19 +45,6 @@ type Breadcrumb = {
|
|
|
32
45
|
link: Signal<string>;
|
|
33
46
|
};
|
|
34
47
|
|
|
35
|
-
/**
|
|
36
|
-
* @internal
|
|
37
|
-
*/
|
|
38
|
-
type ResolvedLeafRoute = {
|
|
39
|
-
route: ActivatedRouteSnapshot;
|
|
40
|
-
segment: {
|
|
41
|
-
path: string;
|
|
42
|
-
resolved: string;
|
|
43
|
-
};
|
|
44
|
-
path: string;
|
|
45
|
-
link: string;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
48
|
/**
|
|
49
49
|
* A function that returns a custom label generation function.
|
|
50
50
|
* The outer function is called in a root injection context
|
|
@@ -136,10 +136,11 @@ type CreateBreadcrumbOptions = {
|
|
|
136
136
|
/**
|
|
137
137
|
* Creates and registers a breadcrumb for a specific route.
|
|
138
138
|
* This function is designed to be used as an Angular Route `ResolveFn`.
|
|
139
|
-
* It handles the registration of the breadcrumb with the `BreadcrumbStore`
|
|
140
|
-
* and ensures automatic deregistration when the route is destroyed.
|
|
141
139
|
*
|
|
142
|
-
*
|
|
140
|
+
* Accepts a static label (`string`), a static options object, or a factory returning either —
|
|
141
|
+
* use a factory when you need `inject()` for dynamic data.
|
|
142
|
+
*
|
|
143
|
+
* @param factoryOrValue A static label, a static `CreateBreadcrumbOptions`, or a factory returning either.
|
|
143
144
|
* @see CreateBreadcrumbOptions
|
|
144
145
|
*
|
|
145
146
|
* @example
|
|
@@ -149,25 +150,26 @@ type CreateBreadcrumbOptions = {
|
|
|
149
150
|
* path: 'home',
|
|
150
151
|
* component: HomeComponent,
|
|
151
152
|
* resolve: {
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* });
|
|
153
|
+
* // shorthand for { label: 'Home' }
|
|
154
|
+
* breadcrumb: createBreadcrumb('Home'),
|
|
155
155
|
* },
|
|
156
|
+
* },
|
|
157
|
+
* {
|
|
156
158
|
* path: 'users/:userId',
|
|
157
159
|
* component: UserProfileComponent,
|
|
158
160
|
* resolve: {
|
|
159
161
|
* breadcrumb: createBreadcrumb(() => {
|
|
160
162
|
* const userStore = inject(UserStore);
|
|
161
163
|
* return {
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
164
|
+
* label: () => userStore.user().name ?? 'Loading...',
|
|
165
|
+
* };
|
|
166
|
+
* }),
|
|
165
167
|
* },
|
|
166
|
-
* }
|
|
168
|
+
* },
|
|
167
169
|
* ];
|
|
168
170
|
* ```
|
|
169
171
|
*/
|
|
170
|
-
declare function createBreadcrumb(
|
|
172
|
+
declare function createBreadcrumb(factoryOrValue: (() => CreateBreadcrumbOptions | string) | string | CreateBreadcrumbOptions): ResolveFn<void>;
|
|
171
173
|
|
|
172
174
|
/**
|
|
173
175
|
* Injects and provides access to a reactive list of breadcrumbs.
|
|
@@ -199,6 +201,38 @@ declare function createBreadcrumb(factory: () => CreateBreadcrumbOptions): Resol
|
|
|
199
201
|
*/
|
|
200
202
|
declare function injectBreadcrumbs(): Signal<Breadcrumb[]>;
|
|
201
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Returns an imperative function that triggers preloading for an arbitrary link, using
|
|
206
|
+
* the same path resolution and {@link PreloadStrategy} pipeline as the {@link Link}
|
|
207
|
+
* (`mmLink`) directive.
|
|
208
|
+
*
|
|
209
|
+
* Use this when the `Link` directive isn't a fit — for example, preloading a route from
|
|
210
|
+
* an effect when a user opens a menu, hovers a non-link element, or reacts to a signal
|
|
211
|
+
* change — and you don't want to render an `<a [mmLink]>` just to request the preload.
|
|
212
|
+
*
|
|
213
|
+
* Requires {@link PreloadStrategy} to be wired up via `provideRouter(routes, withPreloading(PreloadStrategy))`,
|
|
214
|
+
* just like the directive.
|
|
215
|
+
*
|
|
216
|
+
* @returns A function accepting the same link descriptor shape as `mmLink` (`string`,
|
|
217
|
+
* commands array, `UrlTree`, or `null`). Passing `null` or an unresolvable link is a no-op.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* @Component({ ... })
|
|
222
|
+
* export class CommandPaletteComponent {
|
|
223
|
+
* private readonly triggerPreload = injectTriggerPreload();
|
|
224
|
+
*
|
|
225
|
+
* protected readonly highlighted = signal<string | null>(null);
|
|
226
|
+
*
|
|
227
|
+
* constructor() {
|
|
228
|
+
* effect(() => {
|
|
229
|
+
* const target = this.highlighted();
|
|
230
|
+
* if (target) this.triggerPreload(target);
|
|
231
|
+
* });
|
|
232
|
+
* }
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
202
236
|
declare function injectTriggerPreload(): (link: string | any[] | UrlTree | null, relativeTo?: ActivatedRoute, queryParams?: Params, fragment?: string, queryParamsHandling?: "merge" | "preserve" | "") => void;
|
|
203
237
|
/**
|
|
204
238
|
* Configuration for the `mmLink` directive.
|
|
@@ -247,6 +281,151 @@ declare class Link {
|
|
|
247
281
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Link, "[mmLink]", ["mmLink"], { "target": { "alias": "target"; "required": false; "isSignal": true; }; "queryParams": { "alias": "queryParams"; "required": false; "isSignal": true; }; "fragment": { "alias": "fragment"; "required": false; "isSignal": true; }; "queryParamsHandling": { "alias": "queryParamsHandling"; "required": false; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "info": { "alias": "info"; "required": false; "isSignal": true; }; "relativeTo": { "alias": "relativeTo"; "required": false; "isSignal": true; }; "skipLocationChange": { "alias": "skipLocationChange"; "required": false; "isSignal": true; }; "replaceUrl": { "alias": "replaceUrl"; "required": false; "isSignal": true; }; "mmLink": { "alias": "mmLink"; "required": false; "isSignal": true; }; "preloadOn": { "alias": "preloadOn"; "required": false; "isSignal": true; }; "useMouseDown": { "alias": "useMouseDown"; "required": false; "isSignal": true; }; "beforeNavigate": { "alias": "beforeNavigate"; "required": false; "isSignal": true; }; }, { "preloading": "preloading"; }, never, never, true, [{ directive: typeof i1.RouterLink; inputs: { "routerLink": "mmLink"; "target": "target"; "queryParams": "queryParams"; "fragment": "fragment"; "queryParamsHandling": "queryParamsHandling"; "state": "state"; "relativeTo": "relativeTo"; "skipLocationChange": "skipLocationChange"; "replaceUrl": "replaceUrl"; }; outputs: {}; }]>;
|
|
248
282
|
}
|
|
249
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Description of a single navigation item.
|
|
286
|
+
*
|
|
287
|
+
* Reactive fields accept either a static value or a zero-arg function — the function
|
|
288
|
+
* form is wrapped in a `computed` so reading signals inside it produces a reactive value.
|
|
289
|
+
*
|
|
290
|
+
* @typeParam TMeta Arbitrary consumer-defined metadata round-tripped to {@link NavItem.meta}.
|
|
291
|
+
*
|
|
292
|
+
* @see createNavItems
|
|
293
|
+
* @see NavItem
|
|
294
|
+
*/
|
|
295
|
+
type CreateNavItem<TMeta = Record<string, unknown>> = {
|
|
296
|
+
/** Visible text. */
|
|
297
|
+
label: string | (() => string);
|
|
298
|
+
/**
|
|
299
|
+
* The navigation target. Resolved relative to the route the resolver is attached to —
|
|
300
|
+
* the same convention as Angular's `routerLink`:
|
|
301
|
+
*
|
|
302
|
+
* - `'a'` / `'a/b'` / `['a', 'b']` — relative segments, resolve to `${mount}/a` etc.
|
|
303
|
+
* - `'/foo'` / `['/foo', 'bar']` — absolute, leading-slash escape hatch.
|
|
304
|
+
* - A pre-built `UrlTree` is passed through unchanged.
|
|
305
|
+
*
|
|
306
|
+
* Omit (or return `null`) for a pure grouping header — `active` will then fall through
|
|
307
|
+
* to the children-active check.
|
|
308
|
+
*/
|
|
309
|
+
link?: string | any[] | (() => string | any[] | null) | null;
|
|
310
|
+
/** Accessible label. Defaults to `label`. */
|
|
311
|
+
ariaLabel?: string | (() => string);
|
|
312
|
+
/** When true, the item is rendered but non-interactive. Cascades to descendants. */
|
|
313
|
+
disabled?: boolean | (() => boolean);
|
|
314
|
+
/** When true, the item (and its subtree) is filtered out of the consumer-facing array. */
|
|
315
|
+
hidden?: boolean | (() => boolean);
|
|
316
|
+
/** Arbitrary metadata round-tripped on the resulting `NavItem`. */
|
|
317
|
+
meta?: TMeta | (() => TMeta);
|
|
318
|
+
/**
|
|
319
|
+
* Override the match options used to compute `active`. Merged on top of the global default
|
|
320
|
+
* from `provideNavConfig`, which is in turn merged on top of `@angular/router`'s
|
|
321
|
+
* `subsetMatchOptions` defaults.
|
|
322
|
+
*
|
|
323
|
+
* Setting this also implicitly disables the default child-active OR — see
|
|
324
|
+
* {@link matchesWhenChildActive} to opt back in.
|
|
325
|
+
*/
|
|
326
|
+
activeMatch?: Partial<IsActiveMatchOptions>;
|
|
327
|
+
/**
|
|
328
|
+
* Controls whether `active` ORs with descendant `active`.
|
|
329
|
+
*
|
|
330
|
+
* Default: `true` when `activeMatch` is omitted, `false` when `activeMatch` is set.
|
|
331
|
+
* Explicit values override the default.
|
|
332
|
+
*/
|
|
333
|
+
matchesWhenChildActive?: boolean;
|
|
334
|
+
/** Optional stable id. Defaults to the serialized link when present. */
|
|
335
|
+
id?: string | (() => string);
|
|
336
|
+
/** Nested items. */
|
|
337
|
+
children?: CreateNavItem<TMeta>[];
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* A navigation item exposed by `injectNavItems`. All fields are signals so consumers can
|
|
341
|
+
* read reactively without caring whether the source was static or signal-derived.
|
|
342
|
+
*
|
|
343
|
+
* @typeParam TMeta Same as the corresponding {@link CreateNavItem}.
|
|
344
|
+
*/
|
|
345
|
+
type NavItem<TMeta = Record<string, unknown>> = {
|
|
346
|
+
id: Signal<string>;
|
|
347
|
+
label: Signal<string>;
|
|
348
|
+
ariaLabel: Signal<string>;
|
|
349
|
+
/** Serialized URL, or `null` for pure grouping items with no link. */
|
|
350
|
+
link: Signal<string | null>;
|
|
351
|
+
active: Signal<boolean>;
|
|
352
|
+
disabled: Signal<boolean>;
|
|
353
|
+
meta: Signal<TMeta>;
|
|
354
|
+
/** Children that survive the hidden filter. */
|
|
355
|
+
children: Signal<NavItem<TMeta>[]>;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Global configuration for the nav system.
|
|
360
|
+
* @see provideNavConfig
|
|
361
|
+
*/
|
|
362
|
+
type NavConfig = {
|
|
363
|
+
/**
|
|
364
|
+
* Default match options used when computing `NavItem.active`. Per-item `activeMatch`
|
|
365
|
+
* (and the router's built-in `subsetMatchOptions`) are still merged on top.
|
|
366
|
+
*/
|
|
367
|
+
activeMatch?: Partial<IsActiveMatchOptions>;
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Provides global configuration for the nav system.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```typescript
|
|
374
|
+
* provideNavConfig({
|
|
375
|
+
* activeMatch: { queryParams: 'ignored' },
|
|
376
|
+
* }),
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
declare function provideNavConfig(config?: NavConfig): Provider;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Registers a set of nav items for the activating route under the given scope.
|
|
383
|
+
* Mirrors `createBreadcrumb` / `createTitle` — designed to be used in a route's
|
|
384
|
+
* `resolve` map.
|
|
385
|
+
*
|
|
386
|
+
* Multiple scopes can be registered on a single route by giving each its own `name`
|
|
387
|
+
* (and a unique key in the `resolve` map):
|
|
388
|
+
*
|
|
389
|
+
* ```typescript
|
|
390
|
+
* resolve: {
|
|
391
|
+
* mainNav: createNavItems([...], { name: 'main' }),
|
|
392
|
+
* sideNav: createNavItems([...], { name: 'side' }),
|
|
393
|
+
* }
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* Scope override semantics: when multiple routes in the active chain register items
|
|
397
|
+
* under the same scope, the deepest active registration wins. Navigating away restores
|
|
398
|
+
* the shallower registration.
|
|
399
|
+
*/
|
|
400
|
+
declare function createNavItems<TMeta = Record<string, unknown>>(itemsOrFactory: CreateNavItem<TMeta>[] | (() => CreateNavItem<TMeta>[]), options?: {
|
|
401
|
+
name?: string;
|
|
402
|
+
}): ResolveFn<void>;
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Returns a reactive list of nav items for the requested scope.
|
|
406
|
+
*
|
|
407
|
+
* The returned signal reflects the nearest active ancestor route that registered items
|
|
408
|
+
* for `name` via `createNavItems`. Hidden items are filtered out.
|
|
409
|
+
*
|
|
410
|
+
* @typeParam TMeta The shape of `NavItem.meta` for the consuming code. Untyped at the
|
|
411
|
+
* registration site — this is a consumer-side assertion.
|
|
412
|
+
*
|
|
413
|
+
* @example
|
|
414
|
+
* ```typescript
|
|
415
|
+
* @Component({
|
|
416
|
+
* template: `
|
|
417
|
+
* @for (item of items(); track item) {
|
|
418
|
+
* <a [href]="item.link()" [class.active]="item.active()">{{ item.label() }}</a>
|
|
419
|
+
* }
|
|
420
|
+
* `,
|
|
421
|
+
* })
|
|
422
|
+
* export class TopBar {
|
|
423
|
+
* protected readonly items = injectNavItems();
|
|
424
|
+
* }
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
declare function injectNavItems<TMeta = Record<string, unknown>>(name?: string): Signal<NavItem<TMeta>[]>;
|
|
428
|
+
|
|
250
429
|
declare class PreloadStrategy implements PreloadingStrategy {
|
|
251
430
|
private readonly loading;
|
|
252
431
|
private readonly router;
|
|
@@ -339,6 +518,12 @@ declare function queryParam(key: string | (() => string), route?: ActivatedRoute
|
|
|
339
518
|
* @see {createTitle}
|
|
340
519
|
*/
|
|
341
520
|
type TitleConfig = {
|
|
521
|
+
/**
|
|
522
|
+
* The base title to fallback to, by default Title.getTitle() is called on instantiation and that is used as a fallback,
|
|
523
|
+
* which in most cases should resolve to what is in index.html, unless you specifically call Title.setTitle() before any routes,
|
|
524
|
+
* are initialized.
|
|
525
|
+
*/
|
|
526
|
+
initialTitle?: string;
|
|
342
527
|
/**
|
|
343
528
|
* The title to be used when no title is set.
|
|
344
529
|
* If not provided it defaults to an empty string
|
|
@@ -360,13 +545,13 @@ declare function provideTitleConfig(config?: TitleConfig): Provider;
|
|
|
360
545
|
*
|
|
361
546
|
* Creates a title resolver function that can be used in Angular's router.
|
|
362
547
|
*
|
|
363
|
-
* @param
|
|
364
|
-
* A function that returns a string or a Signal<string> representing the title.
|
|
548
|
+
* @param factoryOrValue
|
|
549
|
+
* A function that returns a string or a Signal<string> representing the title or just the string directly.
|
|
365
550
|
* @param awaitValue
|
|
366
551
|
* If `true`, the resolver will wait until the title signal has a value before resolving.
|
|
367
552
|
* Defaults to `false`.
|
|
368
553
|
*/
|
|
369
|
-
declare function createTitle(
|
|
554
|
+
declare function createTitle(factoryOrValue: (() => string | (() => string)) | string, awaitValue?: boolean): ResolveFn<string>;
|
|
370
555
|
|
|
371
556
|
/**
|
|
372
557
|
* Creates a Signal that tracks the current router URL.
|
|
@@ -398,7 +583,7 @@ declare function createTitle(fn: () => string | (() => string), awaitValue?: boo
|
|
|
398
583
|
* }
|
|
399
584
|
* ```
|
|
400
585
|
*/
|
|
401
|
-
declare function url(): Signal<string>;
|
|
586
|
+
declare function url(router?: Router): Signal<string>;
|
|
402
587
|
|
|
403
|
-
export { Link, PreloadStrategy, createBreadcrumb, createTitle, injectBreadcrumbs, injectTriggerPreload, provideBreadcrumbConfig, provideMMLinkDefaultConfig, provideTitleConfig, queryParam, url };
|
|
404
|
-
export type { Breadcrumb, TitleConfig };
|
|
588
|
+
export { Link, PreloadStrategy, createBreadcrumb, createNavItems, createTitle, injectBreadcrumbs, injectNavItems, injectTriggerPreload, provideBreadcrumbConfig, provideMMLinkDefaultConfig, provideNavConfig, provideTitleConfig, queryParam, url };
|
|
589
|
+
export type { Breadcrumb, BreadcrumbConfig, CreateNavItem, NavConfig, NavItem, ResolvedLeafRoute, TitleConfig };
|