@angular/router 17.0.0-next.2 → 17.0.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/esm2022/src/apply_redirects.mjs +8 -3
  2. package/esm2022/src/components/empty_outlet.mjs +3 -3
  3. package/esm2022/src/directives/router_link.mjs +3 -3
  4. package/esm2022/src/directives/router_link_active.mjs +3 -3
  5. package/esm2022/src/directives/router_outlet.mjs +6 -6
  6. package/esm2022/src/index.mjs +2 -2
  7. package/esm2022/src/navigation_transition.mjs +24 -11
  8. package/esm2022/src/operators/resolve_data.mjs +2 -5
  9. package/esm2022/src/page_title_strategy.mjs +6 -6
  10. package/esm2022/src/provide_router.mjs +33 -1
  11. package/esm2022/src/recognize.mjs +34 -50
  12. package/esm2022/src/route_reuse_strategy.mjs +6 -6
  13. package/esm2022/src/router.mjs +57 -226
  14. package/esm2022/src/router_config.mjs +1 -1
  15. package/esm2022/src/router_config_loader.mjs +3 -3
  16. package/esm2022/src/router_module.mjs +7 -6
  17. package/esm2022/src/router_outlet_context.mjs +3 -3
  18. package/esm2022/src/router_preloader.mjs +9 -9
  19. package/esm2022/src/router_scroller.mjs +3 -3
  20. package/esm2022/src/state_manager.mjs +244 -0
  21. package/esm2022/src/url_handling_strategy.mjs +6 -6
  22. package/esm2022/src/url_tree.mjs +3 -3
  23. package/esm2022/src/utils/collection.mjs +9 -3
  24. package/esm2022/src/utils/view_transition.mjs +42 -0
  25. package/esm2022/src/version.mjs +1 -1
  26. package/esm2022/testing/src/router_testing_harness.mjs +6 -6
  27. package/esm2022/testing/src/router_testing_module.mjs +4 -4
  28. package/fesm2022/router.mjs +498 -369
  29. package/fesm2022/router.mjs.map +1 -1
  30. package/fesm2022/testing.mjs +11 -11
  31. package/fesm2022/upgrade.mjs +1 -1
  32. package/index.d.ts +67 -65
  33. package/package.json +4 -4
  34. package/testing/index.d.ts +1 -1
  35. package/upgrade/index.d.ts +1 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v17.0.0-next.2
2
+ * @license Angular v17.0.0-next.4
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 { ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, InjectionToken, reflectComponentType, Component, createEnvironmentInjector, ɵisNgModule, isStandalone, ɵisInjectable, Compiler, InjectFlags, NgModuleFactory, ɵConsole, ɵInitialRenderPendingTasks, NgZone, ɵɵsanitizeUrlOrResourceUrl, booleanAttribute, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, Injector, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
8
+ import { ɵisPromise, ɵRuntimeError, Injectable, EventEmitter, inject, ViewContainerRef, ChangeDetectorRef, EnvironmentInjector, Directive, Input, Output, InjectionToken, reflectComponentType, Component, createEnvironmentInjector, ɵisNgModule, isStandalone, ɵisInjectable, Compiler, InjectFlags, NgModuleFactory, NgZone, afterNextRender, ɵConsole, ɵInitialRenderPendingTasks, ɵɵsanitizeUrlOrResourceUrl, booleanAttribute, Attribute, HostBinding, HostListener, Optional, ContentChildren, makeEnvironmentProviders, APP_BOOTSTRAP_LISTENER, ENVIRONMENT_INITIALIZER, Injector, ApplicationRef, APP_INITIALIZER, NgProbeToken, SkipSelf, NgModule, Inject, Version } from '@angular/core';
9
9
  import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, concat, defer, pipe, throwError, EMPTY, ConnectableObservable, Subject, Subscription } from 'rxjs';
10
10
  import * as i3 from '@angular/common';
11
11
  import { Location, ViewportScroller, LOCATION_INITIALIZED, LocationStrategy, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
@@ -114,8 +114,8 @@ function shallowEqualArrays(a, b) {
114
114
  function shallowEqual(a, b) {
115
115
  // While `undefined` should never be possible, it would sometimes be the case in IE 11
116
116
  // and pre-chromium Edge. The check below accounts for this edge case.
117
- const k1 = a ? Object.keys(a) : undefined;
118
- const k2 = b ? Object.keys(b) : undefined;
117
+ const k1 = a ? getDataKeys(a) : undefined;
118
+ const k2 = b ? getDataKeys(b) : undefined;
119
119
  if (!k1 || !k2 || k1.length != k2.length) {
120
120
  return false;
121
121
  }
@@ -128,6 +128,12 @@ function shallowEqual(a, b) {
128
128
  }
129
129
  return true;
130
130
  }
131
+ /**
132
+ * Gets the keys of an object, including `symbol` keys.
133
+ */
134
+ function getDataKeys(obj) {
135
+ return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
136
+ }
131
137
  /**
132
138
  * Test equality for arrays of strings or a string.
133
139
  */
@@ -419,10 +425,10 @@ function mapChildrenIntoArray(segment, fn) {
419
425
  * @publicApi
420
426
  */
421
427
  class UrlSerializer {
422
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
423
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
428
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
429
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlSerializer, providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }); }
424
430
  }
425
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlSerializer, decorators: [{
431
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlSerializer, decorators: [{
426
432
  type: Injectable,
427
433
  args: [{ providedIn: 'root', useFactory: () => new DefaultUrlSerializer() }]
428
434
  }] });
@@ -1779,10 +1785,10 @@ class ChildrenOutletContexts {
1779
1785
  getContext(childName) {
1780
1786
  return this.contexts.get(childName) || null;
1781
1787
  }
1782
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1783
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1788
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1789
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, providedIn: 'root' }); }
1784
1790
  }
1785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: ChildrenOutletContexts, decorators: [{
1786
1792
  type: Injectable,
1787
1793
  args: [{ providedIn: 'root' }]
1788
1794
  }] });
@@ -2489,10 +2495,10 @@ class RouterOutlet {
2489
2495
  this.inputBinder?.bindActivatedRouteToOutletComponent(this);
2490
2496
  this.activateEvents.emit(this.activated.instance);
2491
2497
  }
2492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2493
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.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 }); }
2498
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2499
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.4", 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 }); }
2494
2500
  }
2495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterOutlet, decorators: [{
2501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterOutlet, decorators: [{
2496
2502
  type: Directive,
2497
2503
  args: [{
2498
2504
  selector: 'router-outlet',
@@ -2595,10 +2601,10 @@ class RoutedComponentInputBinder {
2595
2601
  });
2596
2602
  this.outletDataSubscriptions.set(outlet, dataSubscription);
2597
2603
  }
2598
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2599
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RoutedComponentInputBinder }); }
2604
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RoutedComponentInputBinder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2605
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RoutedComponentInputBinder }); }
2600
2606
  }
2601
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RoutedComponentInputBinder, decorators: [{
2602
2608
  type: Injectable
2603
2609
  }] });
2604
2610
 
@@ -2678,10 +2684,10 @@ function isNavigationCancelingError$1(error) {
2678
2684
  * to this `EmptyOutletComponent`.
2679
2685
  */
2680
2686
  class ɵEmptyOutletComponent {
2681
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2682
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0-next.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"] }] }); }
2687
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: ɵEmptyOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2688
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.0-next.4", 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"] }] }); }
2683
2689
  }
2684
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: ɵEmptyOutletComponent, decorators: [{
2685
2691
  type: Component,
2686
2692
  args: [{
2687
2693
  template: `<router-outlet></router-outlet>`,
@@ -3419,8 +3425,9 @@ class NoMatch {
3419
3425
  this.segmentGroup = segmentGroup || null;
3420
3426
  }
3421
3427
  }
3422
- class AbsoluteRedirect {
3428
+ class AbsoluteRedirect extends Error {
3423
3429
  constructor(urlTree) {
3430
+ super();
3424
3431
  this.urlTree = urlTree;
3425
3432
  }
3426
3433
  }
@@ -3462,7 +3469,11 @@ class ApplyRedirects {
3462
3469
  }
3463
3470
  }
3464
3471
  applyRedirectCommands(segments, redirectTo, posParams) {
3465
- return this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3472
+ const newTree = this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
3473
+ if (redirectTo.startsWith('/')) {
3474
+ throw new AbsoluteRedirect(newTree);
3475
+ }
3476
+ return newTree;
3466
3477
  }
3467
3478
  applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
3468
3479
  const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
@@ -3642,6 +3653,13 @@ function noLeftoversInUrl(segmentGroup, segments, outlet) {
3642
3653
  return segments.length === 0 && !segmentGroup.children[outlet];
3643
3654
  }
3644
3655
 
3656
+ /**
3657
+ * Class used to indicate there were no additional route config matches but that all segments of
3658
+ * the URL were consumed during matching so the route was URL matched. When this happens, we still
3659
+ * try to match child configs in case there are empty path children.
3660
+ */
3661
+ class NoLeftoversInUrl {
3662
+ }
3645
3663
  function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly') {
3646
3664
  return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer)
3647
3665
  .recognize();
@@ -3713,7 +3731,8 @@ class Recognizer {
3713
3731
  if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
3714
3732
  return this.processChildren(injector, config, segmentGroup);
3715
3733
  }
3716
- return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true);
3734
+ return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true)
3735
+ .pipe(map(child => child instanceof TreeNode ? [child] : []));
3717
3736
  }
3718
3737
  /**
3719
3738
  * Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
@@ -3775,7 +3794,7 @@ class Recognizer {
3775
3794
  }), first((x) => !!x), catchError(e => {
3776
3795
  if (isEmptyError(e)) {
3777
3796
  if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
3778
- return of([]);
3797
+ return of(new NoLeftoversInUrl());
3779
3798
  }
3780
3799
  return noMatch$1(segmentGroup);
3781
3800
  }
@@ -3786,7 +3805,7 @@ class Recognizer {
3786
3805
  if (!isImmediateMatch(route, rawSegment, segments, outlet))
3787
3806
  return noMatch$1(rawSegment);
3788
3807
  if (route.redirectTo === undefined) {
3789
- return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects);
3808
+ return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet);
3790
3809
  }
3791
3810
  if (allowRedirects && this.allowRedirects) {
3792
3811
  return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet);
@@ -3794,45 +3813,20 @@ class Recognizer {
3794
3813
  return noMatch$1(rawSegment);
3795
3814
  }
3796
3815
  expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3797
- if (route.path === '**') {
3798
- return this.expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet);
3799
- }
3800
- return this.expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet);
3801
- }
3802
- expandWildCardWithParamsAgainstRouteUsingRedirect(injector, routes, route, outlet) {
3803
- const newTree = this.applyRedirects.applyRedirectCommands([], route.redirectTo, {});
3804
- if (route.redirectTo.startsWith('/')) {
3805
- return absoluteRedirect(newTree);
3806
- }
3807
- return this.applyRedirects.lineralizeSegments(route, newTree)
3808
- .pipe(mergeMap((newSegments) => {
3809
- const group = new UrlSegmentGroup(newSegments, {});
3810
- return this.processSegment(injector, routes, group, newSegments, outlet, false);
3811
- }));
3812
- }
3813
- expandRegularSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
3814
- const { matched, consumedSegments, remainingSegments, positionalParamSegments } = match(segmentGroup, route, segments);
3816
+ const { matched, consumedSegments, positionalParamSegments, remainingSegments, } = route.path === '**' ? createWildcardMatchResult(segments) :
3817
+ match(segmentGroup, route, segments);
3815
3818
  if (!matched)
3816
3819
  return noMatch$1(segmentGroup);
3817
3820
  const newTree = this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);
3818
- if (route.redirectTo.startsWith('/')) {
3819
- return absoluteRedirect(newTree);
3820
- }
3821
3821
  return this.applyRedirects.lineralizeSegments(route, newTree)
3822
3822
  .pipe(mergeMap((newSegments) => {
3823
3823
  return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false);
3824
3824
  }));
3825
3825
  }
3826
- matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, allowRedirects) {
3826
+ matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet) {
3827
3827
  let matchResult;
3828
3828
  if (route.path === '**') {
3829
- const params = segments.length > 0 ? last(segments).parameters : {};
3830
- const snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3831
- matchResult = of({
3832
- snapshot,
3833
- consumedSegments: [],
3834
- remainingSegments: [],
3835
- });
3829
+ matchResult = of(createWildcardMatchResult(segments));
3836
3830
  // Prior versions of the route matching algorithm would stop matching at the wildcard route.
3837
3831
  // We should investigate a better strategy for any existing children. Otherwise, these
3838
3832
  // child segments are silently dropped from the navigation.
@@ -3840,18 +3834,10 @@ class Recognizer {
3840
3834
  rawSegment.children = {};
3841
3835
  }
3842
3836
  else {
3843
- matchResult =
3844
- matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer)
3845
- .pipe(map(({ matched, consumedSegments, remainingSegments, parameters }) => {
3846
- if (!matched) {
3847
- return null;
3848
- }
3849
- const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3850
- return { snapshot, consumedSegments, remainingSegments };
3851
- }));
3837
+ matchResult = matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer);
3852
3838
  }
3853
3839
  return matchResult.pipe(switchMap((result) => {
3854
- if (result === null) {
3840
+ if (!result.matched) {
3855
3841
  return noMatch$1(rawSegment);
3856
3842
  }
3857
3843
  // If the route has an injector created from providers, we should start using that.
@@ -3859,7 +3845,8 @@ class Recognizer {
3859
3845
  return this.getChildConfig(injector, route, segments)
3860
3846
  .pipe(switchMap(({ routes: childConfig }) => {
3861
3847
  const childInjector = route._loadedInjector ?? injector;
3862
- const { snapshot, consumedSegments, remainingSegments } = result;
3848
+ const { consumedSegments, remainingSegments, parameters } = result;
3849
+ const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({ ...this.urlTree.queryParams }), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
3863
3850
  const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments, childConfig);
3864
3851
  if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
3865
3852
  return this.processChildren(childInjector, childConfig, segmentGroup)
@@ -3867,11 +3854,11 @@ class Recognizer {
3867
3854
  if (children === null) {
3868
3855
  return null;
3869
3856
  }
3870
- return [new TreeNode(snapshot, children)];
3857
+ return new TreeNode(snapshot, children);
3871
3858
  }));
3872
3859
  }
3873
3860
  if (childConfig.length === 0 && slicedSegments.length === 0) {
3874
- return of([new TreeNode(snapshot, [])]);
3861
+ return of(new TreeNode(snapshot, []));
3875
3862
  }
3876
3863
  const matchedOnOutlet = getOutlet(route) === outlet;
3877
3864
  // If we matched a config due to empty path match on a different outlet, we need to
@@ -3884,8 +3871,8 @@ class Recognizer {
3884
3871
  // Notice that the children of the named outlet are configured with the primary outlet
3885
3872
  return this
3886
3873
  .processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true)
3887
- .pipe(map(children => {
3888
- return [new TreeNode(snapshot, children)];
3874
+ .pipe(map(child => {
3875
+ return new TreeNode(snapshot, child instanceof TreeNode ? [child] : []);
3889
3876
  }));
3890
3877
  }));
3891
3878
  }));
@@ -3980,6 +3967,15 @@ function getData(route) {
3980
3967
  function getResolve(route) {
3981
3968
  return route.resolve || {};
3982
3969
  }
3970
+ function createWildcardMatchResult(segments) {
3971
+ return {
3972
+ matched: true,
3973
+ parameters: segments.length > 0 ? last(segments).parameters : {},
3974
+ consumedSegments: segments,
3975
+ remainingSegments: [],
3976
+ positionalParamSegments: {},
3977
+ };
3978
+ }
3983
3979
 
3984
3980
  function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy) {
3985
3981
  return mergeMap(t => recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy)
@@ -4025,9 +4021,6 @@ function resolveNode(resolve, futureARS, futureRSS, injector) {
4025
4021
  data[key] = value;
4026
4022
  }))), takeLast(1), mapTo(data), catchError((e) => isEmptyError(e) ? EMPTY : throwError(e)));
4027
4023
  }
4028
- function getDataKeys(obj) {
4029
- return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
4030
- }
4031
4024
  function getResolver(injectionToken, futureARS, futureRSS, injector) {
4032
4025
  const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
4033
4026
  const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);
@@ -4099,10 +4092,10 @@ class TitleStrategy {
4099
4092
  getResolvedTitleForRoute(snapshot) {
4100
4093
  return snapshot.data[RouteTitleKey];
4101
4094
  }
4102
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4103
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4095
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: TitleStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4096
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: TitleStrategy, providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }); }
4104
4097
  }
4105
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: TitleStrategy, decorators: [{
4098
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: TitleStrategy, decorators: [{
4106
4099
  type: Injectable,
4107
4100
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultTitleStrategy) }]
4108
4101
  }] });
@@ -4125,10 +4118,10 @@ class DefaultTitleStrategy extends TitleStrategy {
4125
4118
  this.title.setTitle(title);
4126
4119
  }
4127
4120
  }
4128
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4129
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultTitleStrategy, deps: [{ token: i1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
4122
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultTitleStrategy, providedIn: 'root' }); }
4130
4123
  }
4131
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultTitleStrategy, decorators: [{
4132
4125
  type: Injectable,
4133
4126
  args: [{ providedIn: 'root' }]
4134
4127
  }], ctorParameters: function () { return [{ type: i1.Title }]; } });
@@ -4242,10 +4235,10 @@ class RouterConfigLoader {
4242
4235
  }
4243
4236
  }));
4244
4237
  }
4245
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4246
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterConfigLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4239
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterConfigLoader, providedIn: 'root' }); }
4247
4240
  }
4248
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterConfigLoader, decorators: [{
4241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterConfigLoader, decorators: [{
4249
4242
  type: Injectable,
4250
4243
  args: [{ providedIn: 'root' }]
4251
4244
  }] });
@@ -4261,6 +4254,76 @@ function maybeUnwrapDefaultExport(input) {
4261
4254
  return isWrappedDefaultExport(input) ? input['default'] : input;
4262
4255
  }
4263
4256
 
4257
+ /**
4258
+ * @description
4259
+ *
4260
+ * Provides a way to migrate AngularJS applications to Angular.
4261
+ *
4262
+ * @publicApi
4263
+ */
4264
+ class UrlHandlingStrategy {
4265
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4266
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4267
+ }
4268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4269
+ type: Injectable,
4270
+ args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4271
+ }] });
4272
+ /**
4273
+ * @publicApi
4274
+ */
4275
+ class DefaultUrlHandlingStrategy {
4276
+ shouldProcessUrl(url) {
4277
+ return true;
4278
+ }
4279
+ extract(url) {
4280
+ return url;
4281
+ }
4282
+ merge(newUrlPart, wholeUrl) {
4283
+ return newUrlPart;
4284
+ }
4285
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4286
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4287
+ }
4288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4289
+ type: Injectable,
4290
+ args: [{ providedIn: 'root' }]
4291
+ }] });
4292
+
4293
+ /// <reference types="@types/dom-view-transitions" />
4294
+ const CREATE_VIEW_TRANSITION = new InjectionToken(ngDevMode ? 'view transition helper' : '');
4295
+ /**
4296
+ * A helper function for using browser view transitions. This function skips the call to
4297
+ * `startViewTransition` if the browser does not support it.
4298
+ *
4299
+ * @returns A Promise that resolves when the view transition callback begins.
4300
+ */
4301
+ function createViewTransition(injector) {
4302
+ // Create promises outside the Angular zone to avoid causing extra change detections
4303
+ return injector.get(NgZone).runOutsideAngular(() => {
4304
+ if (!document.startViewTransition) {
4305
+ return Promise.resolve();
4306
+ }
4307
+ let resolveViewTransitionStarted;
4308
+ const viewTransitionStarted = new Promise((resolve) => {
4309
+ resolveViewTransitionStarted = resolve;
4310
+ });
4311
+ document.startViewTransition(() => {
4312
+ resolveViewTransitionStarted();
4313
+ return createRenderPromise(injector);
4314
+ });
4315
+ return viewTransitionStarted;
4316
+ });
4317
+ }
4318
+ /**
4319
+ * Creates a promise that resolves after next render.
4320
+ */
4321
+ function createRenderPromise(injector) {
4322
+ return new Promise(resolve => {
4323
+ afterNextRender(resolve, { injector });
4324
+ });
4325
+ }
4326
+
4264
4327
  class NavigationTransitions {
4265
4328
  get hasRequestedNavigation() {
4266
4329
  return this.navigationId !== 0;
@@ -4287,6 +4350,8 @@ class NavigationTransitions {
4287
4350
  this.titleStrategy = inject(TitleStrategy);
4288
4351
  this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4289
4352
  this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
4353
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4354
+ this.createViewTransition = inject(CREATE_VIEW_TRANSITION, { optional: true });
4290
4355
  this.navigationId = 0;
4291
4356
  /**
4292
4357
  * Hook that enables you to pause navigation after the preactivation phase.
@@ -4315,8 +4380,8 @@ class NavigationTransitions {
4315
4380
  currentUrlTree: initialUrlTree,
4316
4381
  currentRawUrl: initialUrlTree,
4317
4382
  currentBrowserUrl: initialUrlTree,
4318
- extractedUrl: router.urlHandlingStrategy.extract(initialUrlTree),
4319
- urlAfterRedirects: router.urlHandlingStrategy.extract(initialUrlTree),
4383
+ extractedUrl: this.urlHandlingStrategy.extract(initialUrlTree),
4384
+ urlAfterRedirects: this.urlHandlingStrategy.extract(initialUrlTree),
4320
4385
  rawUrl: initialUrlTree,
4321
4386
  extras: {},
4322
4387
  resolve: null,
@@ -4333,7 +4398,7 @@ class NavigationTransitions {
4333
4398
  });
4334
4399
  return this.transitions.pipe(filter(t => t.id !== 0),
4335
4400
  // Extract URL
4336
- map(t => ({ ...t, extractedUrl: router.urlHandlingStrategy.extract(t.rawUrl) })),
4401
+ map(t => ({ ...t, extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })),
4337
4402
  // Using switchMap so we cancel executing navigations when a new one comes in
4338
4403
  switchMap(overallTransitionState => {
4339
4404
  this.currentTransition = overallTransitionState;
@@ -4372,7 +4437,7 @@ class NavigationTransitions {
4372
4437
  t.resolve(null);
4373
4438
  return EMPTY;
4374
4439
  }
4375
- if (router.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
4440
+ if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
4376
4441
  return of(t).pipe(
4377
4442
  // Fire NavigationStart event
4378
4443
  switchMap(t => {
@@ -4401,7 +4466,7 @@ class NavigationTransitions {
4401
4466
  }));
4402
4467
  }
4403
4468
  else if (urlTransition &&
4404
- router.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
4469
+ this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
4405
4470
  /* When the current URL shouldn't be processed, but the previous one
4406
4471
  * was, we handle this "error condition" by navigating to the
4407
4472
  * previously successful URL, but leaving the URL intact.*/
@@ -4415,6 +4480,7 @@ class NavigationTransitions {
4415
4480
  urlAfterRedirects: extractedUrl,
4416
4481
  extras: { ...extras, skipLocationChange: false, replaceUrl: false },
4417
4482
  };
4483
+ this.currentNavigation.finalUrl = extractedUrl;
4418
4484
  return of(overallTransitionState);
4419
4485
  }
4420
4486
  else {
@@ -4499,10 +4565,18 @@ class NavigationTransitions {
4499
4565
  };
4500
4566
  return combineLatest(loadComponents(t.targetSnapshot.root))
4501
4567
  .pipe(defaultIfEmpty(), take(1));
4502
- }), switchTap(() => this.afterPreactivation()), map((t) => {
4568
+ }), switchTap(() => this.afterPreactivation()), switchMap(() => {
4569
+ const viewTransitionStarted = this.createViewTransition?.(this.environmentInjector);
4570
+ // If view transitions are enabled, block the navigation until the view
4571
+ // transition callback starts. Otherwise, continue immediately.
4572
+ return viewTransitionStarted ?
4573
+ from(viewTransitionStarted).pipe(map(() => overallTransitionState)) :
4574
+ of(overallTransitionState);
4575
+ }), map((t) => {
4503
4576
  const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
4504
4577
  this.currentTransition =
4505
4578
  overallTransitionState = { ...t, targetRouterState };
4579
+ this.currentNavigation.targetRouterState = targetRouterState;
4506
4580
  return overallTransitionState;
4507
4581
  }), tap(() => {
4508
4582
  this.events.next(new BeforeActivateRoutes());
@@ -4586,10 +4660,10 @@ class NavigationTransitions {
4586
4660
  this.events.next(navCancel);
4587
4661
  t.resolve(false);
4588
4662
  }
4589
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4590
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4663
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4664
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
4591
4665
  }
4592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NavigationTransitions, decorators: [{
4666
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NavigationTransitions, decorators: [{
4593
4667
  type: Injectable,
4594
4668
  args: [{ providedIn: 'root' }]
4595
4669
  }], ctorParameters: function () { return []; } });
@@ -4605,10 +4679,10 @@ function isBrowserTriggeredNavigation(source) {
4605
4679
  * @publicApi
4606
4680
  */
4607
4681
  class RouteReuseStrategy {
4608
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4609
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4682
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouteReuseStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4683
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouteReuseStrategy, providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }); }
4610
4684
  }
4611
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4685
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouteReuseStrategy, decorators: [{
4612
4686
  type: Injectable,
4613
4687
  args: [{ providedIn: 'root', useFactory: () => inject(DefaultRouteReuseStrategy) }]
4614
4688
  }] });
@@ -4659,46 +4733,238 @@ class BaseRouteReuseStrategy {
4659
4733
  }
4660
4734
  }
4661
4735
  class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
4662
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4663
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4736
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultRouteReuseStrategy, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
4737
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultRouteReuseStrategy, providedIn: 'root' }); }
4664
4738
  }
4665
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4739
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: DefaultRouteReuseStrategy, decorators: [{
4666
4740
  type: Injectable,
4667
4741
  args: [{ providedIn: 'root' }]
4668
4742
  }] });
4669
4743
 
4670
- /**
4671
- * @description
4672
- *
4673
- * Provides a way to migrate AngularJS applications to Angular.
4674
- *
4675
- * @publicApi
4676
- */
4677
- class UrlHandlingStrategy {
4678
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4679
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlHandlingStrategy, providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }); }
4680
- }
4681
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: UrlHandlingStrategy, decorators: [{
4682
- type: Injectable,
4683
- args: [{ providedIn: 'root', useFactory: () => inject(DefaultUrlHandlingStrategy) }]
4684
- }] });
4685
- /**
4686
- * @publicApi
4687
- */
4688
- class DefaultUrlHandlingStrategy {
4689
- shouldProcessUrl(url) {
4690
- return true;
4744
+ class StateManager {
4745
+ constructor() {
4746
+ this.location = inject(Location);
4747
+ this.urlSerializer = inject(UrlSerializer);
4748
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4749
+ this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
4750
+ // These are currently writable via the Router public API but are deprecated and should be made
4751
+ // `private readonly` in the future.
4752
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4753
+ this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
4754
+ /**
4755
+ * Represents the activated `UrlTree` that the `Router` is configured to handle (through
4756
+ * `UrlHandlingStrategy`). That is, after we find the route config tree that we're going to
4757
+ * activate, run guards, and are just about to activate the route, we set the currentUrlTree.
4758
+ *
4759
+ * This should match the `browserUrlTree` when a navigation succeeds. If the
4760
+ * `UrlHandlingStrategy.shouldProcessUrl` is `false`, only the `browserUrlTree` is updated.
4761
+ * @internal
4762
+ */
4763
+ this.currentUrlTree = new UrlTree();
4764
+ /**
4765
+ * Meant to represent the entire browser url after a successful navigation. In the life of a
4766
+ * navigation transition:
4767
+ * 1. The rawUrl represents the full URL that's being navigated to
4768
+ * 2. We apply redirects, which might only apply to _part_ of the URL (due to
4769
+ * `UrlHandlingStrategy`).
4770
+ * 3. Right before activation (because we assume activation will succeed), we update the
4771
+ * rawUrlTree to be a combination of the urlAfterRedirects (again, this might only apply to part
4772
+ * of the initial url) and the rawUrl of the transition (which was the original navigation url in
4773
+ * its full form).
4774
+ * @internal
4775
+ *
4776
+ * Note that this is _only_ here to support `UrlHandlingStrategy.extract` and
4777
+ * `UrlHandlingStrategy.shouldProcessUrl`. If those didn't exist, we could get by with
4778
+ * `currentUrlTree` alone. If a new Router were to be provided (i.e. one that works with the
4779
+ * browser navigation API), we should think about whether this complexity should be carried over.
4780
+ *
4781
+ * - extract: `rawUrlTree` is needed because `extract` may only return part
4782
+ * of the navigation URL. Thus, `currentUrlTree` may only represent _part_ of the browser URL.
4783
+ * When a navigation gets cancelled and we need to reset the URL or a new navigation occurs, we
4784
+ * need to know the _whole_ browser URL, not just the part handled by UrlHandlingStrategy.
4785
+ * - shouldProcessUrl: When this returns `false`, the router just ignores the navigation but still
4786
+ * updates the `rawUrlTree` with the assumption that the navigation was caused by the location
4787
+ * change listener due to a URL update by the AngularJS router. In this case, we still need to
4788
+ * know what the browser's URL is for future navigations.
4789
+ *
4790
+ */
4791
+ this.rawUrlTree = this.currentUrlTree;
4792
+ /**
4793
+ * Meant to represent the part of the browser url that the `Router` is set up to handle (via the
4794
+ * `UrlHandlingStrategy`). This value is updated immediately after the browser url is updated (or
4795
+ * the browser url update is skipped via `skipLocationChange`). With that, note that
4796
+ * `browserUrlTree` _may not_ reflect the actual browser URL for two reasons:
4797
+ *
4798
+ * 1. `UrlHandlingStrategy` only handles part of the URL
4799
+ * 2. `skipLocationChange` does not update the browser url.
4800
+ *
4801
+ * So to reiterate, `browserUrlTree` only represents the Router's internal understanding of the
4802
+ * current route, either before guards with `urlUpdateStrategy === 'eager'` or right before
4803
+ * activation with `'deferred'`.
4804
+ *
4805
+ * This should match the `currentUrlTree` when the navigation succeeds.
4806
+ * @internal
4807
+ */
4808
+ this.browserUrlTree = this.currentUrlTree;
4809
+ /**
4810
+ * The id of the currently active page in the router.
4811
+ * Updated to the transition's target id on a successful navigation.
4812
+ *
4813
+ * This is used to track what page the router last activated. When an attempted navigation fails,
4814
+ * the router can then use this to compute how to restore the state back to the previously active
4815
+ * page.
4816
+ */
4817
+ this.currentPageId = 0;
4818
+ this.lastSuccessfulId = -1;
4819
+ this.routerState = createEmptyState(this.currentUrlTree, null);
4820
+ this.stateMemento = this.createStateMemento();
4691
4821
  }
4692
- extract(url) {
4693
- return url;
4822
+ /**
4823
+ * The ɵrouterPageId of whatever page is currently active in the browser history. This is
4824
+ * important for computing the target page id for new navigations because we need to ensure each
4825
+ * page id in the browser history is 1 more than the previous entry.
4826
+ */
4827
+ get browserPageId() {
4828
+ if (this.canceledNavigationResolution !== 'computed') {
4829
+ return this.currentPageId;
4830
+ }
4831
+ return this.location.getState()?.ɵrouterPageId ?? this.currentPageId;
4694
4832
  }
4695
- merge(newUrlPart, wholeUrl) {
4696
- return newUrlPart;
4833
+ createStateMemento() {
4834
+ return {
4835
+ rawUrlTree: this.rawUrlTree,
4836
+ browserUrlTree: this.browserUrlTree,
4837
+ currentUrlTree: this.currentUrlTree,
4838
+ routerState: this.routerState,
4839
+ };
4697
4840
  }
4698
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultUrlHandlingStrategy, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4699
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultUrlHandlingStrategy, providedIn: 'root' }); }
4841
+ handleNavigationEvent(e, currentTransition) {
4842
+ if (e instanceof NavigationStart) {
4843
+ this.stateMemento = this.createStateMemento();
4844
+ // If the source of the navigation is from a browser event, the URL is
4845
+ // already updated. We already need to sync the internal state.
4846
+ if (isBrowserTriggeredNavigation(currentTransition.trigger)) {
4847
+ this.browserUrlTree = currentTransition.extractedUrl;
4848
+ }
4849
+ }
4850
+ else if (e instanceof NavigationSkipped) {
4851
+ this.rawUrlTree = currentTransition.initialUrl;
4852
+ }
4853
+ else if (e instanceof RoutesRecognized) {
4854
+ if (this.urlUpdateStrategy === 'eager') {
4855
+ if (!currentTransition.extras.skipLocationChange) {
4856
+ const rawUrl = this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
4857
+ this.setBrowserUrl(rawUrl, currentTransition);
4858
+ }
4859
+ this.browserUrlTree = currentTransition.finalUrl;
4860
+ }
4861
+ }
4862
+ else if (e instanceof BeforeActivateRoutes) {
4863
+ this.currentUrlTree = currentTransition.finalUrl;
4864
+ this.rawUrlTree =
4865
+ this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
4866
+ this.routerState = currentTransition.targetRouterState;
4867
+ if (this.urlUpdateStrategy === 'deferred') {
4868
+ if (!currentTransition.extras.skipLocationChange) {
4869
+ this.setBrowserUrl(this.rawUrlTree, currentTransition);
4870
+ }
4871
+ this.browserUrlTree = currentTransition.finalUrl;
4872
+ }
4873
+ }
4874
+ else if (e instanceof NavigationCancel &&
4875
+ (e.code === 3 /* NavigationCancellationCode.GuardRejected */ ||
4876
+ e.code === 2 /* NavigationCancellationCode.NoDataFromResolver */)) {
4877
+ this.restoreHistory(currentTransition);
4878
+ }
4879
+ else if (e instanceof NavigationError) {
4880
+ this.restoreHistory(currentTransition, true);
4881
+ }
4882
+ else if (e instanceof NavigationEnd) {
4883
+ this.lastSuccessfulId = e.id;
4884
+ this.currentPageId = this.browserPageId;
4885
+ }
4886
+ }
4887
+ setBrowserUrl(url, transition) {
4888
+ const path = this.urlSerializer.serialize(url);
4889
+ if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
4890
+ // replacements do not update the target page
4891
+ const currentBrowserPageId = this.browserPageId;
4892
+ const state = {
4893
+ ...transition.extras.state,
4894
+ ...this.generateNgRouterState(transition.id, currentBrowserPageId)
4895
+ };
4896
+ this.location.replaceState(path, '', state);
4897
+ }
4898
+ else {
4899
+ const state = {
4900
+ ...transition.extras.state,
4901
+ ...this.generateNgRouterState(transition.id, this.browserPageId + 1)
4902
+ };
4903
+ this.location.go(path, '', state);
4904
+ }
4905
+ }
4906
+ /**
4907
+ * Performs the necessary rollback action to restore the browser URL to the
4908
+ * state before the transition.
4909
+ * @internal
4910
+ */
4911
+ restoreHistory(navigation, restoringFromCaughtError = false) {
4912
+ if (this.canceledNavigationResolution === 'computed') {
4913
+ const currentBrowserPageId = this.browserPageId;
4914
+ const targetPagePosition = this.currentPageId - currentBrowserPageId;
4915
+ if (targetPagePosition !== 0) {
4916
+ this.location.historyGo(targetPagePosition);
4917
+ }
4918
+ else if (this.currentUrlTree === navigation.finalUrl && targetPagePosition === 0) {
4919
+ // We got to the activation stage (where currentUrlTree is set to the navigation's
4920
+ // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
4921
+ // We still need to reset the router state back to what it was when the navigation started.
4922
+ this.resetState(navigation);
4923
+ // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
4924
+ // Investigate if this can be done by running TGP.
4925
+ this.browserUrlTree = this.stateMemento.browserUrlTree;
4926
+ this.resetUrlToCurrentUrlTree();
4927
+ }
4928
+ else {
4929
+ // The browser URL and router state was not updated before the navigation cancelled so
4930
+ // there's no restoration needed.
4931
+ }
4932
+ }
4933
+ else if (this.canceledNavigationResolution === 'replace') {
4934
+ // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
4935
+ // for `deferred` navigations that haven't change the internal state yet because guards
4936
+ // reject. For 'eager' navigations, it seems like we also really should reset the state
4937
+ // because the navigation was cancelled. Investigate if this can be done by running TGP.
4938
+ if (restoringFromCaughtError) {
4939
+ this.resetState(navigation);
4940
+ }
4941
+ this.resetUrlToCurrentUrlTree();
4942
+ }
4943
+ }
4944
+ resetState(navigation) {
4945
+ this.routerState = this.stateMemento.routerState;
4946
+ this.currentUrlTree = this.stateMemento.currentUrlTree;
4947
+ // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
4948
+ // configured to handle only part of the navigation URL. This means we would only want to reset
4949
+ // the part of the navigation handled by the Angular router rather than the whole URL. In
4950
+ // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
4951
+ // when merging, such as the query params so they are not lost on a refresh.
4952
+ this.rawUrlTree =
4953
+ this.urlHandlingStrategy.merge(this.currentUrlTree, navigation.finalUrl ?? this.rawUrlTree);
4954
+ }
4955
+ resetUrlToCurrentUrlTree() {
4956
+ this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
4957
+ }
4958
+ generateNgRouterState(navigationId, routerPageId) {
4959
+ if (this.canceledNavigationResolution === 'computed') {
4960
+ return { navigationId, ɵrouterPageId: routerPageId };
4961
+ }
4962
+ return { navigationId };
4963
+ }
4964
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: StateManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4965
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: StateManager, providedIn: 'root' }); }
4700
4966
  }
4701
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: DefaultUrlHandlingStrategy, decorators: [{
4967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: StateManager, decorators: [{
4702
4968
  type: Injectable,
4703
4969
  args: [{ providedIn: 'root' }]
4704
4970
  }] });
@@ -4775,21 +5041,14 @@ const subsetMatchOptions = {
4775
5041
  * @publicApi
4776
5042
  */
4777
5043
  class Router {
4778
- // TODO(b/260747083): This should not exist and navigationId should be private in
4779
- // `NavigationTransitions`
4780
- get navigationId() {
4781
- return this.navigationTransitions.navigationId;
5044
+ get currentUrlTree() {
5045
+ return this.stateManager.currentUrlTree;
4782
5046
  }
4783
- /**
4784
- * The ɵrouterPageId of whatever page is currently active in the browser history. This is
4785
- * important for computing the target page id for new navigations because we need to ensure each
4786
- * page id in the browser history is 1 more than the previous entry.
4787
- */
4788
- get browserPageId() {
4789
- if (this.canceledNavigationResolution !== 'computed') {
4790
- return this.currentPageId;
4791
- }
4792
- return this.location.getState()?.ɵrouterPageId ?? this.currentPageId;
5047
+ get rawUrlTree() {
5048
+ return this.stateManager.rawUrlTree;
5049
+ }
5050
+ get browserUrlTree() {
5051
+ return this.stateManager.browserUrlTree;
4793
5052
  }
4794
5053
  /**
4795
5054
  * An event stream for routing events.
@@ -4801,27 +5060,30 @@ class Router {
4801
5060
  // the change.
4802
5061
  return this._events;
4803
5062
  }
5063
+ /**
5064
+ * The current state of routing in this NgModule.
5065
+ */
5066
+ get routerState() {
5067
+ return this.stateManager.routerState;
5068
+ }
4804
5069
  constructor() {
4805
5070
  this.disposed = false;
4806
- /**
4807
- * The id of the currently active page in the router.
4808
- * Updated to the transition's target id on a successful navigation.
4809
- *
4810
- * This is used to track what page the router last activated. When an attempted navigation fails,
4811
- * the router can then use this to compute how to restore the state back to the previously active
4812
- * page.
4813
- */
4814
- this.currentPageId = 0;
4815
- this.console = inject(ɵConsole);
4816
5071
  this.isNgZoneEnabled = false;
5072
+ this.console = inject(ɵConsole);
5073
+ this.stateManager = inject(StateManager);
5074
+ this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
5075
+ this.pendingTasks = inject(ɵInitialRenderPendingTasks);
5076
+ this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
5077
+ this.navigationTransitions = inject(NavigationTransitions);
5078
+ this.urlSerializer = inject(UrlSerializer);
5079
+ this.location = inject(Location);
5080
+ this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4817
5081
  /**
4818
5082
  * The private `Subject` type for the public events exposed in the getter. This is used internally
4819
5083
  * to push events to. The separate field allows us to expose separate types in the public API
4820
5084
  * (i.e., an Observable rather than the Subject).
4821
5085
  */
4822
5086
  this._events = new Subject();
4823
- this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
4824
- this.pendingTasks = inject(ɵInitialRenderPendingTasks);
4825
5087
  /**
4826
5088
  * A handler for navigation errors in this NgModule.
4827
5089
  *
@@ -4844,15 +5106,6 @@ class Router {
4844
5106
  * false otherwise.
4845
5107
  */
4846
5108
  this.navigated = false;
4847
- this.lastSuccessfulId = -1;
4848
- /**
4849
- * A strategy for extracting and merging URLs.
4850
- * Used for AngularJS to Angular migrations.
4851
- *
4852
- * @deprecated Configure using `providers` instead:
4853
- * `{provide: UrlHandlingStrategy, useClass: MyStrategy}`.
4854
- */
4855
- this.urlHandlingStrategy = inject(UrlHandlingStrategy);
4856
5109
  /**
4857
5110
  * A strategy for re-using routes.
4858
5111
  *
@@ -4870,37 +5123,7 @@ class Router {
4870
5123
  * @see {@link RouterModule}
4871
5124
  */
4872
5125
  this.onSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';
4873
- this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
4874
- /**
4875
- * Configures how the Router attempts to restore state when a navigation is cancelled.
4876
- *
4877
- * 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
4878
- * router before the navigation started. This means that if the URL of the browser is updated
4879
- * _before_ the navigation is canceled, the Router will simply replace the item in history rather
4880
- * than trying to restore to the previous location in the session history. This happens most
4881
- * frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward
4882
- * buttons.
4883
- *
4884
- * 'computed' - Will attempt to return to the same index in the session history that corresponds
4885
- * to the Angular route when the navigation gets cancelled. For example, if the browser back
4886
- * button is clicked and the navigation is cancelled, the Router will trigger a forward navigation
4887
- * and vice versa.
4888
- *
4889
- * Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only
4890
- * handles a portion of the URL because the history restoration navigates to the previous place in
4891
- * the browser history rather than simply resetting a portion of the URL.
4892
- *
4893
- * The default value is `replace`.
4894
- *
4895
- * @see {@link withRouterConfig}
4896
- * @see {@link provideRouter}
4897
- * @see {@link RouterModule}
4898
- */
4899
- this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
4900
5126
  this.config = inject(ROUTES, { optional: true })?.flat() ?? [];
4901
- this.navigationTransitions = inject(NavigationTransitions);
4902
- this.urlSerializer = inject(UrlSerializer);
4903
- this.location = inject(Location);
4904
5127
  /**
4905
5128
  * Indicates whether the application has opted in to binding Router data to component inputs.
4906
5129
  *
@@ -4911,94 +5134,48 @@ class Router {
4911
5134
  this.eventsSubscription = new Subscription();
4912
5135
  this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
4913
5136
  this.resetConfig(this.config);
4914
- this.currentUrlTree = new UrlTree();
4915
- this.rawUrlTree = this.currentUrlTree;
4916
- this.browserUrlTree = this.currentUrlTree;
4917
- this.routerState = createEmptyState(this.currentUrlTree, null);
4918
5137
  this.navigationTransitions.setupNavigations(this, this.currentUrlTree, this.routerState)
4919
- .subscribe(t => {
4920
- this.lastSuccessfulId = t.id;
4921
- this.currentPageId = this.browserPageId;
4922
- }, e => {
4923
- this.console.warn(`Unhandled Navigation Error: ${e}`);
5138
+ .subscribe({
5139
+ error: (e) => {
5140
+ this.console.warn(ngDevMode ? `Unhandled Navigation Error: ${e}` : e);
5141
+ }
4924
5142
  });
4925
5143
  this.subscribeToNavigationEvents();
4926
5144
  }
4927
5145
  subscribeToNavigationEvents() {
4928
5146
  const subscription = this.navigationTransitions.events.subscribe(e => {
4929
5147
  try {
4930
- const { currentTransition } = this.navigationTransitions;
4931
- if (currentTransition === null) {
4932
- if (isPublicRouterEvent(e)) {
4933
- this._events.next(e);
4934
- }
4935
- return;
4936
- }
4937
- if (e instanceof NavigationStart) {
4938
- // If the source of the navigation is from a browser event, the URL is
4939
- // already updated. We already need to sync the internal state.
4940
- if (isBrowserTriggeredNavigation(currentTransition.source)) {
4941
- this.browserUrlTree = currentTransition.extractedUrl;
4942
- }
4943
- }
4944
- else if (e instanceof NavigationSkipped) {
4945
- this.rawUrlTree = currentTransition.rawUrl;
4946
- }
4947
- else if (e instanceof RoutesRecognized) {
4948
- if (this.urlUpdateStrategy === 'eager') {
4949
- if (!currentTransition.extras.skipLocationChange) {
4950
- const rawUrl = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4951
- this.setBrowserUrl(rawUrl, currentTransition);
4952
- }
4953
- this.browserUrlTree = currentTransition.urlAfterRedirects;
4954
- }
4955
- }
4956
- else if (e instanceof BeforeActivateRoutes) {
4957
- this.currentUrlTree = currentTransition.urlAfterRedirects;
4958
- this.rawUrlTree = this.urlHandlingStrategy.merge(currentTransition.urlAfterRedirects, currentTransition.rawUrl);
4959
- this.routerState = currentTransition.targetRouterState;
4960
- if (this.urlUpdateStrategy === 'deferred') {
4961
- if (!currentTransition.extras.skipLocationChange) {
4962
- this.setBrowserUrl(this.rawUrlTree, currentTransition);
4963
- }
4964
- this.browserUrlTree = currentTransition.urlAfterRedirects;
4965
- }
4966
- }
4967
- else if (e instanceof NavigationCancel) {
4968
- if (e.code !== 0 /* NavigationCancellationCode.Redirect */ &&
5148
+ const currentTransition = this.navigationTransitions.currentTransition;
5149
+ const currentNavigation = this.navigationTransitions.currentNavigation;
5150
+ if (currentTransition !== null && currentNavigation !== null) {
5151
+ this.stateManager.handleNavigationEvent(e, currentNavigation);
5152
+ if (e instanceof NavigationCancel && e.code !== 0 /* NavigationCancellationCode.Redirect */ &&
4969
5153
  e.code !== 1 /* NavigationCancellationCode.SupersededByNewNavigation */) {
4970
5154
  // It seems weird that `navigated` is set to `true` when the navigation is rejected,
4971
5155
  // however it's how things were written initially. Investigation would need to be done
4972
5156
  // to determine if this can be removed.
4973
5157
  this.navigated = true;
4974
5158
  }
4975
- if (e.code === 3 /* NavigationCancellationCode.GuardRejected */ ||
4976
- e.code === 2 /* NavigationCancellationCode.NoDataFromResolver */) {
4977
- this.restoreHistory(currentTransition);
5159
+ else if (e instanceof NavigationEnd) {
5160
+ this.navigated = true;
5161
+ }
5162
+ else if (e instanceof RedirectRequest) {
5163
+ const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
5164
+ const extras = {
5165
+ skipLocationChange: currentTransition.extras.skipLocationChange,
5166
+ // The URL is already updated at this point if we have 'eager' URL
5167
+ // updates or if the navigation was triggered by the browser (back
5168
+ // button, URL bar, etc). We want to replace that item in history
5169
+ // if the navigation is rejected.
5170
+ replaceUrl: this.urlUpdateStrategy === 'eager' ||
5171
+ isBrowserTriggeredNavigation(currentTransition.source)
5172
+ };
5173
+ this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
5174
+ resolve: currentTransition.resolve,
5175
+ reject: currentTransition.reject,
5176
+ promise: currentTransition.promise
5177
+ });
4978
5178
  }
4979
- }
4980
- else if (e instanceof RedirectRequest) {
4981
- const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
4982
- const extras = {
4983
- skipLocationChange: currentTransition.extras.skipLocationChange,
4984
- // The URL is already updated at this point if we have 'eager' URL
4985
- // updates or if the navigation was triggered by the browser (back
4986
- // button, URL bar, etc). We want to replace that item in history
4987
- // if the navigation is rejected.
4988
- replaceUrl: this.urlUpdateStrategy === 'eager' ||
4989
- isBrowserTriggeredNavigation(currentTransition.source)
4990
- };
4991
- this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
4992
- resolve: currentTransition.resolve,
4993
- reject: currentTransition.reject,
4994
- promise: currentTransition.promise
4995
- });
4996
- }
4997
- if (e instanceof NavigationError) {
4998
- this.restoreHistory(currentTransition, true);
4999
- }
5000
- if (e instanceof NavigationEnd) {
5001
- this.navigated = true;
5002
5179
  }
5003
5180
  // Note that it's important to have the Router process the events _before_ the event is
5004
5181
  // pushed through the public observable. This ensures the correct router state is in place
@@ -5120,7 +5297,6 @@ class Router {
5120
5297
  (typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(config);
5121
5298
  this.config = config.map(standardizeConfig);
5122
5299
  this.navigated = false;
5123
- this.lastSuccessfulId = -1;
5124
5300
  }
5125
5301
  /** @nodoc */
5126
5302
  ngOnDestroy() {
@@ -5337,7 +5513,6 @@ class Router {
5337
5513
  return result;
5338
5514
  }, {});
5339
5515
  }
5340
- /** @internal */
5341
5516
  scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
5342
5517
  if (this.disposed) {
5343
5518
  return Promise.resolve(false);
@@ -5383,88 +5558,10 @@ class Router {
5383
5558
  return Promise.reject(e);
5384
5559
  });
5385
5560
  }
5386
- /** @internal */
5387
- setBrowserUrl(url, transition) {
5388
- const path = this.urlSerializer.serialize(url);
5389
- if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
5390
- // replacements do not update the target page
5391
- const currentBrowserPageId = this.browserPageId;
5392
- const state = {
5393
- ...transition.extras.state,
5394
- ...this.generateNgRouterState(transition.id, currentBrowserPageId)
5395
- };
5396
- this.location.replaceState(path, '', state);
5397
- }
5398
- else {
5399
- const state = {
5400
- ...transition.extras.state,
5401
- ...this.generateNgRouterState(transition.id, this.browserPageId + 1)
5402
- };
5403
- this.location.go(path, '', state);
5404
- }
5405
- }
5406
- /**
5407
- * Performs the necessary rollback action to restore the browser URL to the
5408
- * state before the transition.
5409
- * @internal
5410
- */
5411
- restoreHistory(transition, restoringFromCaughtError = false) {
5412
- if (this.canceledNavigationResolution === 'computed') {
5413
- const currentBrowserPageId = this.browserPageId;
5414
- const targetPagePosition = this.currentPageId - currentBrowserPageId;
5415
- if (targetPagePosition !== 0) {
5416
- this.location.historyGo(targetPagePosition);
5417
- }
5418
- else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
5419
- targetPagePosition === 0) {
5420
- // We got to the activation stage (where currentUrlTree is set to the navigation's
5421
- // finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
5422
- // We still need to reset the router state back to what it was when the navigation started.
5423
- this.resetState(transition);
5424
- // TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
5425
- // Investigate if this can be done by running TGP.
5426
- this.browserUrlTree = transition.currentUrlTree;
5427
- this.resetUrlToCurrentUrlTree();
5428
- }
5429
- else {
5430
- // The browser URL and router state was not updated before the navigation cancelled so
5431
- // there's no restoration needed.
5432
- }
5433
- }
5434
- else if (this.canceledNavigationResolution === 'replace') {
5435
- // TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
5436
- // for `deferred` navigations that haven't change the internal state yet because guards
5437
- // reject. For 'eager' navigations, it seems like we also really should reset the state
5438
- // because the navigation was cancelled. Investigate if this can be done by running TGP.
5439
- if (restoringFromCaughtError) {
5440
- this.resetState(transition);
5441
- }
5442
- this.resetUrlToCurrentUrlTree();
5443
- }
5444
- }
5445
- resetState(t) {
5446
- this.routerState = t.currentRouterState;
5447
- this.currentUrlTree = t.currentUrlTree;
5448
- // Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
5449
- // configured to handle only part of the navigation URL. This means we would only want to reset
5450
- // the part of the navigation handled by the Angular router rather than the whole URL. In
5451
- // addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
5452
- // when merging, such as the query params so they are not lost on a refresh.
5453
- this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
5454
- }
5455
- resetUrlToCurrentUrlTree() {
5456
- this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
5457
- }
5458
- generateNgRouterState(navigationId, routerPageId) {
5459
- if (this.canceledNavigationResolution === 'computed') {
5460
- return { navigationId, ɵrouterPageId: routerPageId };
5461
- }
5462
- return { navigationId };
5463
- }
5464
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5465
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: Router, providedIn: 'root' }); }
5561
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5562
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: Router, providedIn: 'root' }); }
5466
5563
  }
5467
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: Router, decorators: [{
5564
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: Router, decorators: [{
5468
5565
  type: Injectable,
5469
5566
  args: [{ providedIn: 'root' }]
5470
5567
  }], ctorParameters: function () { return []; } });
@@ -5735,10 +5832,10 @@ class RouterLink {
5735
5832
  preserveFragment: this.preserveFragment,
5736
5833
  });
5737
5834
  }
5738
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.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 }); }
5739
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "17.0.0-next.2", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5835
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", 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 }); }
5836
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "17.0.0-next.4", type: RouterLink, isStandalone: true, selector: "[routerLink]", inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", relativeTo: "relativeTo", preserveFragment: ["preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: ["skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: ["replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, host: { listeners: { "click": "onClick($event.button,$event.ctrlKey,$event.shiftKey,$event.altKey,$event.metaKey)" }, properties: { "attr.target": "this.target" } }, usesOnChanges: true, ngImport: i0 }); }
5740
5837
  }
5741
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterLink, decorators: [{
5838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterLink, decorators: [{
5742
5839
  type: Directive,
5743
5840
  args: [{
5744
5841
  selector: '[routerLink]',
@@ -5961,10 +6058,10 @@ class RouterLinkActive {
5961
6058
  const isActiveCheckFn = this.isLinkActive(this.router);
5962
6059
  return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
5963
6060
  }
5964
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.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 }); }
5965
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.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 }); }
6061
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterLinkActive, deps: [{ token: Router }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: RouterLink, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
6062
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.0-next.4", 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 }); }
5966
6063
  }
5967
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterLinkActive, decorators: [{
6064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterLinkActive, decorators: [{
5968
6065
  type: Directive,
5969
6066
  args: [{
5970
6067
  selector: '[routerLinkActive]',
@@ -6016,10 +6113,10 @@ class PreloadAllModules {
6016
6113
  preload(route, fn) {
6017
6114
  return fn().pipe(catchError(() => of(null)));
6018
6115
  }
6019
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6020
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
6116
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: PreloadAllModules, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6117
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: PreloadAllModules, providedIn: 'root' }); }
6021
6118
  }
6022
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: PreloadAllModules, decorators: [{
6119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: PreloadAllModules, decorators: [{
6023
6120
  type: Injectable,
6024
6121
  args: [{ providedIn: 'root' }]
6025
6122
  }] });
@@ -6036,10 +6133,10 @@ class NoPreloading {
6036
6133
  preload(route, fn) {
6037
6134
  return of(null);
6038
6135
  }
6039
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6040
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NoPreloading, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6137
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NoPreloading, providedIn: 'root' }); }
6041
6138
  }
6042
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: NoPreloading, decorators: [{
6139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: NoPreloading, decorators: [{
6043
6140
  type: Injectable,
6044
6141
  args: [{ providedIn: 'root' }]
6045
6142
  }] });
@@ -6132,10 +6229,10 @@ class RouterPreloader {
6132
6229
  }
6133
6230
  });
6134
6231
  }
6135
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6136
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6232
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterPreloader, deps: [{ token: Router }, { token: i0.Compiler }, { token: i0.EnvironmentInjector }, { token: PreloadingStrategy }, { token: RouterConfigLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
6233
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterPreloader, providedIn: 'root' }); }
6137
6234
  }
6138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterPreloader, decorators: [{
6235
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterPreloader, decorators: [{
6139
6236
  type: Injectable,
6140
6237
  args: [{ providedIn: 'root' }]
6141
6238
  }], ctorParameters: function () { return [{ type: Router }, { type: i0.Compiler }, { type: i0.EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }]; } });
@@ -6228,10 +6325,10 @@ class RouterScroller {
6228
6325
  this.routerEventsSubscription?.unsubscribe();
6229
6326
  this.scrollEventsSubscription?.unsubscribe();
6230
6327
  }
6231
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6232
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterScroller }); }
6328
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterScroller, deps: "invalid", target: i0.ɵɵFactoryTarget.Injectable }); }
6329
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterScroller }); }
6233
6330
  }
6234
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterScroller, decorators: [{
6331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterScroller, decorators: [{
6235
6332
  type: Injectable
6236
6333
  }], ctorParameters: function () { return [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: i3.ViewportScroller }, { type: i0.NgZone }, { type: undefined }]; } });
6237
6334
 
@@ -6721,6 +6818,37 @@ function withComponentInputBinding() {
6721
6818
  ];
6722
6819
  return routerFeature(8 /* RouterFeatureKind.ComponentInputBindingFeature */, providers);
6723
6820
  }
6821
+ /**
6822
+ * Enables view transitions in the Router by running the route activation and deactivation inside of
6823
+ * `document.startViewTransition`.
6824
+ *
6825
+ * Note: The View Transitions API is not available in all browsers. If the browser does not support
6826
+ * view transitions, the Router will not attempt to start a view transition and continue processing
6827
+ * the navigation as usual.
6828
+ *
6829
+ * @usageNotes
6830
+ *
6831
+ * Basic example of how you can enable the feature:
6832
+ * ```
6833
+ * const appRoutes: Routes = [];
6834
+ * bootstrapApplication(AppComponent,
6835
+ * {
6836
+ * providers: [
6837
+ * provideRouter(appRoutes, withViewTransitions())
6838
+ * ]
6839
+ * }
6840
+ * );
6841
+ * ```
6842
+ *
6843
+ * @returns A set of providers for use with `provideRouter`.
6844
+ * @see https://developer.chrome.com/docs/web-platform/view-transitions/
6845
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API
6846
+ * @experimental
6847
+ */
6848
+ function withViewTransitions() {
6849
+ const providers = [{ provide: CREATE_VIEW_TRANSITION, useValue: createViewTransition }];
6850
+ return routerFeature(9 /* RouterFeatureKind.ViewTransitionsFeature */, providers);
6851
+ }
6724
6852
 
6725
6853
  /**
6726
6854
  * The directives defined in the `RouterModule`.
@@ -6812,6 +6940,7 @@ class RouterModule {
6812
6940
  { provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken },
6813
6941
  config?.initialNavigation ? provideInitialNavigation(config) : [],
6814
6942
  config?.bindToComponentInputs ? withComponentInputBinding().ɵproviders : [],
6943
+ config?.enableViewTransitions ? withViewTransitions().ɵproviders : [],
6815
6944
  provideRouterInitializer(),
6816
6945
  ],
6817
6946
  };
@@ -6838,11 +6967,11 @@ class RouterModule {
6838
6967
  providers: [{ provide: ROUTES, multi: true, useValue: routes }],
6839
6968
  };
6840
6969
  }
6841
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6842
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6843
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterModule }); }
6970
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterModule, deps: [{ token: ROUTER_FORROOT_GUARD, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
6971
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); }
6972
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterModule }); }
6844
6973
  }
6845
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.2", ngImport: i0, type: RouterModule, decorators: [{
6974
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0-next.4", ngImport: i0, type: RouterModule, decorators: [{
6846
6975
  type: NgModule,
6847
6976
  args: [{
6848
6977
  imports: ROUTER_DIRECTIVES,
@@ -6987,7 +7116,7 @@ function mapToResolve(provider) {
6987
7116
  /**
6988
7117
  * @publicApi
6989
7118
  */
6990
- const VERSION = new Version('17.0.0-next.2');
7119
+ const VERSION = new Version('17.0.0-next.4');
6991
7120
 
6992
7121
  /**
6993
7122
  * @module
@@ -7002,5 +7131,5 @@ const VERSION = new Version('17.0.0-next.2');
7002
7131
  * Generated bundle index. Do not edit.
7003
7132
  */
7004
7133
 
7005
- export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLink as RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, defaultUrlMatcher, mapToCanActivate, mapToCanActivateChild, mapToCanDeactivate, mapToCanMatch, mapToResolve, provideRouter, provideRoutes, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, afterNextNavigation as ɵafterNextNavigation };
7134
+ export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, NoPreloading, OutletContext, PRIMARY_OUTLET, PreloadAllModules, PreloadingStrategy, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, ROUTES, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, Router, RouterEvent, RouterLink, RouterLinkActive, RouterLink as RouterLinkWithHref, RouterModule, RouterOutlet, RouterPreloader, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, convertToParamMap, createUrlTreeFromSnapshot, defaultUrlMatcher, mapToCanActivate, mapToCanActivateChild, mapToCanDeactivate, mapToCanMatch, mapToResolve, provideRouter, provideRoutes, withComponentInputBinding, withDebugTracing, withDisabledInitialNavigation, withEnabledBlockingInitialNavigation, withHashLocation, withInMemoryScrolling, withNavigationErrorHandler, withPreloading, withRouterConfig, withViewTransitions, ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, afterNextNavigation as ɵafterNextNavigation };
7006
7135
  //# sourceMappingURL=router.mjs.map