@angular/router 20.0.0-next.4 → 20.0.0-next.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.
@@ -0,0 +1,1661 @@
1
+ /**
2
+ * @license Angular v20.0.0-next.6
3
+ * (c) 2010-2025 Google LLC. https://angular.io/
4
+ * License: MIT
5
+ */
6
+
7
+ import * as i3 from '@angular/common';
8
+ import { LOCATION_INITIALIZED, HashLocationStrategy, LocationStrategy, ViewportScroller, Location, PathLocationStrategy } from '@angular/common';
9
+ import * as i0 from '@angular/core';
10
+ import { inject, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, ɵRuntimeError as _RuntimeError, ɵɵsanitizeUrlOrResourceUrl as __sanitizeUrlOrResourceUrl, booleanAttribute, HostListener, Input, HostBinding, Attribute, Directive, EventEmitter, Output, ContentChildren, Optional, createEnvironmentInjector, Injectable, InjectionToken, ɵperformanceMarkFeature as _performanceMarkFeature, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, provideAppInitializer, Injector, ApplicationRef, NgZone, SkipSelf, NgModule } from '@angular/core';
11
+ import { NavigationEnd, isUrlTree, Router, ActivatedRoute, RouterConfigLoader, NavigationStart, NavigationSkipped, NavigationSkippedCode, Scroll, UrlSerializer, NavigationTransitions, ROUTES, afterNextNavigation, ROUTER_CONFIGURATION, NAVIGATION_ERROR_HANDLER, RoutedComponentInputBinder, INPUT_BINDER, createViewTransition, CREATE_VIEW_TRANSITION, VIEW_TRANSITION_OPTIONS, stringifyEvent, DefaultUrlSerializer, ChildrenOutletContexts, RouterOutlet, ɵEmptyOutletComponent as _EmptyOutletComponent } from './router-Dq3SgjMt.mjs';
12
+ import { Subject, of, from } from 'rxjs';
13
+ import { mergeAll, catchError, filter, concatMap, mergeMap } from 'rxjs/operators';
14
+
15
+ /**
16
+ * @description
17
+ *
18
+ * When applied to an element in a template, makes that element a link
19
+ * that initiates navigation to a route. Navigation opens one or more routed components
20
+ * in one or more `<router-outlet>` locations on the page.
21
+ *
22
+ * Given a route configuration `[{ path: 'user/:name', component: UserCmp }]`,
23
+ * the following creates a static link to the route:
24
+ * `<a routerLink="/user/bob">link to user component</a>`
25
+ *
26
+ * You can use dynamic values to generate the link.
27
+ * For a dynamic link, pass an array of path segments,
28
+ * followed by the params for each segment.
29
+ * For example, `['/team', teamId, 'user', userName, {details: true}]`
30
+ * generates a link to `/team/11/user/bob;details=true`.
31
+ *
32
+ * Multiple static segments can be merged into one term and combined with dynamic segments.
33
+ * For example, `['/team/11/user', userName, {details: true}]`
34
+ *
35
+ * The input that you provide to the link is treated as a delta to the current URL.
36
+ * For instance, suppose the current URL is `/user/(box//aux:team)`.
37
+ * The link `<a [routerLink]="['/user/jim']">Jim</a>` creates the URL
38
+ * `/user/(jim//aux:team)`.
39
+ * See {@link Router#createUrlTree} for more information.
40
+ *
41
+ * @usageNotes
42
+ *
43
+ * You can use absolute or relative paths in a link, set query parameters,
44
+ * control how parameters are handled, and keep a history of navigation states.
45
+ *
46
+ * ### Relative link paths
47
+ *
48
+ * The first segment name can be prepended with `/`, `./`, or `../`.
49
+ * * If the first segment begins with `/`, the router looks up the route from the root of the
50
+ * app.
51
+ * * If the first segment begins with `./`, or doesn't begin with a slash, the router
52
+ * looks in the children of the current activated route.
53
+ * * If the first segment begins with `../`, the router goes up one level in the route tree.
54
+ *
55
+ * ### Setting and handling query params and fragments
56
+ *
57
+ * The following link adds a query parameter and a fragment to the generated URL:
58
+ *
59
+ * ```html
60
+ * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" fragment="education">
61
+ * link to user component
62
+ * </a>
63
+ * ```
64
+ * By default, the directive constructs the new URL using the given query parameters.
65
+ * The example generates the link: `/user/bob?debug=true#education`.
66
+ *
67
+ * You can instruct the directive to handle query parameters differently
68
+ * by specifying the `queryParamsHandling` option in the link.
69
+ * Allowed values are:
70
+ *
71
+ * - `'merge'`: Merge the given `queryParams` into the current query params.
72
+ * - `'preserve'`: Preserve the current query params.
73
+ *
74
+ * For example:
75
+ *
76
+ * ```html
77
+ * <a [routerLink]="['/user/bob']" [queryParams]="{debug: true}" queryParamsHandling="merge">
78
+ * link to user component
79
+ * </a>
80
+ * ```
81
+ *
82
+ * `queryParams`, `fragment`, `queryParamsHandling`, `preserveFragment`, and `relativeTo`
83
+ * cannot be used when the `routerLink` input is a `UrlTree`.
84
+ *
85
+ * See {@link UrlCreationOptions#queryParamsHandling}.
86
+ *
87
+ * ### Preserving navigation history
88
+ *
89
+ * You can provide a `state` value to be persisted to the browser's
90
+ * [`History.state` property](https://developer.mozilla.org/en-US/docs/Web/API/History#Properties).
91
+ * For example:
92
+ *
93
+ * ```html
94
+ * <a [routerLink]="['/user/bob']" [state]="{tracingId: 123}">
95
+ * link to user component
96
+ * </a>
97
+ * ```
98
+ *
99
+ * Use {@link Router#getCurrentNavigation} to retrieve a saved
100
+ * navigation-state value. For example, to capture the `tracingId` during the `NavigationStart`
101
+ * event:
102
+ *
103
+ * ```ts
104
+ * // Get NavigationStart events
105
+ * router.events.pipe(filter(e => e instanceof NavigationStart)).subscribe(e => {
106
+ * const navigation = router.getCurrentNavigation();
107
+ * tracingService.trace({id: navigation.extras.state.tracingId});
108
+ * });
109
+ * ```
110
+ *
111
+ * ### RouterLink compatible custom elements
112
+ *
113
+ * In order to make a custom element work with routerLink, the corresponding custom
114
+ * element must implement the `href` attribute and must list `href` in the array of
115
+ * the static property/getter `observedAttributes`.
116
+ *
117
+ * @ngModule RouterModule
118
+ *
119
+ * @publicApi
120
+ */
121
+ class RouterLink {
122
+ router;
123
+ route;
124
+ tabIndexAttribute;
125
+ renderer;
126
+ el;
127
+ locationStrategy;
128
+ /**
129
+ * Represents an `href` attribute value applied to a host element,
130
+ * when a host element is an `<a>`/`<area>` tag or a compatible custom element.
131
+ * For other tags, the value is `null`.
132
+ */
133
+ href = null;
134
+ /**
135
+ * Represents the `target` attribute on a host element.
136
+ * This is only used when the host element is
137
+ * an `<a>`/`<area>` tag or a compatible custom element.
138
+ */
139
+ target;
140
+ /**
141
+ * Passed to {@link Router#createUrlTree} as part of the
142
+ * `UrlCreationOptions`.
143
+ * @see {@link UrlCreationOptions#queryParams}
144
+ * @see {@link Router#createUrlTree}
145
+ */
146
+ queryParams;
147
+ /**
148
+ * Passed to {@link Router#createUrlTree} as part of the
149
+ * `UrlCreationOptions`.
150
+ * @see {@link UrlCreationOptions#fragment}
151
+ * @see {@link Router#createUrlTree}
152
+ */
153
+ fragment;
154
+ /**
155
+ * Passed to {@link Router#createUrlTree} as part of the
156
+ * `UrlCreationOptions`.
157
+ * @see {@link UrlCreationOptions#queryParamsHandling}
158
+ * @see {@link Router#createUrlTree}
159
+ */
160
+ queryParamsHandling;
161
+ /**
162
+ * Passed to {@link Router#navigateByUrl} as part of the
163
+ * `NavigationBehaviorOptions`.
164
+ * @see {@link NavigationBehaviorOptions#state}
165
+ * @see {@link Router#navigateByUrl}
166
+ */
167
+ state;
168
+ /**
169
+ * Passed to {@link Router#navigateByUrl} as part of the
170
+ * `NavigationBehaviorOptions`.
171
+ * @see {@link NavigationBehaviorOptions#info}
172
+ * @see {@link Router#navigateByUrl}
173
+ */
174
+ info;
175
+ /**
176
+ * Passed to {@link Router#createUrlTree} as part of the
177
+ * `UrlCreationOptions`.
178
+ * Specify a value here when you do not want to use the default value
179
+ * for `routerLink`, which is the current activated route.
180
+ * Note that a value of `undefined` here will use the `routerLink` default.
181
+ * @see {@link UrlCreationOptions#relativeTo}
182
+ * @see {@link Router#createUrlTree}
183
+ */
184
+ relativeTo;
185
+ /** Whether a host element is an `<a>`/`<area>` tag or a compatible custom element. */
186
+ isAnchorElement;
187
+ subscription;
188
+ /** @internal */
189
+ onChanges = new Subject();
190
+ applicationErrorHandler = inject(_INTERNAL_APPLICATION_ERROR_HANDLER);
191
+ constructor(router, route, tabIndexAttribute, renderer, el, locationStrategy) {
192
+ this.router = router;
193
+ this.route = route;
194
+ this.tabIndexAttribute = tabIndexAttribute;
195
+ this.renderer = renderer;
196
+ this.el = el;
197
+ this.locationStrategy = locationStrategy;
198
+ const tagName = el.nativeElement.tagName?.toLowerCase();
199
+ this.isAnchorElement =
200
+ tagName === 'a' ||
201
+ tagName === 'area' ||
202
+ !!(
203
+ // Avoid breaking in an SSR context where customElements might not be defined.
204
+ (typeof customElements === 'object' &&
205
+ // observedAttributes is an optional static property/getter on a custom element.
206
+ // The spec states that this must be an array of strings.
207
+ customElements.get(tagName)?.observedAttributes?.includes?.('href')));
208
+ if (this.isAnchorElement) {
209
+ this.subscription = router.events.subscribe((s) => {
210
+ if (s instanceof NavigationEnd) {
211
+ this.updateHref();
212
+ }
213
+ });
214
+ }
215
+ else {
216
+ this.setTabIndexIfNotOnNativeEl('0');
217
+ }
218
+ }
219
+ /**
220
+ * Passed to {@link Router#createUrlTree} as part of the
221
+ * `UrlCreationOptions`.
222
+ * @see {@link UrlCreationOptions#preserveFragment}
223
+ * @see {@link Router#createUrlTree}
224
+ */
225
+ preserveFragment = false;
226
+ /**
227
+ * Passed to {@link Router#navigateByUrl} as part of the
228
+ * `NavigationBehaviorOptions`.
229
+ * @see {@link NavigationBehaviorOptions#skipLocationChange}
230
+ * @see {@link Router#navigateByUrl}
231
+ */
232
+ skipLocationChange = false;
233
+ /**
234
+ * Passed to {@link Router#navigateByUrl} as part of the
235
+ * `NavigationBehaviorOptions`.
236
+ * @see {@link NavigationBehaviorOptions#replaceUrl}
237
+ * @see {@link Router#navigateByUrl}
238
+ */
239
+ replaceUrl = false;
240
+ /**
241
+ * Modifies the tab index if there was not a tabindex attribute on the element during
242
+ * instantiation.
243
+ */
244
+ setTabIndexIfNotOnNativeEl(newTabIndex) {
245
+ if (this.tabIndexAttribute != null /* both `null` and `undefined` */ || this.isAnchorElement) {
246
+ return;
247
+ }
248
+ this.applyAttributeValue('tabindex', newTabIndex);
249
+ }
250
+ /** @nodoc */
251
+ // TODO(atscott): Remove changes parameter in major version as a breaking change.
252
+ ngOnChanges(changes) {
253
+ if (ngDevMode &&
254
+ isUrlTree(this.routerLinkInput) &&
255
+ (this.fragment !== undefined ||
256
+ this.queryParams ||
257
+ this.queryParamsHandling ||
258
+ this.preserveFragment ||
259
+ this.relativeTo)) {
260
+ throw new _RuntimeError(4016 /* RuntimeErrorCode.INVALID_ROUTER_LINK_INPUTS */, 'Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value.');
261
+ }
262
+ if (this.isAnchorElement) {
263
+ this.updateHref();
264
+ }
265
+ // This is subscribed to by `RouterLinkActive` so that it knows to update when there are changes
266
+ // to the RouterLinks it's tracking.
267
+ this.onChanges.next(this);
268
+ }
269
+ routerLinkInput = null;
270
+ /**
271
+ * Commands to pass to {@link Router#createUrlTree} or a `UrlTree`.
272
+ * - **array**: commands to pass to {@link Router#createUrlTree}.
273
+ * - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
274
+ * - **UrlTree**: a `UrlTree` for this link rather than creating one from the commands
275
+ * and other inputs that correspond to properties of `UrlCreationOptions`.
276
+ * - **null|undefined**: effectively disables the `routerLink`
277
+ * @see {@link Router#createUrlTree}
278
+ */
279
+ set routerLink(commandsOrUrlTree) {
280
+ if (commandsOrUrlTree == null) {
281
+ this.routerLinkInput = null;
282
+ this.setTabIndexIfNotOnNativeEl(null);
283
+ }
284
+ else {
285
+ if (isUrlTree(commandsOrUrlTree)) {
286
+ this.routerLinkInput = commandsOrUrlTree;
287
+ }
288
+ else {
289
+ this.routerLinkInput = Array.isArray(commandsOrUrlTree)
290
+ ? commandsOrUrlTree
291
+ : [commandsOrUrlTree];
292
+ }
293
+ this.setTabIndexIfNotOnNativeEl('0');
294
+ }
295
+ }
296
+ /** @nodoc */
297
+ onClick(button, ctrlKey, shiftKey, altKey, metaKey) {
298
+ const urlTree = this.urlTree;
299
+ if (urlTree === null) {
300
+ return true;
301
+ }
302
+ if (this.isAnchorElement) {
303
+ if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) {
304
+ return true;
305
+ }
306
+ if (typeof this.target === 'string' && this.target != '_self') {
307
+ return true;
308
+ }
309
+ }
310
+ const extras = {
311
+ skipLocationChange: this.skipLocationChange,
312
+ replaceUrl: this.replaceUrl,
313
+ state: this.state,
314
+ info: this.info,
315
+ };
316
+ // navigateByUrl is mocked frequently in tests... Reduce breakages when adding `catch`
317
+ this.router.navigateByUrl(urlTree, extras)?.catch((e) => {
318
+ this.applicationErrorHandler(e);
319
+ });
320
+ // Return `false` for `<a>` elements to prevent default action
321
+ // and cancel the native behavior, since the navigation is handled
322
+ // by the Router.
323
+ return !this.isAnchorElement;
324
+ }
325
+ /** @nodoc */
326
+ ngOnDestroy() {
327
+ this.subscription?.unsubscribe();
328
+ }
329
+ updateHref() {
330
+ const urlTree = this.urlTree;
331
+ this.href =
332
+ urlTree !== null && this.locationStrategy
333
+ ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree))
334
+ : null;
335
+ const sanitizedValue = this.href === null
336
+ ? null
337
+ : // This class represents a directive that can be added to both `<a>` elements,
338
+ // as well as other elements. As a result, we can't define security context at
339
+ // compile time. So the security context is deferred to runtime.
340
+ // The `ɵɵsanitizeUrlOrResourceUrl` selects the necessary sanitizer function
341
+ // based on the tag and property names. The logic mimics the one from
342
+ // `packages/compiler/src/schema/dom_security_schema.ts`, which is used at compile time.
343
+ //
344
+ // Note: we should investigate whether we can switch to using `@HostBinding('attr.href')`
345
+ // instead of applying a value via a renderer, after a final merge of the
346
+ // `RouterLinkWithHref` directive.
347
+ __sanitizeUrlOrResourceUrl(this.href, this.el.nativeElement.tagName.toLowerCase(), 'href');
348
+ this.applyAttributeValue('href', sanitizedValue);
349
+ }
350
+ applyAttributeValue(attrName, attrValue) {
351
+ const renderer = this.renderer;
352
+ const nativeElement = this.el.nativeElement;
353
+ if (attrValue !== null) {
354
+ renderer.setAttribute(nativeElement, attrName, attrValue);
355
+ }
356
+ else {
357
+ renderer.removeAttribute(nativeElement, attrName);
358
+ }
359
+ }
360
+ get urlTree() {
361
+ if (this.routerLinkInput === null) {
362
+ return null;
363
+ }
364
+ else if (isUrlTree(this.routerLinkInput)) {
365
+ return this.routerLinkInput;
366
+ }
367
+ return this.router.createUrlTree(this.routerLinkInput, {
368
+ // If the `relativeTo` input is not defined, we want to use `this.route` by default.
369
+ // Otherwise, we should use the value provided by the user in the input.
370
+ relativeTo: this.relativeTo !== undefined ? this.relativeTo : this.route,
371
+ queryParams: this.queryParams,
372
+ fragment: this.fragment,
373
+ queryParamsHandling: this.queryParamsHandling,
374
+ preserveFragment: this.preserveFragment,
375
+ });
376
+ }
377
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterLink, deps: [{ token: Router }, { token: ActivatedRoute }, { token: 'tabindex', attribute: true }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.LocationStrategy }], target: i0.ɵɵFactoryTarget.Directive });
378
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.0.0-next.6", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", info: "info", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 });
379
+ }
380
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterLink, decorators: [{
381
+ type: Directive,
382
+ args: [{
383
+ selector: '[routerLink]',
384
+ }]
385
+ }], ctorParameters: () => [{ type: Router }, { type: ActivatedRoute }, { type: undefined, decorators: [{
386
+ type: Attribute,
387
+ args: ['tabindex']
388
+ }] }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i3.LocationStrategy }], propDecorators: { target: [{
389
+ type: HostBinding,
390
+ args: ['attr.target']
391
+ }, {
392
+ type: Input
393
+ }], queryParams: [{
394
+ type: Input
395
+ }], fragment: [{
396
+ type: Input
397
+ }], queryParamsHandling: [{
398
+ type: Input
399
+ }], state: [{
400
+ type: Input
401
+ }], info: [{
402
+ type: Input
403
+ }], relativeTo: [{
404
+ type: Input
405
+ }], preserveFragment: [{
406
+ type: Input,
407
+ args: [{ transform: booleanAttribute }]
408
+ }], skipLocationChange: [{
409
+ type: Input,
410
+ args: [{ transform: booleanAttribute }]
411
+ }], replaceUrl: [{
412
+ type: Input,
413
+ args: [{ transform: booleanAttribute }]
414
+ }], routerLink: [{
415
+ type: Input
416
+ }], onClick: [{
417
+ type: HostListener,
418
+ args: ['click', [
419
+ '$event.button',
420
+ '$event.ctrlKey',
421
+ '$event.shiftKey',
422
+ '$event.altKey',
423
+ '$event.metaKey',
424
+ ]]
425
+ }] } });
426
+
427
+ /**
428
+ *
429
+ * @description
430
+ *
431
+ * Tracks whether the linked route of an element is currently active, and allows you
432
+ * to specify one or more CSS classes to add to the element when the linked route
433
+ * is active.
434
+ *
435
+ * Use this directive to create a visual distinction for elements associated with an active route.
436
+ * For example, the following code highlights the word "Bob" when the router
437
+ * activates the associated route:
438
+ *
439
+ * ```html
440
+ * <a routerLink="/user/bob" routerLinkActive="active-link">Bob</a>
441
+ * ```
442
+ *
443
+ * Whenever the URL is either '/user' or '/user/bob', the "active-link" class is
444
+ * added to the anchor tag. If the URL changes, the class is removed.
445
+ *
446
+ * You can set more than one class using a space-separated string or an array.
447
+ * For example:
448
+ *
449
+ * ```html
450
+ * <a routerLink="/user/bob" routerLinkActive="class1 class2">Bob</a>
451
+ * <a routerLink="/user/bob" [routerLinkActive]="['class1', 'class2']">Bob</a>
452
+ * ```
453
+ *
454
+ * To add the classes only when the URL matches the link exactly, add the option `exact: true`:
455
+ *
456
+ * ```html
457
+ * <a routerLink="/user/bob" routerLinkActive="active-link" [routerLinkActiveOptions]="{exact:
458
+ * true}">Bob</a>
459
+ * ```
460
+ *
461
+ * To directly check the `isActive` status of the link, assign the `RouterLinkActive`
462
+ * instance to a template variable.
463
+ * For example, the following checks the status without assigning any CSS classes:
464
+ *
465
+ * ```html
466
+ * <a routerLink="/user/bob" routerLinkActive #rla="routerLinkActive">
467
+ * Bob {{ rla.isActive ? '(already open)' : ''}}
468
+ * </a>
469
+ * ```
470
+ *
471
+ * You can apply the `RouterLinkActive` directive to an ancestor of linked elements.
472
+ * For example, the following sets the active-link class on the `<div>` parent tag
473
+ * when the URL is either '/user/jim' or '/user/bob'.
474
+ *
475
+ * ```html
476
+ * <div routerLinkActive="active-link" [routerLinkActiveOptions]="{exact: true}">
477
+ * <a routerLink="/user/jim">Jim</a>
478
+ * <a routerLink="/user/bob">Bob</a>
479
+ * </div>
480
+ * ```
481
+ *
482
+ * The `RouterLinkActive` directive can also be used to set the aria-current attribute
483
+ * to provide an alternative distinction for active elements to visually impaired users.
484
+ *
485
+ * For example, the following code adds the 'active' class to the Home Page link when it is
486
+ * indeed active and in such case also sets its aria-current attribute to 'page':
487
+ *
488
+ * ```html
489
+ * <a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home Page</a>
490
+ * ```
491
+ *
492
+ * @ngModule RouterModule
493
+ *
494
+ * @publicApi
495
+ */
496
+ class RouterLinkActive {
497
+ router;
498
+ element;
499
+ renderer;
500
+ cdr;
501
+ link;
502
+ links;
503
+ classes = [];
504
+ routerEventsSubscription;
505
+ linkInputChangesSubscription;
506
+ _isActive = false;
507
+ get isActive() {
508
+ return this._isActive;
509
+ }
510
+ /**
511
+ * Options to configure how to determine if the router link is active.
512
+ *
513
+ * These options are passed to the `Router.isActive()` function.
514
+ *
515
+ * @see {@link Router#isActive}
516
+ */
517
+ routerLinkActiveOptions = { exact: false };
518
+ /**
519
+ * Aria-current attribute to apply when the router link is active.
520
+ *
521
+ * Possible values: `'page'` | `'step'` | `'location'` | `'date'` | `'time'` | `true` | `false`.
522
+ *
523
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current}
524
+ */
525
+ ariaCurrentWhenActive;
526
+ /**
527
+ *
528
+ * You can use the output `isActiveChange` to get notified each time the link becomes
529
+ * active or inactive.
530
+ *
531
+ * Emits:
532
+ * true -> Route is active
533
+ * false -> Route is inactive
534
+ *
535
+ * ```html
536
+ * <a
537
+ * routerLink="/user/bob"
538
+ * routerLinkActive="active-link"
539
+ * (isActiveChange)="this.onRouterLinkActive($event)">Bob</a>
540
+ * ```
541
+ */
542
+ isActiveChange = new EventEmitter();
543
+ constructor(router, element, renderer, cdr, link) {
544
+ this.router = router;
545
+ this.element = element;
546
+ this.renderer = renderer;
547
+ this.cdr = cdr;
548
+ this.link = link;
549
+ this.routerEventsSubscription = router.events.subscribe((s) => {
550
+ if (s instanceof NavigationEnd) {
551
+ this.update();
552
+ }
553
+ });
554
+ }
555
+ /** @nodoc */
556
+ ngAfterContentInit() {
557
+ // `of(null)` is used to force subscribe body to execute once immediately (like `startWith`).
558
+ of(this.links.changes, of(null))
559
+ .pipe(mergeAll())
560
+ .subscribe((_) => {
561
+ this.update();
562
+ this.subscribeToEachLinkOnChanges();
563
+ });
564
+ }
565
+ subscribeToEachLinkOnChanges() {
566
+ this.linkInputChangesSubscription?.unsubscribe();
567
+ const allLinkChanges = [...this.links.toArray(), this.link]
568
+ .filter((link) => !!link)
569
+ .map((link) => link.onChanges);
570
+ this.linkInputChangesSubscription = from(allLinkChanges)
571
+ .pipe(mergeAll())
572
+ .subscribe((link) => {
573
+ if (this._isActive !== this.isLinkActive(this.router)(link)) {
574
+ this.update();
575
+ }
576
+ });
577
+ }
578
+ set routerLinkActive(data) {
579
+ const classes = Array.isArray(data) ? data : data.split(' ');
580
+ this.classes = classes.filter((c) => !!c);
581
+ }
582
+ /** @nodoc */
583
+ ngOnChanges(changes) {
584
+ this.update();
585
+ }
586
+ /** @nodoc */
587
+ ngOnDestroy() {
588
+ this.routerEventsSubscription.unsubscribe();
589
+ this.linkInputChangesSubscription?.unsubscribe();
590
+ }
591
+ update() {
592
+ if (!this.links || !this.router.navigated)
593
+ return;
594
+ queueMicrotask(() => {
595
+ const hasActiveLinks = this.hasActiveLinks();
596
+ this.classes.forEach((c) => {
597
+ if (hasActiveLinks) {
598
+ this.renderer.addClass(this.element.nativeElement, c);
599
+ }
600
+ else {
601
+ this.renderer.removeClass(this.element.nativeElement, c);
602
+ }
603
+ });
604
+ if (hasActiveLinks && this.ariaCurrentWhenActive !== undefined) {
605
+ this.renderer.setAttribute(this.element.nativeElement, 'aria-current', this.ariaCurrentWhenActive.toString());
606
+ }
607
+ else {
608
+ this.renderer.removeAttribute(this.element.nativeElement, 'aria-current');
609
+ }
610
+ // Only emit change if the active state changed.
611
+ if (this._isActive !== hasActiveLinks) {
612
+ this._isActive = hasActiveLinks;
613
+ this.cdr.markForCheck();
614
+ // Emit on isActiveChange after classes are updated
615
+ this.isActiveChange.emit(hasActiveLinks);
616
+ }
617
+ });
618
+ }
619
+ isLinkActive(router) {
620
+ const options = isActiveMatchOptions(this.routerLinkActiveOptions)
621
+ ? this.routerLinkActiveOptions
622
+ : // While the types should disallow `undefined` here, it's possible without strict inputs
623
+ this.routerLinkActiveOptions.exact || false;
624
+ return (link) => {
625
+ const urlTree = link.urlTree;
626
+ return urlTree ? router.isActive(urlTree, options) : false;
627
+ };
628
+ }
629
+ hasActiveLinks() {
630
+ const isActiveCheckFn = this.isLinkActive(this.router);
631
+ return (this.link && isActiveCheckFn(this.link)) || this.links.some(isActiveCheckFn);
632
+ }
633
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
634
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.0-next.6", type: RouterLinkActive, isStandalone: true, selector: "[routerLinkActive]", inputs: { routerLinkActiveOptions: "routerLinkActiveOptions", ariaCurrentWhenActive: "ariaCurrentWhenActive", routerLinkActive: "routerLinkActive" }, outputs: { isActiveChange: "isActiveChange" }, queries: [{ propertyName: "links", predicate: RouterLink, descendants: true }], exportAs: ["routerLinkActive"], usesOnChanges: true, ngImport: i0 });
635
+ }
636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterLinkActive, decorators: [{
637
+ type: Directive,
638
+ args: [{
639
+ selector: '[routerLinkActive]',
640
+ exportAs: 'routerLinkActive',
641
+ }]
642
+ }], ctorParameters: () => [{ type: Router }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: RouterLink, decorators: [{
643
+ type: Optional
644
+ }] }], propDecorators: { links: [{
645
+ type: ContentChildren,
646
+ args: [RouterLink, { descendants: true }]
647
+ }], routerLinkActiveOptions: [{
648
+ type: Input
649
+ }], ariaCurrentWhenActive: [{
650
+ type: Input
651
+ }], isActiveChange: [{
652
+ type: Output
653
+ }], routerLinkActive: [{
654
+ type: Input
655
+ }] } });
656
+ /**
657
+ * Use instead of `'paths' in options` to be compatible with property renaming
658
+ */
659
+ function isActiveMatchOptions(options) {
660
+ return !!options.paths;
661
+ }
662
+
663
+ /**
664
+ * @description
665
+ *
666
+ * Provides a preloading strategy.
667
+ *
668
+ * @publicApi
669
+ */
670
+ class PreloadingStrategy {
671
+ }
672
+ /**
673
+ * @description
674
+ *
675
+ * Provides a preloading strategy that preloads all modules as quickly as possible.
676
+ *
677
+ * ```ts
678
+ * RouterModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules})
679
+ * ```
680
+ *
681
+ * @publicApi
682
+ */
683
+ class PreloadAllModules {
684
+ preload(route, fn) {
685
+ return fn().pipe(catchError(() => of(null)));
686
+ }
687
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
688
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
689
+ }
690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: PreloadAllModules, decorators: [{
691
+ type: Injectable,
692
+ args: [{ providedIn: 'root' }]
693
+ }] });
694
+ /**
695
+ * @description
696
+ *
697
+ * Provides a preloading strategy that does not preload any modules.
698
+ *
699
+ * This strategy is enabled by default.
700
+ *
701
+ * @publicApi
702
+ */
703
+ class NoPreloading {
704
+ preload(route, fn) {
705
+ return of(null);
706
+ }
707
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
708
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: NoPreloading, providedIn: 'root' });
709
+ }
710
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: NoPreloading, decorators: [{
711
+ type: Injectable,
712
+ args: [{ providedIn: 'root' }]
713
+ }] });
714
+ /**
715
+ * The preloader optimistically loads all router configurations to
716
+ * make navigations into lazily-loaded sections of the application faster.
717
+ *
718
+ * The preloader runs in the background. When the router bootstraps, the preloader
719
+ * starts listening to all navigation events. After every such event, the preloader
720
+ * will check if any configurations can be loaded lazily.
721
+ *
722
+ * If a route is protected by `canLoad` guards, the preloaded will not load it.
723
+ *
724
+ * @publicApi
725
+ */
726
+ class RouterPreloader {
727
+ router;
728
+ injector;
729
+ preloadingStrategy;
730
+ loader;
731
+ subscription;
732
+ constructor(router, compiler, injector, preloadingStrategy, loader) {
733
+ this.router = router;
734
+ this.injector = injector;
735
+ this.preloadingStrategy = preloadingStrategy;
736
+ this.loader = loader;
737
+ }
738
+ setUpPreloading() {
739
+ this.subscription = this.router.events
740
+ .pipe(filter((e) => e instanceof NavigationEnd), concatMap(() => this.preload()))
741
+ .subscribe(() => { });
742
+ }
743
+ preload() {
744
+ return this.processRoutes(this.injector, this.router.config);
745
+ }
746
+ /** @nodoc */
747
+ ngOnDestroy() {
748
+ if (this.subscription) {
749
+ this.subscription.unsubscribe();
750
+ }
751
+ }
752
+ processRoutes(injector, routes) {
753
+ const res = [];
754
+ for (const route of routes) {
755
+ if (route.providers && !route._injector) {
756
+ route._injector = createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
757
+ }
758
+ const injectorForCurrentRoute = route._injector ?? injector;
759
+ const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
760
+ // Note that `canLoad` is only checked as a condition that prevents `loadChildren` and not
761
+ // `loadComponent`. `canLoad` guards only block loading of child routes by design. This
762
+ // happens as a consequence of needing to descend into children for route matching immediately
763
+ // while component loading is deferred until route activation. Because `canLoad` guards can
764
+ // have side effects, we cannot execute them here so we instead skip preloading altogether
765
+ // when present. Lastly, it remains to be decided whether `canLoad` should behave this way
766
+ // at all. Code splitting and lazy loading is separate from client-side authorization checks
767
+ // and should not be used as a security measure to prevent loading of code.
768
+ if ((route.loadChildren && !route._loadedRoutes && route.canLoad === undefined) ||
769
+ (route.loadComponent && !route._loadedComponent)) {
770
+ res.push(this.preloadConfig(injectorForCurrentRoute, route));
771
+ }
772
+ if (route.children || route._loadedRoutes) {
773
+ res.push(this.processRoutes(injectorForChildren, (route.children ?? route._loadedRoutes)));
774
+ }
775
+ }
776
+ return from(res).pipe(mergeAll());
777
+ }
778
+ preloadConfig(injector, route) {
779
+ return this.preloadingStrategy.preload(route, () => {
780
+ let loadedChildren$;
781
+ if (route.loadChildren && route.canLoad === undefined) {
782
+ loadedChildren$ = this.loader.loadChildren(injector, route);
783
+ }
784
+ else {
785
+ loadedChildren$ = of(null);
786
+ }
787
+ const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
788
+ if (config === null) {
789
+ return of(void 0);
790
+ }
791
+ route._loadedRoutes = config.routes;
792
+ route._loadedInjector = config.injector;
793
+ // If the loaded config was a module, use that as the module/module injector going
794
+ // forward. Otherwise, continue using the current module/module injector.
795
+ return this.processRoutes(config.injector ?? injector, config.routes);
796
+ }));
797
+ if (route.loadComponent && !route._loadedComponent) {
798
+ const loadComponent$ = this.loader.loadComponent(route);
799
+ return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
800
+ }
801
+ else {
802
+ return recursiveLoadChildren$;
803
+ }
804
+ });
805
+ }
806
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
807
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
808
+ }
809
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterPreloader, decorators: [{
810
+ type: Injectable,
811
+ args: [{ providedIn: 'root' }]
812
+ }], ctorParameters: () => [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }] });
813
+
814
+ const ROUTER_SCROLLER = new InjectionToken('');
815
+ class RouterScroller {
816
+ urlSerializer;
817
+ transitions;
818
+ viewportScroller;
819
+ zone;
820
+ options;
821
+ routerEventsSubscription;
822
+ scrollEventsSubscription;
823
+ lastId = 0;
824
+ lastSource = 'imperative';
825
+ restoredId = 0;
826
+ store = {};
827
+ /** @nodoc */
828
+ constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) {
829
+ this.urlSerializer = urlSerializer;
830
+ this.transitions = transitions;
831
+ this.viewportScroller = viewportScroller;
832
+ this.zone = zone;
833
+ this.options = options;
834
+ // Default both options to 'disabled'
835
+ options.scrollPositionRestoration ||= 'disabled';
836
+ options.anchorScrolling ||= 'disabled';
837
+ }
838
+ init() {
839
+ // we want to disable the automatic scrolling because having two places
840
+ // responsible for scrolling results race conditions, especially given
841
+ // that browser don't implement this behavior consistently
842
+ if (this.options.scrollPositionRestoration !== 'disabled') {
843
+ this.viewportScroller.setHistoryScrollRestoration('manual');
844
+ }
845
+ this.routerEventsSubscription = this.createScrollEvents();
846
+ this.scrollEventsSubscription = this.consumeScrollEvents();
847
+ }
848
+ createScrollEvents() {
849
+ return this.transitions.events.subscribe((e) => {
850
+ if (e instanceof NavigationStart) {
851
+ // store the scroll position of the current stable navigations.
852
+ this.store[this.lastId] = this.viewportScroller.getScrollPosition();
853
+ this.lastSource = e.navigationTrigger;
854
+ this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
855
+ }
856
+ else if (e instanceof NavigationEnd) {
857
+ this.lastId = e.id;
858
+ this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);
859
+ }
860
+ else if (e instanceof NavigationSkipped &&
861
+ e.code === NavigationSkippedCode.IgnoredSameUrlNavigation) {
862
+ this.lastSource = undefined;
863
+ this.restoredId = 0;
864
+ this.scheduleScrollEvent(e, this.urlSerializer.parse(e.url).fragment);
865
+ }
866
+ });
867
+ }
868
+ consumeScrollEvents() {
869
+ return this.transitions.events.subscribe((e) => {
870
+ if (!(e instanceof Scroll))
871
+ return;
872
+ // a popstate event. The pop state event will always ignore anchor scrolling.
873
+ if (e.position) {
874
+ if (this.options.scrollPositionRestoration === 'top') {
875
+ this.viewportScroller.scrollToPosition([0, 0]);
876
+ }
877
+ else if (this.options.scrollPositionRestoration === 'enabled') {
878
+ this.viewportScroller.scrollToPosition(e.position);
879
+ }
880
+ // imperative navigation "forward"
881
+ }
882
+ else {
883
+ if (e.anchor && this.options.anchorScrolling === 'enabled') {
884
+ this.viewportScroller.scrollToAnchor(e.anchor);
885
+ }
886
+ else if (this.options.scrollPositionRestoration !== 'disabled') {
887
+ this.viewportScroller.scrollToPosition([0, 0]);
888
+ }
889
+ }
890
+ });
891
+ }
892
+ scheduleScrollEvent(routerEvent, anchor) {
893
+ this.zone.runOutsideAngular(async () => {
894
+ // The scroll event needs to be delayed until after change detection. Otherwise, we may
895
+ // attempt to restore the scroll position before the router outlet has fully rendered the
896
+ // component by executing its update block of the template function.
897
+ //
898
+ // #57109 (we need to wait at least a macrotask before scrolling. AfterNextRender resolves in microtask event loop with Zones)
899
+ // We could consider _also_ waiting for a render promise though one should have already happened or been scheduled by this point
900
+ // and should definitely happen before rAF/setTimeout.
901
+ // #53985 (cannot rely solely on setTimeout because a frame may paint before the timeout)
902
+ await new Promise((resolve) => {
903
+ setTimeout(resolve);
904
+ if (typeof requestAnimationFrame !== 'undefined') {
905
+ requestAnimationFrame(resolve);
906
+ }
907
+ });
908
+ this.zone.run(() => {
909
+ this.transitions.events.next(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
910
+ });
911
+ });
912
+ }
913
+ /** @nodoc */
914
+ ngOnDestroy() {
915
+ this.routerEventsSubscription?.unsubscribe();
916
+ this.scrollEventsSubscription?.unsubscribe();
917
+ }
918
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
919
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterScroller });
920
+ }
921
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterScroller, decorators: [{
922
+ type: Injectable
923
+ }], ctorParameters: () => [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }] });
924
+
925
+ /**
926
+ * Sets up providers necessary to enable `Router` functionality for the application.
927
+ * Allows to configure a set of routes as well as extra features that should be enabled.
928
+ *
929
+ * @usageNotes
930
+ *
931
+ * Basic example of how you can add a Router to your application:
932
+ * ```ts
933
+ * const appRoutes: Routes = [];
934
+ * bootstrapApplication(AppComponent, {
935
+ * providers: [provideRouter(appRoutes)]
936
+ * });
937
+ * ```
938
+ *
939
+ * You can also enable optional features in the Router by adding functions from the `RouterFeatures`
940
+ * type:
941
+ * ```ts
942
+ * const appRoutes: Routes = [];
943
+ * bootstrapApplication(AppComponent,
944
+ * {
945
+ * providers: [
946
+ * provideRouter(appRoutes,
947
+ * withDebugTracing(),
948
+ * withRouterConfig({paramsInheritanceStrategy: 'always'}))
949
+ * ]
950
+ * }
951
+ * );
952
+ * ```
953
+ *
954
+ * @see {@link RouterFeatures}
955
+ *
956
+ * @publicApi
957
+ * @param routes A set of `Route`s to use for the application routing table.
958
+ * @param features Optional features to configure additional router behaviors.
959
+ * @returns A set of providers to setup a Router.
960
+ */
961
+ function provideRouter(routes, ...features) {
962
+ return makeEnvironmentProviders([
963
+ { provide: ROUTES, multi: true, useValue: routes },
964
+ typeof ngDevMode === 'undefined' || ngDevMode
965
+ ? { provide: ROUTER_IS_PROVIDED, useValue: true }
966
+ : [],
967
+ { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
968
+ { provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: getBootstrapListener },
969
+ features.map((feature) => feature.ɵproviders),
970
+ ]);
971
+ }
972
+ function rootRoute(router) {
973
+ return router.routerState.root;
974
+ }
975
+ /**
976
+ * Helper function to create an object that represents a Router feature.
977
+ */
978
+ function routerFeature(kind, providers) {
979
+ return { ɵkind: kind, ɵproviders: providers };
980
+ }
981
+ /**
982
+ * An Injection token used to indicate whether `provideRouter` or `RouterModule.forRoot` was ever
983
+ * called.
984
+ */
985
+ const ROUTER_IS_PROVIDED = new InjectionToken('', {
986
+ providedIn: 'root',
987
+ factory: () => false,
988
+ });
989
+ const routerIsProvidedDevModeCheck = {
990
+ provide: ENVIRONMENT_INITIALIZER,
991
+ multi: true,
992
+ useFactory() {
993
+ return () => {
994
+ if (!inject(ROUTER_IS_PROVIDED)) {
995
+ console.warn('`provideRoutes` was called without `provideRouter` or `RouterModule.forRoot`. ' +
996
+ 'This is likely a mistake.');
997
+ }
998
+ };
999
+ },
1000
+ };
1001
+ /**
1002
+ * Registers a DI provider for a set of routes.
1003
+ * @param routes The route configuration to provide.
1004
+ *
1005
+ * @usageNotes
1006
+ *
1007
+ * ```ts
1008
+ * @NgModule({
1009
+ * providers: [provideRoutes(ROUTES)]
1010
+ * })
1011
+ * class LazyLoadedChildModule {}
1012
+ * ```
1013
+ *
1014
+ * @deprecated If necessary, provide routes using the `ROUTES` `InjectionToken`.
1015
+ * @see {@link ROUTES}
1016
+ * @publicApi
1017
+ */
1018
+ function provideRoutes(routes) {
1019
+ return [
1020
+ { provide: ROUTES, multi: true, useValue: routes },
1021
+ typeof ngDevMode === 'undefined' || ngDevMode ? routerIsProvidedDevModeCheck : [],
1022
+ ];
1023
+ }
1024
+ /**
1025
+ * Enables customizable scrolling behavior for router navigations.
1026
+ *
1027
+ * @usageNotes
1028
+ *
1029
+ * Basic example of how you can enable scrolling feature:
1030
+ * ```ts
1031
+ * const appRoutes: Routes = [];
1032
+ * bootstrapApplication(AppComponent,
1033
+ * {
1034
+ * providers: [
1035
+ * provideRouter(appRoutes, withInMemoryScrolling())
1036
+ * ]
1037
+ * }
1038
+ * );
1039
+ * ```
1040
+ *
1041
+ * @see {@link provideRouter}
1042
+ * @see {@link ViewportScroller}
1043
+ *
1044
+ * @publicApi
1045
+ * @param options Set of configuration parameters to customize scrolling behavior, see
1046
+ * `InMemoryScrollingOptions` for additional information.
1047
+ * @returns A set of providers for use with `provideRouter`.
1048
+ */
1049
+ function withInMemoryScrolling(options = {}) {
1050
+ const providers = [
1051
+ {
1052
+ provide: ROUTER_SCROLLER,
1053
+ useFactory: () => {
1054
+ const viewportScroller = inject(ViewportScroller);
1055
+ const zone = inject(NgZone);
1056
+ const transitions = inject(NavigationTransitions);
1057
+ const urlSerializer = inject(UrlSerializer);
1058
+ return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);
1059
+ },
1060
+ },
1061
+ ];
1062
+ return routerFeature(4 /* RouterFeatureKind.InMemoryScrollingFeature */, providers);
1063
+ }
1064
+ function getBootstrapListener() {
1065
+ const injector = inject(Injector);
1066
+ return (bootstrappedComponentRef) => {
1067
+ const ref = injector.get(ApplicationRef);
1068
+ if (bootstrappedComponentRef !== ref.components[0]) {
1069
+ return;
1070
+ }
1071
+ const router = injector.get(Router);
1072
+ const bootstrapDone = injector.get(BOOTSTRAP_DONE);
1073
+ if (injector.get(INITIAL_NAVIGATION) === 1 /* InitialNavigation.EnabledNonBlocking */) {
1074
+ router.initialNavigation();
1075
+ }
1076
+ injector.get(ROUTER_PRELOADER, null, { optional: true })?.setUpPreloading();
1077
+ injector.get(ROUTER_SCROLLER, null, { optional: true })?.init();
1078
+ router.resetRootComponentType(ref.componentTypes[0]);
1079
+ if (!bootstrapDone.closed) {
1080
+ bootstrapDone.next();
1081
+ bootstrapDone.complete();
1082
+ bootstrapDone.unsubscribe();
1083
+ }
1084
+ };
1085
+ }
1086
+ /**
1087
+ * A subject used to indicate that the bootstrapping phase is done. When initial navigation is
1088
+ * `enabledBlocking`, the first navigation waits until bootstrapping is finished before continuing
1089
+ * to the activation phase.
1090
+ */
1091
+ const BOOTSTRAP_DONE = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'bootstrap done indicator' : '', {
1092
+ factory: () => {
1093
+ return new Subject();
1094
+ },
1095
+ });
1096
+ const INITIAL_NAVIGATION = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'initial navigation' : '', { providedIn: 'root', factory: () => 1 /* InitialNavigation.EnabledNonBlocking */ });
1097
+ /**
1098
+ * Configures initial navigation to start before the root component is created.
1099
+ *
1100
+ * The bootstrap is blocked until the initial navigation is complete. This should be set in case
1101
+ * you use [server-side rendering](guide/ssr), but do not enable [hydration](guide/hydration) for
1102
+ * your application.
1103
+ *
1104
+ * @usageNotes
1105
+ *
1106
+ * Basic example of how you can enable this navigation behavior:
1107
+ * ```ts
1108
+ * const appRoutes: Routes = [];
1109
+ * bootstrapApplication(AppComponent,
1110
+ * {
1111
+ * providers: [
1112
+ * provideRouter(appRoutes, withEnabledBlockingInitialNavigation())
1113
+ * ]
1114
+ * }
1115
+ * );
1116
+ * ```
1117
+ *
1118
+ * @see {@link provideRouter}
1119
+ *
1120
+ * @publicApi
1121
+ * @returns A set of providers for use with `provideRouter`.
1122
+ */
1123
+ function withEnabledBlockingInitialNavigation() {
1124
+ const providers = [
1125
+ { provide: INITIAL_NAVIGATION, useValue: 0 /* InitialNavigation.EnabledBlocking */ },
1126
+ provideAppInitializer(() => {
1127
+ const injector = inject(Injector);
1128
+ const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve());
1129
+ return locationInitialized.then(() => {
1130
+ return new Promise((resolve) => {
1131
+ const router = injector.get(Router);
1132
+ const bootstrapDone = injector.get(BOOTSTRAP_DONE);
1133
+ afterNextNavigation(router, () => {
1134
+ // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored
1135
+ // without a redirect.
1136
+ resolve(true);
1137
+ });
1138
+ injector.get(NavigationTransitions).afterPreactivation = () => {
1139
+ // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
1140
+ // assume activation will complete successfully (even though this is not
1141
+ // guaranteed).
1142
+ resolve(true);
1143
+ return bootstrapDone.closed ? of(void 0) : bootstrapDone;
1144
+ };
1145
+ router.initialNavigation();
1146
+ });
1147
+ });
1148
+ }),
1149
+ ];
1150
+ return routerFeature(2 /* RouterFeatureKind.EnabledBlockingInitialNavigationFeature */, providers);
1151
+ }
1152
+ /**
1153
+ * Disables initial navigation.
1154
+ *
1155
+ * Use if there is a reason to have more control over when the router starts its initial navigation
1156
+ * due to some complex initialization logic.
1157
+ *
1158
+ * @usageNotes
1159
+ *
1160
+ * Basic example of how you can disable initial navigation:
1161
+ * ```ts
1162
+ * const appRoutes: Routes = [];
1163
+ * bootstrapApplication(AppComponent,
1164
+ * {
1165
+ * providers: [
1166
+ * provideRouter(appRoutes, withDisabledInitialNavigation())
1167
+ * ]
1168
+ * }
1169
+ * );
1170
+ * ```
1171
+ *
1172
+ * @see {@link provideRouter}
1173
+ *
1174
+ * @returns A set of providers for use with `provideRouter`.
1175
+ *
1176
+ * @publicApi
1177
+ */
1178
+ function withDisabledInitialNavigation() {
1179
+ const providers = [
1180
+ provideAppInitializer(() => {
1181
+ inject(Router).setUpLocationChangeListener();
1182
+ }),
1183
+ { provide: INITIAL_NAVIGATION, useValue: 2 /* InitialNavigation.Disabled */ },
1184
+ ];
1185
+ return routerFeature(3 /* RouterFeatureKind.DisabledInitialNavigationFeature */, providers);
1186
+ }
1187
+ /**
1188
+ * Enables logging of all internal navigation events to the console.
1189
+ * Extra logging might be useful for debugging purposes to inspect Router event sequence.
1190
+ *
1191
+ * @usageNotes
1192
+ *
1193
+ * Basic example of how you can enable debug tracing:
1194
+ * ```ts
1195
+ * const appRoutes: Routes = [];
1196
+ * bootstrapApplication(AppComponent,
1197
+ * {
1198
+ * providers: [
1199
+ * provideRouter(appRoutes, withDebugTracing())
1200
+ * ]
1201
+ * }
1202
+ * );
1203
+ * ```
1204
+ *
1205
+ * @see {@link provideRouter}
1206
+ *
1207
+ * @returns A set of providers for use with `provideRouter`.
1208
+ *
1209
+ * @publicApi
1210
+ */
1211
+ function withDebugTracing() {
1212
+ let providers = [];
1213
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
1214
+ providers = [
1215
+ {
1216
+ provide: ENVIRONMENT_INITIALIZER,
1217
+ multi: true,
1218
+ useFactory: () => {
1219
+ const router = inject(Router);
1220
+ return () => router.events.subscribe((e) => {
1221
+ // tslint:disable:no-console
1222
+ console.group?.(`Router Event: ${e.constructor.name}`);
1223
+ console.log(stringifyEvent(e));
1224
+ console.log(e);
1225
+ console.groupEnd?.();
1226
+ // tslint:enable:no-console
1227
+ });
1228
+ },
1229
+ },
1230
+ ];
1231
+ }
1232
+ else {
1233
+ providers = [];
1234
+ }
1235
+ return routerFeature(1 /* RouterFeatureKind.DebugTracingFeature */, providers);
1236
+ }
1237
+ const ROUTER_PRELOADER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'router preloader' : '');
1238
+ /**
1239
+ * Allows to configure a preloading strategy to use. The strategy is configured by providing a
1240
+ * reference to a class that implements a `PreloadingStrategy`.
1241
+ *
1242
+ * @usageNotes
1243
+ *
1244
+ * Basic example of how you can configure preloading:
1245
+ * ```ts
1246
+ * const appRoutes: Routes = [];
1247
+ * bootstrapApplication(AppComponent,
1248
+ * {
1249
+ * providers: [
1250
+ * provideRouter(appRoutes, withPreloading(PreloadAllModules))
1251
+ * ]
1252
+ * }
1253
+ * );
1254
+ * ```
1255
+ *
1256
+ * @see {@link provideRouter}
1257
+ *
1258
+ * @param preloadingStrategy A reference to a class that implements a `PreloadingStrategy` that
1259
+ * should be used.
1260
+ * @returns A set of providers for use with `provideRouter`.
1261
+ *
1262
+ * @publicApi
1263
+ */
1264
+ function withPreloading(preloadingStrategy) {
1265
+ const providers = [
1266
+ { provide: ROUTER_PRELOADER, useExisting: RouterPreloader },
1267
+ { provide: PreloadingStrategy, useExisting: preloadingStrategy },
1268
+ ];
1269
+ return routerFeature(0 /* RouterFeatureKind.PreloadingFeature */, providers);
1270
+ }
1271
+ /**
1272
+ * Allows to provide extra parameters to configure Router.
1273
+ *
1274
+ * @usageNotes
1275
+ *
1276
+ * Basic example of how you can provide extra configuration options:
1277
+ * ```ts
1278
+ * const appRoutes: Routes = [];
1279
+ * bootstrapApplication(AppComponent,
1280
+ * {
1281
+ * providers: [
1282
+ * provideRouter(appRoutes, withRouterConfig({
1283
+ * onSameUrlNavigation: 'reload'
1284
+ * }))
1285
+ * ]
1286
+ * }
1287
+ * );
1288
+ * ```
1289
+ *
1290
+ * @see {@link provideRouter}
1291
+ *
1292
+ * @param options A set of parameters to configure Router, see `RouterConfigOptions` for
1293
+ * additional information.
1294
+ * @returns A set of providers for use with `provideRouter`.
1295
+ *
1296
+ * @publicApi
1297
+ */
1298
+ function withRouterConfig(options) {
1299
+ const providers = [{ provide: ROUTER_CONFIGURATION, useValue: options }];
1300
+ return routerFeature(5 /* RouterFeatureKind.RouterConfigurationFeature */, providers);
1301
+ }
1302
+ /**
1303
+ * Provides the location strategy that uses the URL fragment instead of the history API.
1304
+ *
1305
+ * @usageNotes
1306
+ *
1307
+ * Basic example of how you can use the hash location option:
1308
+ * ```ts
1309
+ * const appRoutes: Routes = [];
1310
+ * bootstrapApplication(AppComponent,
1311
+ * {
1312
+ * providers: [
1313
+ * provideRouter(appRoutes, withHashLocation())
1314
+ * ]
1315
+ * }
1316
+ * );
1317
+ * ```
1318
+ *
1319
+ * @see {@link provideRouter}
1320
+ * @see {@link /api/common/HashLocationStrategy HashLocationStrategy}
1321
+ *
1322
+ * @returns A set of providers for use with `provideRouter`.
1323
+ *
1324
+ * @publicApi
1325
+ */
1326
+ function withHashLocation() {
1327
+ const providers = [{ provide: LocationStrategy, useClass: HashLocationStrategy }];
1328
+ return routerFeature(6 /* RouterFeatureKind.RouterHashLocationFeature */, providers);
1329
+ }
1330
+ /**
1331
+ * Provides a function which is called when a navigation error occurs.
1332
+ *
1333
+ * This function is run inside application's [injection context](guide/di/dependency-injection-context)
1334
+ * so you can use the [`inject`](api/core/inject) function.
1335
+ *
1336
+ * This function can return a `RedirectCommand` to convert the error to a redirect, similar to returning
1337
+ * a `UrlTree` or `RedirectCommand` from a guard. This will also prevent the `Router` from emitting
1338
+ * `NavigationError`; it will instead emit `NavigationCancel` with code NavigationCancellationCode.Redirect.
1339
+ * Return values other than `RedirectCommand` are ignored and do not change any behavior with respect to
1340
+ * how the `Router` handles the error.
1341
+ *
1342
+ * @usageNotes
1343
+ *
1344
+ * Basic example of how you can use the error handler option:
1345
+ * ```ts
1346
+ * const appRoutes: Routes = [];
1347
+ * bootstrapApplication(AppComponent,
1348
+ * {
1349
+ * providers: [
1350
+ * provideRouter(appRoutes, withNavigationErrorHandler((e: NavigationError) =>
1351
+ * inject(MyErrorTracker).trackError(e)))
1352
+ * ]
1353
+ * }
1354
+ * );
1355
+ * ```
1356
+ *
1357
+ * @see {@link NavigationError}
1358
+ * @see {@link /api/core/inject inject}
1359
+ * @see {@link runInInjectionContext}
1360
+ *
1361
+ * @returns A set of providers for use with `provideRouter`.
1362
+ *
1363
+ * @publicApi
1364
+ */
1365
+ function withNavigationErrorHandler(handler) {
1366
+ const providers = [
1367
+ {
1368
+ provide: NAVIGATION_ERROR_HANDLER,
1369
+ useValue: handler,
1370
+ },
1371
+ ];
1372
+ return routerFeature(7 /* RouterFeatureKind.NavigationErrorHandlerFeature */, providers);
1373
+ }
1374
+ /**
1375
+ * Enables binding information from the `Router` state directly to the inputs of the component in
1376
+ * `Route` configurations.
1377
+ *
1378
+ * @usageNotes
1379
+ *
1380
+ * Basic example of how you can enable the feature:
1381
+ * ```ts
1382
+ * const appRoutes: Routes = [];
1383
+ * bootstrapApplication(AppComponent,
1384
+ * {
1385
+ * providers: [
1386
+ * provideRouter(appRoutes, withComponentInputBinding())
1387
+ * ]
1388
+ * }
1389
+ * );
1390
+ * ```
1391
+ *
1392
+ * The router bindings information from any of the following sources:
1393
+ *
1394
+ * - query parameters
1395
+ * - path and matrix parameters
1396
+ * - static route data
1397
+ * - data from resolvers
1398
+ *
1399
+ * Duplicate keys are resolved in the same order from above, from least to greatest,
1400
+ * meaning that resolvers have the highest precedence and override any of the other information
1401
+ * from the route.
1402
+ *
1403
+ * Importantly, when an input does not have an item in the route data with a matching key, this
1404
+ * input is set to `undefined`. This prevents previous information from being
1405
+ * retained if the data got removed from the route (i.e. if a query parameter is removed).
1406
+ * Default values can be provided with a resolver on the route to ensure the value is always present
1407
+ * or an input and use an input transform in the component.
1408
+ *
1409
+ * @see {@link /guide/components/inputs#input-transforms Input Transforms}
1410
+ * @returns A set of providers for use with `provideRouter`.
1411
+ */
1412
+ function withComponentInputBinding() {
1413
+ const providers = [
1414
+ RoutedComponentInputBinder,
1415
+ { provide: INPUT_BINDER, useExisting: RoutedComponentInputBinder },
1416
+ ];
1417
+ return routerFeature(8 /* RouterFeatureKind.ComponentInputBindingFeature */, providers);
1418
+ }
1419
+ /**
1420
+ * Enables view transitions in the Router by running the route activation and deactivation inside of
1421
+ * `document.startViewTransition`.
1422
+ *
1423
+ * Note: The View Transitions API is not available in all browsers. If the browser does not support
1424
+ * view transitions, the Router will not attempt to start a view transition and continue processing
1425
+ * the navigation as usual.
1426
+ *
1427
+ * @usageNotes
1428
+ *
1429
+ * Basic example of how you can enable the feature:
1430
+ * ```ts
1431
+ * const appRoutes: Routes = [];
1432
+ * bootstrapApplication(AppComponent,
1433
+ * {
1434
+ * providers: [
1435
+ * provideRouter(appRoutes, withViewTransitions())
1436
+ * ]
1437
+ * }
1438
+ * );
1439
+ * ```
1440
+ *
1441
+ * @returns A set of providers for use with `provideRouter`.
1442
+ * @see https://developer.chrome.com/docs/web-platform/view-transitions/
1443
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
1444
+ * @developerPreview
1445
+ */
1446
+ function withViewTransitions(options) {
1447
+ _performanceMarkFeature('NgRouterViewTransitions');
1448
+ const providers = [
1449
+ { provide: CREATE_VIEW_TRANSITION, useValue: createViewTransition },
1450
+ {
1451
+ provide: VIEW_TRANSITION_OPTIONS,
1452
+ useValue: { skipNextTransition: !!options?.skipInitialTransition, ...options },
1453
+ },
1454
+ ];
1455
+ return routerFeature(9 /* RouterFeatureKind.ViewTransitionsFeature */, providers);
1456
+ }
1457
+
1458
+ /**
1459
+ * The directives defined in the `RouterModule`.
1460
+ */
1461
+ const ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent];
1462
+ /**
1463
+ * @docsNotRequired
1464
+ */
1465
+ const ROUTER_FORROOT_GUARD = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'router duplicate forRoot guard' : '');
1466
+ // TODO(atscott): All of these except `ActivatedRoute` are `providedIn: 'root'`. They are only kept
1467
+ // here to avoid a breaking change whereby the provider order matters based on where the
1468
+ // `RouterModule`/`RouterTestingModule` is imported. These can/should be removed as a "breaking"
1469
+ // change in a major version.
1470
+ const ROUTER_PROVIDERS = [
1471
+ Location,
1472
+ { provide: UrlSerializer, useClass: DefaultUrlSerializer },
1473
+ Router,
1474
+ ChildrenOutletContexts,
1475
+ { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] },
1476
+ RouterConfigLoader,
1477
+ // Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can
1478
+ // be removed when `provideRoutes` is removed.
1479
+ typeof ngDevMode === 'undefined' || ngDevMode
1480
+ ? { provide: ROUTER_IS_PROVIDED, useValue: true }
1481
+ : [],
1482
+ ];
1483
+ /**
1484
+ * @description
1485
+ *
1486
+ * Adds directives and providers for in-app navigation among views defined in an application.
1487
+ * Use the Angular `Router` service to declaratively specify application states and manage state
1488
+ * transitions.
1489
+ *
1490
+ * You can import this NgModule multiple times, once for each lazy-loaded bundle.
1491
+ * However, only one `Router` service can be active.
1492
+ * To ensure this, there are two ways to register routes when importing this module:
1493
+ *
1494
+ * * The `forRoot()` method creates an `NgModule` that contains all the directives, the given
1495
+ * routes, and the `Router` service itself.
1496
+ * * The `forChild()` method creates an `NgModule` that contains all the directives and the given
1497
+ * routes, but does not include the `Router` service.
1498
+ *
1499
+ * @see [Routing and Navigation guide](guide/routing/common-router-tasks) for an
1500
+ * overview of how the `Router` service should be used.
1501
+ *
1502
+ * @publicApi
1503
+ */
1504
+ class RouterModule {
1505
+ constructor() {
1506
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
1507
+ inject(ROUTER_FORROOT_GUARD, { optional: true });
1508
+ }
1509
+ }
1510
+ /**
1511
+ * Creates and configures a module with all the router providers and directives.
1512
+ * Optionally sets up an application listener to perform an initial navigation.
1513
+ *
1514
+ * When registering the NgModule at the root, import as follows:
1515
+ *
1516
+ * ```ts
1517
+ * @NgModule({
1518
+ * imports: [RouterModule.forRoot(ROUTES)]
1519
+ * })
1520
+ * class MyNgModule {}
1521
+ * ```
1522
+ *
1523
+ * @param routes An array of `Route` objects that define the navigation paths for the application.
1524
+ * @param config An `ExtraOptions` configuration object that controls how navigation is performed.
1525
+ * @return The new `NgModule`.
1526
+ *
1527
+ */
1528
+ static forRoot(routes, config) {
1529
+ return {
1530
+ ngModule: RouterModule,
1531
+ providers: [
1532
+ ROUTER_PROVIDERS,
1533
+ typeof ngDevMode === 'undefined' || ngDevMode
1534
+ ? config?.enableTracing
1535
+ ? withDebugTracing().ɵproviders
1536
+ : []
1537
+ : [],
1538
+ { provide: ROUTES, multi: true, useValue: routes },
1539
+ typeof ngDevMode === 'undefined' || ngDevMode
1540
+ ? {
1541
+ provide: ROUTER_FORROOT_GUARD,
1542
+ useFactory: provideForRootGuard,
1543
+ deps: [[Router, new Optional(), new SkipSelf()]],
1544
+ }
1545
+ : [],
1546
+ config?.errorHandler
1547
+ ? {
1548
+ provide: NAVIGATION_ERROR_HANDLER,
1549
+ useValue: config.errorHandler,
1550
+ }
1551
+ : [],
1552
+ { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} },
1553
+ config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(),
1554
+ provideRouterScroller(),
1555
+ config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [],
1556
+ config?.initialNavigation ? provideInitialNavigation(config) : [],
1557
+ config?.bindToComponentInputs ? withComponentInputBinding().ɵproviders : [],
1558
+ config?.enableViewTransitions ? withViewTransitions().ɵproviders : [],
1559
+ provideRouterInitializer(),
1560
+ ],
1561
+ };
1562
+ }
1563
+ /**
1564
+ * Creates a module with all the router directives and a provider registering routes,
1565
+ * without creating a new Router service.
1566
+ * When registering for submodules and lazy-loaded submodules, create the NgModule as follows:
1567
+ *
1568
+ * ```ts
1569
+ * @NgModule({
1570
+ * imports: [RouterModule.forChild(ROUTES)]
1571
+ * })
1572
+ * class MyNgModule {}
1573
+ * ```
1574
+ *
1575
+ * @param routes An array of `Route` objects that define the navigation paths for the submodule.
1576
+ * @return The new NgModule.
1577
+ *
1578
+ */
1579
+ static forChild(routes) {
1580
+ return {
1581
+ ngModule: RouterModule,
1582
+ providers: [{ provide: ROUTES, multi: true, useValue: routes }],
1583
+ };
1584
+ }
1585
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1586
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, _EmptyOutletComponent] });
1587
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterModule });
1588
+ }
1589
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0-next.6", ngImport: i0, type: RouterModule, decorators: [{
1590
+ type: NgModule,
1591
+ args: [{
1592
+ imports: ROUTER_DIRECTIVES,
1593
+ exports: ROUTER_DIRECTIVES,
1594
+ }]
1595
+ }], ctorParameters: () => [] });
1596
+ /**
1597
+ * For internal use by `RouterModule` only. Note that this differs from `withInMemoryRouterScroller`
1598
+ * because it reads from the `ExtraOptions` which should not be used in the standalone world.
1599
+ */
1600
+ function provideRouterScroller() {
1601
+ return {
1602
+ provide: ROUTER_SCROLLER,
1603
+ useFactory: () => {
1604
+ const viewportScroller = inject(ViewportScroller);
1605
+ const zone = inject(NgZone);
1606
+ const config = inject(ROUTER_CONFIGURATION);
1607
+ const transitions = inject(NavigationTransitions);
1608
+ const urlSerializer = inject(UrlSerializer);
1609
+ if (config.scrollOffset) {
1610
+ viewportScroller.setOffset(config.scrollOffset);
1611
+ }
1612
+ return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);
1613
+ },
1614
+ };
1615
+ }
1616
+ // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` should
1617
+ // provide hash location directly via `{provide: LocationStrategy, useClass: HashLocationStrategy}`.
1618
+ function provideHashLocationStrategy() {
1619
+ return { provide: LocationStrategy, useClass: HashLocationStrategy };
1620
+ }
1621
+ // Note: For internal use only with `RouterModule`. Standalone setup via `provideRouter` does not
1622
+ // need this at all because `PathLocationStrategy` is the default factory for `LocationStrategy`.
1623
+ function providePathLocationStrategy() {
1624
+ return { provide: LocationStrategy, useClass: PathLocationStrategy };
1625
+ }
1626
+ function provideForRootGuard(router) {
1627
+ if (router) {
1628
+ throw new _RuntimeError(4007 /* RuntimeErrorCode.FOR_ROOT_CALLED_TWICE */, `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector.` +
1629
+ ` Lazy loaded modules should use RouterModule.forChild() instead.`);
1630
+ }
1631
+ return 'guarded';
1632
+ }
1633
+ // Note: For internal use only with `RouterModule`. Standalone router setup with `provideRouter`
1634
+ // users call `withXInitialNavigation` directly.
1635
+ function provideInitialNavigation(config) {
1636
+ return [
1637
+ config.initialNavigation === 'disabled' ? withDisabledInitialNavigation().ɵproviders : [],
1638
+ config.initialNavigation === 'enabledBlocking'
1639
+ ? withEnabledBlockingInitialNavigation().ɵproviders
1640
+ : [],
1641
+ ];
1642
+ }
1643
+ // TODO(atscott): This should not be in the public API
1644
+ /**
1645
+ * A DI token for the router initializer that
1646
+ * is called after the app is bootstrapped.
1647
+ *
1648
+ * @publicApi
1649
+ */
1650
+ const ROUTER_INITIALIZER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'Router Initializer' : '');
1651
+ function provideRouterInitializer() {
1652
+ return [
1653
+ // ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
1654
+ // have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.
1655
+ { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener },
1656
+ { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER },
1657
+ ];
1658
+ }
1659
+
1660
+ export { NoPreloading, PreloadAllModules, PreloadingStrategy, ROUTER_INITIALIZER, ROUTER_PROVIDERS, RouterLink, RouterLinkActive, RouterModule, RouterPreloader, provideRouter, provideRoutes, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, withViewTransitions };
1661
+ //# sourceMappingURL=router_module-uhyNxaa0.mjs.map