@angular/router 15.0.0 → 15.0.2

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.
Files changed (40) hide show
  1. package/esm2020/src/components/empty_outlet.mjs +3 -3
  2. package/esm2020/src/deprecated_load_children.mjs +3 -1
  3. package/esm2020/src/directives/router_link.mjs +3 -3
  4. package/esm2020/src/directives/router_link_active.mjs +3 -3
  5. package/esm2020/src/directives/router_outlet.mjs +5 -5
  6. package/esm2020/src/index.mjs +1 -1
  7. package/esm2020/src/models.mjs +1 -1
  8. package/esm2020/src/navigation_transition.mjs +380 -0
  9. package/esm2020/src/operators/activate_routes.mjs +1 -1
  10. package/esm2020/src/operators/apply_redirects.mjs +1 -1
  11. package/esm2020/src/operators/check_guards.mjs +1 -1
  12. package/esm2020/src/operators/recognize.mjs +1 -1
  13. package/esm2020/src/operators/resolve_data.mjs +1 -1
  14. package/esm2020/src/page_title_strategy.mjs +6 -6
  15. package/esm2020/src/private_export.mjs +1 -1
  16. package/esm2020/src/provide_router.mjs +11 -15
  17. package/esm2020/src/route_reuse_strategy.mjs +15 -1
  18. package/esm2020/src/router.mjs +76 -407
  19. package/esm2020/src/router_config_loader.mjs +3 -3
  20. package/esm2020/src/router_module.mjs +9 -7
  21. package/esm2020/src/router_outlet_context.mjs +3 -3
  22. package/esm2020/src/router_preloader.mjs +9 -9
  23. package/esm2020/src/router_scroller.mjs +20 -21
  24. package/esm2020/src/router_state.mjs +1 -1
  25. package/esm2020/src/url_handling_strategy.mjs +15 -1
  26. package/esm2020/src/url_tree.mjs +4 -4
  27. package/esm2020/src/version.mjs +1 -1
  28. package/esm2020/testing/src/router_testing_module.mjs +4 -4
  29. package/fesm2015/router.mjs +790 -732
  30. package/fesm2015/router.mjs.map +1 -1
  31. package/fesm2015/testing.mjs +5 -5
  32. package/fesm2015/upgrade.mjs +1 -1
  33. package/fesm2020/router.mjs +794 -735
  34. package/fesm2020/router.mjs.map +1 -1
  35. package/fesm2020/testing.mjs +5 -5
  36. package/fesm2020/upgrade.mjs +1 -1
  37. package/index.d.ts +24 -80
  38. package/package.json +4 -4
  39. package/testing/index.d.ts +1 -1
  40. package/upgrade/index.d.ts +1 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v15.0.0
2
+ * @license Angular v15.0.2
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import * as i0 from '@angular/core';
8
- import { ɵisObservable, ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, ɵisInjectable, InjectionToken, InjectFlags, NgModuleFactory, Injector, Compiler, NgModuleRef, ɵConsole, NgZone, ɵcoerceToBoolean, ɵɵsanitizeUrlOrResourceUrl, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
8
+ import { ɵisObservable, ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, Component, createEnvironmentInjector, ɵisStandalone, ComponentFactoryResolver, ɵisInjectable, InjectionToken, InjectFlags, NgModuleFactory, Injector, Compiler, ɵConsole, NgZone, ɵcoerceToBoolean, ɵɵsanitizeUrlOrResourceUrl, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
9
9
  import { from, of, BehaviorSubject, EmptyError, combineLatest, concat, defer, pipe, throwError, Observable, EMPTY, ConnectableObservable, Subject } from 'rxjs';
10
10
  import * as i3 from '@angular/common';
11
11
  import { Location, ViewportScroller, LOCATION_INITIALIZED, LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
@@ -202,7 +202,7 @@ function wrapIntoObservable(value) {
202
202
  * Use of this source code is governed by an MIT-style license that can be
203
203
  * found in the LICENSE file at https://angular.io/license
204
204
  */
205
- const NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode;
205
+ const NG_DEV_MODE$a = typeof ngDevMode === 'undefined' || ngDevMode;
206
206
  const pathCompareMap = {
207
207
  'exact': equalSegmentGroups,
208
208
  'subset': containsSegmentGroup,
@@ -327,7 +327,7 @@ class UrlTree {
327
327
  this.root = root;
328
328
  this.queryParams = queryParams;
329
329
  this.fragment = fragment;
330
- if (NG_DEV_MODE$9) {
330
+ if (NG_DEV_MODE$a) {
331
331
  if (root.segments.length > 0) {
332
332
  throw new ɵRuntimeError(4015 /* RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT */, 'The root `UrlSegmentGroup` should not contain `segments`. ' +
333
333
  'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
@@ -461,9 +461,9 @@ function mapChildrenIntoArray(segment, fn) {
461
461
  */
462
462
  class UrlSerializer {
463
463
  }
464
- UrlSerializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
465
- UrlSerializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() });
466
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UrlSerializer, decorators: [{
464
+ UrlSerializer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
465
+ UrlSerializer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() });
466
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlSerializer, decorators: [{
467
467
  type: Injectable,
468
468
  args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
469
469
  }] });
@@ -675,7 +675,7 @@ class UrlParser {
675
675
  parseSegment() {
676
676
  const path = matchSegments(this.remaining);
677
677
  if (path === '' && this.peekStartsWith(';')) {
678
- throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */, NG_DEV_MODE$9 && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
678
+ throw new ɵRuntimeError(4009 /* RuntimeErrorCode.EMPTY_PATH_WITH_PARAMS */, NG_DEV_MODE$a && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
679
679
  }
680
680
  this.capture(path);
681
681
  return new UrlSegment(decode(path), this.parseMatrixParams());
@@ -744,7 +744,7 @@ class UrlParser {
744
744
  // if is is not one of these characters, then the segment was unescaped
745
745
  // or the group was not closed
746
746
  if (next !== '/' && next !== ')' && next !== ';') {
747
- throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */, NG_DEV_MODE$9 && `Cannot parse url '${this.url}'`);
747
+ throw new ɵRuntimeError(4010 /* RuntimeErrorCode.UNPARSABLE_URL */, NG_DEV_MODE$a && `Cannot parse url '${this.url}'`);
748
748
  }
749
749
  let outletName = undefined;
750
750
  if (path.indexOf(':') > -1) {
@@ -775,7 +775,7 @@ class UrlParser {
775
775
  }
776
776
  capture(str) {
777
777
  if (!this.consumeOptional(str)) {
778
- throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */, NG_DEV_MODE$9 && `Expected "${str}".`);
778
+ throw new ɵRuntimeError(4011 /* RuntimeErrorCode.UNEXPECTED_VALUE_IN_URL */, NG_DEV_MODE$a && `Expected "${str}".`);
779
779
  }
780
780
  }
781
781
  }
@@ -828,7 +828,7 @@ function isUrlTree(v) {
828
828
  * Use of this source code is governed by an MIT-style license that can be
829
829
  * found in the LICENSE file at https://angular.io/license
830
830
  */
831
- const NG_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode;
831
+ const NG_DEV_MODE$9 = typeof ngDevMode === 'undefined' || ngDevMode;
832
832
  /**
833
833
  * Creates a `UrlTree` relative to an `ActivatedRouteSnapshot`.
834
834
  *
@@ -997,11 +997,11 @@ class Navigation {
997
997
  this.numberOfDoubleDots = numberOfDoubleDots;
998
998
  this.commands = commands;
999
999
  if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
1000
- throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */, NG_DEV_MODE$8 && 'Root segment cannot have matrix parameters');
1000
+ throw new ɵRuntimeError(4003 /* RuntimeErrorCode.ROOT_SEGMENT_MATRIX_PARAMS */, NG_DEV_MODE$9 && 'Root segment cannot have matrix parameters');
1001
1001
  }
1002
1002
  const cmdWithOutlet = commands.find(isCommandWithOutlets);
1003
1003
  if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
1004
- throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */, NG_DEV_MODE$8 && '{outlets:{}} has to be the last command');
1004
+ throw new ɵRuntimeError(4004 /* RuntimeErrorCode.MISPLACED_OUTLETS_COMMAND */, NG_DEV_MODE$9 && '{outlets:{}} has to be the last command');
1005
1005
  }
1006
1006
  }
1007
1007
  toRoot() {
@@ -1100,7 +1100,7 @@ function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
1100
1100
  dd -= ci;
1101
1101
  g = g.parent;
1102
1102
  if (!g) {
1103
- throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */, NG_DEV_MODE$8 && 'Invalid number of \'../\'');
1103
+ throw new ɵRuntimeError(4005 /* RuntimeErrorCode.INVALID_DOUBLE_DOTS */, NG_DEV_MODE$9 && 'Invalid number of \'../\'');
1104
1104
  }
1105
1105
  ci = g.segments.length;
1106
1106
  }
@@ -2380,9 +2380,9 @@ class ChildrenOutletContexts {
2380
2380
  return this.contexts.get(childName) || null;
2381
2381
  }
2382
2382
  }
2383
- ChildrenOutletContexts.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2384
- ChildrenOutletContexts.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' });
2385
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
2383
+ ChildrenOutletContexts.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2384
+ ChildrenOutletContexts.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' });
2385
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
2386
2386
  type: Injectable,
2387
2387
  args: [{ providedIn: 'root' }]
2388
2388
  }] });
@@ -2394,7 +2394,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
2394
2394
  * Use of this source code is governed by an MIT-style license that can be
2395
2395
  * found in the LICENSE file at https://angular.io/license
2396
2396
  */
2397
- const NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode;
2397
+ const NG_DEV_MODE$8 = typeof ngDevMode === 'undefined' || ngDevMode;
2398
2398
  /**
2399
2399
  * @description
2400
2400
  *
@@ -2533,12 +2533,12 @@ class RouterOutlet {
2533
2533
  */
2534
2534
  get component() {
2535
2535
  if (!this.activated)
2536
- throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$7 && 'Outlet is not activated');
2536
+ throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
2537
2537
  return this.activated.instance;
2538
2538
  }
2539
2539
  get activatedRoute() {
2540
2540
  if (!this.activated)
2541
- throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$7 && 'Outlet is not activated');
2541
+ throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
2542
2542
  return this._activatedRoute;
2543
2543
  }
2544
2544
  get activatedRouteData() {
@@ -2552,7 +2552,7 @@ class RouterOutlet {
2552
2552
  */
2553
2553
  detach() {
2554
2554
  if (!this.activated)
2555
- throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$7 && 'Outlet is not activated');
2555
+ throw new ɵRuntimeError(4012 /* RuntimeErrorCode.OUTLET_NOT_ACTIVATED */, NG_DEV_MODE$8 && 'Outlet is not activated');
2556
2556
  this.location.detach();
2557
2557
  const cmp = this.activated;
2558
2558
  this.activated = null;
@@ -2580,11 +2580,11 @@ class RouterOutlet {
2580
2580
  }
2581
2581
  activateWith(activatedRoute, resolverOrInjector) {
2582
2582
  if (this.isActivated) {
2583
- throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */, NG_DEV_MODE$7 && 'Cannot activate an already activated outlet');
2583
+ throw new ɵRuntimeError(4013 /* RuntimeErrorCode.OUTLET_ALREADY_ACTIVATED */, NG_DEV_MODE$8 && 'Cannot activate an already activated outlet');
2584
2584
  }
2585
2585
  this._activatedRoute = activatedRoute;
2586
2586
  const location = this.location;
2587
- const snapshot = activatedRoute._futureSnapshot;
2587
+ const snapshot = activatedRoute.snapshot;
2588
2588
  const component = snapshot.component;
2589
2589
  const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
2590
2590
  const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
@@ -2602,9 +2602,9 @@ class RouterOutlet {
2602
2602
  this.activateEvents.emit(this.activated.instance);
2603
2603
  }
2604
2604
  }
2605
- RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2606
- RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 });
2607
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterOutlet, decorators: [{
2605
+ RouterOutlet.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2606
+ RouterOutlet.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", type: RouterOutlet, isStandalone: true, selector: "router-outlet", inputs: { name: "name" }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], usesOnChanges: true, ngImport: i0 });
2607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterOutlet, decorators: [{
2608
2608
  type: Directive,
2609
2609
  args: [{
2610
2610
  selector: 'router-outlet',
@@ -2664,9 +2664,9 @@ function isComponentFactoryResolver(item) {
2664
2664
  */
2665
2665
  class ɵEmptyOutletComponent {
2666
2666
  }
2667
- ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2668
- ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
2669
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2667
+ ɵEmptyOutletComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2668
+ ɵEmptyOutletComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: ɵEmptyOutletComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `<router-outlet></router-outlet>`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
2669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2670
2670
  type: Component,
2671
2671
  args: [{
2672
2672
  template: `<router-outlet></router-outlet>`,
@@ -3578,7 +3578,7 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
3578
3578
  * Use of this source code is governed by an MIT-style license that can be
3579
3579
  * found in the LICENSE file at https://angular.io/license
3580
3580
  */
3581
- const NG_DEV_MODE$6 = typeof ngDevMode === 'undefined' || ngDevMode;
3581
+ const NG_DEV_MODE$7 = typeof ngDevMode === 'undefined' || ngDevMode;
3582
3582
  class NoMatch$1 {
3583
3583
  constructor(segmentGroup) {
3584
3584
  this.segmentGroup = segmentGroup || null;
@@ -3596,11 +3596,11 @@ function absoluteRedirect(newTree) {
3596
3596
  return throwError(new AbsoluteRedirect(newTree));
3597
3597
  }
3598
3598
  function namedOutletsRedirect(redirectTo) {
3599
- return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, NG_DEV_MODE$6 &&
3599
+ return throwError(new ɵRuntimeError(4000 /* RuntimeErrorCode.NAMED_OUTLET_REDIRECT */, NG_DEV_MODE$7 &&
3600
3600
  `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
3601
3601
  }
3602
3602
  function canLoadFails(route) {
3603
- return throwError(navigationCancelingError(NG_DEV_MODE$6 &&
3603
+ return throwError(navigationCancelingError(NG_DEV_MODE$7 &&
3604
3604
  `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, 3 /* NavigationCancellationCode.GuardRejected */));
3605
3605
  }
3606
3606
  /**
@@ -3660,7 +3660,7 @@ class ApplyRedirects {
3660
3660
  }));
3661
3661
  }
3662
3662
  noMatchError(e) {
3663
- return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, NG_DEV_MODE$6 && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
3663
+ return new ɵRuntimeError(4002 /* RuntimeErrorCode.NO_MATCH */, NG_DEV_MODE$7 && `Cannot match any routes. URL Segment: '${e.segmentGroup}'`);
3664
3664
  }
3665
3665
  createUrlTree(rootCandidate, queryParams, fragment) {
3666
3666
  const root = createRoot(rootCandidate);
@@ -3875,7 +3875,7 @@ class ApplyRedirects {
3875
3875
  findPosParam(redirectTo, redirectToUrlSegment, posParams) {
3876
3876
  const pos = posParams[redirectToUrlSegment.path.substring(1)];
3877
3877
  if (!pos)
3878
- throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, NG_DEV_MODE$6 &&
3878
+ throw new ɵRuntimeError(4001 /* RuntimeErrorCode.MISSING_REDIRECT */, NG_DEV_MODE$7 &&
3879
3879
  `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
3880
3880
  return pos;
3881
3881
  }
@@ -3911,7 +3911,7 @@ function applyRedirects(environmentInjector, configLoader, urlSerializer, config
3911
3911
  * Use of this source code is governed by an MIT-style license that can be
3912
3912
  * found in the LICENSE file at https://angular.io/license
3913
3913
  */
3914
- const NG_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3914
+ const NG_DEV_MODE$6 = typeof ngDevMode === 'undefined' || !!ngDevMode;
3915
3915
  class NoMatch {
3916
3916
  }
3917
3917
  function newObservableError(e) {
@@ -3999,7 +3999,7 @@ class Recognizer {
3999
3999
  // multiple activated results for the same outlet. We should merge the children of
4000
4000
  // these results so the final return value is only one `TreeNode` per outlet.
4001
4001
  const mergedChildren = mergeEmptyPathMatches(children);
4002
- if (NG_DEV_MODE$5) {
4002
+ if (NG_DEV_MODE$6) {
4003
4003
  // This should really never happen - we are only taking the first match for each
4004
4004
  // outlet and merge the empty path matches.
4005
4005
  checkOutletNameUniqueness(mergedChildren);
@@ -4154,7 +4154,7 @@ function checkOutletNameUniqueness(nodes) {
4154
4154
  if (routeWithSameOutletName) {
4155
4155
  const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
4156
4156
  const c = n.value.url.map(s => s.toString()).join('/');
4157
- throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, NG_DEV_MODE$5 && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
4157
+ throw new ɵRuntimeError(4006 /* RuntimeErrorCode.TWO_SEGMENTS_WITH_SAME_OUTLET */, NG_DEV_MODE$6 && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
4158
4158
  }
4159
4159
  names[n.value.outlet] = n.value;
4160
4160
  });
@@ -4292,173 +4292,8 @@ function switchTap(next) {
4292
4292
  * Use of this source code is governed by an MIT-style license that can be
4293
4293
  * found in the LICENSE file at https://angular.io/license
4294
4294
  */
4295
- /**
4296
- * Provides a strategy for setting the page title after a router navigation.
4297
- *
4298
- * The built-in implementation traverses the router state snapshot and finds the deepest primary
4299
- * outlet with `title` property. Given the `Routes` below, navigating to
4300
- * `/base/child(popup:aux)` would result in the document title being set to "child".
4301
- * ```
4302
- * [
4303
- * {path: 'base', title: 'base', children: [
4304
- * {path: 'child', title: 'child'},
4305
- * ],
4306
- * {path: 'aux', outlet: 'popup', title: 'popupTitle'}
4307
- * ]
4308
- * ```
4309
- *
4310
- * This class can be used as a base class for custom title strategies. That is, you can create your
4311
- * own class that extends the `TitleStrategy`. Note that in the above example, the `title`
4312
- * from the named outlet is never used. However, a custom strategy might be implemented to
4313
- * incorporate titles in named outlets.
4314
- *
4315
- * @publicApi
4316
- * @see [Page title guide](guide/router#setting-the-page-title)
4317
- */
4318
- class TitleStrategy {
4319
- /**
4320
- * @returns The `title` of the deepest primary route.
4321
- */
4322
- buildTitle(snapshot) {
4323
- let pageTitle;
4324
- let route = snapshot.root;
4325
- while (route !== undefined) {
4326
- pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
4327
- route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
4328
- }
4329
- return pageTitle;
4330
- }
4331
- /**
4332
- * Given an `ActivatedRouteSnapshot`, returns the final value of the
4333
- * `Route.title` property, which can either be a static string or a resolved value.
4334
- */
4335
- getResolvedTitleForRoute(snapshot) {
4336
- return snapshot.data[RouteTitleKey];
4337
- }
4338
- }
4339
- TitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4340
- TitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) });
4341
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: TitleStrategy, decorators: [{
4342
- type: Injectable,
4343
- args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4344
- }] });
4345
- /**
4346
- * The default `TitleStrategy` used by the router that updates the title using the `Title` service.
4347
- */
4348
- class DefaultTitleStrategy extends TitleStrategy {
4349
- constructor(title) {
4350
- super();
4351
- this.title = title;
4352
- }
4353
- /**
4354
- * Sets the title of the browser to the given value.
4355
- *
4356
- * @param title The `pageTitle` from the deepest primary route.
4357
- */
4358
- updateTitle(snapshot) {
4359
- const title = this.buildTitle(snapshot);
4360
- if (title !== undefined) {
4361
- this.title.setTitle(title);
4362
- }
4363
- }
4364
- }
4365
- DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
4366
- DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
4367
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4368
- type: Injectable,
4369
- args: [{ providedIn: 'root' }]
4370
- }], ctorParameters: function () { return [{ type: i1.Title }]; } });
4371
-
4372
- /**
4373
- * @license
4374
- * Copyright Google LLC All Rights Reserved.
4375
- *
4376
- * Use of this source code is governed by an MIT-style license that can be
4377
- * found in the LICENSE file at https://angular.io/license
4378
- */
4379
- /**
4380
- * @description
4381
- *
4382
- * Provides a way to customize when activated routes get reused.
4383
- *
4384
- * @publicApi
4385
- */
4386
- class RouteReuseStrategy {
4387
- }
4388
- /**
4389
- * @description
4390
- *
4391
- * This base route reuse strategy only reuses routes when the matched router configs are
4392
- * identical. This prevents components from being destroyed and recreated
4393
- * when just the route parameters, query parameters or fragment change
4394
- * (that is, the existing component is _reused_).
4395
- *
4396
- * This strategy does not store any routes for later reuse.
4397
- *
4398
- * Angular uses this strategy by default.
4399
- *
4400
- *
4401
- * It can be used as a base class for custom route reuse strategies, i.e. you can create your own
4402
- * class that extends the `BaseRouteReuseStrategy` one.
4403
- * @publicApi
4404
- */
4405
- class BaseRouteReuseStrategy {
4406
- /**
4407
- * Whether the given route should detach for later reuse.
4408
- * Always returns false for `BaseRouteReuseStrategy`.
4409
- * */
4410
- shouldDetach(route) {
4411
- return false;
4412
- }
4413
- /**
4414
- * A no-op; the route is never stored since this strategy never detaches routes for later re-use.
4415
- */
4416
- store(route, detachedTree) { }
4417
- /** Returns `false`, meaning the route (and its subtree) is never reattached */
4418
- shouldAttach(route) {
4419
- return false;
4420
- }
4421
- /** Returns `null` because this strategy does not store routes for later re-use. */
4422
- retrieve(route) {
4423
- return null;
4424
- }
4425
- /**
4426
- * Determines if a route should be reused.
4427
- * This strategy returns `true` when the future route config and current route config are
4428
- * identical.
4429
- */
4430
- shouldReuseRoute(future, curr) {
4431
- return future.routeConfig === curr.routeConfig;
4432
- }
4433
- }
4434
- class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4435
- }
4436
-
4437
- /**
4438
- * @license
4439
- * Copyright Google LLC All Rights Reserved.
4440
- *
4441
- * Use of this source code is governed by an MIT-style license that can be
4442
- * found in the LICENSE file at https://angular.io/license
4443
- */
4444
- const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4445
- /**
4446
- * A [DI token](guide/glossary/#di-token) for the router service.
4447
- *
4448
- * @publicApi
4449
- */
4450
- const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE$4 ? 'router config' : '', {
4451
- providedIn: 'root',
4452
- factory: () => ({}),
4453
- });
4454
-
4455
- /**
4456
- * @license
4457
- * Copyright Google LLC All Rights Reserved.
4458
- *
4459
- * Use of this source code is governed by an MIT-style license that can be
4460
- * found in the LICENSE file at https://angular.io/license
4461
- */
4295
+ // This file exists to support the legacy `loadChildren: string` behavior being patched back into
4296
+ // Angular.
4462
4297
  function deprecatedLoadChildrenString(injector, loadChildren) {
4463
4298
  return null;
4464
4299
  }
@@ -4470,7 +4305,7 @@ function deprecatedLoadChildrenString(injector, loadChildren) {
4470
4305
  * Use of this source code is governed by an MIT-style license that can be
4471
4306
  * found in the LICENSE file at https://angular.io/license
4472
4307
  */
4473
- const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4308
+ const NG_DEV_MODE$5 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4474
4309
  /**
4475
4310
  * The [DI token](guide/glossary/#di-token) for a router configuration.
4476
4311
  *
@@ -4504,7 +4339,7 @@ class RouterConfigLoader {
4504
4339
  if (this.onLoadEndListener) {
4505
4340
  this.onLoadEndListener(route);
4506
4341
  }
4507
- NG_DEV_MODE$3 && assertStandalone(route.path ?? '', component);
4342
+ NG_DEV_MODE$5 && assertStandalone(route.path ?? '', component);
4508
4343
  route._loadedComponent = component;
4509
4344
  }), finalize(() => {
4510
4345
  this.componentLoaders.delete(route);
@@ -4547,7 +4382,7 @@ class RouterConfigLoader {
4547
4382
  rawRoutes = flatten(injector.get(ROUTES, [], InjectFlags.Self | InjectFlags.Optional));
4548
4383
  }
4549
4384
  const routes = rawRoutes.map(standardizeConfig);
4550
- NG_DEV_MODE$3 && validateConfig(routes, route.path, requireStandaloneComponents);
4385
+ NG_DEV_MODE$5 && validateConfig(routes, route.path, requireStandaloneComponents);
4551
4386
  return { routes, injector };
4552
4387
  }), finalize(() => {
4553
4388
  this.childrenLoaders.delete(route);
@@ -4574,9 +4409,9 @@ class RouterConfigLoader {
4574
4409
  }));
4575
4410
  }
4576
4411
  }
4577
- RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4578
- RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' });
4579
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterConfigLoader, decorators: [{
4412
+ RouterConfigLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, deps: [{ token: i0.Injector }, { token: i0.Compiler }], target: i0.ɵɵFactoryTarget.Injectable });
4413
+ RouterConfigLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' });
4414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
4580
4415
  type: Injectable,
4581
4416
  args: [{ providedIn: 'root' }]
4582
4417
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.Compiler }]; } });
@@ -4599,104 +4434,646 @@ function maybeUnwrapDefaultExport(input) {
4599
4434
  * Use of this source code is governed by an MIT-style license that can be
4600
4435
  * found in the LICENSE file at https://angular.io/license
4601
4436
  */
4602
- /**
4603
- * @description
4604
- *
4605
- * Provides a way to migrate AngularJS applications to Angular.
4606
- *
4607
- * @publicApi
4608
- */
4609
- class UrlHandlingStrategy {
4610
- }
4611
- /**
4612
- * @publicApi
4613
- */
4614
- class DefaultUrlHandlingStrategy {
4615
- shouldProcessUrl(url) {
4616
- return true;
4617
- }
4618
- extract(url) {
4619
- return url;
4620
- }
4621
- merge(newUrlPart, wholeUrl) {
4622
- return newUrlPart;
4623
- }
4624
- }
4625
-
4626
- /**
4627
- * @license
4628
- * Copyright Google LLC All Rights Reserved.
4629
- *
4630
- * Use of this source code is governed by an MIT-style license that can be
4631
- * found in the LICENSE file at https://angular.io/license
4632
- */
4633
- const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4634
- function defaultErrorHandler(error) {
4635
- throw error;
4636
- }
4637
- function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
4638
- return urlSerializer.parse('/');
4639
- }
4640
- /**
4641
- * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
4642
- * (exact = true).
4643
- */
4644
- const exactMatchOptions = {
4645
- paths: 'exact',
4646
- fragment: 'ignored',
4647
- matrixParams: 'ignored',
4648
- queryParams: 'exact'
4649
- };
4650
- /**
4651
- * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
4652
- * (exact = false).
4653
- */
4654
- const subsetMatchOptions = {
4655
- paths: 'subset',
4656
- fragment: 'ignored',
4657
- matrixParams: 'ignored',
4658
- queryParams: 'subset'
4659
- };
4660
- function assignExtraOptionsToRouter(opts, router) {
4661
- if (opts.errorHandler) {
4662
- router.errorHandler = opts.errorHandler;
4663
- }
4664
- if (opts.malformedUriErrorHandler) {
4665
- router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
4666
- }
4667
- if (opts.onSameUrlNavigation) {
4668
- router.onSameUrlNavigation = opts.onSameUrlNavigation;
4437
+ const NG_DEV_MODE$4 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4438
+ class NavigationTransitions {
4439
+ constructor() {
4440
+ this.currentNavigation = null;
4441
+ this.lastSuccessfulNavigation = null;
4442
+ this.events = new Subject();
4443
+ this.configLoader = inject(RouterConfigLoader);
4444
+ this.environmentInjector = inject(EnvironmentInjector);
4445
+ this.urlSerializer = inject(UrlSerializer);
4446
+ this.rootContexts = inject(ChildrenOutletContexts);
4447
+ this.navigationId = 0;
4448
+ const onLoadStart = (r) => this.events.next(new RouteConfigLoadStart(r));
4449
+ const onLoadEnd = (r) => this.events.next(new RouteConfigLoadEnd(r));
4450
+ this.configLoader.onLoadEndListener = onLoadEnd;
4451
+ this.configLoader.onLoadStartListener = onLoadStart;
4669
4452
  }
4670
- if (opts.paramsInheritanceStrategy) {
4671
- router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
4453
+ get hasRequestedNavigation() {
4454
+ return this.navigationId !== 0;
4672
4455
  }
4673
- if (opts.urlUpdateStrategy) {
4674
- router.urlUpdateStrategy = opts.urlUpdateStrategy;
4456
+ complete() {
4457
+ this.transitions?.complete();
4675
4458
  }
4676
- if (opts.canceledNavigationResolution) {
4677
- router.canceledNavigationResolution = opts.canceledNavigationResolution;
4459
+ handleNavigationRequest(request) {
4460
+ const id = ++this.navigationId;
4461
+ this.transitions?.next({ ...this.transitions.value, ...request, id });
4678
4462
  }
4679
- }
4680
- function setupRouter() {
4681
- const urlSerializer = inject(UrlSerializer);
4682
- const contexts = inject(ChildrenOutletContexts);
4463
+ setupNavigations(router) {
4464
+ this.transitions = new BehaviorSubject({
4465
+ id: 0,
4466
+ targetPageId: 0,
4467
+ currentUrlTree: router.currentUrlTree,
4468
+ currentRawUrl: router.currentUrlTree,
4469
+ extractedUrl: router.urlHandlingStrategy.extract(router.currentUrlTree),
4470
+ urlAfterRedirects: router.urlHandlingStrategy.extract(router.currentUrlTree),
4471
+ rawUrl: router.currentUrlTree,
4472
+ extras: {},
4473
+ resolve: null,
4474
+ reject: null,
4475
+ promise: Promise.resolve(true),
4476
+ source: 'imperative',
4477
+ restoredState: null,
4478
+ currentSnapshot: router.routerState.snapshot,
4479
+ targetSnapshot: null,
4480
+ currentRouterState: router.routerState,
4481
+ targetRouterState: null,
4482
+ guards: { canActivateChecks: [], canDeactivateChecks: [] },
4483
+ guardsResult: null,
4484
+ });
4485
+ return this.transitions.pipe(filter(t => t.id !== 0),
4486
+ // Extract URL
4487
+ map(t => ({ ...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl) })),
4488
+ // Using switchMap so we cancel executing navigations when a new one comes in
4489
+ switchMap(overallTransitionState => {
4490
+ let completed = false;
4491
+ let errored = false;
4492
+ return of(overallTransitionState)
4493
+ .pipe(
4494
+ // Store the Navigation object
4495
+ tap(t => {
4496
+ this.currentNavigation = {
4497
+ id: t.id,
4498
+ initialUrl: t.rawUrl,
4499
+ extractedUrl: t.extractedUrl,
4500
+ trigger: t.source,
4501
+ extras: t.extras,
4502
+ previousNavigation: !this.lastSuccessfulNavigation ? null : {
4503
+ ...this.lastSuccessfulNavigation,
4504
+ previousNavigation: null,
4505
+ },
4506
+ };
4507
+ }), switchMap(t => {
4508
+ const browserUrlTree = router.browserUrlTree.toString();
4509
+ const urlTransition = !router.navigated ||
4510
+ t.extractedUrl.toString() !== browserUrlTree ||
4511
+ // Navigations which succeed or ones which fail and are cleaned up
4512
+ // correctly should result in `browserUrlTree` and `currentUrlTree`
4513
+ // matching. If this is not the case, assume something went wrong and
4514
+ // try processing the URL again.
4515
+ browserUrlTree !== router.currentUrlTree.toString();
4516
+ const processCurrentUrl = (router.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
4517
+ router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
4518
+ if (processCurrentUrl) {
4519
+ // If the source of the navigation is from a browser event, the URL is
4520
+ // already updated. We already need to sync the internal state.
4521
+ if (isBrowserTriggeredNavigation(t.source)) {
4522
+ router.browserUrlTree = t.extractedUrl;
4523
+ }
4524
+ return of(t).pipe(
4525
+ // Fire NavigationStart event
4526
+ switchMap(t => {
4527
+ const transition = this.transitions?.getValue();
4528
+ this.events.next(new NavigationStart(t.id, this.urlSerializer.serialize(t.extractedUrl), t.source, t.restoredState));
4529
+ if (transition !== this.transitions?.getValue()) {
4530
+ return EMPTY;
4531
+ }
4532
+ // This delay is required to match old behavior that forced
4533
+ // navigation to always be async
4534
+ return Promise.resolve(t);
4535
+ }),
4536
+ // ApplyRedirects
4537
+ applyRedirects(this.environmentInjector, this.configLoader, this.urlSerializer, router.config),
4538
+ // Update the currentNavigation
4539
+ // `urlAfterRedirects` is guaranteed to be set after this point
4540
+ tap(t => {
4541
+ this.currentNavigation = {
4542
+ ...this.currentNavigation,
4543
+ finalUrl: t.urlAfterRedirects
4544
+ };
4545
+ overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
4546
+ }),
4547
+ // Recognize
4548
+ recognize(this.environmentInjector, router.rootComponentType, router.config, this.urlSerializer, router.paramsInheritanceStrategy),
4549
+ // Update URL if in `eager` update mode
4550
+ tap(t => {
4551
+ overallTransitionState.targetSnapshot = t.targetSnapshot;
4552
+ if (router.urlUpdateStrategy === 'eager') {
4553
+ if (!t.extras.skipLocationChange) {
4554
+ const rawUrl = router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
4555
+ router.setBrowserUrl(rawUrl, t);
4556
+ }
4557
+ router.browserUrlTree = t.urlAfterRedirects;
4558
+ }
4559
+ // Fire RoutesRecognized
4560
+ const routesRecognized = new RoutesRecognized(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4561
+ this.events.next(routesRecognized);
4562
+ }));
4563
+ }
4564
+ else {
4565
+ const processPreviousUrl = urlTransition && router.rawUrlTree &&
4566
+ router.urlHandlingStrategy.shouldProcessUrl(router.rawUrlTree);
4567
+ /* When the current URL shouldn't be processed, but the previous one
4568
+ * was, we handle this "error condition" by navigating to the
4569
+ * previously successful URL, but leaving the URL intact.*/
4570
+ if (processPreviousUrl) {
4571
+ const { id, extractedUrl, source, restoredState, extras } = t;
4572
+ const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
4573
+ this.events.next(navStart);
4574
+ const targetSnapshot = createEmptyState(extractedUrl, router.rootComponentType)
4575
+ .snapshot;
4576
+ overallTransitionState = {
4577
+ ...t,
4578
+ targetSnapshot,
4579
+ urlAfterRedirects: extractedUrl,
4580
+ extras: { ...extras, skipLocationChange: false, replaceUrl: false },
4581
+ };
4582
+ return of(overallTransitionState);
4583
+ }
4584
+ else {
4585
+ /* When neither the current or previous URL can be processed, do
4586
+ * nothing other than update router's internal reference to the
4587
+ * current "settled" URL. This way the next navigation will be coming
4588
+ * from the current URL in the browser.
4589
+ */
4590
+ router.rawUrlTree = t.rawUrl;
4591
+ t.resolve(null);
4592
+ return EMPTY;
4593
+ }
4594
+ }
4595
+ }),
4596
+ // --- GUARDS ---
4597
+ tap(t => {
4598
+ const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4599
+ this.events.next(guardsStart);
4600
+ }), map(t => {
4601
+ overallTransitionState = {
4602
+ ...t,
4603
+ guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
4604
+ };
4605
+ return overallTransitionState;
4606
+ }), checkGuards(this.environmentInjector, (evt) => this.events.next(evt)), tap(t => {
4607
+ overallTransitionState.guardsResult = t.guardsResult;
4608
+ if (isUrlTree(t.guardsResult)) {
4609
+ throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
4610
+ }
4611
+ const guardsEnd = new GuardsCheckEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
4612
+ this.events.next(guardsEnd);
4613
+ }), filter(t => {
4614
+ if (!t.guardsResult) {
4615
+ router.restoreHistory(t);
4616
+ this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */, router);
4617
+ return false;
4618
+ }
4619
+ return true;
4620
+ }),
4621
+ // --- RESOLVE ---
4622
+ switchTap(t => {
4623
+ if (t.guards.canActivateChecks.length) {
4624
+ return of(t).pipe(tap(t => {
4625
+ const resolveStart = new ResolveStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4626
+ this.events.next(resolveStart);
4627
+ }), switchMap(t => {
4628
+ let dataResolved = false;
4629
+ return of(t).pipe(resolveData(router.paramsInheritanceStrategy, this.environmentInjector), tap({
4630
+ next: () => dataResolved = true,
4631
+ complete: () => {
4632
+ if (!dataResolved) {
4633
+ router.restoreHistory(t);
4634
+ this.cancelNavigationTransition(t, NG_DEV_MODE$4 ?
4635
+ `At least one route resolver didn't emit any value.` :
4636
+ '', 2 /* NavigationCancellationCode.NoDataFromResolver */, router);
4637
+ }
4638
+ }
4639
+ }));
4640
+ }), tap(t => {
4641
+ const resolveEnd = new ResolveEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
4642
+ this.events.next(resolveEnd);
4643
+ }));
4644
+ }
4645
+ return undefined;
4646
+ }),
4647
+ // --- LOAD COMPONENTS ---
4648
+ switchTap((t) => {
4649
+ const loadComponents = (route) => {
4650
+ const loaders = [];
4651
+ if (route.routeConfig?.loadComponent &&
4652
+ !route.routeConfig._loadedComponent) {
4653
+ loaders.push(this.configLoader.loadComponent(route.routeConfig)
4654
+ .pipe(tap(loadedComponent => {
4655
+ route.component = loadedComponent;
4656
+ }), map(() => void 0)));
4657
+ }
4658
+ for (const child of route.children) {
4659
+ loaders.push(...loadComponents(child));
4660
+ }
4661
+ return loaders;
4662
+ };
4663
+ return combineLatest(loadComponents(t.targetSnapshot.root))
4664
+ .pipe(defaultIfEmpty(), take(1));
4665
+ }), switchTap(() => router.afterPreactivation()), map((t) => {
4666
+ const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4667
+ overallTransitionState = { ...t, targetRouterState };
4668
+ return (overallTransitionState);
4669
+ }),
4670
+ /* Once here, we are about to activate synchronously. The assumption is
4671
+ this will succeed, and user code may read from the Router service.
4672
+ Therefore before activation, we need to update router properties storing
4673
+ the current URL and the RouterState, as well as updated the browser URL.
4674
+ All this should happen *before* activating. */
4675
+ tap((t) => {
4676
+ router.currentUrlTree = t.urlAfterRedirects;
4677
+ router.rawUrlTree =
4678
+ router.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
4679
+ router.routerState =
4680
+ t.targetRouterState;
4681
+ if (router.urlUpdateStrategy === 'deferred') {
4682
+ if (!t.extras.skipLocationChange) {
4683
+ router.setBrowserUrl(router.rawUrlTree, t);
4684
+ }
4685
+ router.browserUrlTree = t.urlAfterRedirects;
4686
+ }
4687
+ }), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt)), tap({
4688
+ next: (t) => {
4689
+ completed = true;
4690
+ this.lastSuccessfulNavigation = this.currentNavigation;
4691
+ router.navigated = true;
4692
+ this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(router.currentUrlTree)));
4693
+ router.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
4694
+ t.resolve(true);
4695
+ },
4696
+ complete: () => {
4697
+ completed = true;
4698
+ }
4699
+ }), finalize(() => {
4700
+ /* When the navigation stream finishes either through error or success,
4701
+ * we set the `completed` or `errored` flag. However, there are some
4702
+ * situations where we could get here without either of those being set.
4703
+ * For instance, a redirect during NavigationStart. Therefore, this is a
4704
+ * catch-all to make sure the NavigationCancel event is fired when a
4705
+ * navigation gets cancelled but not caught by other means. */
4706
+ if (!completed && !errored) {
4707
+ const cancelationReason = NG_DEV_MODE$4 ?
4708
+ `Navigation ID ${overallTransitionState
4709
+ .id} is not equal to the current navigation id ${this.navigationId}` :
4710
+ '';
4711
+ this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 /* NavigationCancellationCode.SupersededByNewNavigation */, router);
4712
+ }
4713
+ // Only clear current navigation if it is still set to the one that
4714
+ // finalized.
4715
+ if (this.currentNavigation?.id === overallTransitionState.id) {
4716
+ this.currentNavigation = null;
4717
+ }
4718
+ }), catchError((e) => {
4719
+ errored = true;
4720
+ /* This error type is issued during Redirect, and is handled as a
4721
+ * cancellation rather than an error. */
4722
+ if (isNavigationCancelingError$1(e)) {
4723
+ if (!isRedirectingNavigationCancelingError$1(e)) {
4724
+ // Set property only if we're not redirecting. If we landed on a page
4725
+ // and redirect to `/` route, the new navigation is going to see the
4726
+ // `/` isn't a change from the default currentUrlTree and won't
4727
+ // navigate. This is only applicable with initial navigation, so
4728
+ // setting `navigated` only when not redirecting resolves this
4729
+ // scenario.
4730
+ router.navigated = true;
4731
+ router.restoreHistory(overallTransitionState, true);
4732
+ }
4733
+ const navCancel = new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
4734
+ this.events.next(navCancel);
4735
+ // When redirecting, we need to delay resolving the navigation
4736
+ // promise and push it to the redirect navigation
4737
+ if (!isRedirectingNavigationCancelingError$1(e)) {
4738
+ overallTransitionState.resolve(false);
4739
+ }
4740
+ else {
4741
+ const mergedTree = router.urlHandlingStrategy.merge(e.url, router.rawUrlTree);
4742
+ const extras = {
4743
+ skipLocationChange: overallTransitionState.extras.skipLocationChange,
4744
+ // The URL is already updated at this point if we have 'eager' URL
4745
+ // updates or if the navigation was triggered by the browser (back
4746
+ // button, URL bar, etc). We want to replace that item in history
4747
+ // if the navigation is rejected.
4748
+ replaceUrl: router.urlUpdateStrategy === 'eager' ||
4749
+ isBrowserTriggeredNavigation(overallTransitionState.source)
4750
+ };
4751
+ router.scheduleNavigation(mergedTree, 'imperative', null, extras, {
4752
+ resolve: overallTransitionState.resolve,
4753
+ reject: overallTransitionState.reject,
4754
+ promise: overallTransitionState.promise
4755
+ });
4756
+ }
4757
+ /* All other errors should reset to the router's internal URL reference
4758
+ * to the pre-error state. */
4759
+ }
4760
+ else {
4761
+ router.restoreHistory(overallTransitionState, true);
4762
+ const navError = new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
4763
+ this.events.next(navError);
4764
+ try {
4765
+ overallTransitionState.resolve(router.errorHandler(e));
4766
+ }
4767
+ catch (ee) {
4768
+ overallTransitionState.reject(ee);
4769
+ }
4770
+ }
4771
+ return EMPTY;
4772
+ }));
4773
+ // TODO(jasonaden): remove cast once g3 is on updated TypeScript
4774
+ }));
4775
+ }
4776
+ cancelNavigationTransition(t, reason, code, router) {
4777
+ const navCancel = new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);
4778
+ this.events.next(navCancel);
4779
+ t.resolve(false);
4780
+ }
4781
+ }
4782
+ NavigationTransitions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4783
+ NavigationTransitions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, providedIn: 'root' });
4784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NavigationTransitions, decorators: [{
4785
+ type: Injectable,
4786
+ args: [{ providedIn: 'root' }]
4787
+ }], ctorParameters: function () { return []; } });
4788
+ function isBrowserTriggeredNavigation(source) {
4789
+ return source !== 'imperative';
4790
+ }
4791
+
4792
+ /**
4793
+ * @license
4794
+ * Copyright Google LLC All Rights Reserved.
4795
+ *
4796
+ * Use of this source code is governed by an MIT-style license that can be
4797
+ * found in the LICENSE file at https://angular.io/license
4798
+ */
4799
+ /**
4800
+ * Provides a strategy for setting the page title after a router navigation.
4801
+ *
4802
+ * The built-in implementation traverses the router state snapshot and finds the deepest primary
4803
+ * outlet with `title` property. Given the `Routes` below, navigating to
4804
+ * `/base/child(popup:aux)` would result in the document title being set to "child".
4805
+ * ```
4806
+ * [
4807
+ * {path: 'base', title: 'base', children: [
4808
+ * {path: 'child', title: 'child'},
4809
+ * ],
4810
+ * {path: 'aux', outlet: 'popup', title: 'popupTitle'}
4811
+ * ]
4812
+ * ```
4813
+ *
4814
+ * This class can be used as a base class for custom title strategies. That is, you can create your
4815
+ * own class that extends the `TitleStrategy`. Note that in the above example, the `title`
4816
+ * from the named outlet is never used. However, a custom strategy might be implemented to
4817
+ * incorporate titles in named outlets.
4818
+ *
4819
+ * @publicApi
4820
+ * @see [Page title guide](guide/router#setting-the-page-title)
4821
+ */
4822
+ class TitleStrategy {
4823
+ /**
4824
+ * @returns The `title` of the deepest primary route.
4825
+ */
4826
+ buildTitle(snapshot) {
4827
+ let pageTitle;
4828
+ let route = snapshot.root;
4829
+ while (route !== undefined) {
4830
+ pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
4831
+ route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
4832
+ }
4833
+ return pageTitle;
4834
+ }
4835
+ /**
4836
+ * Given an `ActivatedRouteSnapshot`, returns the final value of the
4837
+ * `Route.title` property, which can either be a static string or a resolved value.
4838
+ */
4839
+ getResolvedTitleForRoute(snapshot) {
4840
+ return snapshot.data[RouteTitleKey];
4841
+ }
4842
+ }
4843
+ TitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4844
+ TitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) });
4845
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: TitleStrategy, decorators: [{
4846
+ type: Injectable,
4847
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4848
+ }] });
4849
+ /**
4850
+ * The default `TitleStrategy` used by the router that updates the title using the `Title` service.
4851
+ */
4852
+ class DefaultTitleStrategy extends TitleStrategy {
4853
+ constructor(title) {
4854
+ super();
4855
+ this.title = title;
4856
+ }
4857
+ /**
4858
+ * Sets the title of the browser to the given value.
4859
+ *
4860
+ * @param title The `pageTitle` from the deepest primary route.
4861
+ */
4862
+ updateTitle(snapshot) {
4863
+ const title = this.buildTitle(snapshot);
4864
+ if (title !== undefined) {
4865
+ this.title.setTitle(title);
4866
+ }
4867
+ }
4868
+ }
4869
+ DefaultTitleStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable });
4870
+ DefaultTitleStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' });
4871
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4872
+ type: Injectable,
4873
+ args: [{ providedIn: 'root' }]
4874
+ }], ctorParameters: function () { return [{ type: i1.Title }]; } });
4875
+
4876
+ /**
4877
+ * @license
4878
+ * Copyright Google LLC All Rights Reserved.
4879
+ *
4880
+ * Use of this source code is governed by an MIT-style license that can be
4881
+ * found in the LICENSE file at https://angular.io/license
4882
+ */
4883
+ /**
4884
+ * @description
4885
+ *
4886
+ * Provides a way to customize when activated routes get reused.
4887
+ *
4888
+ * @publicApi
4889
+ */
4890
+ class RouteReuseStrategy {
4891
+ }
4892
+ RouteReuseStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4893
+ RouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) });
4894
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4895
+ type: Injectable,
4896
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
4897
+ }] });
4898
+ /**
4899
+ * @description
4900
+ *
4901
+ * This base route reuse strategy only reuses routes when the matched router configs are
4902
+ * identical. This prevents components from being destroyed and recreated
4903
+ * when just the route parameters, query parameters or fragment change
4904
+ * (that is, the existing component is _reused_).
4905
+ *
4906
+ * This strategy does not store any routes for later reuse.
4907
+ *
4908
+ * Angular uses this strategy by default.
4909
+ *
4910
+ *
4911
+ * It can be used as a base class for custom route reuse strategies, i.e. you can create your own
4912
+ * class that extends the `BaseRouteReuseStrategy` one.
4913
+ * @publicApi
4914
+ */
4915
+ class BaseRouteReuseStrategy {
4916
+ /**
4917
+ * Whether the given route should detach for later reuse.
4918
+ * Always returns false for `BaseRouteReuseStrategy`.
4919
+ * */
4920
+ shouldDetach(route) {
4921
+ return false;
4922
+ }
4923
+ /**
4924
+ * A no-op; the route is never stored since this strategy never detaches routes for later re-use.
4925
+ */
4926
+ store(route, detachedTree) { }
4927
+ /** Returns `false`, meaning the route (and its subtree) is never reattached */
4928
+ shouldAttach(route) {
4929
+ return false;
4930
+ }
4931
+ /** Returns `null` because this strategy does not store routes for later re-use. */
4932
+ retrieve(route) {
4933
+ return null;
4934
+ }
4935
+ /**
4936
+ * Determines if a route should be reused.
4937
+ * This strategy returns `true` when the future route config and current route config are
4938
+ * identical.
4939
+ */
4940
+ shouldReuseRoute(future, curr) {
4941
+ return future.routeConfig === curr.routeConfig;
4942
+ }
4943
+ }
4944
+ class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4945
+ }
4946
+ DefaultRouteReuseStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
4947
+ DefaultRouteReuseStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' });
4948
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4949
+ type: Injectable,
4950
+ args: [{ providedIn: 'root' }]
4951
+ }] });
4952
+
4953
+ /**
4954
+ * @license
4955
+ * Copyright Google LLC All Rights Reserved.
4956
+ *
4957
+ * Use of this source code is governed by an MIT-style license that can be
4958
+ * found in the LICENSE file at https://angular.io/license
4959
+ */
4960
+ const NG_DEV_MODE$3 = typeof ngDevMode === 'undefined' || !!ngDevMode;
4961
+ /**
4962
+ * A [DI token](guide/glossary/#di-token) for the router service.
4963
+ *
4964
+ * @publicApi
4965
+ */
4966
+ const ROUTER_CONFIGURATION = new InjectionToken(NG_DEV_MODE$3 ? 'router config' : '', {
4967
+ providedIn: 'root',
4968
+ factory: () => ({}),
4969
+ });
4970
+
4971
+ /**
4972
+ * @license
4973
+ * Copyright Google LLC All Rights Reserved.
4974
+ *
4975
+ * Use of this source code is governed by an MIT-style license that can be
4976
+ * found in the LICENSE file at https://angular.io/license
4977
+ */
4978
+ /**
4979
+ * @description
4980
+ *
4981
+ * Provides a way to migrate AngularJS applications to Angular.
4982
+ *
4983
+ * @publicApi
4984
+ */
4985
+ class UrlHandlingStrategy {
4986
+ }
4987
+ UrlHandlingStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
4988
+ UrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) });
4989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4990
+ type: Injectable,
4991
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4992
+ }] });
4993
+ /**
4994
+ * @publicApi
4995
+ */
4996
+ class DefaultUrlHandlingStrategy {
4997
+ shouldProcessUrl(url) {
4998
+ return true;
4999
+ }
5000
+ extract(url) {
5001
+ return url;
5002
+ }
5003
+ merge(newUrlPart, wholeUrl) {
5004
+ return newUrlPart;
5005
+ }
5006
+ }
5007
+ DefaultUrlHandlingStrategy.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5008
+ DefaultUrlHandlingStrategy.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' });
5009
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
5010
+ type: Injectable,
5011
+ args: [{ providedIn: 'root' }]
5012
+ }] });
5013
+
5014
+ /**
5015
+ * @license
5016
+ * Copyright Google LLC All Rights Reserved.
5017
+ *
5018
+ * Use of this source code is governed by an MIT-style license that can be
5019
+ * found in the LICENSE file at https://angular.io/license
5020
+ */
5021
+ const NG_DEV_MODE$2 = typeof ngDevMode === 'undefined' || !!ngDevMode;
5022
+ function defaultErrorHandler(error) {
5023
+ throw error;
5024
+ }
5025
+ function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
5026
+ return urlSerializer.parse('/');
5027
+ }
5028
+ /**
5029
+ * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
5030
+ * (exact = true).
5031
+ */
5032
+ const exactMatchOptions = {
5033
+ paths: 'exact',
5034
+ fragment: 'ignored',
5035
+ matrixParams: 'ignored',
5036
+ queryParams: 'exact'
5037
+ };
5038
+ /**
5039
+ * The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
5040
+ * (exact = false).
5041
+ */
5042
+ const subsetMatchOptions = {
5043
+ paths: 'subset',
5044
+ fragment: 'ignored',
5045
+ matrixParams: 'ignored',
5046
+ queryParams: 'subset'
5047
+ };
5048
+ function assignExtraOptionsToRouter(opts, router) {
5049
+ if (opts.errorHandler) {
5050
+ router.errorHandler = opts.errorHandler;
5051
+ }
5052
+ if (opts.malformedUriErrorHandler) {
5053
+ router.malformedUriErrorHandler = opts.malformedUriErrorHandler;
5054
+ }
5055
+ if (opts.onSameUrlNavigation) {
5056
+ router.onSameUrlNavigation = opts.onSameUrlNavigation;
5057
+ }
5058
+ if (opts.paramsInheritanceStrategy) {
5059
+ router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
5060
+ }
5061
+ if (opts.urlUpdateStrategy) {
5062
+ router.urlUpdateStrategy = opts.urlUpdateStrategy;
5063
+ }
5064
+ if (opts.canceledNavigationResolution) {
5065
+ router.canceledNavigationResolution = opts.canceledNavigationResolution;
5066
+ }
5067
+ }
5068
+ function setupRouter() {
5069
+ const urlSerializer = inject(UrlSerializer);
5070
+ const contexts = inject(ChildrenOutletContexts);
4683
5071
  const location = inject(Location);
4684
5072
  const injector = inject(Injector);
4685
5073
  const compiler = inject(Compiler);
4686
5074
  const config = inject(ROUTES, { optional: true }) ?? [];
4687
5075
  const opts = inject(ROUTER_CONFIGURATION, { optional: true }) ?? {};
4688
- const defaultTitleStrategy = inject(DefaultTitleStrategy);
4689
- const titleStrategy = inject(TitleStrategy, { optional: true });
4690
- const urlHandlingStrategy = inject(UrlHandlingStrategy, { optional: true });
4691
- const routeReuseStrategy = inject(RouteReuseStrategy, { optional: true });
4692
5076
  const router = new Router(null, urlSerializer, contexts, location, injector, compiler, flatten(config));
4693
- if (urlHandlingStrategy) {
4694
- router.urlHandlingStrategy = urlHandlingStrategy;
4695
- }
4696
- if (routeReuseStrategy) {
4697
- router.routeReuseStrategy = routeReuseStrategy;
4698
- }
4699
- router.titleStrategy = titleStrategy ?? defaultTitleStrategy;
4700
5077
  assignExtraOptionsToRouter(opts, router);
4701
5078
  return router;
4702
5079
  }
@@ -4717,16 +5094,15 @@ class Router {
4717
5094
  * Creates the router service.
4718
5095
  */
4719
5096
  // TODO: vsavkin make internal after the final is out.
4720
- constructor(rootComponentType, urlSerializer, rootContexts, location, injector, compiler, config) {
5097
+ constructor(
5098
+ /** @internal */
5099
+ rootComponentType, urlSerializer, rootContexts, location, injector, compiler, config) {
4721
5100
  this.rootComponentType = rootComponentType;
4722
5101
  this.urlSerializer = urlSerializer;
4723
5102
  this.rootContexts = rootContexts;
4724
5103
  this.location = location;
4725
5104
  this.config = config;
4726
- this.lastSuccessfulNavigation = null;
4727
- this.currentNavigation = null;
4728
5105
  this.disposed = false;
4729
- this.navigationId = 0;
4730
5106
  /**
4731
5107
  * The id of the currently active page in the router.
4732
5108
  * Updated to the transition's target id on a successful navigation.
@@ -4737,10 +5113,6 @@ class Router {
4737
5113
  */
4738
5114
  this.currentPageId = 0;
4739
5115
  this.isNgZoneEnabled = false;
4740
- /**
4741
- * An event stream for routing events in this NgModule.
4742
- */
4743
- this.events = new Subject();
4744
5116
  /**
4745
5117
  * A handler for navigation errors in this NgModule.
4746
5118
  */
@@ -4769,11 +5141,15 @@ class Router {
4769
5141
  * A strategy for extracting and merging URLs.
4770
5142
  * Used for AngularJS to Angular migrations.
4771
5143
  */
4772
- this.urlHandlingStrategy = new DefaultUrlHandlingStrategy();
5144
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4773
5145
  /**
4774
5146
  * A strategy for re-using routes.
4775
5147
  */
4776
- this.routeReuseStrategy = new DefaultRouteReuseStrategy();
5148
+ this.routeReuseStrategy = inject(RouteReuseStrategy);
5149
+ /**
5150
+ * A strategy for setting the title based on the `routerState`.
5151
+ */
5152
+ this.titleStrategy = inject(TitleStrategy);
4777
5153
  /**
4778
5154
  * How to handle a navigation request to the current URL. One of:
4779
5155
  *
@@ -4829,43 +5205,26 @@ class Router {
4829
5205
  *
4830
5206
  */
4831
5207
  this.canceledNavigationResolution = 'replace';
4832
- const onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r));
4833
- const onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r));
4834
- this.configLoader = injector.get(RouterConfigLoader);
4835
- this.configLoader.onLoadEndListener = onLoadEnd;
4836
- this.configLoader.onLoadStartListener = onLoadStart;
4837
- this.ngModule = injector.get(NgModuleRef);
5208
+ this.navigationTransitions = inject(NavigationTransitions);
4838
5209
  this.console = injector.get(ɵConsole);
4839
5210
  const ngZone = injector.get(NgZone);
4840
- this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
4841
- this.resetConfig(config);
4842
- this.currentUrlTree = new UrlTree();
4843
- this.rawUrlTree = this.currentUrlTree;
4844
- this.browserUrlTree = this.currentUrlTree;
4845
- this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
4846
- this.transitions = new BehaviorSubject({
4847
- id: 0,
4848
- targetPageId: 0,
4849
- currentUrlTree: this.currentUrlTree,
4850
- currentRawUrl: this.currentUrlTree,
4851
- extractedUrl: this.urlHandlingStrategy.extract(this.currentUrlTree),
4852
- urlAfterRedirects: this.urlHandlingStrategy.extract(this.currentUrlTree),
4853
- rawUrl: this.currentUrlTree,
4854
- extras: {},
4855
- resolve: null,
4856
- reject: null,
4857
- promise: Promise.resolve(true),
4858
- source: 'imperative',
4859
- restoredState: null,
4860
- currentSnapshot: this.routerState.snapshot,
4861
- targetSnapshot: null,
4862
- currentRouterState: this.routerState,
4863
- targetRouterState: null,
4864
- guards: { canActivateChecks: [], canDeactivateChecks: [] },
4865
- guardsResult: null,
5211
+ this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
5212
+ this.resetConfig(config);
5213
+ this.currentUrlTree = new UrlTree();
5214
+ this.rawUrlTree = this.currentUrlTree;
5215
+ this.browserUrlTree = this.currentUrlTree;
5216
+ this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
5217
+ this.navigationTransitions.setupNavigations(this).subscribe(t => {
5218
+ this.lastSuccessfulId = t.id;
5219
+ this.currentPageId = t.targetPageId;
5220
+ }, e => {
5221
+ this.console.warn(`Unhandled Navigation Error: ${e}`);
4866
5222
  });
4867
- this.navigations = this.setupNavigations(this.transitions);
4868
- this.processNavigations();
5223
+ }
5224
+ // TODO(b/260747083): This should not exist and navigationId should be private in
5225
+ // `NavigationTransitions`
5226
+ get navigationId() {
5227
+ return this.navigationTransitions.navigationId;
4869
5228
  }
4870
5229
  /**
4871
5230
  * The ɵrouterPageId of whatever page is currently active in the browser history. This is
@@ -4875,290 +5234,15 @@ class Router {
4875
5234
  get browserPageId() {
4876
5235
  return this.location.getState()?.ɵrouterPageId;
4877
5236
  }
4878
- setupNavigations(transitions) {
4879
- const eventsSubject = this.events;
4880
- return transitions.pipe(filter(t => t.id !== 0),
4881
- // Extract URL
4882
- map(t => ({ ...t, extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })),
4883
- // Using switchMap so we cancel executing navigations when a new one comes in
4884
- switchMap(overallTransitionState => {
4885
- let completed = false;
4886
- let errored = false;
4887
- return of(overallTransitionState)
4888
- .pipe(
4889
- // Store the Navigation object
4890
- tap(t => {
4891
- this.currentNavigation = {
4892
- id: t.id,
4893
- initialUrl: t.rawUrl,
4894
- extractedUrl: t.extractedUrl,
4895
- trigger: t.source,
4896
- extras: t.extras,
4897
- previousNavigation: this.lastSuccessfulNavigation ?
4898
- { ...this.lastSuccessfulNavigation, previousNavigation: null } :
4899
- null
4900
- };
4901
- }), switchMap(t => {
4902
- const browserUrlTree = this.browserUrlTree.toString();
4903
- const urlTransition = !this.navigated ||
4904
- t.extractedUrl.toString() !== browserUrlTree ||
4905
- // Navigations which succeed or ones which fail and are cleaned up
4906
- // correctly should result in `browserUrlTree` and `currentUrlTree`
4907
- // matching. If this is not the case, assume something went wrong and
4908
- // try processing the URL again.
4909
- browserUrlTree !== this.currentUrlTree.toString();
4910
- const processCurrentUrl = (this.onSameUrlNavigation === 'reload' ? true : urlTransition) &&
4911
- this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl);
4912
- if (processCurrentUrl) {
4913
- // If the source of the navigation is from a browser event, the URL is
4914
- // already updated. We already need to sync the internal state.
4915
- if (isBrowserTriggeredNavigation(t.source)) {
4916
- this.browserUrlTree = t.extractedUrl;
4917
- }
4918
- return of(t).pipe(
4919
- // Fire NavigationStart event
4920
- switchMap(t => {
4921
- const transition = this.transitions.getValue();
4922
- eventsSubject.next(new NavigationStart(t.id, this.serializeUrl(t.extractedUrl), t.source, t.restoredState));
4923
- if (transition !== this.transitions.getValue()) {
4924
- return EMPTY;
4925
- }
4926
- // This delay is required to match old behavior that forced
4927
- // navigation to always be async
4928
- return Promise.resolve(t);
4929
- }),
4930
- // ApplyRedirects
4931
- applyRedirects(this.ngModule.injector, this.configLoader, this.urlSerializer, this.config),
4932
- // Update the currentNavigation
4933
- // `urlAfterRedirects` is guaranteed to be set after this point
4934
- tap(t => {
4935
- this.currentNavigation = {
4936
- ...this.currentNavigation,
4937
- finalUrl: t.urlAfterRedirects
4938
- };
4939
- overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
4940
- }),
4941
- // Recognize
4942
- recognize(this.ngModule.injector, this.rootComponentType, this.config, this.urlSerializer, this.paramsInheritanceStrategy),
4943
- // Update URL if in `eager` update mode
4944
- tap(t => {
4945
- overallTransitionState.targetSnapshot = t.targetSnapshot;
4946
- if (this.urlUpdateStrategy === 'eager') {
4947
- if (!t.extras.skipLocationChange) {
4948
- const rawUrl = this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
4949
- this.setBrowserUrl(rawUrl, t);
4950
- }
4951
- this.browserUrlTree = t.urlAfterRedirects;
4952
- }
4953
- // Fire RoutesRecognized
4954
- const routesRecognized = new RoutesRecognized(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
4955
- eventsSubject.next(routesRecognized);
4956
- }));
4957
- }
4958
- else {
4959
- const processPreviousUrl = urlTransition && this.rawUrlTree &&
4960
- this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree);
4961
- /* When the current URL shouldn't be processed, but the previous one
4962
- * was, we handle this "error condition" by navigating to the
4963
- * previously successful URL, but leaving the URL intact.*/
4964
- if (processPreviousUrl) {
4965
- const { id, extractedUrl, source, restoredState, extras } = t;
4966
- const navStart = new NavigationStart(id, this.serializeUrl(extractedUrl), source, restoredState);
4967
- eventsSubject.next(navStart);
4968
- const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
4969
- overallTransitionState = {
4970
- ...t,
4971
- targetSnapshot,
4972
- urlAfterRedirects: extractedUrl,
4973
- extras: { ...extras, skipLocationChange: false, replaceUrl: false },
4974
- };
4975
- return of(overallTransitionState);
4976
- }
4977
- else {
4978
- /* When neither the current or previous URL can be processed, do
4979
- * nothing other than update router's internal reference to the
4980
- * current "settled" URL. This way the next navigation will be coming
4981
- * from the current URL in the browser.
4982
- */
4983
- this.rawUrlTree = t.rawUrl;
4984
- t.resolve(null);
4985
- return EMPTY;
4986
- }
4987
- }
4988
- }),
4989
- // --- GUARDS ---
4990
- tap(t => {
4991
- const guardsStart = new GuardsCheckStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
4992
- this.triggerEvent(guardsStart);
4993
- }), map(t => {
4994
- overallTransitionState = {
4995
- ...t,
4996
- guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
4997
- };
4998
- return overallTransitionState;
4999
- }), checkGuards(this.ngModule.injector, (evt) => this.triggerEvent(evt)), tap(t => {
5000
- overallTransitionState.guardsResult = t.guardsResult;
5001
- if (isUrlTree(t.guardsResult)) {
5002
- throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
5003
- }
5004
- const guardsEnd = new GuardsCheckEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
5005
- this.triggerEvent(guardsEnd);
5006
- }), filter(t => {
5007
- if (!t.guardsResult) {
5008
- this.restoreHistory(t);
5009
- this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */);
5010
- return false;
5011
- }
5012
- return true;
5013
- }),
5014
- // --- RESOLVE ---
5015
- switchTap(t => {
5016
- if (t.guards.canActivateChecks.length) {
5017
- return of(t).pipe(tap(t => {
5018
- const resolveStart = new ResolveStart(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
5019
- this.triggerEvent(resolveStart);
5020
- }), switchMap(t => {
5021
- let dataResolved = false;
5022
- return of(t).pipe(resolveData(this.paramsInheritanceStrategy, this.ngModule.injector), tap({
5023
- next: () => dataResolved = true,
5024
- complete: () => {
5025
- if (!dataResolved) {
5026
- this.restoreHistory(t);
5027
- this.cancelNavigationTransition(t, NG_DEV_MODE$2 ?
5028
- `At least one route resolver didn't emit any value.` :
5029
- '', 2 /* NavigationCancellationCode.NoDataFromResolver */);
5030
- }
5031
- }
5032
- }));
5033
- }), tap(t => {
5034
- const resolveEnd = new ResolveEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot);
5035
- this.triggerEvent(resolveEnd);
5036
- }));
5037
- }
5038
- return undefined;
5039
- }),
5040
- // --- LOAD COMPONENTS ---
5041
- switchTap((t) => {
5042
- const loadComponents = (route) => {
5043
- const loaders = [];
5044
- if (route.routeConfig?.loadComponent &&
5045
- !route.routeConfig._loadedComponent) {
5046
- loaders.push(this.configLoader.loadComponent(route.routeConfig)
5047
- .pipe(tap(loadedComponent => {
5048
- route.component = loadedComponent;
5049
- }), map(() => void 0)));
5050
- }
5051
- for (const child of route.children) {
5052
- loaders.push(...loadComponents(child));
5053
- }
5054
- return loaders;
5055
- };
5056
- return combineLatest(loadComponents(t.targetSnapshot.root))
5057
- .pipe(defaultIfEmpty(), take(1));
5058
- }), switchTap(() => this.afterPreactivation()), map((t) => {
5059
- const targetRouterState = createRouterState(this.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
5060
- overallTransitionState = { ...t, targetRouterState };
5061
- return (overallTransitionState);
5062
- }),
5063
- /* Once here, we are about to activate synchronously. The assumption is
5064
- this will succeed, and user code may read from the Router service.
5065
- Therefore before activation, we need to update router properties storing
5066
- the current URL and the RouterState, as well as updated the browser URL.
5067
- All this should happen *before* activating. */
5068
- tap((t) => {
5069
- this.currentUrlTree = t.urlAfterRedirects;
5070
- this.rawUrlTree =
5071
- this.urlHandlingStrategy.merge(t.urlAfterRedirects, t.rawUrl);
5072
- this.routerState = t.targetRouterState;
5073
- if (this.urlUpdateStrategy === 'deferred') {
5074
- if (!t.extras.skipLocationChange) {
5075
- this.setBrowserUrl(this.rawUrlTree, t);
5076
- }
5077
- this.browserUrlTree = t.urlAfterRedirects;
5078
- }
5079
- }), activateRoutes(this.rootContexts, this.routeReuseStrategy, (evt) => this.triggerEvent(evt)), tap({
5080
- next() {
5081
- completed = true;
5082
- },
5083
- complete() {
5084
- completed = true;
5085
- }
5086
- }), finalize(() => {
5087
- /* When the navigation stream finishes either through error or success,
5088
- * we set the `completed` or `errored` flag. However, there are some
5089
- * situations where we could get here without either of those being set.
5090
- * For instance, a redirect during NavigationStart. Therefore, this is a
5091
- * catch-all to make sure the NavigationCancel event is fired when a
5092
- * navigation gets cancelled but not caught by other means. */
5093
- if (!completed && !errored) {
5094
- const cancelationReason = NG_DEV_MODE$2 ?
5095
- `Navigation ID ${overallTransitionState
5096
- .id} is not equal to the current navigation id ${this.navigationId}` :
5097
- '';
5098
- this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 /* NavigationCancellationCode.SupersededByNewNavigation */);
5099
- }
5100
- // Only clear current navigation if it is still set to the one that
5101
- // finalized.
5102
- if (this.currentNavigation?.id === overallTransitionState.id) {
5103
- this.currentNavigation = null;
5104
- }
5105
- }), catchError((e) => {
5106
- errored = true;
5107
- /* This error type is issued during Redirect, and is handled as a
5108
- * cancellation rather than an error. */
5109
- if (isNavigationCancelingError$1(e)) {
5110
- if (!isRedirectingNavigationCancelingError$1(e)) {
5111
- // Set property only if we're not redirecting. If we landed on a page
5112
- // and redirect to `/` route, the new navigation is going to see the
5113
- // `/` isn't a change from the default currentUrlTree and won't
5114
- // navigate. This is only applicable with initial navigation, so
5115
- // setting `navigated` only when not redirecting resolves this
5116
- // scenario.
5117
- this.navigated = true;
5118
- this.restoreHistory(overallTransitionState, true);
5119
- }
5120
- const navCancel = new NavigationCancel(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e.message, e.cancellationCode);
5121
- eventsSubject.next(navCancel);
5122
- // When redirecting, we need to delay resolving the navigation
5123
- // promise and push it to the redirect navigation
5124
- if (!isRedirectingNavigationCancelingError$1(e)) {
5125
- overallTransitionState.resolve(false);
5126
- }
5127
- else {
5128
- const mergedTree = this.urlHandlingStrategy.merge(e.url, this.rawUrlTree);
5129
- const extras = {
5130
- skipLocationChange: overallTransitionState.extras.skipLocationChange,
5131
- // The URL is already updated at this point if we have 'eager' URL
5132
- // updates or if the navigation was triggered by the browser (back
5133
- // button, URL bar, etc). We want to replace that item in history
5134
- // if the navigation is rejected.
5135
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
5136
- isBrowserTriggeredNavigation(overallTransitionState.source)
5137
- };
5138
- this.scheduleNavigation(mergedTree, 'imperative', null, extras, {
5139
- resolve: overallTransitionState.resolve,
5140
- reject: overallTransitionState.reject,
5141
- promise: overallTransitionState.promise
5142
- });
5143
- }
5144
- /* All other errors should reset to the router's internal URL reference
5145
- * to the pre-error state. */
5146
- }
5147
- else {
5148
- this.restoreHistory(overallTransitionState, true);
5149
- const navError = new NavigationError(overallTransitionState.id, this.serializeUrl(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
5150
- eventsSubject.next(navError);
5151
- try {
5152
- overallTransitionState.resolve(this.errorHandler(e));
5153
- }
5154
- catch (ee) {
5155
- overallTransitionState.reject(ee);
5156
- }
5157
- }
5158
- return EMPTY;
5159
- }));
5160
- // TODO(jasonaden): remove cast once g3 is on updated TypeScript
5161
- }));
5237
+ /**
5238
+ * An event stream for routing events.
5239
+ */
5240
+ get events() {
5241
+ // TODO(atscott): This _should_ be events.asObservable(). However, this change requires internal
5242
+ // cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't
5243
+ // allowed/supported but we still have to fix these or file bugs against the teams before making
5244
+ // the change.
5245
+ return this.navigationTransitions.events;
5162
5246
  }
5163
5247
  /**
5164
5248
  * @internal
@@ -5170,15 +5254,12 @@ class Router {
5170
5254
  // this will simplify the lifecycle of the router.
5171
5255
  this.routerState.root.component = this.rootComponentType;
5172
5256
  }
5173
- setTransition(t) {
5174
- this.transitions.next({ ...this.transitions.value, ...t });
5175
- }
5176
5257
  /**
5177
5258
  * Sets up the location change listener and performs the initial navigation.
5178
5259
  */
5179
5260
  initialNavigation() {
5180
5261
  this.setUpLocationChangeListener();
5181
- if (this.navigationId === 0) {
5262
+ if (!this.navigationTransitions.hasRequestedNavigation) {
5182
5263
  this.navigateByUrl(this.location.path(true), { replaceUrl: true });
5183
5264
  }
5184
5265
  }
@@ -5199,11 +5280,18 @@ class Router {
5199
5280
  // hybrid apps.
5200
5281
  setTimeout(() => {
5201
5282
  const extras = { replaceUrl: true };
5202
- // Navigations coming from Angular router have a navigationId state
5203
- // property. When this exists, restore the state.
5204
- const state = event.state?.navigationId ? event.state : null;
5205
- if (state) {
5206
- const stateCopy = { ...state };
5283
+ // TODO: restoredState should always include the entire state, regardless
5284
+ // of navigationId. This requires a breaking change to update the type on
5285
+ // NavigationStart’s restoredState, which currently requires navigationId
5286
+ // to always be present. The Router used to only restore history state if
5287
+ // a navigationId was present.
5288
+ // The stored navigationId is used by the RouterScroller to retrieve the scroll
5289
+ // position for the page.
5290
+ const restoredState = event.state?.navigationId ? event.state : null;
5291
+ // Separate to NavigationStart.restoredState, we must also restore the state to
5292
+ // history.state and generate a new navigationId, since it will be overwritten
5293
+ if (event.state) {
5294
+ const stateCopy = { ...event.state };
5207
5295
  delete stateCopy.navigationId;
5208
5296
  delete stateCopy.ɵrouterPageId;
5209
5297
  if (Object.keys(stateCopy).length !== 0) {
@@ -5211,7 +5299,7 @@ class Router {
5211
5299
  }
5212
5300
  }
5213
5301
  const urlTree = this.parseUrl(event['url']);
5214
- this.scheduleNavigation(urlTree, source, state, extras);
5302
+ this.scheduleNavigation(urlTree, source, restoredState, extras);
5215
5303
  }, 0);
5216
5304
  }
5217
5305
  });
@@ -5226,11 +5314,7 @@ class Router {
5226
5314
  * and `null` when idle.
5227
5315
  */
5228
5316
  getCurrentNavigation() {
5229
- return this.currentNavigation;
5230
- }
5231
- /** @internal */
5232
- triggerEvent(event) {
5233
- this.events.next(event);
5317
+ return this.navigationTransitions.currentNavigation;
5234
5318
  }
5235
5319
  /**
5236
5320
  * Resets the route configuration used for navigation and generating links.
@@ -5260,7 +5344,7 @@ class Router {
5260
5344
  }
5261
5345
  /** Disposes of the router. */
5262
5346
  dispose() {
5263
- this.transitions.complete();
5347
+ this.navigationTransitions.complete();
5264
5348
  if (this.locationSubscription) {
5265
5349
  this.locationSubscription.unsubscribe();
5266
5350
  this.locationSubscription = undefined;
@@ -5445,20 +5529,7 @@ class Router {
5445
5529
  return result;
5446
5530
  }, {});
5447
5531
  }
5448
- processNavigations() {
5449
- this.navigations.subscribe(t => {
5450
- this.navigated = true;
5451
- this.lastSuccessfulId = t.id;
5452
- this.currentPageId = t.targetPageId;
5453
- this.events
5454
- .next(new NavigationEnd(t.id, this.serializeUrl(t.extractedUrl), this.serializeUrl(this.currentUrlTree)));
5455
- this.lastSuccessfulNavigation = this.currentNavigation;
5456
- this.titleStrategy?.updateTitle(this.routerState.snapshot);
5457
- t.resolve(true);
5458
- }, e => {
5459
- this.console.warn(`Unhandled Navigation Error: ${e}`);
5460
- });
5461
- }
5532
+ /** @internal */
5462
5533
  scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
5463
5534
  if (this.disposed) {
5464
5535
  return Promise.resolve(false);
@@ -5477,7 +5548,6 @@ class Router {
5477
5548
  reject = rej;
5478
5549
  });
5479
5550
  }
5480
- const id = ++this.navigationId;
5481
5551
  let targetPageId;
5482
5552
  if (this.canceledNavigationResolution === 'computed') {
5483
5553
  const isInitialPage = this.currentPageId === 0;
@@ -5505,13 +5575,12 @@ class Router {
5505
5575
  // This is unused when `canceledNavigationResolution` is not computed.
5506
5576
  targetPageId = 0;
5507
5577
  }
5508
- this.setTransition({
5509
- id,
5578
+ this.navigationTransitions.handleNavigationRequest({
5510
5579
  targetPageId,
5511
5580
  source,
5512
5581
  restoredState,
5513
5582
  currentUrlTree: this.currentUrlTree,
5514
- currentRawUrl: this.rawUrlTree,
5583
+ currentRawUrl: this.currentUrlTree,
5515
5584
  rawUrl,
5516
5585
  extras,
5517
5586
  resolve,
@@ -5526,10 +5595,14 @@ class Router {
5526
5595
  return Promise.reject(e);
5527
5596
  });
5528
5597
  }
5529
- setBrowserUrl(url, t) {
5598
+ /** @internal */
5599
+ setBrowserUrl(url, transition) {
5530
5600
  const path = this.urlSerializer.serialize(url);
5531
- const state = { ...t.extras.state, ...this.generateNgRouterState(t.id, t.targetPageId) };
5532
- if (this.location.isCurrentPathEqualTo(path) || !!t.extras.replaceUrl) {
5601
+ const state = {
5602
+ ...transition.extras.state,
5603
+ ...this.generateNgRouterState(transition.id, transition.targetPageId)
5604
+ };
5605
+ if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
5533
5606
  this.location.replaceState(path, '', state);
5534
5607
  }
5535
5608
  else {
@@ -5539,28 +5612,30 @@ class Router {
5539
5612
  /**
5540
5613
  * Performs the necessary rollback action to restore the browser URL to the
5541
5614
  * state before the transition.
5615
+ * @internal
5542
5616
  */
5543
- restoreHistory(t, restoringFromCaughtError = false) {
5617
+ restoreHistory(transition, restoringFromCaughtError = false) {
5544
5618
  if (this.canceledNavigationResolution === 'computed') {
5545
- const targetPagePosition = this.currentPageId - t.targetPageId;
5619
+ const targetPagePosition = this.currentPageId - transition.targetPageId;
5546
5620
  // The navigator change the location before triggered the browser event,
5547
5621
  // so we need to go back to the current url if the navigation is canceled.
5548
5622
  // Also, when navigation gets cancelled while using url update strategy eager, then we need to
5549
5623
  // go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called
5550
5624
  // before any verification.
5551
- const browserUrlUpdateOccurred = (t.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
5552
- this.currentUrlTree === this.currentNavigation?.finalUrl);
5625
+ const browserUrlUpdateOccurred = (transition.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
5626
+ this.currentUrlTree === this.getCurrentNavigation()?.finalUrl);
5553
5627
  if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
5554
5628
  this.location.historyGo(targetPagePosition);
5555
5629
  }
5556
- else if (this.currentUrlTree === this.currentNavigation?.finalUrl && targetPagePosition === 0) {
5630
+ else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
5631
+ targetPagePosition === 0) {
5557
5632
  // We got to the activation stage (where currentUrlTree is set to the navigation's
5558
5633
  // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
5559
5634
  // We still need to reset the router state back to what it was when the navigation started.
5560
- this.resetState(t);
5635
+ this.resetState(transition);
5561
5636
  // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
5562
5637
  // Investigate if this can be done by running TGP.
5563
- this.browserUrlTree = t.currentUrlTree;
5638
+ this.browserUrlTree = transition.currentUrlTree;
5564
5639
  this.resetUrlToCurrentUrlTree();
5565
5640
  }
5566
5641
  else {
@@ -5574,7 +5649,7 @@ class Router {
5574
5649
  // reject. For 'eager' navigations, it seems like we also really should reset the state
5575
5650
  // because the navigation was cancelled. Investigate if this can be done by running TGP.
5576
5651
  if (restoringFromCaughtError) {
5577
- this.resetState(t);
5652
+ this.resetState(transition);
5578
5653
  }
5579
5654
  this.resetUrlToCurrentUrlTree();
5580
5655
  }
@@ -5592,11 +5667,6 @@ class Router {
5592
5667
  resetUrlToCurrentUrlTree() {
5593
5668
  this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
5594
5669
  }
5595
- cancelNavigationTransition(t, reason, code) {
5596
- const navCancel = new NavigationCancel(t.id, this.serializeUrl(t.extractedUrl), reason, code);
5597
- this.triggerEvent(navCancel);
5598
- t.resolve(false);
5599
- }
5600
5670
  generateNgRouterState(navigationId, routerPageId) {
5601
5671
  if (this.canceledNavigationResolution === 'computed') {
5602
5672
  return { navigationId, ɵrouterPageId: routerPageId };
@@ -5604,9 +5674,9 @@ class Router {
5604
5674
  return { navigationId };
5605
5675
  }
5606
5676
  }
5607
- Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5608
- Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Router, providedIn: 'root', useFactory: setupRouter });
5609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: Router, decorators: [{
5677
+ Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
5678
+ Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, providedIn: 'root', useFactory: setupRouter });
5679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: Router, decorators: [{
5610
5680
  type: Injectable,
5611
5681
  args: [{
5612
5682
  providedIn: 'root',
@@ -5621,9 +5691,6 @@ function validateCommands(commands) {
5621
5691
  }
5622
5692
  }
5623
5693
  }
5624
- function isBrowserTriggeredNavigation(source) {
5625
- return source !== 'imperative';
5626
- }
5627
5694
 
5628
5695
  /**
5629
5696
  * @license
@@ -5905,9 +5972,9 @@ class RouterLink {
5905
5972
  });
5906
5973
  }
5907
5974
  }
5908
- RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", 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 });
5909
- RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", 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 });
5910
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterLink, decorators: [{
5975
+ RouterLink.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", 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 });
5976
+ RouterLink.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: "preserveFragment", skipLocationChange: "skipLocationChange", replaceUrl: "replaceUrl", 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 });
5977
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLink, decorators: [{
5911
5978
  type: Directive,
5912
5979
  args: [{
5913
5980
  selector: '[routerLink]',
@@ -6132,9 +6199,9 @@ class RouterLinkActive {
6132
6199
  return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
6133
6200
  }
6134
6201
  }
6135
- RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
6136
- RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.0", 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 });
6137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterLinkActive, decorators: [{
6202
+ RouterLinkActive.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
6203
+ RouterLinkActive.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.2", 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 });
6204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterLinkActive, decorators: [{
6138
6205
  type: Directive,
6139
6206
  args: [{
6140
6207
  selector: '[routerLinkActive]',
@@ -6194,9 +6261,9 @@ class PreloadAllModules {
6194
6261
  return fn().pipe(catchError(() => of(null)));
6195
6262
  }
6196
6263
  }
6197
- PreloadAllModules.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6198
- PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
6199
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: PreloadAllModules, decorators: [{
6264
+ PreloadAllModules.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6265
+ PreloadAllModules.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, providedIn: 'root' });
6266
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: PreloadAllModules, decorators: [{
6200
6267
  type: Injectable,
6201
6268
  args: [{ providedIn: 'root' }]
6202
6269
  }] });
@@ -6214,9 +6281,9 @@ class NoPreloading {
6214
6281
  return of(null);
6215
6282
  }
6216
6283
  }
6217
- NoPreloading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6218
- NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NoPreloading, providedIn: 'root' });
6219
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: NoPreloading, decorators: [{
6284
+ NoPreloading.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6285
+ NoPreloading.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, providedIn: 'root' });
6286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: NoPreloading, decorators: [{
6220
6287
  type: Injectable,
6221
6288
  args: [{ providedIn: 'root' }]
6222
6289
  }] });
@@ -6310,9 +6377,9 @@ class RouterPreloader {
6310
6377
  });
6311
6378
  }
6312
6379
  }
6313
- RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
6314
- RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
6315
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterPreloader, decorators: [{
6380
+ RouterPreloader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable });
6381
+ RouterPreloader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, providedIn: 'root' });
6382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterPreloader, decorators: [{
6316
6383
  type: Injectable,
6317
6384
  args: [{ providedIn: 'root' }]
6318
6385
  }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
@@ -6326,9 +6393,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImpor
6326
6393
  */
6327
6394
  const ROUTER_SCROLLER = new InjectionToken('');
6328
6395
  class RouterScroller {
6329
- constructor(router,
6330
- /** @docsNotRequired */ viewportScroller, zone, options = {}) {
6331
- this.router = router;
6396
+ /** @nodoc */
6397
+ constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) {
6398
+ this.urlSerializer = urlSerializer;
6399
+ this.transitions = transitions;
6332
6400
  this.viewportScroller = viewportScroller;
6333
6401
  this.zone = zone;
6334
6402
  this.options = options;
@@ -6351,7 +6419,7 @@ class RouterScroller {
6351
6419
  this.scrollEventsSubscription = this.consumeScrollEvents();
6352
6420
  }
6353
6421
  createScrollEvents() {
6354
- return this.router.events.subscribe(e => {
6422
+ return this.transitions.events.subscribe(e => {
6355
6423
  if (e instanceof NavigationStart) {
6356
6424
  // store the scroll position of the current stable navigations.
6357
6425
  this.store[this.lastId] = this.viewportScroller.getScrollPosition();
@@ -6360,12 +6428,12 @@ class RouterScroller {
6360
6428
  }
6361
6429
  else if (e instanceof NavigationEnd) {
6362
6430
  this.lastId = e.id;
6363
- this.scheduleScrollEvent(e, this.router.parseUrl(e.urlAfterRedirects).fragment);
6431
+ this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);
6364
6432
  }
6365
6433
  });
6366
6434
  }
6367
6435
  consumeScrollEvents() {
6368
- return this.router.events.subscribe(e => {
6436
+ return this.transitions.events.subscribe(e => {
6369
6437
  if (!(e instanceof Scroll))
6370
6438
  return;
6371
6439
  // a popstate event. The pop state event will always ignore anchor scrolling.
@@ -6395,26 +6463,22 @@ class RouterScroller {
6395
6463
  // component by executing its update block of the template function.
6396
6464
  setTimeout(() => {
6397
6465
  this.zone.run(() => {
6398
- this.router.triggerEvent(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
6466
+ this.transitions.events.next(new Scroll(routerEvent, this.lastSource === 'popstate' ? this.store[this.restoredId] : null, anchor));
6399
6467
  });
6400
6468
  }, 0);
6401
6469
  });
6402
6470
  }
6403
6471
  /** @nodoc */
6404
6472
  ngOnDestroy() {
6405
- if (this.routerEventsSubscription) {
6406
- this.routerEventsSubscription.unsubscribe();
6407
- }
6408
- if (this.scrollEventsSubscription) {
6409
- this.scrollEventsSubscription.unsubscribe();
6410
- }
6473
+ this.routerEventsSubscription?.unsubscribe();
6474
+ this.scrollEventsSubscription?.unsubscribe();
6411
6475
  }
6412
6476
  }
6413
- RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6414
- RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterScroller });
6415
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterScroller, decorators: [{
6477
+ RouterScroller.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable });
6478
+ RouterScroller.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller });
6479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterScroller, decorators: [{
6416
6480
  type: Injectable
6417
- }], ctorParameters: function () { return [{ type: Router }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
6481
+ }], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
6418
6482
 
6419
6483
  /**
6420
6484
  * @license
@@ -6551,10 +6615,11 @@ function withInMemoryScrolling(options = {}) {
6551
6615
  const providers = [{
6552
6616
  provide: ROUTER_SCROLLER,
6553
6617
  useFactory: () => {
6554
- const router = inject(Router);
6555
6618
  const viewportScroller = inject(ViewportScroller);
6556
6619
  const zone = inject(NgZone);
6557
- return new RouterScroller(router, viewportScroller, zone, options);
6620
+ const transitions = inject(NavigationTransitions);
6621
+ const urlSerializer = inject(UrlSerializer);
6622
+ return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);
6558
6623
  },
6559
6624
  }];
6560
6625
  return routerFeature(4 /* RouterFeatureKind.InMemoryScrollingFeature */, providers);
@@ -6574,8 +6639,10 @@ function getBootstrapListener() {
6574
6639
  injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
6575
6640
  injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
6576
6641
  router.resetRootComponentType(ref.componentTypes[0]);
6577
- bootstrapDone.next();
6578
- bootstrapDone.complete();
6642
+ if (!bootstrapDone.closed) {
6643
+ bootstrapDone.next();
6644
+ bootstrapDone.unsubscribe();
6645
+ }
6579
6646
  };
6580
6647
  }
6581
6648
  /**
@@ -6623,7 +6690,6 @@ function withEnabledBlockingInitialNavigation() {
6623
6690
  deps: [Injector],
6624
6691
  useFactory: (injector) => {
6625
6692
  const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve());
6626
- let initNavigation = false;
6627
6693
  /**
6628
6694
  * Performs the given action once the router finishes its next/current navigation.
6629
6695
  *
@@ -6658,21 +6724,13 @@ function withEnabledBlockingInitialNavigation() {
6658
6724
  // Unblock APP_INITIALIZER in case the initial navigation was canceled or errored
6659
6725
  // without a redirect.
6660
6726
  resolve(true);
6661
- initNavigation = true;
6662
6727
  });
6663
6728
  router.afterPreactivation = () => {
6664
6729
  // Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
6665
6730
  // assume activation will complete successfully (even though this is not
6666
6731
  // guaranteed).
6667
6732
  resolve(true);
6668
- // only the initial navigation should be delayed until bootstrapping is done.
6669
- if (!initNavigation) {
6670
- return bootstrapDone.closed ? of(void 0) : bootstrapDone;
6671
- // subsequent navigations should not be delayed
6672
- }
6673
- else {
6674
- return of(void 0);
6675
- }
6733
+ return bootstrapDone.closed ? of(void 0) : bootstrapDone;
6676
6734
  };
6677
6735
  router.initialNavigation();
6678
6736
  });
@@ -6961,10 +7019,10 @@ class RouterModule {
6961
7019
  };
6962
7020
  }
6963
7021
  }
6964
- RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
6965
- RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] });
6966
- RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterModule, imports: [ɵEmptyOutletComponent] });
6967
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: RouterModule, decorators: [{
7022
+ RouterModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule });
7023
+ RouterModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] });
7024
+ RouterModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, imports: [ɵEmptyOutletComponent] });
7025
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: RouterModule, decorators: [{
6968
7026
  type: NgModule,
6969
7027
  args: [{
6970
7028
  imports: ROUTER_DIRECTIVES,
@@ -6984,14 +7042,15 @@ function provideRouterScroller() {
6984
7042
  return {
6985
7043
  provide: ROUTER_SCROLLER,
6986
7044
  useFactory: () => {
6987
- const router = inject(Router);
6988
7045
  const viewportScroller = inject(ViewportScroller);
6989
7046
  const zone = inject(NgZone);
6990
7047
  const config = inject(ROUTER_CONFIGURATION);
7048
+ const transitions = inject(NavigationTransitions);
7049
+ const urlSerializer = inject(UrlSerializer);
6991
7050
  if (config.scrollOffset) {
6992
7051
  viewportScroller.setOffset(config.scrollOffset);
6993
7052
  }
6994
- return new RouterScroller(router, viewportScroller, zone, config);
7053
+ return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);
6995
7054
  },
6996
7055
  };
6997
7056
  }
@@ -7049,7 +7108,7 @@ function provideRouterInitializer() {
7049
7108
  /**
7050
7109
  * @publicApi
7051
7110
  */
7052
- const VERSION = new Version('15.0.0');
7111
+ const VERSION = new Version('15.0.2');
7053
7112
 
7054
7113
  /**
7055
7114
  * @license