import {
Title
} from "./chunk-Y4CEYMY2.js";
import "./chunk-X7WBA24Z.js";
import {
DOCUMENT,
HashLocationStrategy,
LOCATION_INITIALIZED,
Location,
LocationStrategy,
PathLocationStrategy,
ViewportScroller
} from "./chunk-OSQBUYO6.js";
import {
APP_BOOTSTRAP_LISTENER,
APP_INITIALIZER,
ApplicationRef,
Attribute,
BehaviorSubject,
ChangeDetectorRef,
Compiler,
Component,
ConnectableObservable,
Console,
ContentChildren,
Directive,
EMPTY,
ENVIRONMENT_INITIALIZER,
ElementRef,
EmptyError,
EnvironmentInjector,
EventEmitter,
HostBinding,
HostListener,
InitialRenderPendingTasks,
Inject,
InjectFlags,
Injectable,
InjectionToken,
Injector,
Input,
NgModule,
NgModuleFactory$1,
NgZone,
Optional,
Output,
Renderer2,
RuntimeError,
SkipSelf,
Subject,
Subscription,
Version,
ViewContainerRef,
afterNextRender,
booleanAttribute,
catchError,
combineLatest,
concat,
concatMap,
createEnvironmentInjector,
defaultIfEmpty,
defer,
filter,
finalize,
first,
from,
inject,
isInjectable,
isNgModule,
isObservable,
isPromise,
isStandalone,
last,
makeEnvironmentProviders,
map,
mapTo,
mergeAll,
mergeMap,
of,
pipe,
refCount,
reflectComponentType,
runInInjectionContext,
scan,
setClassMetadata,
startWith,
switchMap,
take,
takeLast,
takeUntil,
tap,
throwError,
ɵɵInputTransformsFeature,
ɵɵNgOnChangesFeature,
ɵɵStandaloneFeature,
ɵɵattribute,
ɵɵcontentQuery,
ɵɵdefineComponent,
ɵɵdefineDirective,
ɵɵdefineInjectable,
ɵɵdefineInjector,
ɵɵdefineNgModule,
ɵɵdirectiveInject,
ɵɵelement,
ɵɵgetInheritedFactory,
ɵɵinject,
ɵɵinjectAttribute,
ɵɵinvalidFactory,
ɵɵlistener,
ɵɵloadQuery,
ɵɵqueryRefresh,
ɵɵsanitizeUrlOrResourceUrl
} from "./chunk-FGESKT7O.js";
import {
__spreadProps,
__spreadValues
} from "./chunk-HSNDBVJ3.js";
// node_modules/@angular/router/fesm2022/router.mjs
var PRIMARY_OUTLET = "primary";
var RouteTitleKey = Symbol("RouteTitle");
var ParamsAsMap = class {
constructor(params) {
this.params = params || {};
}
has(name) {
return Object.prototype.hasOwnProperty.call(this.params, name);
}
get(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v[0] : v;
}
return null;
}
getAll(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v : [v];
}
return [];
}
get keys() {
return Object.keys(this.params);
}
};
function convertToParamMap(params) {
return new ParamsAsMap(params);
}
function defaultUrlMatcher(segments, segmentGroup, route) {
const parts = route.path.split("/");
if (parts.length > segments.length) {
return null;
}
if (route.pathMatch === "full" && (segmentGroup.hasChildren() || parts.length < segments.length)) {
return null;
}
const posParams = {};
for (let index = 0; index < parts.length; index++) {
const part = parts[index];
const segment = segments[index];
const isParameter = part.startsWith(":");
if (isParameter) {
posParams[part.substring(1)] = segment;
} else if (part !== segment.path) {
return null;
}
}
return {
consumed: segments.slice(0, parts.length),
posParams
};
}
function shallowEqualArrays(a, b) {
if (a.length !== b.length)
return false;
for (let i = 0; i < a.length; ++i) {
if (!shallowEqual(a[i], b[i]))
return false;
}
return true;
}
function shallowEqual(a, b) {
const k1 = a ? getDataKeys(a) : void 0;
const k2 = b ? getDataKeys(b) : void 0;
if (!k1 || !k2 || k1.length != k2.length) {
return false;
}
let key;
for (let i = 0; i < k1.length; i++) {
key = k1[i];
if (!equalArraysOrString(a[key], b[key])) {
return false;
}
}
return true;
}
function getDataKeys(obj) {
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
}
function equalArraysOrString(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length)
return false;
const aSorted = [...a].sort();
const bSorted = [...b].sort();
return aSorted.every((val, index) => bSorted[index] === val);
} else {
return a === b;
}
}
function last2(a) {
return a.length > 0 ? a[a.length - 1] : null;
}
function wrapIntoObservable(value) {
if (isObservable(value)) {
return value;
}
if (isPromise(value)) {
return from(Promise.resolve(value));
}
return of(value);
}
var pathCompareMap = {
"exact": equalSegmentGroups,
"subset": containsSegmentGroup
};
var paramCompareMap = {
"exact": equalParams,
"subset": containsParams,
"ignored": () => true
};
function containsTree(container, containee, options) {
return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && !(options.fragment === "exact" && container.fragment !== containee.fragment);
}
function equalParams(container, containee) {
return shallowEqual(container, containee);
}
function equalSegmentGroups(container, containee, matrixParams) {
if (!equalPath(container.segments, containee.segments))
return false;
if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) {
return false;
}
if (container.numberOfChildren !== containee.numberOfChildren)
return false;
for (const c in containee.children) {
if (!container.children[c])
return false;
if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams))
return false;
}
return true;
}
function containsParams(container, containee) {
return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every((key) => equalArraysOrString(container[key], containee[key]));
}
function containsSegmentGroup(container, containee, matrixParams) {
return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams);
}
function containsSegmentGroupHelper(container, containee, containeePaths, matrixParams) {
if (container.segments.length > containeePaths.length) {
const current = container.segments.slice(0, containeePaths.length);
if (!equalPath(current, containeePaths))
return false;
if (containee.hasChildren())
return false;
if (!matrixParamsMatch(current, containeePaths, matrixParams))
return false;
return true;
} else if (container.segments.length === containeePaths.length) {
if (!equalPath(container.segments, containeePaths))
return false;
if (!matrixParamsMatch(container.segments, containeePaths, matrixParams))
return false;
for (const c in containee.children) {
if (!container.children[c])
return false;
if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) {
return false;
}
}
return true;
} else {
const current = containeePaths.slice(0, container.segments.length);
const next = containeePaths.slice(container.segments.length);
if (!equalPath(container.segments, current))
return false;
if (!matrixParamsMatch(container.segments, current, matrixParams))
return false;
if (!container.children[PRIMARY_OUTLET])
return false;
return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next, matrixParams);
}
}
function matrixParamsMatch(containerPaths, containeePaths, options) {
return containeePaths.every((containeeSegment, i) => {
return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters);
});
}
var UrlTree = class {
constructor(root = new UrlSegmentGroup([], {}), queryParams = {}, fragment = null) {
this.root = root;
this.queryParams = queryParams;
this.fragment = fragment;
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (root.segments.length > 0) {
throw new RuntimeError(4015, "The root `UrlSegmentGroup` should not contain `segments`. Instead, these segments belong in the `children` so they can be associated with a named outlet.");
}
}
}
get queryParamMap() {
if (!this._queryParamMap) {
this._queryParamMap = convertToParamMap(this.queryParams);
}
return this._queryParamMap;
}
/** @docsNotRequired */
toString() {
return DEFAULT_SERIALIZER.serialize(this);
}
};
var UrlSegmentGroup = class {
constructor(segments, children) {
this.segments = segments;
this.children = children;
this.parent = null;
Object.values(children).forEach((v) => v.parent = this);
}
/** Whether the segment has child segments */
hasChildren() {
return this.numberOfChildren > 0;
}
/** Number of child segments */
get numberOfChildren() {
return Object.keys(this.children).length;
}
/** @docsNotRequired */
toString() {
return serializePaths(this);
}
};
var UrlSegment = class {
constructor(path, parameters) {
this.path = path;
this.parameters = parameters;
}
get parameterMap() {
if (!this._parameterMap) {
this._parameterMap = convertToParamMap(this.parameters);
}
return this._parameterMap;
}
/** @docsNotRequired */
toString() {
return serializePath(this);
}
};
function equalSegments(as, bs) {
return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));
}
function equalPath(as, bs) {
if (as.length !== bs.length)
return false;
return as.every((a, i) => a.path === bs[i].path);
}
function mapChildrenIntoArray(segment, fn) {
let res = [];
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet === PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet !== PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
return res;
}
var _UrlSerializer = class _UrlSerializer {
};
_UrlSerializer.ɵfac = function UrlSerializer_Factory(t) {
return new (t || _UrlSerializer)();
};
_UrlSerializer.ɵprov = ɵɵdefineInjectable({
token: _UrlSerializer,
factory: () => (() => new DefaultUrlSerializer())(),
providedIn: "root"
});
var UrlSerializer = _UrlSerializer;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(UrlSerializer, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => new DefaultUrlSerializer()
}]
}], null, null);
})();
var DefaultUrlSerializer = class {
/** Parses a url into a `UrlTree` */
parse(url) {
const p = new UrlParser(url);
return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
}
/** Converts a `UrlTree` into a url */
serialize(tree2) {
const segment = `/${serializeSegment(tree2.root, true)}`;
const query = serializeQueryParams(tree2.queryParams);
const fragment = typeof tree2.fragment === `string` ? `#${encodeUriFragment(tree2.fragment)}` : "";
return `${segment}${query}${fragment}`;
}
};
var DEFAULT_SERIALIZER = new DefaultUrlSerializer();
function serializePaths(segment) {
return segment.segments.map((p) => serializePath(p)).join("/");
}
function serializeSegment(segment, root) {
if (!segment.hasChildren()) {
return serializePaths(segment);
}
if (root) {
const primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : "";
const children = [];
Object.entries(segment.children).forEach(([k, v]) => {
if (k !== PRIMARY_OUTLET) {
children.push(`${k}:${serializeSegment(v, false)}`);
}
});
return children.length > 0 ? `${primary}(${children.join("//")})` : primary;
} else {
const children = mapChildrenIntoArray(segment, (v, k) => {
if (k === PRIMARY_OUTLET) {
return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
}
return [`${k}:${serializeSegment(v, false)}`];
});
if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) {
return `${serializePaths(segment)}/${children[0]}`;
}
return `${serializePaths(segment)}/(${children.join("//")})`;
}
}
function encodeUriString(s) {
return encodeURIComponent(s).replace(/%40/g, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",");
}
function encodeUriQuery(s) {
return encodeUriString(s).replace(/%3B/gi, ";");
}
function encodeUriFragment(s) {
return encodeURI(s);
}
function encodeUriSegment(s) {
return encodeUriString(s).replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/%26/gi, "&");
}
function decode(s) {
return decodeURIComponent(s);
}
function decodeQuery(s) {
return decode(s.replace(/\+/g, "%20"));
}
function serializePath(path) {
return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
}
function serializeMatrixParams(params) {
return Object.keys(params).map((key) => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`).join("");
}
function serializeQueryParams(params) {
const strParams = Object.keys(params).map((name) => {
const value = params[name];
return Array.isArray(value) ? value.map((v) => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join("&") : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
}).filter((s) => !!s);
return strParams.length ? `?${strParams.join("&")}` : "";
}
var SEGMENT_RE = /^[^\/()?;#]+/;
function matchSegments(str) {
const match2 = str.match(SEGMENT_RE);
return match2 ? match2[0] : "";
}
var MATRIX_PARAM_SEGMENT_RE = /^[^\/()?;=#]+/;
function matchMatrixKeySegments(str) {
const match2 = str.match(MATRIX_PARAM_SEGMENT_RE);
return match2 ? match2[0] : "";
}
var QUERY_PARAM_RE = /^[^=?]+/;
function matchQueryParams(str) {
const match2 = str.match(QUERY_PARAM_RE);
return match2 ? match2[0] : "";
}
var QUERY_PARAM_VALUE_RE = /^[^]+/;
function matchUrlQueryParamValue(str) {
const match2 = str.match(QUERY_PARAM_VALUE_RE);
return match2 ? match2[0] : "";
}
var UrlParser = class {
constructor(url) {
this.url = url;
this.remaining = url;
}
parseRootSegment() {
this.consumeOptional("/");
if (this.remaining === "" || this.peekStartsWith("?") || this.peekStartsWith("#")) {
return new UrlSegmentGroup([], {});
}
return new UrlSegmentGroup([], this.parseChildren());
}
parseQueryParams() {
const params = {};
if (this.consumeOptional("?")) {
do {
this.parseQueryParam(params);
} while (this.consumeOptional("&"));
}
return params;
}
parseFragment() {
return this.consumeOptional("#") ? decodeURIComponent(this.remaining) : null;
}
parseChildren() {
if (this.remaining === "") {
return {};
}
this.consumeOptional("/");
const segments = [];
if (!this.peekStartsWith("(")) {
segments.push(this.parseSegment());
}
while (this.peekStartsWith("/") && !this.peekStartsWith("//") && !this.peekStartsWith("/(")) {
this.capture("/");
segments.push(this.parseSegment());
}
let children = {};
if (this.peekStartsWith("/(")) {
this.capture("/");
children = this.parseParens(true);
}
let res = {};
if (this.peekStartsWith("(")) {
res = this.parseParens(false);
}
if (segments.length > 0 || Object.keys(children).length > 0) {
res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children);
}
return res;
}
// parse a segment with its matrix parameters
// ie `name;k1=v1;k2`
parseSegment() {
const path = matchSegments(this.remaining);
if (path === "" && this.peekStartsWith(";")) {
throw new RuntimeError(4009, (typeof ngDevMode === "undefined" || ngDevMode) && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
}
this.capture(path);
return new UrlSegment(decode(path), this.parseMatrixParams());
}
parseMatrixParams() {
const params = {};
while (this.consumeOptional(";")) {
this.parseParam(params);
}
return params;
}
parseParam(params) {
const key = matchMatrixKeySegments(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = "";
if (this.consumeOptional("=")) {
const valueMatch = matchSegments(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
params[decode(key)] = decode(value);
}
// Parse a single query parameter `name[=value]`
parseQueryParam(params) {
const key = matchQueryParams(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = "";
if (this.consumeOptional("=")) {
const valueMatch = matchUrlQueryParamValue(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
const decodedKey = decodeQuery(key);
const decodedVal = decodeQuery(value);
if (params.hasOwnProperty(decodedKey)) {
let currentVal = params[decodedKey];
if (!Array.isArray(currentVal)) {
currentVal = [currentVal];
params[decodedKey] = currentVal;
}
currentVal.push(decodedVal);
} else {
params[decodedKey] = decodedVal;
}
}
// parse `(a/b//outlet_name:c/d)`
parseParens(allowPrimary) {
const segments = {};
this.capture("(");
while (!this.consumeOptional(")") && this.remaining.length > 0) {
const path = matchSegments(this.remaining);
const next = this.remaining[path.length];
if (next !== "/" && next !== ")" && next !== ";") {
throw new RuntimeError(4010, (typeof ngDevMode === "undefined" || ngDevMode) && `Cannot parse url '${this.url}'`);
}
let outletName = void 0;
if (path.indexOf(":") > -1) {
outletName = path.slice(0, path.indexOf(":"));
this.capture(outletName);
this.capture(":");
} else if (allowPrimary) {
outletName = PRIMARY_OUTLET;
}
const children = this.parseChildren();
segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children);
this.consumeOptional("//");
}
return segments;
}
peekStartsWith(str) {
return this.remaining.startsWith(str);
}
// Consumes the prefix when it is present and returns whether it has been consumed
consumeOptional(str) {
if (this.peekStartsWith(str)) {
this.remaining = this.remaining.substring(str.length);
return true;
}
return false;
}
capture(str) {
if (!this.consumeOptional(str)) {
throw new RuntimeError(4011, (typeof ngDevMode === "undefined" || ngDevMode) && `Expected "${str}".`);
}
}
};
function createRoot(rootCandidate) {
return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], {
[PRIMARY_OUTLET]: rootCandidate
}) : rootCandidate;
}
function squashSegmentGroup(segmentGroup) {
const newChildren = {};
for (const childOutlet of Object.keys(segmentGroup.children)) {
const child = segmentGroup.children[childOutlet];
const childCandidate = squashSegmentGroup(child);
if (childOutlet === PRIMARY_OUTLET && childCandidate.segments.length === 0 && childCandidate.hasChildren()) {
for (const [grandChildOutlet, grandChild] of Object.entries(childCandidate.children)) {
newChildren[grandChildOutlet] = grandChild;
}
} else if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {
newChildren[childOutlet] = childCandidate;
}
}
const s = new UrlSegmentGroup(segmentGroup.segments, newChildren);
return mergeTrivialChildren(s);
}
function mergeTrivialChildren(s) {
if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
const c = s.children[PRIMARY_OUTLET];
return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
}
return s;
}
function isUrlTree(v) {
return v instanceof UrlTree;
}
function createUrlTreeFromSnapshot(relativeTo, commands, queryParams = null, fragment = null) {
const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo);
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment);
}
function createSegmentGroupFromRoute(route) {
let targetGroup;
function createSegmentGroupFromRouteRecursive(currentRoute) {
const childOutlets = {};
for (const childSnapshot of currentRoute.children) {
const root = createSegmentGroupFromRouteRecursive(childSnapshot);
childOutlets[childSnapshot.outlet] = root;
}
const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets);
if (currentRoute === route) {
targetGroup = segmentGroup;
}
return segmentGroup;
}
const rootCandidate = createSegmentGroupFromRouteRecursive(route.root);
const rootSegmentGroup = createRoot(rootCandidate);
return targetGroup ?? rootSegmentGroup;
}
function createUrlTreeFromSegmentGroup(relativeTo, commands, queryParams, fragment) {
let root = relativeTo;
while (root.parent) {
root = root.parent;
}
if (commands.length === 0) {
return tree(root, root, root, queryParams, fragment);
}
const nav = computeNavigation(commands);
if (nav.toRoot()) {
return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment);
}
const position = findStartingPositionForTargetGroup(nav, root, relativeTo);
const newSegmentGroup = position.processChildren ? updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) : updateSegmentGroup(position.segmentGroup, position.index, nav.commands);
return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment);
}
function isMatrixParams(command) {
return typeof command === "object" && command != null && !command.outlets && !command.segmentPath;
}
function isCommandWithOutlets(command) {
return typeof command === "object" && command != null && command.outlets;
}
function tree(oldRoot, oldSegmentGroup, newSegmentGroup, queryParams, fragment) {
let qp = {};
if (queryParams) {
Object.entries(queryParams).forEach(([name, value]) => {
qp[name] = Array.isArray(value) ? value.map((v) => `${v}`) : `${value}`;
});
}
let rootCandidate;
if (oldRoot === oldSegmentGroup) {
rootCandidate = newSegmentGroup;
} else {
rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup);
}
const newRoot = createRoot(squashSegmentGroup(rootCandidate));
return new UrlTree(newRoot, qp, fragment);
}
function replaceSegment(current, oldSegment, newSegment) {
const children = {};
Object.entries(current.children).forEach(([outletName, c]) => {
if (c === oldSegment) {
children[outletName] = newSegment;
} else {
children[outletName] = replaceSegment(c, oldSegment, newSegment);
}
});
return new UrlSegmentGroup(current.segments, children);
}
var Navigation = class {
constructor(isAbsolute, numberOfDoubleDots, commands) {
this.isAbsolute = isAbsolute;
this.numberOfDoubleDots = numberOfDoubleDots;
this.commands = commands;
if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
throw new RuntimeError(4003, (typeof ngDevMode === "undefined" || ngDevMode) && "Root segment cannot have matrix parameters");
}
const cmdWithOutlet = commands.find(isCommandWithOutlets);
if (cmdWithOutlet && cmdWithOutlet !== last2(commands)) {
throw new RuntimeError(4004, (typeof ngDevMode === "undefined" || ngDevMode) && "{outlets:{}} has to be the last command");
}
}
toRoot() {
return this.isAbsolute && this.commands.length === 1 && this.commands[0] == "/";
}
};
function computeNavigation(commands) {
if (typeof commands[0] === "string" && commands.length === 1 && commands[0] === "/") {
return new Navigation(true, 0, commands);
}
let numberOfDoubleDots = 0;
let isAbsolute = false;
const res = commands.reduce((res2, cmd, cmdIdx) => {
if (typeof cmd === "object" && cmd != null) {
if (cmd.outlets) {
const outlets = {};
Object.entries(cmd.outlets).forEach(([name, commands2]) => {
outlets[name] = typeof commands2 === "string" ? commands2.split("/") : commands2;
});
return [...res2, {
outlets
}];
}
if (cmd.segmentPath) {
return [...res2, cmd.segmentPath];
}
}
if (!(typeof cmd === "string")) {
return [...res2, cmd];
}
if (cmdIdx === 0) {
cmd.split("/").forEach((urlPart, partIndex) => {
if (partIndex == 0 && urlPart === ".") {
} else if (partIndex == 0 && urlPart === "") {
isAbsolute = true;
} else if (urlPart === "..") {
numberOfDoubleDots++;
} else if (urlPart != "") {
res2.push(urlPart);
}
});
return res2;
}
return [...res2, cmd];
}, []);
return new Navigation(isAbsolute, numberOfDoubleDots, res);
}
var Position = class {
constructor(segmentGroup, processChildren, index) {
this.segmentGroup = segmentGroup;
this.processChildren = processChildren;
this.index = index;
}
};
function findStartingPositionForTargetGroup(nav, root, target) {
if (nav.isAbsolute) {
return new Position(root, true, 0);
}
if (!target) {
return new Position(root, false, NaN);
}
if (target.parent === null) {
return new Position(target, true, 0);
}
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
const index = target.segments.length - 1 + modifier;
return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots);
}
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
let g = group;
let ci = index;
let dd = numberOfDoubleDots;
while (dd > ci) {
dd -= ci;
g = g.parent;
if (!g) {
throw new RuntimeError(4005, (typeof ngDevMode === "undefined" || ngDevMode) && "Invalid number of '../'");
}
ci = g.segments.length;
}
return new Position(g, false, ci - dd);
}
function getOutlets(commands) {
if (isCommandWithOutlets(commands[0])) {
return commands[0].outlets;
}
return {
[PRIMARY_OUTLET]: commands
};
}
function updateSegmentGroup(segmentGroup, startIndex, commands) {
if (!segmentGroup) {
segmentGroup = new UrlSegmentGroup([], {});
}
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
}
const m = prefixedWith(segmentGroup, startIndex, commands);
const slicedCommands = commands.slice(m.commandIndex);
if (m.match && m.pathIndex < segmentGroup.segments.length) {
const g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {});
g.children[PRIMARY_OUTLET] = new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children);
return updateSegmentGroupChildren(g, 0, slicedCommands);
} else if (m.match && slicedCommands.length === 0) {
return new UrlSegmentGroup(segmentGroup.segments, {});
} else if (m.match && !segmentGroup.hasChildren()) {
return createNewSegmentGroup(segmentGroup, startIndex, commands);
} else if (m.match) {
return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands);
} else {
return createNewSegmentGroup(segmentGroup, startIndex, commands);
}
}
function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
if (commands.length === 0) {
return new UrlSegmentGroup(segmentGroup.segments, {});
} else {
const outlets = getOutlets(commands);
const children = {};
if (Object.keys(outlets).some((o) => o !== PRIMARY_OUTLET) && segmentGroup.children[PRIMARY_OUTLET] && segmentGroup.numberOfChildren === 1 && segmentGroup.children[PRIMARY_OUTLET].segments.length === 0) {
const childrenOfEmptyChild = updateSegmentGroupChildren(segmentGroup.children[PRIMARY_OUTLET], startIndex, commands);
return new UrlSegmentGroup(segmentGroup.segments, childrenOfEmptyChild.children);
}
Object.entries(outlets).forEach(([outlet, commands2]) => {
if (typeof commands2 === "string") {
commands2 = [commands2];
}
if (commands2 !== null) {
children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands2);
}
});
Object.entries(segmentGroup.children).forEach(([childOutlet, child]) => {
if (outlets[childOutlet] === void 0) {
children[childOutlet] = child;
}
});
return new UrlSegmentGroup(segmentGroup.segments, children);
}
}
function prefixedWith(segmentGroup, startIndex, commands) {
let currentCommandIndex = 0;
let currentPathIndex = startIndex;
const noMatch2 = {
match: false,
pathIndex: 0,
commandIndex: 0
};
while (currentPathIndex < segmentGroup.segments.length) {
if (currentCommandIndex >= commands.length)
return noMatch2;
const path = segmentGroup.segments[currentPathIndex];
const command = commands[currentCommandIndex];
if (isCommandWithOutlets(command)) {
break;
}
const curr = `${command}`;
const next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null;
if (currentPathIndex > 0 && curr === void 0)
break;
if (curr && next && typeof next === "object" && next.outlets === void 0) {
if (!compare(curr, next, path))
return noMatch2;
currentCommandIndex += 2;
} else {
if (!compare(curr, {}, path))
return noMatch2;
currentCommandIndex++;
}
currentPathIndex++;
}
return {
match: true,
pathIndex: currentPathIndex,
commandIndex: currentCommandIndex
};
}
function createNewSegmentGroup(segmentGroup, startIndex, commands) {
const paths = segmentGroup.segments.slice(0, startIndex);
let i = 0;
while (i < commands.length) {
const command = commands[i];
if (isCommandWithOutlets(command)) {
const children = createNewSegmentChildren(command.outlets);
return new UrlSegmentGroup(paths, children);
}
if (i === 0 && isMatrixParams(commands[0])) {
const p = segmentGroup.segments[startIndex];
paths.push(new UrlSegment(p.path, stringify(commands[0])));
i++;
continue;
}
const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`;
const next = i < commands.length - 1 ? commands[i + 1] : null;
if (curr && next && isMatrixParams(next)) {
paths.push(new UrlSegment(curr, stringify(next)));
i += 2;
} else {
paths.push(new UrlSegment(curr, {}));
i++;
}
}
return new UrlSegmentGroup(paths, {});
}
function createNewSegmentChildren(outlets) {
const children = {};
Object.entries(outlets).forEach(([outlet, commands]) => {
if (typeof commands === "string") {
commands = [commands];
}
if (commands !== null) {
children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
}
});
return children;
}
function stringify(params) {
const res = {};
Object.entries(params).forEach(([k, v]) => res[k] = `${v}`);
return res;
}
function compare(path, params, segment) {
return path == segment.path && shallowEqual(params, segment.parameters);
}
var IMPERATIVE_NAVIGATION = "imperative";
var RouterEvent = class {
constructor(id, url) {
this.id = id;
this.url = url;
}
};
var NavigationStart = class extends RouterEvent {
constructor(id, url, navigationTrigger = "imperative", restoredState = null) {
super(id, url);
this.type = 0;
this.navigationTrigger = navigationTrigger;
this.restoredState = restoredState;
}
/** @docsNotRequired */
toString() {
return `NavigationStart(id: ${this.id}, url: '${this.url}')`;
}
};
var NavigationEnd = class extends RouterEvent {
constructor(id, url, urlAfterRedirects) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.type = 1;
}
/** @docsNotRequired */
toString() {
return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
}
};
var NavigationCancel = class extends RouterEvent {
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
this.type = 2;
}
/** @docsNotRequired */
toString() {
return `NavigationCancel(id: ${this.id}, url: '${this.url}')`;
}
};
var NavigationSkipped = class extends RouterEvent {
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
this.type = 16;
}
};
var NavigationError = class extends RouterEvent {
constructor(id, url, error, target) {
super(id, url);
this.error = error;
this.target = target;
this.type = 3;
}
/** @docsNotRequired */
toString() {
return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
}
};
var RoutesRecognized = class extends RouterEvent {
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.type = 4;
}
/** @docsNotRequired */
toString() {
return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
};
var GuardsCheckStart = class extends RouterEvent {
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.type = 7;
}
toString() {
return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
};
var GuardsCheckEnd = class extends RouterEvent {
constructor(id, url, urlAfterRedirects, state, shouldActivate) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.shouldActivate = shouldActivate;
this.type = 8;
}
toString() {
return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
}
};
var ResolveStart = class extends RouterEvent {
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.type = 5;
}
toString() {
return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
};
var ResolveEnd = class extends RouterEvent {
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.type = 6;
}
toString() {
return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
};
var RouteConfigLoadStart = class {
constructor(route) {
this.route = route;
this.type = 9;
}
toString() {
return `RouteConfigLoadStart(path: ${this.route.path})`;
}
};
var RouteConfigLoadEnd = class {
constructor(route) {
this.route = route;
this.type = 10;
}
toString() {
return `RouteConfigLoadEnd(path: ${this.route.path})`;
}
};
var ChildActivationStart = class {
constructor(snapshot) {
this.snapshot = snapshot;
this.type = 11;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || "";
return `ChildActivationStart(path: '${path}')`;
}
};
var ChildActivationEnd = class {
constructor(snapshot) {
this.snapshot = snapshot;
this.type = 12;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || "";
return `ChildActivationEnd(path: '${path}')`;
}
};
var ActivationStart = class {
constructor(snapshot) {
this.snapshot = snapshot;
this.type = 13;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || "";
return `ActivationStart(path: '${path}')`;
}
};
var ActivationEnd = class {
constructor(snapshot) {
this.snapshot = snapshot;
this.type = 14;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || "";
return `ActivationEnd(path: '${path}')`;
}
};
var Scroll = class {
constructor(routerEvent, position, anchor) {
this.routerEvent = routerEvent;
this.position = position;
this.anchor = anchor;
this.type = 15;
}
toString() {
const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
}
};
var BeforeActivateRoutes = class {
};
var RedirectRequest = class {
constructor(url) {
this.url = url;
}
};
function stringifyEvent(routerEvent) {
switch (routerEvent.type) {
case 14:
return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`;
case 13:
return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`;
case 12:
return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`;
case 11:
return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`;
case 8:
return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
case 7:
return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case 2:
return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case 16:
return `NavigationSkipped(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case 1:
return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
case 3:
return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
case 0:
return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case 6:
return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case 5:
return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case 10:
return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
case 9:
return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
case 4:
return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case 15:
const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
}
}
var OutletContext = class {
constructor() {
this.outlet = null;
this.route = null;
this.injector = null;
this.children = new ChildrenOutletContexts();
this.attachRef = null;
}
};
var _ChildrenOutletContexts = class _ChildrenOutletContexts {
constructor() {
this.contexts = /* @__PURE__ */ new Map();
}
/** Called when a `RouterOutlet` directive is instantiated */
onChildOutletCreated(childName, outlet) {
const context = this.getOrCreateContext(childName);
context.outlet = outlet;
this.contexts.set(childName, context);
}
/**
* Called when a `RouterOutlet` directive is destroyed.
* We need to keep the context as the outlet could be destroyed inside a NgIf and might be
* re-created later.
*/
onChildOutletDestroyed(childName) {
const context = this.getContext(childName);
if (context) {
context.outlet = null;
context.attachRef = null;
}
}
/**
* Called when the corresponding route is deactivated during navigation.
* Because the component get destroyed, all children outlet are destroyed.
*/
onOutletDeactivated() {
const contexts = this.contexts;
this.contexts = /* @__PURE__ */ new Map();
return contexts;
}
onOutletReAttached(contexts) {
this.contexts = contexts;
}
getOrCreateContext(childName) {
let context = this.getContext(childName);
if (!context) {
context = new OutletContext();
this.contexts.set(childName, context);
}
return context;
}
getContext(childName) {
return this.contexts.get(childName) || null;
}
};
_ChildrenOutletContexts.ɵfac = function ChildrenOutletContexts_Factory(t) {
return new (t || _ChildrenOutletContexts)();
};
_ChildrenOutletContexts.ɵprov = ɵɵdefineInjectable({
token: _ChildrenOutletContexts,
factory: _ChildrenOutletContexts.ɵfac,
providedIn: "root"
});
var ChildrenOutletContexts = _ChildrenOutletContexts;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ChildrenOutletContexts, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var Tree = class {
constructor(root) {
this._root = root;
}
get root() {
return this._root.value;
}
/**
* @internal
*/
parent(t) {
const p = this.pathFromRoot(t);
return p.length > 1 ? p[p.length - 2] : null;
}
/**
* @internal
*/
children(t) {
const n = findNode(t, this._root);
return n ? n.children.map((t2) => t2.value) : [];
}
/**
* @internal
*/
firstChild(t) {
const n = findNode(t, this._root);
return n && n.children.length > 0 ? n.children[0].value : null;
}
/**
* @internal
*/
siblings(t) {
const p = findPath(t, this._root);
if (p.length < 2)
return [];
const c = p[p.length - 2].children.map((c2) => c2.value);
return c.filter((cc) => cc !== t);
}
/**
* @internal
*/
pathFromRoot(t) {
return findPath(t, this._root).map((s) => s.value);
}
};
function findNode(value, node) {
if (value === node.value)
return node;
for (const child of node.children) {
const node2 = findNode(value, child);
if (node2)
return node2;
}
return null;
}
function findPath(value, node) {
if (value === node.value)
return [node];
for (const child of node.children) {
const path = findPath(value, child);
if (path.length) {
path.unshift(node);
return path;
}
}
return [];
}
var TreeNode = class {
constructor(value, children) {
this.value = value;
this.children = children;
}
toString() {
return `TreeNode(${this.value})`;
}
};
function nodeChildrenAsMap(node) {
const map2 = {};
if (node) {
node.children.forEach((child) => map2[child.value.outlet] = child);
}
return map2;
}
var RouterState = class extends Tree {
/** @internal */
constructor(root, snapshot) {
super(root);
this.snapshot = snapshot;
setRouterState(this, root);
}
toString() {
return this.snapshot.toString();
}
};
function createEmptyState(urlTree, rootComponent) {
const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
const emptyUrl = new BehaviorSubject([new UrlSegment("", {})]);
const emptyParams = new BehaviorSubject({});
const emptyData = new BehaviorSubject({});
const emptyQueryParams = new BehaviorSubject({});
const fragment = new BehaviorSubject("");
const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
activated.snapshot = snapshot.root;
return new RouterState(new TreeNode(activated, []), snapshot);
}
function createEmptyStateSnapshot(urlTree, rootComponent) {
const emptyParams = {};
const emptyData = {};
const emptyQueryParams = {};
const fragment = "";
const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, {});
return new RouterStateSnapshot("", new TreeNode(activated, []));
}
var ActivatedRoute = class {
/** @internal */
constructor(urlSubject, paramsSubject, queryParamsSubject, fragmentSubject, dataSubject, outlet, component, futureSnapshot) {
this.urlSubject = urlSubject;
this.paramsSubject = paramsSubject;
this.queryParamsSubject = queryParamsSubject;
this.fragmentSubject = fragmentSubject;
this.dataSubject = dataSubject;
this.outlet = outlet;
this.component = component;
this._futureSnapshot = futureSnapshot;
this.title = this.dataSubject?.pipe(map((d) => d[RouteTitleKey])) ?? of(void 0);
this.url = urlSubject;
this.params = paramsSubject;
this.queryParams = queryParamsSubject;
this.fragment = fragmentSubject;
this.data = dataSubject;
}
/** The configuration used to match this route. */
get routeConfig() {
return this._futureSnapshot.routeConfig;
}
/** The root of the router state. */
get root() {
return this._routerState.root;
}
/** The parent of this route in the router state tree. */
get parent() {
return this._routerState.parent(this);
}
/** The first child of this route in the router state tree. */
get firstChild() {
return this._routerState.firstChild(this);
}
/** The children of this route in the router state tree. */
get children() {
return this._routerState.children(this);
}
/** The path from the root of the router state tree to this route. */
get pathFromRoot() {
return this._routerState.pathFromRoot(this);
}
/**
* An Observable that contains a map of the required and optional parameters
* specific to the route.
* The map supports retrieving single and multiple values from the same parameter.
*/
get paramMap() {
if (!this._paramMap) {
this._paramMap = this.params.pipe(map((p) => convertToParamMap(p)));
}
return this._paramMap;
}
/**
* An Observable that contains a map of the query parameters available to all routes.
* The map supports retrieving single and multiple values from the query parameter.
*/
get queryParamMap() {
if (!this._queryParamMap) {
this._queryParamMap = this.queryParams.pipe(map((p) => convertToParamMap(p)));
}
return this._queryParamMap;
}
toString() {
return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;
}
};
function getInherited(route, parent, paramsInheritanceStrategy = "emptyOnly") {
let inherited;
const {
routeConfig
} = route;
if (parent !== null && (paramsInheritanceStrategy === "always" || // inherit parent data if route is empty path
routeConfig?.path === "" || // inherit parent data if parent was componentless
!parent.component && !parent.routeConfig?.loadComponent)) {
inherited = {
params: __spreadValues(__spreadValues({}, parent.params), route.params),
data: __spreadValues(__spreadValues({}, parent.data), route.data),
resolve: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, route.data), parent.data), routeConfig?.data), route._resolvedData)
};
} else {
inherited = {
params: route.params,
data: route.data,
resolve: __spreadValues(__spreadValues({}, route.data), route._resolvedData ?? {})
};
}
if (routeConfig && hasStaticTitle(routeConfig)) {
inherited.resolve[RouteTitleKey] = routeConfig.title;
}
return inherited;
}
var ActivatedRouteSnapshot = class {
/** The resolved route title */
get title() {
return this.data?.[RouteTitleKey];
}
/** @internal */
constructor(url, params, queryParams, fragment, data, outlet, component, routeConfig, resolve) {
this.url = url;
this.params = params;
this.queryParams = queryParams;
this.fragment = fragment;
this.data = data;
this.outlet = outlet;
this.component = component;
this.routeConfig = routeConfig;
this._resolve = resolve;
}
/** The root of the router state */
get root() {
return this._routerState.root;
}
/** The parent of this route in the router state tree */
get parent() {
return this._routerState.parent(this);
}
/** The first child of this route in the router state tree */
get firstChild() {
return this._routerState.firstChild(this);
}
/** The children of this route in the router state tree */
get children() {
return this._routerState.children(this);
}
/** The path from the root of the router state tree to this route */
get pathFromRoot() {
return this._routerState.pathFromRoot(this);
}
get paramMap() {
if (!this._paramMap) {
this._paramMap = convertToParamMap(this.params);
}
return this._paramMap;
}
get queryParamMap() {
if (!this._queryParamMap) {
this._queryParamMap = convertToParamMap(this.queryParams);
}
return this._queryParamMap;
}
toString() {
const url = this.url.map((segment) => segment.toString()).join("/");
const matched = this.routeConfig ? this.routeConfig.path : "";
return `Route(url:'${url}', path:'${matched}')`;
}
};
var RouterStateSnapshot = class extends Tree {
/** @internal */
constructor(url, root) {
super(root);
this.url = url;
setRouterState(this, root);
}
toString() {
return serializeNode(this._root);
}
};
function setRouterState(state, node) {
node.value._routerState = state;
node.children.forEach((c) => setRouterState(state, c));
}
function serializeNode(node) {
const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(", ")} } ` : "";
return `${node.value}${c}`;
}
function advanceActivatedRoute(route) {
if (route.snapshot) {
const currentSnapshot = route.snapshot;
const nextSnapshot = route._futureSnapshot;
route.snapshot = nextSnapshot;
if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
route.queryParamsSubject.next(nextSnapshot.queryParams);
}
if (currentSnapshot.fragment !== nextSnapshot.fragment) {
route.fragmentSubject.next(nextSnapshot.fragment);
}
if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
route.paramsSubject.next(nextSnapshot.params);
}
if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
route.urlSubject.next(nextSnapshot.url);
}
if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
route.dataSubject.next(nextSnapshot.data);
}
} else {
route.snapshot = route._futureSnapshot;
route.dataSubject.next(route._futureSnapshot.data);
}
}
function equalParamsAndUrlSegments(a, b) {
const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
const parentsMismatch = !a.parent !== !b.parent;
return equalUrlParams && !parentsMismatch && (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent));
}
function hasStaticTitle(config) {
return typeof config.title === "string" || config.title === null;
}
var _RouterOutlet = class _RouterOutlet {
constructor() {
this.activated = null;
this._activatedRoute = null;
this.name = PRIMARY_OUTLET;
this.activateEvents = new EventEmitter();
this.deactivateEvents = new EventEmitter();
this.attachEvents = new EventEmitter();
this.detachEvents = new EventEmitter();
this.parentContexts = inject(ChildrenOutletContexts);
this.location = inject(ViewContainerRef);
this.changeDetector = inject(ChangeDetectorRef);
this.environmentInjector = inject(EnvironmentInjector);
this.inputBinder = inject(INPUT_BINDER, {
optional: true
});
this.supportsBindingToComponentInputs = true;
}
/** @internal */
get activatedComponentRef() {
return this.activated;
}
/** @nodoc */
ngOnChanges(changes) {
if (changes["name"]) {
const {
firstChange,
previousValue
} = changes["name"];
if (firstChange) {
return;
}
if (this.isTrackedInParentContexts(previousValue)) {
this.deactivate();
this.parentContexts.onChildOutletDestroyed(previousValue);
}
this.initializeOutletWithName();
}
}
/** @nodoc */
ngOnDestroy() {
if (this.isTrackedInParentContexts(this.name)) {
this.parentContexts.onChildOutletDestroyed(this.name);
}
this.inputBinder?.unsubscribeFromRouteData(this);
}
isTrackedInParentContexts(outletName) {
return this.parentContexts.getContext(outletName)?.outlet === this;
}
/** @nodoc */
ngOnInit() {
this.initializeOutletWithName();
}
initializeOutletWithName() {
this.parentContexts.onChildOutletCreated(this.name, this);
if (this.activated) {
return;
}
const context = this.parentContexts.getContext(this.name);
if (context?.route) {
if (context.attachRef) {
this.attach(context.attachRef, context.route);
} else {
this.activateWith(context.route, context.injector);
}
}
}
get isActivated() {
return !!this.activated;
}
/**
* @returns The currently activated component instance.
* @throws An error if the outlet is not activated.
*/
get component() {
if (!this.activated)
throw new RuntimeError(4012, (typeof ngDevMode === "undefined" || ngDevMode) && "Outlet is not activated");
return this.activated.instance;
}
get activatedRoute() {
if (!this.activated)
throw new RuntimeError(4012, (typeof ngDevMode === "undefined" || ngDevMode) && "Outlet is not activated");
return this._activatedRoute;
}
get activatedRouteData() {
if (this._activatedRoute) {
return this._activatedRoute.snapshot.data;
}
return {};
}
/**
* Called when the `RouteReuseStrategy` instructs to detach the subtree
*/
detach() {
if (!this.activated)
throw new RuntimeError(4012, (typeof ngDevMode === "undefined" || ngDevMode) && "Outlet is not activated");
this.location.detach();
const cmp = this.activated;
this.activated = null;
this._activatedRoute = null;
this.detachEvents.emit(cmp.instance);
return cmp;
}
/**
* Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
*/
attach(ref, activatedRoute) {
this.activated = ref;
this._activatedRoute = activatedRoute;
this.location.insert(ref.hostView);
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
this.attachEvents.emit(ref.instance);
}
deactivate() {
if (this.activated) {
const c = this.component;
this.activated.destroy();
this.activated = null;
this._activatedRoute = null;
this.deactivateEvents.emit(c);
}
}
activateWith(activatedRoute, environmentInjector) {
if (this.isActivated) {
throw new RuntimeError(4013, (typeof ngDevMode === "undefined" || ngDevMode) && "Cannot activate an already activated outlet");
}
this._activatedRoute = activatedRoute;
const location = this.location;
const snapshot = activatedRoute.snapshot;
const component = snapshot.component;
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
this.activated = location.createComponent(component, {
index: location.length,
injector,
environmentInjector: environmentInjector ?? this.environmentInjector
});
this.changeDetector.markForCheck();
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
this.activateEvents.emit(this.activated.instance);
}
};
_RouterOutlet.ɵfac = function RouterOutlet_Factory(t) {
return new (t || _RouterOutlet)();
};
_RouterOutlet.ɵdir = ɵɵdefineDirective({
type: _RouterOutlet,
selectors: [["router-outlet"]],
inputs: {
name: "name"
},
outputs: {
activateEvents: "activate",
deactivateEvents: "deactivate",
attachEvents: "attach",
detachEvents: "detach"
},
exportAs: ["outlet"],
standalone: true,
features: [ɵɵNgOnChangesFeature]
});
var RouterOutlet = _RouterOutlet;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterOutlet, [{
type: Directive,
args: [{
selector: "router-outlet",
exportAs: "outlet",
standalone: true
}]
}], null, {
name: [{
type: Input
}],
activateEvents: [{
type: Output,
args: ["activate"]
}],
deactivateEvents: [{
type: Output,
args: ["deactivate"]
}],
attachEvents: [{
type: Output,
args: ["attach"]
}],
detachEvents: [{
type: Output,
args: ["detach"]
}]
});
})();
var OutletInjector = class {
constructor(route, childContexts, parent) {
this.route = route;
this.childContexts = childContexts;
this.parent = parent;
}
get(token, notFoundValue) {
if (token === ActivatedRoute) {
return this.route;
}
if (token === ChildrenOutletContexts) {
return this.childContexts;
}
return this.parent.get(token, notFoundValue);
}
};
var INPUT_BINDER = new InjectionToken("");
var _RoutedComponentInputBinder = class _RoutedComponentInputBinder {
constructor() {
this.outletDataSubscriptions = /* @__PURE__ */ new Map();
}
bindActivatedRouteToOutletComponent(outlet) {
this.unsubscribeFromRouteData(outlet);
this.subscribeToRouteData(outlet);
}
unsubscribeFromRouteData(outlet) {
this.outletDataSubscriptions.get(outlet)?.unsubscribe();
this.outletDataSubscriptions.delete(outlet);
}
subscribeToRouteData(outlet) {
const {
activatedRoute
} = outlet;
const dataSubscription = combineLatest([activatedRoute.queryParams, activatedRoute.params, activatedRoute.data]).pipe(switchMap(([queryParams, params, data], index) => {
data = __spreadValues(__spreadValues(__spreadValues({}, queryParams), params), data);
if (index === 0) {
return of(data);
}
return Promise.resolve(data);
})).subscribe((data) => {
if (!outlet.isActivated || !outlet.activatedComponentRef || outlet.activatedRoute !== activatedRoute || activatedRoute.component === null) {
this.unsubscribeFromRouteData(outlet);
return;
}
const mirror = reflectComponentType(activatedRoute.component);
if (!mirror) {
this.unsubscribeFromRouteData(outlet);
return;
}
for (const {
templateName
} of mirror.inputs) {
outlet.activatedComponentRef.setInput(templateName, data[templateName]);
}
});
this.outletDataSubscriptions.set(outlet, dataSubscription);
}
};
_RoutedComponentInputBinder.ɵfac = function RoutedComponentInputBinder_Factory(t) {
return new (t || _RoutedComponentInputBinder)();
};
_RoutedComponentInputBinder.ɵprov = ɵɵdefineInjectable({
token: _RoutedComponentInputBinder,
factory: _RoutedComponentInputBinder.ɵfac
});
var RoutedComponentInputBinder = _RoutedComponentInputBinder;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RoutedComponentInputBinder, [{
type: Injectable
}], null, null);
})();
function createRouterState(routeReuseStrategy, curr, prevState) {
const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : void 0);
return new RouterState(root, curr);
}
function createNode(routeReuseStrategy, curr, prevState) {
if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
const value = prevState.value;
value._futureSnapshot = curr.value;
const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
return new TreeNode(value, children);
} else {
if (routeReuseStrategy.shouldAttach(curr.value)) {
const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);
if (detachedRouteHandle !== null) {
const tree2 = detachedRouteHandle.route;
tree2.value._futureSnapshot = curr.value;
tree2.children = curr.children.map((c) => createNode(routeReuseStrategy, c));
return tree2;
}
}
const value = createActivatedRoute(curr.value);
const children = curr.children.map((c) => createNode(routeReuseStrategy, c));
return new TreeNode(value, children);
}
}
function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
return curr.children.map((child) => {
for (const p of prevState.children) {
if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {
return createNode(routeReuseStrategy, child, p);
}
}
return createNode(routeReuseStrategy, child);
});
}
function createActivatedRoute(c) {
return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c);
}
var NAVIGATION_CANCELING_ERROR = "ngNavigationCancelingError";
function redirectingNavigationError(urlSerializer, redirect) {
const {
redirectTo,
navigationBehaviorOptions
} = isUrlTree(redirect) ? {
redirectTo: redirect,
navigationBehaviorOptions: void 0
} : redirect;
const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, 0, redirect);
error.url = redirectTo;
error.navigationBehaviorOptions = navigationBehaviorOptions;
return error;
}
function navigationCancelingError(message, code, redirectUrl) {
const error = new Error("NavigationCancelingError: " + (message || ""));
error[NAVIGATION_CANCELING_ERROR] = true;
error.cancellationCode = code;
if (redirectUrl) {
error.url = redirectUrl;
}
return error;
}
function isRedirectingNavigationCancelingError$1(error) {
return isNavigationCancelingError$1(error) && isUrlTree(error.url);
}
function isNavigationCancelingError$1(error) {
return error && error[NAVIGATION_CANCELING_ERROR];
}
var _ɵEmptyOutletComponent = class _ɵEmptyOutletComponent {
};
_ɵEmptyOutletComponent.ɵfac = function ɵEmptyOutletComponent_Factory(t) {
return new (t || _ɵEmptyOutletComponent)();
};
_ɵEmptyOutletComponent.ɵcmp = ɵɵdefineComponent({
type: _ɵEmptyOutletComponent,
selectors: [["ng-component"]],
standalone: true,
features: [ɵɵStandaloneFeature],
decls: 1,
vars: 0,
template: function ɵEmptyOutletComponent_Template(rf, ctx) {
if (rf & 1) {
ɵɵelement(0, "router-outlet");
}
},
dependencies: [RouterOutlet],
encapsulation: 2
});
var ɵEmptyOutletComponent = _ɵEmptyOutletComponent;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ɵEmptyOutletComponent, [{
type: Component,
args: [{
template: ``,
imports: [RouterOutlet],
standalone: true
}]
}], null, null);
})();
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
if (route.providers && !route._injector) {
route._injector = createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
}
return route._injector ?? currentInjector;
}
function validateConfig(config, parentPath = "", requireStandaloneComponents = false) {
for (let i = 0; i < config.length; i++) {
const route = config[i];
const fullPath = getFullPath(parentPath, route);
validateNode(route, fullPath, requireStandaloneComponents);
}
}
function assertStandalone(fullPath, component) {
if (component && isNgModule(component)) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}'. You are using 'loadComponent' with a module, but it must be used with standalone components. Use 'loadChildren' instead.`);
} else if (component && !isStandalone(component)) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}'. The component must be standalone.`);
}
}
function validateNode(route, fullPath, requireStandaloneComponents) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (!route) {
throw new RuntimeError(4014, `
Invalid configuration of route '${fullPath}': Encountered undefined route.
The reason might be an extra comma.
Example:
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },, << two commas
{ path: 'detail/:id', component: HeroDetailComponent }
];
`);
}
if (Array.isArray(route)) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': Array cannot be specified`);
}
if (!route.redirectTo && !route.component && !route.loadComponent && !route.children && !route.loadChildren && route.outlet && route.outlet !== PRIMARY_OUTLET) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`);
}
if (route.redirectTo && route.children) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
}
if (route.redirectTo && route.loadChildren) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
}
if (route.children && route.loadChildren) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
}
if (route.redirectTo && (route.component || route.loadComponent)) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
}
if (route.component && route.loadComponent) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
}
if (route.redirectTo && route.canActivate) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation so canActivate will never be executed.`);
}
if (route.path && route.matcher) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
}
if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
}
if (route.path === void 0 && route.matcher === void 0) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
}
if (typeof route.path === "string" && route.path.charAt(0) === "/") {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': path cannot start with a slash`);
}
if (route.path === "" && route.redirectTo !== void 0 && route.pathMatch === void 0) {
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
throw new RuntimeError(4014, `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
}
if (requireStandaloneComponents) {
assertStandalone(fullPath, route.component);
}
}
if (route.children) {
validateConfig(route.children, fullPath, requireStandaloneComponents);
}
}
function getFullPath(parentPath, currentRoute) {
if (!currentRoute) {
return parentPath;
}
if (!parentPath && !currentRoute.path) {
return "";
} else if (parentPath && !currentRoute.path) {
return `${parentPath}/`;
} else if (!parentPath && currentRoute.path) {
return currentRoute.path;
} else {
return `${parentPath}/${currentRoute.path}`;
}
}
function standardizeConfig(r) {
const children = r.children && r.children.map(standardizeConfig);
const c = children ? __spreadProps(__spreadValues({}, r), {
children
}) : __spreadValues({}, r);
if (!c.component && !c.loadComponent && (children || c.loadChildren) && c.outlet && c.outlet !== PRIMARY_OUTLET) {
c.component = ɵEmptyOutletComponent;
}
return c;
}
function getOutlet(route) {
return route.outlet || PRIMARY_OUTLET;
}
function sortByMatchingOutlets(routes, outletName) {
const sortedConfig = routes.filter((r) => getOutlet(r) === outletName);
sortedConfig.push(...routes.filter((r) => getOutlet(r) !== outletName));
return sortedConfig;
}
function getClosestRouteInjector(snapshot) {
if (!snapshot)
return null;
if (snapshot.routeConfig?._injector) {
return snapshot.routeConfig._injector;
}
for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig;
if (route?._loadedInjector)
return route._loadedInjector;
if (route?._injector)
return route._injector;
}
return null;
}
var warnedAboutUnsupportedInputBinding = false;
var activateRoutes = (rootContexts, routeReuseStrategy, forwardEvent, inputBindingEnabled) => map((t) => {
new ActivateRoutes(routeReuseStrategy, t.targetRouterState, t.currentRouterState, forwardEvent, inputBindingEnabled).activate(rootContexts);
return t;
});
var ActivateRoutes = class {
constructor(routeReuseStrategy, futureState, currState, forwardEvent, inputBindingEnabled) {
this.routeReuseStrategy = routeReuseStrategy;
this.futureState = futureState;
this.currState = currState;
this.forwardEvent = forwardEvent;
this.inputBindingEnabled = inputBindingEnabled;
}
activate(parentContexts) {
const futureRoot = this.futureState._root;
const currRoot = this.currState ? this.currState._root : null;
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
advanceActivatedRoute(this.futureState.root);
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
}
// De-activate the child route that are not re-used for the future state
deactivateChildRoutes(futureNode, currNode, contexts) {
const children = nodeChildrenAsMap(currNode);
futureNode.children.forEach((futureChild) => {
const childOutletName = futureChild.value.outlet;
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
delete children[childOutletName];
});
Object.values(children).forEach((v) => {
this.deactivateRouteAndItsChildren(v, contexts);
});
}
deactivateRoutes(futureNode, currNode, parentContext) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
if (future === curr) {
if (future.component) {
const context = parentContext.getContext(future.outlet);
if (context) {
this.deactivateChildRoutes(futureNode, currNode, context.children);
}
} else {
this.deactivateChildRoutes(futureNode, currNode, parentContext);
}
} else {
if (curr) {
this.deactivateRouteAndItsChildren(currNode, parentContext);
}
}
}
deactivateRouteAndItsChildren(route, parentContexts) {
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
this.detachAndStoreRouteSubtree(route, parentContexts);
} else {
this.deactivateRouteAndOutlet(route, parentContexts);
}
}
detachAndStoreRouteSubtree(route, parentContexts) {
const context = parentContexts.getContext(route.value.outlet);
const contexts = context && route.value.component ? context.children : parentContexts;
const children = nodeChildrenAsMap(route);
for (const childOutlet of Object.keys(children)) {
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
}
if (context && context.outlet) {
const componentRef = context.outlet.detach();
const contexts2 = context.children.onOutletDeactivated();
this.routeReuseStrategy.store(route.value.snapshot, {
componentRef,
route,
contexts: contexts2
});
}
}
deactivateRouteAndOutlet(route, parentContexts) {
const context = parentContexts.getContext(route.value.outlet);
const contexts = context && route.value.component ? context.children : parentContexts;
const children = nodeChildrenAsMap(route);
for (const childOutlet of Object.keys(children)) {
this.deactivateRouteAndItsChildren(children[childOutlet], contexts);
}
if (context) {
if (context.outlet) {
context.outlet.deactivate();
context.children.onOutletDeactivated();
}
context.attachRef = null;
context.route = null;
}
}
activateChildRoutes(futureNode, currNode, contexts) {
const children = nodeChildrenAsMap(currNode);
futureNode.children.forEach((c) => {
this.activateRoutes(c, children[c.value.outlet], contexts);
this.forwardEvent(new ActivationEnd(c.value.snapshot));
});
if (futureNode.children.length) {
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
}
}
activateRoutes(futureNode, currNode, parentContexts) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
advanceActivatedRoute(future);
if (future === curr) {
if (future.component) {
const context = parentContexts.getOrCreateContext(future.outlet);
this.activateChildRoutes(futureNode, currNode, context.children);
} else {
this.activateChildRoutes(futureNode, currNode, parentContexts);
}
} else {
if (future.component) {
const context = parentContexts.getOrCreateContext(future.outlet);
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
const stored = this.routeReuseStrategy.retrieve(future.snapshot);
this.routeReuseStrategy.store(future.snapshot, null);
context.children.onOutletReAttached(stored.contexts);
context.attachRef = stored.componentRef;
context.route = stored.route.value;
if (context.outlet) {
context.outlet.attach(stored.componentRef, stored.route.value);
}
advanceActivatedRoute(stored.route.value);
this.activateChildRoutes(futureNode, null, context.children);
} else {
const injector = getClosestRouteInjector(future.snapshot);
context.attachRef = null;
context.route = future;
context.injector = injector;
if (context.outlet) {
context.outlet.activateWith(future, context.injector);
}
this.activateChildRoutes(futureNode, null, context.children);
}
} else {
this.activateChildRoutes(futureNode, null, parentContexts);
}
}
if (typeof ngDevMode === "undefined" || ngDevMode) {
const context = parentContexts.getOrCreateContext(future.outlet);
const outlet = context.outlet;
if (outlet && this.inputBindingEnabled && !outlet.supportsBindingToComponentInputs && !warnedAboutUnsupportedInputBinding) {
console.warn(`'withComponentInputBinding' feature is enabled but this application is using an outlet that may not support binding to component inputs.`);
warnedAboutUnsupportedInputBinding = true;
}
}
}
};
var CanActivate = class {
constructor(path) {
this.path = path;
this.route = this.path[this.path.length - 1];
}
};
var CanDeactivate = class {
constructor(component, route) {
this.component = component;
this.route = route;
}
};
function getAllRouteGuards(future, curr, parentContexts) {
const futureRoot = future._root;
const currRoot = curr ? curr._root : null;
return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
}
function getCanActivateChild(p) {
const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
if (!canActivateChild || canActivateChild.length === 0)
return null;
return {
node: p,
guards: canActivateChild
};
}
function getTokenOrFunctionIdentity(tokenOrFunction, injector) {
const NOT_FOUND = Symbol();
const result = injector.get(tokenOrFunction, NOT_FOUND);
if (result === NOT_FOUND) {
if (typeof tokenOrFunction === "function" && !isInjectable(tokenOrFunction)) {
return tokenOrFunction;
} else {
return injector.get(tokenOrFunction);
}
}
return result;
}
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
canDeactivateChecks: [],
canActivateChecks: []
}) {
const prevChildren = nodeChildrenAsMap(currNode);
futureNode.children.forEach((c) => {
getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
delete prevChildren[c.value.outlet];
});
Object.entries(prevChildren).forEach(([k, v]) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks));
return checks;
}
function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
canDeactivateChecks: [],
canActivateChecks: []
}) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
if (curr && future.routeConfig === curr.routeConfig) {
const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers);
if (shouldRun) {
checks.canActivateChecks.push(new CanActivate(futurePath));
} else {
future.data = curr.data;
future._resolvedData = curr._resolvedData;
}
if (future.component) {
getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
} else {
getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
}
if (shouldRun && context && context.outlet && context.outlet.isActivated) {
checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
}
} else {
if (curr) {
deactivateRouteAndItsChildren(currNode, context, checks);
}
checks.canActivateChecks.push(new CanActivate(futurePath));
if (future.component) {
getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
} else {
getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
}
}
return checks;
}
function shouldRunGuardsAndResolvers(curr, future, mode) {
if (typeof mode === "function") {
return mode(curr, future);
}
switch (mode) {
case "pathParamsChange":
return !equalPath(curr.url, future.url);
case "pathParamsOrQueryParamsChange":
return !equalPath(curr.url, future.url) || !shallowEqual(curr.queryParams, future.queryParams);
case "always":
return true;
case "paramsOrQueryParamsChange":
return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams);
case "paramsChange":
default:
return !equalParamsAndUrlSegments(curr, future);
}
}
function deactivateRouteAndItsChildren(route, context, checks) {
const children = nodeChildrenAsMap(route);
const r = route.value;
Object.entries(children).forEach(([childName, node]) => {
if (!r.component) {
deactivateRouteAndItsChildren(node, context, checks);
} else if (context) {
deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
} else {
deactivateRouteAndItsChildren(node, null, checks);
}
});
if (!r.component) {
checks.canDeactivateChecks.push(new CanDeactivate(null, r));
} else if (context && context.outlet && context.outlet.isActivated) {
checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
} else {
checks.canDeactivateChecks.push(new CanDeactivate(null, r));
}
}
function isFunction(v) {
return typeof v === "function";
}
function isBoolean(v) {
return typeof v === "boolean";
}
function isCanLoad(guard) {
return guard && isFunction(guard.canLoad);
}
function isCanActivate(guard) {
return guard && isFunction(guard.canActivate);
}
function isCanActivateChild(guard) {
return guard && isFunction(guard.canActivateChild);
}
function isCanDeactivate(guard) {
return guard && isFunction(guard.canDeactivate);
}
function isCanMatch(guard) {
return guard && isFunction(guard.canMatch);
}
function isEmptyError(e) {
return e instanceof EmptyError || e?.name === "EmptyError";
}
var INITIAL_VALUE = Symbol("INITIAL_VALUE");
function prioritizedGuardValue() {
return switchMap((obs) => {
return combineLatest(obs.map((o) => o.pipe(take(1), startWith(INITIAL_VALUE)))).pipe(map((results) => {
for (const result of results) {
if (result === true) {
continue;
} else if (result === INITIAL_VALUE) {
return INITIAL_VALUE;
} else if (result === false || result instanceof UrlTree) {
return result;
}
}
return true;
}), filter((item) => item !== INITIAL_VALUE), take(1));
});
}
function checkGuards(injector, forwardEvent) {
return mergeMap((t) => {
const {
targetSnapshot,
currentSnapshot,
guards: {
canActivateChecks,
canDeactivateChecks
}
} = t;
if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
return of(__spreadProps(__spreadValues({}, t), {
guardsResult: true
}));
}
return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot, injector).pipe(mergeMap((canDeactivate) => {
return canDeactivate && isBoolean(canDeactivate) ? runCanActivateChecks(targetSnapshot, canActivateChecks, injector, forwardEvent) : of(canDeactivate);
}), map((guardsResult) => __spreadProps(__spreadValues({}, t), {
guardsResult
})));
});
}
function runCanDeactivateChecks(checks, futureRSS, currRSS, injector) {
return from(checks).pipe(mergeMap((check) => runCanDeactivate(check.component, check.route, currRSS, futureRSS, injector)), first((result) => {
return result !== true;
}, true));
}
function runCanActivateChecks(futureSnapshot, checks, injector, forwardEvent) {
return from(checks).pipe(concatMap((check) => {
return concat(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path, injector), runCanActivate(futureSnapshot, check.route, injector));
}), first((result) => {
return result !== true;
}, true));
}
function fireActivationStart(snapshot, forwardEvent) {
if (snapshot !== null && forwardEvent) {
forwardEvent(new ActivationStart(snapshot));
}
return of(true);
}
function fireChildActivationStart(snapshot, forwardEvent) {
if (snapshot !== null && forwardEvent) {
forwardEvent(new ChildActivationStart(snapshot));
}
return of(true);
}
function runCanActivate(futureRSS, futureARS, injector) {
const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
if (!canActivate || canActivate.length === 0)
return of(true);
const canActivateObservables = canActivate.map((canActivate2) => {
return defer(() => {
const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
const guard = getTokenOrFunctionIdentity(canActivate2, closestInjector);
const guardVal = isCanActivate(guard) ? guard.canActivate(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => guard(futureARS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
});
return of(canActivateObservables).pipe(prioritizedGuardValue());
}
function runCanActivateChild(futureRSS, path, injector) {
const futureARS = path[path.length - 1];
const canActivateChildGuards = path.slice(0, path.length - 1).reverse().map((p) => getCanActivateChild(p)).filter((_) => _ !== null);
const canActivateChildGuardsMapped = canActivateChildGuards.map((d) => {
return defer(() => {
const guardsMapped = d.guards.map((canActivateChild) => {
const closestInjector = getClosestRouteInjector(d.node) ?? injector;
const guard = getTokenOrFunctionIdentity(canActivateChild, closestInjector);
const guardVal = isCanActivateChild(guard) ? guard.canActivateChild(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => guard(futureARS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
return of(guardsMapped).pipe(prioritizedGuardValue());
});
});
return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
}
function runCanDeactivate(component, currARS, currRSS, futureRSS, injector) {
const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
if (!canDeactivate || canDeactivate.length === 0)
return of(true);
const canDeactivateObservables = canDeactivate.map((c) => {
const closestInjector = getClosestRouteInjector(currARS) ?? injector;
const guard = getTokenOrFunctionIdentity(c, closestInjector);
const guardVal = isCanDeactivate(guard) ? guard.canDeactivate(component, currARS, currRSS, futureRSS) : runInInjectionContext(closestInjector, () => guard(component, currARS, currRSS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
return of(canDeactivateObservables).pipe(prioritizedGuardValue());
}
function runCanLoadGuards(injector, route, segments, urlSerializer) {
const canLoad = route.canLoad;
if (canLoad === void 0 || canLoad.length === 0) {
return of(true);
}
const canLoadObservables = canLoad.map((injectionToken) => {
const guard = getTokenOrFunctionIdentity(injectionToken, injector);
const guardVal = isCanLoad(guard) ? guard.canLoad(route, segments) : runInInjectionContext(injector, () => guard(route, segments));
return wrapIntoObservable(guardVal);
});
return of(canLoadObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}
function redirectIfUrlTree(urlSerializer) {
return pipe(tap((result) => {
if (!isUrlTree(result))
return;
throw redirectingNavigationError(urlSerializer, result);
}), map((result) => result === true));
}
function runCanMatchGuards(injector, route, segments, urlSerializer) {
const canMatch = route.canMatch;
if (!canMatch || canMatch.length === 0)
return of(true);
const canMatchObservables = canMatch.map((injectionToken) => {
const guard = getTokenOrFunctionIdentity(injectionToken, injector);
const guardVal = isCanMatch(guard) ? guard.canMatch(route, segments) : runInInjectionContext(injector, () => guard(route, segments));
return wrapIntoObservable(guardVal);
});
return of(canMatchObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}
var NoMatch = class {
constructor(segmentGroup) {
this.segmentGroup = segmentGroup || null;
}
};
var AbsoluteRedirect = class extends Error {
constructor(urlTree) {
super();
this.urlTree = urlTree;
}
};
function noMatch$1(segmentGroup) {
return throwError(new NoMatch(segmentGroup));
}
function namedOutletsRedirect(redirectTo) {
return throwError(new RuntimeError(4e3, (typeof ngDevMode === "undefined" || ngDevMode) && `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`));
}
function canLoadFails(route) {
return throwError(navigationCancelingError(
(typeof ngDevMode === "undefined" || ngDevMode) && `Cannot load children because the guard of the route "path: '${route.path}'" returned false`,
3
/* NavigationCancellationCode.GuardRejected */
));
}
var ApplyRedirects = class {
constructor(urlSerializer, urlTree) {
this.urlSerializer = urlSerializer;
this.urlTree = urlTree;
}
lineralizeSegments(route, urlTree) {
let res = [];
let c = urlTree.root;
while (true) {
res = res.concat(c.segments);
if (c.numberOfChildren === 0) {
return of(res);
}
if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
return namedOutletsRedirect(route.redirectTo);
}
c = c.children[PRIMARY_OUTLET];
}
}
applyRedirectCommands(segments, redirectTo, posParams) {
const newTree = this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
if (redirectTo.startsWith("/")) {
throw new AbsoluteRedirect(newTree);
}
return newTree;
}
applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
}
createQueryParams(redirectToParams, actualParams) {
const res = {};
Object.entries(redirectToParams).forEach(([k, v]) => {
const copySourceValue = typeof v === "string" && v.startsWith(":");
if (copySourceValue) {
const sourceName = v.substring(1);
res[k] = actualParams[sourceName];
} else {
res[k] = v;
}
});
return res;
}
createSegmentGroup(redirectTo, group, segments, posParams) {
const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
let children = {};
Object.entries(group.children).forEach(([name, child]) => {
children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
});
return new UrlSegmentGroup(updatedSegments, children);
}
createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
return redirectToSegments.map((s) => s.path.startsWith(":") ? this.findPosParam(redirectTo, s, posParams) : this.findOrReturn(s, actualSegments));
}
findPosParam(redirectTo, redirectToUrlSegment, posParams) {
const pos = posParams[redirectToUrlSegment.path.substring(1)];
if (!pos)
throw new RuntimeError(4001, (typeof ngDevMode === "undefined" || ngDevMode) && `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
return pos;
}
findOrReturn(redirectToUrlSegment, actualSegments) {
let idx = 0;
for (const s of actualSegments) {
if (s.path === redirectToUrlSegment.path) {
actualSegments.splice(idx);
return s;
}
idx++;
}
return redirectToUrlSegment;
}
};
var noMatch = {
matched: false,
consumedSegments: [],
remainingSegments: [],
parameters: {},
positionalParamSegments: {}
};
function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer) {
const result = match(segmentGroup, route, segments);
if (!result.matched) {
return of(result);
}
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
return runCanMatchGuards(injector, route, segments, urlSerializer).pipe(map((v) => v === true ? result : __spreadValues({}, noMatch)));
}
function match(segmentGroup, route, segments) {
if (route.path === "**") {
return createWildcardMatchResult(segments);
}
if (route.path === "") {
if (route.pathMatch === "full" && (segmentGroup.hasChildren() || segments.length > 0)) {
return __spreadValues({}, noMatch);
}
return {
matched: true,
consumedSegments: [],
remainingSegments: segments,
parameters: {},
positionalParamSegments: {}
};
}
const matcher = route.matcher || defaultUrlMatcher;
const res = matcher(segments, segmentGroup, route);
if (!res)
return __spreadValues({}, noMatch);
const posParams = {};
Object.entries(res.posParams ?? {}).forEach(([k, v]) => {
posParams[k] = v.path;
});
const parameters = res.consumed.length > 0 ? __spreadValues(__spreadValues({}, posParams), res.consumed[res.consumed.length - 1].parameters) : posParams;
return {
matched: true,
consumedSegments: res.consumed,
remainingSegments: segments.slice(res.consumed.length),
// TODO(atscott): investigate combining parameters and positionalParamSegments
parameters,
positionalParamSegments: res.posParams ?? {}
};
}
function createWildcardMatchResult(segments) {
return {
matched: true,
parameters: segments.length > 0 ? last2(segments).parameters : {},
consumedSegments: segments,
remainingSegments: [],
positionalParamSegments: {}
};
}
function split(segmentGroup, consumedSegments, slicedSegments, config) {
if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
const s2 = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
return {
segmentGroup: s2,
slicedSegments: []
};
}
if (slicedSegments.length === 0 && containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
const s2 = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, config, segmentGroup.children));
return {
segmentGroup: s2,
slicedSegments
};
}
const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
return {
segmentGroup: s,
slicedSegments
};
}
function addEmptyPathsToChildrenIfNeeded(segmentGroup, consumedSegments, slicedSegments, routes, children) {
const res = {};
for (const r of routes) {
if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return __spreadValues(__spreadValues({}, children), res);
}
function createChildrenForEmptyPaths(routes, primarySegment) {
const res = {};
res[PRIMARY_OUTLET] = primarySegment;
for (const r of routes) {
if (r.path === "" && getOutlet(r) !== PRIMARY_OUTLET) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return res;
}
function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
return routes.some((r) => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
}
function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
return routes.some((r) => emptyPathMatch(segmentGroup, slicedSegments, r));
}
function emptyPathMatch(segmentGroup, slicedSegments, r) {
if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === "full") {
return false;
}
return r.path === "";
}
function isImmediateMatch(route, rawSegment, segments, outlet) {
if (getOutlet(route) !== outlet && (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
return false;
}
return match(rawSegment, route, segments).matched;
}
function noLeftoversInUrl(segmentGroup, segments, outlet) {
return segments.length === 0 && !segmentGroup.children[outlet];
}
var NoLeftoversInUrl = class {
};
function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = "emptyOnly") {
return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer).recognize();
}
var MAX_ALLOWED_REDIRECTS = 31;
var Recognizer = class {
constructor(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer) {
this.injector = injector;
this.configLoader = configLoader;
this.rootComponentType = rootComponentType;
this.config = config;
this.urlTree = urlTree;
this.paramsInheritanceStrategy = paramsInheritanceStrategy;
this.urlSerializer = urlSerializer;
this.applyRedirects = new ApplyRedirects(this.urlSerializer, this.urlTree);
this.absoluteRedirectCount = 0;
this.allowRedirects = true;
}
noMatchError(e) {
return new RuntimeError(4002, typeof ngDevMode === "undefined" || ngDevMode ? `Cannot match any routes. URL Segment: '${e.segmentGroup}'` : `'${e.segmentGroup}'`);
}
recognize() {
const rootSegmentGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
return this.match(rootSegmentGroup).pipe(map((children) => {
const root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(__spreadValues({}, this.urlTree.queryParams)), this.urlTree.fragment, {}, PRIMARY_OUTLET, this.rootComponentType, null, {});
const rootNode = new TreeNode(root, children);
const routeState = new RouterStateSnapshot("", rootNode);
const tree2 = createUrlTreeFromSnapshot(root, [], this.urlTree.queryParams, this.urlTree.fragment);
tree2.queryParams = this.urlTree.queryParams;
routeState.url = this.urlSerializer.serialize(tree2);
this.inheritParamsAndData(routeState._root, null);
return {
state: routeState,
tree: tree2
};
}));
}
match(rootSegmentGroup) {
const expanded$ = this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET);
return expanded$.pipe(catchError((e) => {
if (e instanceof AbsoluteRedirect) {
this.urlTree = e.urlTree;
return this.match(e.urlTree.root);
}
if (e instanceof NoMatch) {
throw this.noMatchError(e);
}
throw e;
}));
}
inheritParamsAndData(routeNode, parent) {
const route = routeNode.value;
const i = getInherited(route, parent, this.paramsInheritanceStrategy);
route.params = Object.freeze(i.params);
route.data = Object.freeze(i.data);
routeNode.children.forEach((n) => this.inheritParamsAndData(n, route));
}
processSegmentGroup(injector, config, segmentGroup, outlet) {
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return this.processChildren(injector, config, segmentGroup);
}
return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true).pipe(map((child) => child instanceof TreeNode ? [child] : []));
}
/**
* Matches every child outlet in the `segmentGroup` to a `Route` in the config. Returns `null` if
* we cannot find a match for _any_ of the children.
*
* @param config - The `Routes` to match against
* @param segmentGroup - The `UrlSegmentGroup` whose children need to be matched against the
* config.
*/
processChildren(injector, config, segmentGroup) {
const childOutlets = [];
for (const child of Object.keys(segmentGroup.children)) {
if (child === "primary") {
childOutlets.unshift(child);
} else {
childOutlets.push(child);
}
}
return from(childOutlets).pipe(concatMap((childOutlet) => {
const child = segmentGroup.children[childOutlet];
const sortedConfig = sortByMatchingOutlets(config, childOutlet);
return this.processSegmentGroup(injector, sortedConfig, child, childOutlet);
}), scan((children, outletChildren) => {
children.push(...outletChildren);
return children;
}), defaultIfEmpty(null), last(), mergeMap((children) => {
if (children === null)
return noMatch$1(segmentGroup);
const mergedChildren = mergeEmptyPathMatches(children);
if (typeof ngDevMode === "undefined" || ngDevMode) {
checkOutletNameUniqueness(mergedChildren);
}
sortActivatedRouteSnapshots(mergedChildren);
return of(mergedChildren);
}));
}
processSegment(injector, routes, segmentGroup, segments, outlet, allowRedirects) {
return from(routes).pipe(concatMap((r) => {
return this.processSegmentAgainstRoute(r._injector ?? injector, routes, r, segmentGroup, segments, outlet, allowRedirects).pipe(catchError((e) => {
if (e instanceof NoMatch) {
return of(null);
}
throw e;
}));
}), first((x) => !!x), catchError((e) => {
if (isEmptyError(e)) {
if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
return of(new NoLeftoversInUrl());
}
return noMatch$1(segmentGroup);
}
throw e;
}));
}
processSegmentAgainstRoute(injector, routes, route, rawSegment, segments, outlet, allowRedirects) {
if (!isImmediateMatch(route, rawSegment, segments, outlet))
return noMatch$1(rawSegment);
if (route.redirectTo === void 0) {
return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet);
}
if (this.allowRedirects && allowRedirects) {
return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet);
}
return noMatch$1(rawSegment);
}
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet) {
const {
matched,
consumedSegments,
positionalParamSegments,
remainingSegments
} = match(segmentGroup, route, segments);
if (!matched)
return noMatch$1(segmentGroup);
if (route.redirectTo.startsWith("/")) {
this.absoluteRedirectCount++;
if (this.absoluteRedirectCount > MAX_ALLOWED_REDIRECTS) {
if (ngDevMode) {
throw new RuntimeError(4016, `Detected possible infinite redirect when redirecting from '${this.urlTree}' to '${route.redirectTo}'.
This is currently a dev mode only error but will become a call stack size exceeded error in production in a future major version.`);
}
this.allowRedirects = false;
}
}
const newTree = this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments);
return this.applyRedirects.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false);
}));
}
matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet) {
const matchResult = matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer);
if (route.path === "**") {
rawSegment.children = {};
}
return matchResult.pipe(switchMap((result) => {
if (!result.matched) {
return noMatch$1(rawSegment);
}
injector = route._injector ?? injector;
return this.getChildConfig(injector, route, segments).pipe(switchMap(({
routes: childConfig
}) => {
const childInjector = route._loadedInjector ?? injector;
const {
consumedSegments,
remainingSegments,
parameters
} = result;
const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze(__spreadValues({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route));
const {
segmentGroup,
slicedSegments
} = split(rawSegment, consumedSegments, remainingSegments, childConfig);
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
return this.processChildren(childInjector, childConfig, segmentGroup).pipe(map((children) => {
if (children === null) {
return null;
}
return new TreeNode(snapshot, children);
}));
}
if (childConfig.length === 0 && slicedSegments.length === 0) {
return of(new TreeNode(snapshot, []));
}
const matchedOnOutlet = getOutlet(route) === outlet;
return this.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true).pipe(map((child) => {
return new TreeNode(snapshot, child instanceof TreeNode ? [child] : []);
}));
}));
}));
}
getChildConfig(injector, route, segments) {
if (route.children) {
return of({
routes: route.children,
injector
});
}
if (route.loadChildren) {
if (route._loadedRoutes !== void 0) {
return of({
routes: route._loadedRoutes,
injector: route._loadedInjector
});
}
return runCanLoadGuards(injector, route, segments, this.urlSerializer).pipe(mergeMap((shouldLoadResult) => {
if (shouldLoadResult) {
return this.configLoader.loadChildren(injector, route).pipe(tap((cfg) => {
route._loadedRoutes = cfg.routes;
route._loadedInjector = cfg.injector;
}));
}
return canLoadFails(route);
}));
}
return of({
routes: [],
injector
});
}
};
function sortActivatedRouteSnapshots(nodes) {
nodes.sort((a, b) => {
if (a.value.outlet === PRIMARY_OUTLET)
return -1;
if (b.value.outlet === PRIMARY_OUTLET)
return 1;
return a.value.outlet.localeCompare(b.value.outlet);
});
}
function hasEmptyPathConfig(node) {
const config = node.value.routeConfig;
return config && config.path === "";
}
function mergeEmptyPathMatches(nodes) {
const result = [];
const mergedNodes = /* @__PURE__ */ new Set();
for (const node of nodes) {
if (!hasEmptyPathConfig(node)) {
result.push(node);
continue;
}
const duplicateEmptyPathNode = result.find((resultNode) => node.value.routeConfig === resultNode.value.routeConfig);
if (duplicateEmptyPathNode !== void 0) {
duplicateEmptyPathNode.children.push(...node.children);
mergedNodes.add(duplicateEmptyPathNode);
} else {
result.push(node);
}
}
for (const mergedNode of mergedNodes) {
const mergedChildren = mergeEmptyPathMatches(mergedNode.children);
result.push(new TreeNode(mergedNode.value, mergedChildren));
}
return result.filter((n) => !mergedNodes.has(n));
}
function checkOutletNameUniqueness(nodes) {
const names = {};
nodes.forEach((n) => {
const routeWithSameOutletName = names[n.value.outlet];
if (routeWithSameOutletName) {
const p = routeWithSameOutletName.url.map((s) => s.toString()).join("/");
const c = n.value.url.map((s) => s.toString()).join("/");
throw new RuntimeError(4006, (typeof ngDevMode === "undefined" || ngDevMode) && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
}
names[n.value.outlet] = n.value;
});
}
function getData(route) {
return route.data || {};
}
function getResolve(route) {
return route.resolve || {};
}
function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy) {
return mergeMap((t) => recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy).pipe(map(({
state: targetSnapshot,
tree: urlAfterRedirects
}) => {
return __spreadProps(__spreadValues({}, t), {
targetSnapshot,
urlAfterRedirects
});
})));
}
function resolveData(paramsInheritanceStrategy, injector) {
return mergeMap((t) => {
const {
targetSnapshot,
guards: {
canActivateChecks
}
} = t;
if (!canActivateChecks.length) {
return of(t);
}
const routesWithResolversToRun = new Set(canActivateChecks.map((check) => check.route));
const routesNeedingDataUpdates = /* @__PURE__ */ new Set();
for (const route of routesWithResolversToRun) {
if (routesNeedingDataUpdates.has(route)) {
continue;
}
for (const newRoute of flattenRouteTree(route)) {
routesNeedingDataUpdates.add(newRoute);
}
}
let routesProcessed = 0;
return from(routesNeedingDataUpdates).pipe(concatMap((route) => {
if (routesWithResolversToRun.has(route)) {
return runResolve(route, targetSnapshot, paramsInheritanceStrategy, injector);
} else {
route.data = getInherited(route, route.parent, paramsInheritanceStrategy).resolve;
return of(void 0);
}
}), tap(() => routesProcessed++), takeLast(1), mergeMap((_) => routesProcessed === routesNeedingDataUpdates.size ? of(t) : EMPTY));
});
}
function flattenRouteTree(route) {
const descendants = route.children.map((child) => flattenRouteTree(child)).flat();
return [route, ...descendants];
}
function runResolve(futureARS, futureRSS, paramsInheritanceStrategy, injector) {
const config = futureARS.routeConfig;
const resolve = futureARS._resolve;
if (config?.title !== void 0 && !hasStaticTitle(config)) {
resolve[RouteTitleKey] = config.title;
}
return resolveNode(resolve, futureARS, futureRSS, injector).pipe(map((resolvedData) => {
futureARS._resolvedData = resolvedData;
futureARS.data = getInherited(futureARS, futureARS.parent, paramsInheritanceStrategy).resolve;
return null;
}));
}
function resolveNode(resolve, futureARS, futureRSS, injector) {
const keys = getDataKeys(resolve);
if (keys.length === 0) {
return of({});
}
const data = {};
return from(keys).pipe(mergeMap((key) => getResolver(resolve[key], futureARS, futureRSS, injector).pipe(first(), tap((value) => {
data[key] = value;
}))), takeLast(1), mapTo(data), catchError((e) => isEmptyError(e) ? EMPTY : throwError(e)));
}
function getResolver(injectionToken, futureARS, futureRSS, injector) {
const closestInjector = getClosestRouteInjector(futureARS) ?? injector;
const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);
const resolverValue = resolver.resolve ? resolver.resolve(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => resolver(futureARS, futureRSS));
return wrapIntoObservable(resolverValue);
}
function switchTap(next) {
return switchMap((v) => {
const nextResult = next(v);
if (nextResult) {
return from(nextResult).pipe(map(() => v));
}
return of(v);
});
}
var _TitleStrategy = class _TitleStrategy {
/**
* @returns The `title` of the deepest primary route.
*/
buildTitle(snapshot) {
let pageTitle;
let route = snapshot.root;
while (route !== void 0) {
pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
route = route.children.find((child) => child.outlet === PRIMARY_OUTLET);
}
return pageTitle;
}
/**
* Given an `ActivatedRouteSnapshot`, returns the final value of the
* `Route.title` property, which can either be a static string or a resolved value.
*/
getResolvedTitleForRoute(snapshot) {
return snapshot.data[RouteTitleKey];
}
};
_TitleStrategy.ɵfac = function TitleStrategy_Factory(t) {
return new (t || _TitleStrategy)();
};
_TitleStrategy.ɵprov = ɵɵdefineInjectable({
token: _TitleStrategy,
factory: () => (() => inject(DefaultTitleStrategy))(),
providedIn: "root"
});
var TitleStrategy = _TitleStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TitleStrategy, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(DefaultTitleStrategy)
}]
}], null, null);
})();
var _DefaultTitleStrategy = class _DefaultTitleStrategy extends TitleStrategy {
constructor(title) {
super();
this.title = title;
}
/**
* Sets the title of the browser to the given value.
*
* @param title The `pageTitle` from the deepest primary route.
*/
updateTitle(snapshot) {
const title = this.buildTitle(snapshot);
if (title !== void 0) {
this.title.setTitle(title);
}
}
};
_DefaultTitleStrategy.ɵfac = function DefaultTitleStrategy_Factory(t) {
return new (t || _DefaultTitleStrategy)(ɵɵinject(Title));
};
_DefaultTitleStrategy.ɵprov = ɵɵdefineInjectable({
token: _DefaultTitleStrategy,
factory: _DefaultTitleStrategy.ɵfac,
providedIn: "root"
});
var DefaultTitleStrategy = _DefaultTitleStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DefaultTitleStrategy, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: Title
}], null);
})();
var ROUTER_CONFIGURATION = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "router config" : "", {
providedIn: "root",
factory: () => ({})
});
var ROUTES = new InjectionToken("ROUTES");
var _RouterConfigLoader = class _RouterConfigLoader {
constructor() {
this.componentLoaders = /* @__PURE__ */ new WeakMap();
this.childrenLoaders = /* @__PURE__ */ new WeakMap();
this.compiler = inject(Compiler);
}
loadComponent(route) {
if (this.componentLoaders.get(route)) {
return this.componentLoaders.get(route);
} else if (route._loadedComponent) {
return of(route._loadedComponent);
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const loadRunner = wrapIntoObservable(route.loadComponent()).pipe(map(maybeUnwrapDefaultExport), tap((component) => {
if (this.onLoadEndListener) {
this.onLoadEndListener(route);
}
(typeof ngDevMode === "undefined" || ngDevMode) && assertStandalone(route.path ?? "", component);
route._loadedComponent = component;
}), finalize(() => {
this.componentLoaders.delete(route);
}));
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
this.componentLoaders.set(route, loader);
return loader;
}
loadChildren(parentInjector, route) {
if (this.childrenLoaders.get(route)) {
return this.childrenLoaders.get(route);
} else if (route._loadedRoutes) {
return of({
routes: route._loadedRoutes,
injector: route._loadedInjector
});
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const moduleFactoryOrRoutes$ = loadChildren(route, this.compiler, parentInjector, this.onLoadEndListener);
const loadRunner = moduleFactoryOrRoutes$.pipe(finalize(() => {
this.childrenLoaders.delete(route);
}));
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
this.childrenLoaders.set(route, loader);
return loader;
}
};
_RouterConfigLoader.ɵfac = function RouterConfigLoader_Factory(t) {
return new (t || _RouterConfigLoader)();
};
_RouterConfigLoader.ɵprov = ɵɵdefineInjectable({
token: _RouterConfigLoader,
factory: _RouterConfigLoader.ɵfac,
providedIn: "root"
});
var RouterConfigLoader = _RouterConfigLoader;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterConfigLoader, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
function loadChildren(route, compiler, parentInjector, onLoadEndListener) {
return wrapIntoObservable(route.loadChildren()).pipe(map(maybeUnwrapDefaultExport), mergeMap((t) => {
if (t instanceof NgModuleFactory$1 || Array.isArray(t)) {
return of(t);
} else {
return from(compiler.compileModuleAsync(t));
}
}), map((factoryOrRoutes) => {
if (onLoadEndListener) {
onLoadEndListener(route);
}
let injector;
let rawRoutes;
let requireStandaloneComponents = false;
if (Array.isArray(factoryOrRoutes)) {
rawRoutes = factoryOrRoutes;
requireStandaloneComponents = true;
} else {
injector = factoryOrRoutes.create(parentInjector).injector;
rawRoutes = injector.get(ROUTES, [], {
optional: true,
self: true
}).flat();
}
const routes = rawRoutes.map(standardizeConfig);
(typeof ngDevMode === "undefined" || ngDevMode) && validateConfig(routes, route.path, requireStandaloneComponents);
return {
routes,
injector
};
}));
}
function isWrappedDefaultExport(value) {
return value && typeof value === "object" && "default" in value;
}
function maybeUnwrapDefaultExport(input) {
return isWrappedDefaultExport(input) ? input["default"] : input;
}
var _UrlHandlingStrategy = class _UrlHandlingStrategy {
};
_UrlHandlingStrategy.ɵfac = function UrlHandlingStrategy_Factory(t) {
return new (t || _UrlHandlingStrategy)();
};
_UrlHandlingStrategy.ɵprov = ɵɵdefineInjectable({
token: _UrlHandlingStrategy,
factory: () => (() => inject(DefaultUrlHandlingStrategy))(),
providedIn: "root"
});
var UrlHandlingStrategy = _UrlHandlingStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(UrlHandlingStrategy, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(DefaultUrlHandlingStrategy)
}]
}], null, null);
})();
var _DefaultUrlHandlingStrategy = class _DefaultUrlHandlingStrategy {
shouldProcessUrl(url) {
return true;
}
extract(url) {
return url;
}
merge(newUrlPart, wholeUrl) {
return newUrlPart;
}
};
_DefaultUrlHandlingStrategy.ɵfac = function DefaultUrlHandlingStrategy_Factory(t) {
return new (t || _DefaultUrlHandlingStrategy)();
};
_DefaultUrlHandlingStrategy.ɵprov = ɵɵdefineInjectable({
token: _DefaultUrlHandlingStrategy,
factory: _DefaultUrlHandlingStrategy.ɵfac,
providedIn: "root"
});
var DefaultUrlHandlingStrategy = _DefaultUrlHandlingStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DefaultUrlHandlingStrategy, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var CREATE_VIEW_TRANSITION = new InjectionToken(ngDevMode ? "view transition helper" : "");
var VIEW_TRANSITION_OPTIONS = new InjectionToken(ngDevMode ? "view transition options" : "");
function createViewTransition(injector, from2, to) {
const transitionOptions = injector.get(VIEW_TRANSITION_OPTIONS);
const document = injector.get(DOCUMENT);
return injector.get(NgZone).runOutsideAngular(() => {
if (!document.startViewTransition || transitionOptions.skipNextTransition) {
transitionOptions.skipNextTransition = false;
return Promise.resolve();
}
let resolveViewTransitionStarted;
const viewTransitionStarted = new Promise((resolve) => {
resolveViewTransitionStarted = resolve;
});
const transition = document.startViewTransition(() => {
resolveViewTransitionStarted();
return createRenderPromise(injector);
});
const {
onViewTransitionCreated
} = transitionOptions;
if (onViewTransitionCreated) {
runInInjectionContext(injector, () => onViewTransitionCreated({
transition,
from: from2,
to
}));
}
return viewTransitionStarted;
});
}
function createRenderPromise(injector) {
return new Promise((resolve) => {
afterNextRender(resolve, {
injector
});
});
}
var _NavigationTransitions = class _NavigationTransitions {
get hasRequestedNavigation() {
return this.navigationId !== 0;
}
constructor() {
this.currentNavigation = null;
this.currentTransition = null;
this.lastSuccessfulNavigation = null;
this.events = new Subject();
this.transitionAbortSubject = new Subject();
this.configLoader = inject(RouterConfigLoader);
this.environmentInjector = inject(EnvironmentInjector);
this.urlSerializer = inject(UrlSerializer);
this.rootContexts = inject(ChildrenOutletContexts);
this.location = inject(Location);
this.inputBindingEnabled = inject(INPUT_BINDER, {
optional: true
}) !== null;
this.titleStrategy = inject(TitleStrategy);
this.options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || "emptyOnly";
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
this.createViewTransition = inject(CREATE_VIEW_TRANSITION, {
optional: true
});
this.navigationId = 0;
this.afterPreactivation = () => of(void 0);
this.rootComponentType = null;
const onLoadStart = (r) => this.events.next(new RouteConfigLoadStart(r));
const onLoadEnd = (r) => this.events.next(new RouteConfigLoadEnd(r));
this.configLoader.onLoadEndListener = onLoadEnd;
this.configLoader.onLoadStartListener = onLoadStart;
}
complete() {
this.transitions?.complete();
}
handleNavigationRequest(request) {
const id = ++this.navigationId;
this.transitions?.next(__spreadProps(__spreadValues(__spreadValues({}, this.transitions.value), request), {
id
}));
}
setupNavigations(router, initialUrlTree, initialRouterState) {
this.transitions = new BehaviorSubject({
id: 0,
currentUrlTree: initialUrlTree,
currentRawUrl: initialUrlTree,
extractedUrl: this.urlHandlingStrategy.extract(initialUrlTree),
urlAfterRedirects: this.urlHandlingStrategy.extract(initialUrlTree),
rawUrl: initialUrlTree,
extras: {},
resolve: null,
reject: null,
promise: Promise.resolve(true),
source: IMPERATIVE_NAVIGATION,
restoredState: null,
currentSnapshot: initialRouterState.snapshot,
targetSnapshot: null,
currentRouterState: initialRouterState,
targetRouterState: null,
guards: {
canActivateChecks: [],
canDeactivateChecks: []
},
guardsResult: null
});
return this.transitions.pipe(
filter((t) => t.id !== 0),
// Extract URL
map((t) => __spreadProps(__spreadValues({}, t), {
extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl)
})),
// Using switchMap so we cancel executing navigations when a new one comes in
switchMap((overallTransitionState) => {
this.currentTransition = overallTransitionState;
let completed = false;
let errored = false;
return of(overallTransitionState).pipe(
// Store the Navigation object
tap((t) => {
this.currentNavigation = {
id: t.id,
initialUrl: t.rawUrl,
extractedUrl: t.extractedUrl,
trigger: t.source,
extras: t.extras,
previousNavigation: !this.lastSuccessfulNavigation ? null : __spreadProps(__spreadValues({}, this.lastSuccessfulNavigation), {
previousNavigation: null
})
};
}),
switchMap((t) => {
const urlTransition = !router.navigated || this.isUpdatingInternalState() || this.isUpdatedBrowserUrl();
const onSameUrlNavigation = t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;
if (!urlTransition && onSameUrlNavigation !== "reload") {
const reason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation to ${t.rawUrl} was ignored because it is the same as the current Router URL.` : "";
this.events.next(new NavigationSkipped(
t.id,
this.urlSerializer.serialize(t.rawUrl),
reason,
0
/* NavigationSkippedCode.IgnoredSameUrlNavigation */
));
t.resolve(null);
return EMPTY;
}
if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
return of(t).pipe(
// Fire NavigationStart event
switchMap((t2) => {
const transition = this.transitions?.getValue();
this.events.next(new NavigationStart(t2.id, this.urlSerializer.serialize(t2.extractedUrl), t2.source, t2.restoredState));
if (transition !== this.transitions?.getValue()) {
return EMPTY;
}
return Promise.resolve(t2);
}),
// Recognize
recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy),
// Update URL if in `eager` update mode
tap((t2) => {
overallTransitionState.targetSnapshot = t2.targetSnapshot;
overallTransitionState.urlAfterRedirects = t2.urlAfterRedirects;
this.currentNavigation = __spreadProps(__spreadValues({}, this.currentNavigation), {
finalUrl: t2.urlAfterRedirects
});
const routesRecognized = new RoutesRecognized(t2.id, this.urlSerializer.serialize(t2.extractedUrl), this.urlSerializer.serialize(t2.urlAfterRedirects), t2.targetSnapshot);
this.events.next(routesRecognized);
})
);
} else if (urlTransition && this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
const {
id,
extractedUrl,
source,
restoredState,
extras
} = t;
const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
this.events.next(navStart);
const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
this.currentTransition = overallTransitionState = __spreadProps(__spreadValues({}, t), {
targetSnapshot,
urlAfterRedirects: extractedUrl,
extras: __spreadProps(__spreadValues({}, extras), {
skipLocationChange: false,
replaceUrl: false
})
});
this.currentNavigation.finalUrl = extractedUrl;
return of(overallTransitionState);
} else {
const reason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation was ignored because the UrlHandlingStrategy indicated neither the current URL ${t.currentRawUrl} nor target URL ${t.rawUrl} should be processed.` : "";
this.events.next(new NavigationSkipped(
t.id,
this.urlSerializer.serialize(t.extractedUrl),
reason,
1
/* NavigationSkippedCode.IgnoredByUrlHandlingStrategy */
));
t.resolve(null);
return EMPTY;
}
}),
// --- GUARDS ---
tap((t) => {
const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(guardsStart);
}),
map((t) => {
this.currentTransition = overallTransitionState = __spreadProps(__spreadValues({}, t), {
guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
});
return overallTransitionState;
}),
checkGuards(this.environmentInjector, (evt) => this.events.next(evt)),
tap((t) => {
overallTransitionState.guardsResult = t.guardsResult;
if (isUrlTree(t.guardsResult)) {
throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
}
const guardsEnd = new GuardsCheckEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
this.events.next(guardsEnd);
}),
filter((t) => {
if (!t.guardsResult) {
this.cancelNavigationTransition(
t,
"",
3
/* NavigationCancellationCode.GuardRejected */
);
return false;
}
return true;
}),
// --- RESOLVE ---
switchTap((t) => {
if (t.guards.canActivateChecks.length) {
return of(t).pipe(tap((t2) => {
const resolveStart = new ResolveStart(t2.id, this.urlSerializer.serialize(t2.extractedUrl), this.urlSerializer.serialize(t2.urlAfterRedirects), t2.targetSnapshot);
this.events.next(resolveStart);
}), switchMap((t2) => {
let dataResolved = false;
return of(t2).pipe(resolveData(this.paramsInheritanceStrategy, this.environmentInjector), tap({
next: () => dataResolved = true,
complete: () => {
if (!dataResolved) {
this.cancelNavigationTransition(
t2,
typeof ngDevMode === "undefined" || ngDevMode ? `At least one route resolver didn't emit any value.` : "",
2
/* NavigationCancellationCode.NoDataFromResolver */
);
}
}
}));
}), tap((t2) => {
const resolveEnd = new ResolveEnd(t2.id, this.urlSerializer.serialize(t2.extractedUrl), this.urlSerializer.serialize(t2.urlAfterRedirects), t2.targetSnapshot);
this.events.next(resolveEnd);
}));
}
return void 0;
}),
// --- LOAD COMPONENTS ---
switchTap((t) => {
const loadComponents = (route) => {
const loaders = [];
if (route.routeConfig?.loadComponent && !route.routeConfig._loadedComponent) {
loaders.push(this.configLoader.loadComponent(route.routeConfig).pipe(tap((loadedComponent) => {
route.component = loadedComponent;
}), map(() => void 0)));
}
for (const child of route.children) {
loaders.push(...loadComponents(child));
}
return loaders;
};
return combineLatest(loadComponents(t.targetSnapshot.root)).pipe(defaultIfEmpty(), take(1));
}),
switchTap(() => this.afterPreactivation()),
switchMap(() => {
const {
currentSnapshot,
targetSnapshot
} = overallTransitionState;
const viewTransitionStarted = this.createViewTransition?.(this.environmentInjector, currentSnapshot.root, targetSnapshot.root);
return viewTransitionStarted ? from(viewTransitionStarted).pipe(map(() => overallTransitionState)) : of(overallTransitionState);
}),
map((t) => {
const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
this.currentTransition = overallTransitionState = __spreadProps(__spreadValues({}, t), {
targetRouterState
});
this.currentNavigation.targetRouterState = targetRouterState;
return overallTransitionState;
}),
tap(() => {
this.events.next(new BeforeActivateRoutes());
}),
activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt), this.inputBindingEnabled),
// Ensure that if some observable used to drive the transition doesn't
// complete, the navigation still finalizes This should never happen, but
// this is done as a safety measure to avoid surfacing this error (#49567).
take(1),
tap({
next: (t) => {
completed = true;
this.lastSuccessfulNavigation = this.currentNavigation;
this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
this.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
t.resolve(true);
},
complete: () => {
completed = true;
}
}),
// There used to be a lot more logic happening directly within the
// transition Observable. Some of this logic has been refactored out to
// other places but there may still be errors that happen there. This gives
// us a way to cancel the transition from the outside. This may also be
// required in the future to support something like the abort signal of the
// Navigation API where the navigation gets aborted from outside the
// transition.
takeUntil(this.transitionAbortSubject.pipe(tap((err) => {
throw err;
}))),
finalize(() => {
if (!completed && !errored) {
const cancelationReason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : "";
this.cancelNavigationTransition(
overallTransitionState,
cancelationReason,
1
/* NavigationCancellationCode.SupersededByNewNavigation */
);
}
if (this.currentNavigation?.id === overallTransitionState.id) {
this.currentNavigation = null;
}
}),
catchError((e) => {
errored = true;
if (isNavigationCancelingError$1(e)) {
this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode));
if (!isRedirectingNavigationCancelingError$1(e)) {
overallTransitionState.resolve(false);
} else {
this.events.next(new RedirectRequest(e.url));
}
} else {
this.events.next(new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? void 0));
try {
overallTransitionState.resolve(router.errorHandler(e));
} catch (ee) {
overallTransitionState.reject(ee);
}
}
return EMPTY;
})
);
})
);
}
cancelNavigationTransition(t, reason, code) {
const navCancel = new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);
this.events.next(navCancel);
t.resolve(false);
}
/**
* @returns Whether we're navigating to somewhere that is not what the Router is
* currently set to.
*/
isUpdatingInternalState() {
return this.currentTransition?.extractedUrl.toString() !== this.currentTransition?.currentUrlTree.toString();
}
/**
* @returns Whether we're updating the browser URL to something new (navigation is going
* to somewhere not displayed in the URL bar and we will update the URL
* bar if navigation succeeds).
*/
isUpdatedBrowserUrl() {
const extractedBrowserUrl = this.urlHandlingStrategy.extract(this.urlSerializer.parse(this.location.path(true)));
return extractedBrowserUrl.toString() !== this.currentTransition?.extractedUrl.toString() && !this.currentTransition?.extras.skipLocationChange;
}
};
_NavigationTransitions.ɵfac = function NavigationTransitions_Factory(t) {
return new (t || _NavigationTransitions)();
};
_NavigationTransitions.ɵprov = ɵɵdefineInjectable({
token: _NavigationTransitions,
factory: _NavigationTransitions.ɵfac,
providedIn: "root"
});
var NavigationTransitions = _NavigationTransitions;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NavigationTransitions, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function isBrowserTriggeredNavigation(source) {
return source !== IMPERATIVE_NAVIGATION;
}
var _RouteReuseStrategy = class _RouteReuseStrategy {
};
_RouteReuseStrategy.ɵfac = function RouteReuseStrategy_Factory(t) {
return new (t || _RouteReuseStrategy)();
};
_RouteReuseStrategy.ɵprov = ɵɵdefineInjectable({
token: _RouteReuseStrategy,
factory: () => (() => inject(DefaultRouteReuseStrategy))(),
providedIn: "root"
});
var RouteReuseStrategy = _RouteReuseStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouteReuseStrategy, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(DefaultRouteReuseStrategy)
}]
}], null, null);
})();
var BaseRouteReuseStrategy = class {
/**
* Whether the given route should detach for later reuse.
* Always returns false for `BaseRouteReuseStrategy`.
* */
shouldDetach(route) {
return false;
}
/**
* A no-op; the route is never stored since this strategy never detaches routes for later re-use.
*/
store(route, detachedTree) {
}
/** Returns `false`, meaning the route (and its subtree) is never reattached */
shouldAttach(route) {
return false;
}
/** Returns `null` because this strategy does not store routes for later re-use. */
retrieve(route) {
return null;
}
/**
* Determines if a route should be reused.
* This strategy returns `true` when the future route config and current route config are
* identical.
*/
shouldReuseRoute(future, curr) {
return future.routeConfig === curr.routeConfig;
}
};
var _DefaultRouteReuseStrategy = class _DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
};
_DefaultRouteReuseStrategy.ɵfac = (() => {
let ɵDefaultRouteReuseStrategy_BaseFactory;
return function DefaultRouteReuseStrategy_Factory(t) {
return (ɵDefaultRouteReuseStrategy_BaseFactory || (ɵDefaultRouteReuseStrategy_BaseFactory = ɵɵgetInheritedFactory(_DefaultRouteReuseStrategy)))(t || _DefaultRouteReuseStrategy);
};
})();
_DefaultRouteReuseStrategy.ɵprov = ɵɵdefineInjectable({
token: _DefaultRouteReuseStrategy,
factory: _DefaultRouteReuseStrategy.ɵfac,
providedIn: "root"
});
var DefaultRouteReuseStrategy = _DefaultRouteReuseStrategy;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DefaultRouteReuseStrategy, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var _StateManager = class _StateManager {
};
_StateManager.ɵfac = function StateManager_Factory(t) {
return new (t || _StateManager)();
};
_StateManager.ɵprov = ɵɵdefineInjectable({
token: _StateManager,
factory: () => (() => inject(HistoryStateManager))(),
providedIn: "root"
});
var StateManager = _StateManager;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(StateManager, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(HistoryStateManager)
}]
}], null, null);
})();
var _HistoryStateManager = class _HistoryStateManager extends StateManager {
constructor() {
super(...arguments);
this.location = inject(Location);
this.urlSerializer = inject(UrlSerializer);
this.options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
this.canceledNavigationResolution = this.options.canceledNavigationResolution || "replace";
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
this.urlUpdateStrategy = this.options.urlUpdateStrategy || "deferred";
this.currentUrlTree = new UrlTree();
this.rawUrlTree = this.currentUrlTree;
this.currentPageId = 0;
this.lastSuccessfulId = -1;
this.routerState = createEmptyState(this.currentUrlTree, null);
this.stateMemento = this.createStateMemento();
}
getCurrentUrlTree() {
return this.currentUrlTree;
}
getRawUrlTree() {
return this.rawUrlTree;
}
restoredState() {
return this.location.getState();
}
/**
* The ɵrouterPageId of whatever page is currently active in the browser history. This is
* important for computing the target page id for new navigations because we need to ensure each
* page id in the browser history is 1 more than the previous entry.
*/
get browserPageId() {
if (this.canceledNavigationResolution !== "computed") {
return this.currentPageId;
}
return this.restoredState()?.ɵrouterPageId ?? this.currentPageId;
}
getRouterState() {
return this.routerState;
}
createStateMemento() {
return {
rawUrlTree: this.rawUrlTree,
currentUrlTree: this.currentUrlTree,
routerState: this.routerState
};
}
registerNonRouterCurrentEntryChangeListener(listener) {
return this.location.subscribe((event) => {
if (event["type"] === "popstate") {
listener(event["url"], event.state);
}
});
}
handleRouterEvent(e, currentTransition) {
if (e instanceof NavigationStart) {
this.stateMemento = this.createStateMemento();
} else if (e instanceof NavigationSkipped) {
this.rawUrlTree = currentTransition.initialUrl;
} else if (e instanceof RoutesRecognized) {
if (this.urlUpdateStrategy === "eager") {
if (!currentTransition.extras.skipLocationChange) {
const rawUrl = this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
this.setBrowserUrl(rawUrl, currentTransition);
}
}
} else if (e instanceof BeforeActivateRoutes) {
this.currentUrlTree = currentTransition.finalUrl;
this.rawUrlTree = this.urlHandlingStrategy.merge(currentTransition.finalUrl, currentTransition.initialUrl);
this.routerState = currentTransition.targetRouterState;
if (this.urlUpdateStrategy === "deferred") {
if (!currentTransition.extras.skipLocationChange) {
this.setBrowserUrl(this.rawUrlTree, currentTransition);
}
}
} else if (e instanceof NavigationCancel && (e.code === 3 || e.code === 2)) {
this.restoreHistory(currentTransition);
} else if (e instanceof NavigationError) {
this.restoreHistory(currentTransition, true);
} else if (e instanceof NavigationEnd) {
this.lastSuccessfulId = e.id;
this.currentPageId = this.browserPageId;
}
}
setBrowserUrl(url, transition) {
const path = this.urlSerializer.serialize(url);
if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
const currentBrowserPageId = this.browserPageId;
const state = __spreadValues(__spreadValues({}, transition.extras.state), this.generateNgRouterState(transition.id, currentBrowserPageId));
this.location.replaceState(path, "", state);
} else {
const state = __spreadValues(__spreadValues({}, transition.extras.state), this.generateNgRouterState(transition.id, this.browserPageId + 1));
this.location.go(path, "", state);
}
}
/**
* Performs the necessary rollback action to restore the browser URL to the
* state before the transition.
*/
restoreHistory(navigation, restoringFromCaughtError = false) {
if (this.canceledNavigationResolution === "computed") {
const currentBrowserPageId = this.browserPageId;
const targetPagePosition = this.currentPageId - currentBrowserPageId;
if (targetPagePosition !== 0) {
this.location.historyGo(targetPagePosition);
} else if (this.currentUrlTree === navigation.finalUrl && targetPagePosition === 0) {
this.resetState(navigation);
this.resetUrlToCurrentUrlTree();
} else {
}
} else if (this.canceledNavigationResolution === "replace") {
if (restoringFromCaughtError) {
this.resetState(navigation);
}
this.resetUrlToCurrentUrlTree();
}
}
resetState(navigation) {
this.routerState = this.stateMemento.routerState;
this.currentUrlTree = this.stateMemento.currentUrlTree;
this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, navigation.finalUrl ?? this.rawUrlTree);
}
resetUrlToCurrentUrlTree() {
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), "", this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
}
generateNgRouterState(navigationId, routerPageId) {
if (this.canceledNavigationResolution === "computed") {
return {
navigationId,
ɵrouterPageId: routerPageId
};
}
return {
navigationId
};
}
};
_HistoryStateManager.ɵfac = (() => {
let ɵHistoryStateManager_BaseFactory;
return function HistoryStateManager_Factory(t) {
return (ɵHistoryStateManager_BaseFactory || (ɵHistoryStateManager_BaseFactory = ɵɵgetInheritedFactory(_HistoryStateManager)))(t || _HistoryStateManager);
};
})();
_HistoryStateManager.ɵprov = ɵɵdefineInjectable({
token: _HistoryStateManager,
factory: _HistoryStateManager.ɵfac,
providedIn: "root"
});
var HistoryStateManager = _HistoryStateManager;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HistoryStateManager, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var NavigationResult;
(function(NavigationResult2) {
NavigationResult2[NavigationResult2["COMPLETE"] = 0] = "COMPLETE";
NavigationResult2[NavigationResult2["FAILED"] = 1] = "FAILED";
NavigationResult2[NavigationResult2["REDIRECTING"] = 2] = "REDIRECTING";
})(NavigationResult || (NavigationResult = {}));
function afterNextNavigation(router, action) {
router.events.pipe(filter((e) => e instanceof NavigationEnd || e instanceof NavigationCancel || e instanceof NavigationError || e instanceof NavigationSkipped), map((e) => {
if (e instanceof NavigationEnd || e instanceof NavigationSkipped) {
return NavigationResult.COMPLETE;
}
const redirecting = e instanceof NavigationCancel ? e.code === 0 || e.code === 1 : false;
return redirecting ? NavigationResult.REDIRECTING : NavigationResult.FAILED;
}), filter((result) => result !== NavigationResult.REDIRECTING), take(1)).subscribe(() => {
action();
});
}
function defaultErrorHandler(error) {
throw error;
}
var exactMatchOptions = {
paths: "exact",
fragment: "ignored",
matrixParams: "ignored",
queryParams: "exact"
};
var subsetMatchOptions = {
paths: "subset",
fragment: "ignored",
matrixParams: "ignored",
queryParams: "subset"
};
var _Router = class _Router {
get currentUrlTree() {
return this.stateManager.getCurrentUrlTree();
}
get rawUrlTree() {
return this.stateManager.getRawUrlTree();
}
/**
* An event stream for routing events.
*/
get events() {
return this._events;
}
/**
* The current state of routing in this NgModule.
*/
get routerState() {
return this.stateManager.getRouterState();
}
constructor() {
this.disposed = false;
this.isNgZoneEnabled = false;
this.console = inject(Console);
this.stateManager = inject(StateManager);
this.options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
this.pendingTasks = inject(InitialRenderPendingTasks);
this.urlUpdateStrategy = this.options.urlUpdateStrategy || "deferred";
this.navigationTransitions = inject(NavigationTransitions);
this.urlSerializer = inject(UrlSerializer);
this.location = inject(Location);
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
this._events = new Subject();
this.errorHandler = this.options.errorHandler || defaultErrorHandler;
this.navigated = false;
this.routeReuseStrategy = inject(RouteReuseStrategy);
this.onSameUrlNavigation = this.options.onSameUrlNavigation || "ignore";
this.config = inject(ROUTES, {
optional: true
})?.flat() ?? [];
this.componentInputBindingEnabled = !!inject(INPUT_BINDER, {
optional: true
});
this.eventsSubscription = new Subscription();
this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
this.resetConfig(this.config);
this.navigationTransitions.setupNavigations(this, this.currentUrlTree, this.routerState).subscribe({
error: (e) => {
this.console.warn(ngDevMode ? `Unhandled Navigation Error: ${e}` : e);
}
});
this.subscribeToNavigationEvents();
}
subscribeToNavigationEvents() {
const subscription = this.navigationTransitions.events.subscribe((e) => {
try {
const currentTransition = this.navigationTransitions.currentTransition;
const currentNavigation = this.navigationTransitions.currentNavigation;
if (currentTransition !== null && currentNavigation !== null) {
this.stateManager.handleRouterEvent(e, currentNavigation);
if (e instanceof NavigationCancel && e.code !== 0 && e.code !== 1) {
this.navigated = true;
} else if (e instanceof NavigationEnd) {
this.navigated = true;
} else if (e instanceof RedirectRequest) {
const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
const extras = {
skipLocationChange: currentTransition.extras.skipLocationChange,
// The URL is already updated at this point if we have 'eager' URL
// updates or if the navigation was triggered by the browser (back
// button, URL bar, etc). We want to replace that item in history
// if the navigation is rejected.
replaceUrl: this.urlUpdateStrategy === "eager" || isBrowserTriggeredNavigation(currentTransition.source)
};
this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
resolve: currentTransition.resolve,
reject: currentTransition.reject,
promise: currentTransition.promise
});
}
}
if (isPublicRouterEvent(e)) {
this._events.next(e);
}
} catch (e2) {
this.navigationTransitions.transitionAbortSubject.next(e2);
}
});
this.eventsSubscription.add(subscription);
}
/** @internal */
resetRootComponentType(rootComponentType) {
this.routerState.root.component = rootComponentType;
this.navigationTransitions.rootComponentType = rootComponentType;
}
/**
* Sets up the location change listener and performs the initial navigation.
*/
initialNavigation() {
this.setUpLocationChangeListener();
if (!this.navigationTransitions.hasRequestedNavigation) {
this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, this.stateManager.restoredState());
}
}
/**
* Sets up the location change listener. This listener detects navigations triggered from outside
* the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
* navigation so that the correct events, guards, etc. are triggered.
*/
setUpLocationChangeListener() {
if (!this.nonRouterCurrentEntryChangeSubscription) {
this.nonRouterCurrentEntryChangeSubscription = this.stateManager.registerNonRouterCurrentEntryChangeListener((url, state) => {
setTimeout(() => {
this.navigateToSyncWithBrowser(url, "popstate", state);
}, 0);
});
}
}
/**
* Schedules a router navigation to synchronize Router state with the browser state.
*
* This is done as a response to a popstate event and the initial navigation. These
* two scenarios represent times when the browser URL/state has been updated and
* the Router needs to respond to ensure its internal state matches.
*/
navigateToSyncWithBrowser(url, source, state) {
const extras = {
replaceUrl: true
};
const restoredState = state?.navigationId ? state : null;
if (state) {
const stateCopy = __spreadValues({}, state);
delete stateCopy.navigationId;
delete stateCopy.ɵrouterPageId;
if (Object.keys(stateCopy).length !== 0) {
extras.state = stateCopy;
}
}
const urlTree = this.parseUrl(url);
this.scheduleNavigation(urlTree, source, restoredState, extras);
}
/** The current URL. */
get url() {
return this.serializeUrl(this.currentUrlTree);
}
/**
* Returns the current `Navigation` object when the router is navigating,
* and `null` when idle.
*/
getCurrentNavigation() {
return this.navigationTransitions.currentNavigation;
}
/**
* The `Navigation` object of the most recent navigation to succeed and `null` if there
* has not been a successful navigation yet.
*/
get lastSuccessfulNavigation() {
return this.navigationTransitions.lastSuccessfulNavigation;
}
/**
* Resets the route configuration used for navigation and generating links.
*
* @param config The route array for the new configuration.
*
* @usageNotes
*
* ```
* router.resetConfig([
* { path: 'team/:id', component: TeamCmp, children: [
* { path: 'simple', component: SimpleCmp },
* { path: 'user/:name', component: UserCmp }
* ]}
* ]);
* ```
*/
resetConfig(config) {
(typeof ngDevMode === "undefined" || ngDevMode) && validateConfig(config);
this.config = config.map(standardizeConfig);
this.navigated = false;
}
/** @nodoc */
ngOnDestroy() {
this.dispose();
}
/** Disposes of the router. */
dispose() {
this.navigationTransitions.complete();
if (this.nonRouterCurrentEntryChangeSubscription) {
this.nonRouterCurrentEntryChangeSubscription.unsubscribe();
this.nonRouterCurrentEntryChangeSubscription = void 0;
}
this.disposed = true;
this.eventsSubscription.unsubscribe();
}
/**
* Appends URL segments to the current URL tree to create a new URL tree.
*
* @param commands An array of URL fragments with which to construct the new URL tree.
* If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
* segments, followed by the parameters for each segment.
* The fragments are applied to the current URL tree or the one provided in the `relativeTo`
* property of the options object, if supplied.
* @param navigationExtras Options that control the navigation strategy.
* @returns The new URL tree.
*
* @usageNotes
*
* ```
* // create /team/33/user/11
* router.createUrlTree(['/team', 33, 'user', 11]);
*
* // create /team/33;expand=true/user/11
* router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
*
* // you can collapse static segments like this (this works only with the first passed-in value):
* router.createUrlTree(['/team/33/user', userId]);
*
* // If the first segment can contain slashes, and you do not want the router to split it,
* // you can do the following:
* router.createUrlTree([{segmentPath: '/one/two'}]);
*
* // create /team/33/(user/11//right:chat)
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
*
* // remove the right secondary node
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
*
* // assuming the current url is `/team/33/user/11` and the route points to `user/11`
*
* // navigate to /team/33/user/11/details
* router.createUrlTree(['details'], {relativeTo: route});
*
* // navigate to /team/33/user/22
* router.createUrlTree(['../22'], {relativeTo: route});
*
* // navigate to /team/44/user/22
* router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
*
* Note that a value of `null` or `undefined` for `relativeTo` indicates that the
* tree should be created relative to the root.
* ```
*/
createUrlTree(commands, navigationExtras = {}) {
const {
relativeTo,
queryParams,
fragment,
queryParamsHandling,
preserveFragment
} = navigationExtras;
const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
let q = null;
switch (queryParamsHandling) {
case "merge":
q = __spreadValues(__spreadValues({}, this.currentUrlTree.queryParams), queryParams);
break;
case "preserve":
q = this.currentUrlTree.queryParams;
break;
default:
q = queryParams || null;
}
if (q !== null) {
q = this.removeEmptyProps(q);
}
let relativeToUrlSegmentGroup;
try {
const relativeToSnapshot = relativeTo ? relativeTo.snapshot : this.routerState.snapshot.root;
relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeToSnapshot);
} catch (e) {
if (typeof commands[0] !== "string" || !commands[0].startsWith("/")) {
commands = [];
}
relativeToUrlSegmentGroup = this.currentUrlTree.root;
}
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, q, f ?? null);
}
/**
* Navigates to a view using an absolute route path.
*
* @param url An absolute path for a defined route. The function does not apply any delta to the
* current URL.
* @param extras An object containing properties that modify the navigation strategy.
*
* @returns A Promise that resolves to 'true' when navigation succeeds,
* to 'false' when navigation fails, or is rejected on error.
*
* @usageNotes
*
* The following calls request navigation to an absolute path.
*
* ```
* router.navigateByUrl("/team/33/user/11");
*
* // Navigate without updating the URL
* router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
* ```
*
* @see [Routing and Navigation guide](guide/router)
*
*/
navigateByUrl(url, extras = {
skipLocationChange: false
}) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
}
}
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);
}
/**
* Navigate based on the provided array of commands and a starting point.
* If no starting route is provided, the navigation is absolute.
*
* @param commands An array of URL fragments with which to construct the target URL.
* If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
* segments, followed by the parameters for each segment.
* The fragments are applied to the current URL or the one provided in the `relativeTo` property
* of the options object, if supplied.
* @param extras An options object that determines how the URL should be constructed or
* interpreted.
*
* @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation
* fails,
* or is rejected on error.
*
* @usageNotes
*
* The following calls request navigation to a dynamic route path relative to the current URL.
*
* ```
* router.navigate(['team', 33, 'user', 11], {relativeTo: route});
*
* // Navigate without updating the URL, overriding the default behavior
* router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
* ```
*
* @see [Routing and Navigation guide](guide/router)
*
*/
navigate(commands, extras = {
skipLocationChange: false
}) {
validateCommands(commands);
return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
}
/** Serializes a `UrlTree` into a string */
serializeUrl(url) {
return this.urlSerializer.serialize(url);
}
/** Parses a string into a `UrlTree` */
parseUrl(url) {
try {
return this.urlSerializer.parse(url);
} catch {
return this.urlSerializer.parse("/");
}
}
isActive(url, matchOptions) {
let options;
if (matchOptions === true) {
options = __spreadValues({}, exactMatchOptions);
} else if (matchOptions === false) {
options = __spreadValues({}, subsetMatchOptions);
} else {
options = matchOptions;
}
if (isUrlTree(url)) {
return containsTree(this.currentUrlTree, url, options);
}
const urlTree = this.parseUrl(url);
return containsTree(this.currentUrlTree, urlTree, options);
}
removeEmptyProps(params) {
return Object.keys(params).reduce((result, key) => {
const value = params[key];
if (value !== null && value !== void 0) {
result[key] = value;
}
return result;
}, {});
}
scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
if (this.disposed) {
return Promise.resolve(false);
}
let resolve;
let reject;
let promise;
if (priorPromise) {
resolve = priorPromise.resolve;
reject = priorPromise.reject;
promise = priorPromise.promise;
} else {
promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
}
const taskId = this.pendingTasks.add();
afterNextNavigation(this, () => {
queueMicrotask(() => this.pendingTasks.remove(taskId));
});
this.navigationTransitions.handleNavigationRequest({
source,
restoredState,
currentUrlTree: this.currentUrlTree,
currentRawUrl: this.currentUrlTree,
rawUrl,
extras,
resolve,
reject,
promise,
currentSnapshot: this.routerState.snapshot,
currentRouterState: this.routerState
});
return promise.catch((e) => {
return Promise.reject(e);
});
}
};
_Router.ɵfac = function Router_Factory(t) {
return new (t || _Router)();
};
_Router.ɵprov = ɵɵdefineInjectable({
token: _Router,
factory: _Router.ɵfac,
providedIn: "root"
});
var Router = _Router;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Router, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function validateCommands(commands) {
for (let i = 0; i < commands.length; i++) {
const cmd = commands[i];
if (cmd == null) {
throw new RuntimeError(4008, (typeof ngDevMode === "undefined" || ngDevMode) && `The requested path contains ${cmd} segment at index ${i}`);
}
}
}
function isPublicRouterEvent(e) {
return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest);
}
var _RouterLink = class _RouterLink {
constructor(router, route, tabIndexAttribute, renderer, el, locationStrategy) {
this.router = router;
this.route = route;
this.tabIndexAttribute = tabIndexAttribute;
this.renderer = renderer;
this.el = el;
this.locationStrategy = locationStrategy;
this.href = null;
this.commands = null;
this.onChanges = new Subject();
this.preserveFragment = false;
this.skipLocationChange = false;
this.replaceUrl = false;
const tagName = el.nativeElement.tagName?.toLowerCase();
this.isAnchorElement = tagName === "a" || tagName === "area";
if (this.isAnchorElement) {
this.subscription = router.events.subscribe((s) => {
if (s instanceof NavigationEnd) {
this.updateHref();
}
});
} else {
this.setTabIndexIfNotOnNativeEl("0");
}
}
/**
* Modifies the tab index if there was not a tabindex attribute on the element during
* instantiation.
*/
setTabIndexIfNotOnNativeEl(newTabIndex) {
if (this.tabIndexAttribute != null || this.isAnchorElement) {
return;
}
this.applyAttributeValue("tabindex", newTabIndex);
}
/** @nodoc */
ngOnChanges(changes) {
if (this.isAnchorElement) {
this.updateHref();
}
this.onChanges.next(this);
}
/**
* Commands to pass to {@link Router#createUrlTree}.
* - **array**: commands to pass to {@link Router#createUrlTree}.
* - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
* - **null|undefined**: effectively disables the `routerLink`
* @see {@link Router#createUrlTree}
*/
set routerLink(commands) {
if (commands != null) {
this.commands = Array.isArray(commands) ? commands : [commands];
this.setTabIndexIfNotOnNativeEl("0");
} else {
this.commands = null;
this.setTabIndexIfNotOnNativeEl(null);
}
}
/** @nodoc */
onClick(button, ctrlKey, shiftKey, altKey, metaKey) {
if (this.urlTree === null) {
return true;
}
if (this.isAnchorElement) {
if (button !== 0 || ctrlKey || shiftKey || altKey || metaKey) {
return true;
}
if (typeof this.target === "string" && this.target != "_self") {
return true;
}
}
const extras = {
skipLocationChange: this.skipLocationChange,
replaceUrl: this.replaceUrl,
state: this.state
};
this.router.navigateByUrl(this.urlTree, extras);
return !this.isAnchorElement;
}
/** @nodoc */
ngOnDestroy() {
this.subscription?.unsubscribe();
}
updateHref() {
this.href = this.urlTree !== null && this.locationStrategy ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(this.urlTree)) : null;
const sanitizedValue = this.href === null ? null : (
// This class represents a directive that can be added to both `` elements,
// as well as other elements. As a result, we can't define security context at
// compile time. So the security context is deferred to runtime.
// The `ɵɵsanitizeUrlOrResourceUrl` selects the necessary sanitizer function
// based on the tag and property names. The logic mimics the one from
// `packages/compiler/src/schema/dom_security_schema.ts`, which is used at compile time.
//
// Note: we should investigate whether we can switch to using `@HostBinding('attr.href')`
// instead of applying a value via a renderer, after a final merge of the
// `RouterLinkWithHref` directive.
ɵɵsanitizeUrlOrResourceUrl(this.href, this.el.nativeElement.tagName.toLowerCase(), "href")
);
this.applyAttributeValue("href", sanitizedValue);
}
applyAttributeValue(attrName, attrValue) {
const renderer = this.renderer;
const nativeElement = this.el.nativeElement;
if (attrValue !== null) {
renderer.setAttribute(nativeElement, attrName, attrValue);
} else {
renderer.removeAttribute(nativeElement, attrName);
}
}
get urlTree() {
if (this.commands === null) {
return null;
}
return this.router.createUrlTree(this.commands, {
// If the `relativeTo` input is not defined, we want to use `this.route` by default.
// Otherwise, we should use the value provided by the user in the input.
relativeTo: this.relativeTo !== void 0 ? this.relativeTo : this.route,
queryParams: this.queryParams,
fragment: this.fragment,
queryParamsHandling: this.queryParamsHandling,
preserveFragment: this.preserveFragment
});
}
};
_RouterLink.ɵfac = function RouterLink_Factory(t) {
return new (t || _RouterLink)(ɵɵdirectiveInject(Router), ɵɵdirectiveInject(ActivatedRoute), ɵɵinjectAttribute("tabindex"), ɵɵdirectiveInject(Renderer2), ɵɵdirectiveInject(ElementRef), ɵɵdirectiveInject(LocationStrategy));
};
_RouterLink.ɵdir = ɵɵdefineDirective({
type: _RouterLink,
selectors: [["", "routerLink", ""]],
hostVars: 1,
hostBindings: function RouterLink_HostBindings(rf, ctx) {
if (rf & 1) {
ɵɵlistener("click", function RouterLink_click_HostBindingHandler($event) {
return ctx.onClick($event.button, $event.ctrlKey, $event.shiftKey, $event.altKey, $event.metaKey);
});
}
if (rf & 2) {
ɵɵattribute("target", ctx.target);
}
},
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"
},
standalone: true,
features: [ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature]
});
var RouterLink = _RouterLink;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterLink, [{
type: Directive,
args: [{
selector: "[routerLink]",
standalone: true
}]
}], () => [{
type: Router
}, {
type: ActivatedRoute
}, {
type: void 0,
decorators: [{
type: Attribute,
args: ["tabindex"]
}]
}, {
type: Renderer2
}, {
type: ElementRef
}, {
type: LocationStrategy
}], {
target: [{
type: HostBinding,
args: ["attr.target"]
}, {
type: Input
}],
queryParams: [{
type: Input
}],
fragment: [{
type: Input
}],
queryParamsHandling: [{
type: Input
}],
state: [{
type: Input
}],
relativeTo: [{
type: Input
}],
preserveFragment: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
skipLocationChange: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
replaceUrl: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
routerLink: [{
type: Input
}],
onClick: [{
type: HostListener,
args: ["click", ["$event.button", "$event.ctrlKey", "$event.shiftKey", "$event.altKey", "$event.metaKey"]]
}]
});
})();
var _RouterLinkActive = class _RouterLinkActive {
get isActive() {
return this._isActive;
}
constructor(router, element, renderer, cdr, link) {
this.router = router;
this.element = element;
this.renderer = renderer;
this.cdr = cdr;
this.link = link;
this.classes = [];
this._isActive = false;
this.routerLinkActiveOptions = {
exact: false
};
this.isActiveChange = new EventEmitter();
this.routerEventsSubscription = router.events.subscribe((s) => {
if (s instanceof NavigationEnd) {
this.update();
}
});
}
/** @nodoc */
ngAfterContentInit() {
of(this.links.changes, of(null)).pipe(mergeAll()).subscribe((_) => {
this.update();
this.subscribeToEachLinkOnChanges();
});
}
subscribeToEachLinkOnChanges() {
this.linkInputChangesSubscription?.unsubscribe();
const allLinkChanges = [...this.links.toArray(), this.link].filter((link) => !!link).map((link) => link.onChanges);
this.linkInputChangesSubscription = from(allLinkChanges).pipe(mergeAll()).subscribe((link) => {
if (this._isActive !== this.isLinkActive(this.router)(link)) {
this.update();
}
});
}
set routerLinkActive(data) {
const classes = Array.isArray(data) ? data : data.split(" ");
this.classes = classes.filter((c) => !!c);
}
/** @nodoc */
ngOnChanges(changes) {
this.update();
}
/** @nodoc */
ngOnDestroy() {
this.routerEventsSubscription.unsubscribe();
this.linkInputChangesSubscription?.unsubscribe();
}
update() {
if (!this.links || !this.router.navigated)
return;
queueMicrotask(() => {
const hasActiveLinks = this.hasActiveLinks();
if (this._isActive !== hasActiveLinks) {
this._isActive = hasActiveLinks;
this.cdr.markForCheck();
this.classes.forEach((c) => {
if (hasActiveLinks) {
this.renderer.addClass(this.element.nativeElement, c);
} else {
this.renderer.removeClass(this.element.nativeElement, c);
}
});
if (hasActiveLinks && this.ariaCurrentWhenActive !== void 0) {
this.renderer.setAttribute(this.element.nativeElement, "aria-current", this.ariaCurrentWhenActive.toString());
} else {
this.renderer.removeAttribute(this.element.nativeElement, "aria-current");
}
this.isActiveChange.emit(hasActiveLinks);
}
});
}
isLinkActive(router) {
const options = isActiveMatchOptions(this.routerLinkActiveOptions) ? this.routerLinkActiveOptions : (
// While the types should disallow `undefined` here, it's possible without strict inputs
this.routerLinkActiveOptions.exact || false
);
return (link) => link.urlTree ? router.isActive(link.urlTree, options) : false;
}
hasActiveLinks() {
const isActiveCheckFn = this.isLinkActive(this.router);
return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn);
}
};
_RouterLinkActive.ɵfac = function RouterLinkActive_Factory(t) {
return new (t || _RouterLinkActive)(ɵɵdirectiveInject(Router), ɵɵdirectiveInject(ElementRef), ɵɵdirectiveInject(Renderer2), ɵɵdirectiveInject(ChangeDetectorRef), ɵɵdirectiveInject(RouterLink, 8));
};
_RouterLinkActive.ɵdir = ɵɵdefineDirective({
type: _RouterLinkActive,
selectors: [["", "routerLinkActive", ""]],
contentQueries: function RouterLinkActive_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
ɵɵcontentQuery(dirIndex, RouterLink, 5);
}
if (rf & 2) {
let _t;
ɵɵqueryRefresh(_t = ɵɵloadQuery()) && (ctx.links = _t);
}
},
inputs: {
routerLinkActiveOptions: "routerLinkActiveOptions",
ariaCurrentWhenActive: "ariaCurrentWhenActive",
routerLinkActive: "routerLinkActive"
},
outputs: {
isActiveChange: "isActiveChange"
},
exportAs: ["routerLinkActive"],
standalone: true,
features: [ɵɵNgOnChangesFeature]
});
var RouterLinkActive = _RouterLinkActive;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterLinkActive, [{
type: Directive,
args: [{
selector: "[routerLinkActive]",
exportAs: "routerLinkActive",
standalone: true
}]
}], () => [{
type: Router
}, {
type: ElementRef
}, {
type: Renderer2
}, {
type: ChangeDetectorRef
}, {
type: RouterLink,
decorators: [{
type: Optional
}]
}], {
links: [{
type: ContentChildren,
args: [RouterLink, {
descendants: true
}]
}],
routerLinkActiveOptions: [{
type: Input
}],
ariaCurrentWhenActive: [{
type: Input
}],
isActiveChange: [{
type: Output
}],
routerLinkActive: [{
type: Input
}]
});
})();
function isActiveMatchOptions(options) {
return !!options.paths;
}
var PreloadingStrategy = class {
};
var _PreloadAllModules = class _PreloadAllModules {
preload(route, fn) {
return fn().pipe(catchError(() => of(null)));
}
};
_PreloadAllModules.ɵfac = function PreloadAllModules_Factory(t) {
return new (t || _PreloadAllModules)();
};
_PreloadAllModules.ɵprov = ɵɵdefineInjectable({
token: _PreloadAllModules,
factory: _PreloadAllModules.ɵfac,
providedIn: "root"
});
var PreloadAllModules = _PreloadAllModules;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PreloadAllModules, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var _NoPreloading = class _NoPreloading {
preload(route, fn) {
return of(null);
}
};
_NoPreloading.ɵfac = function NoPreloading_Factory(t) {
return new (t || _NoPreloading)();
};
_NoPreloading.ɵprov = ɵɵdefineInjectable({
token: _NoPreloading,
factory: _NoPreloading.ɵfac,
providedIn: "root"
});
var NoPreloading = _NoPreloading;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NoPreloading, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var _RouterPreloader = class _RouterPreloader {
constructor(router, compiler, injector, preloadingStrategy, loader) {
this.router = router;
this.injector = injector;
this.preloadingStrategy = preloadingStrategy;
this.loader = loader;
}
setUpPreloading() {
this.subscription = this.router.events.pipe(filter((e) => e instanceof NavigationEnd), concatMap(() => this.preload())).subscribe(() => {
});
}
preload() {
return this.processRoutes(this.injector, this.router.config);
}
/** @nodoc */
ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
processRoutes(injector, routes) {
const res = [];
for (const route of routes) {
if (route.providers && !route._injector) {
route._injector = createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
}
const injectorForCurrentRoute = route._injector ?? injector;
const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
if (route.loadChildren && !route._loadedRoutes && route.canLoad === void 0 || route.loadComponent && !route._loadedComponent) {
res.push(this.preloadConfig(injectorForCurrentRoute, route));
}
if (route.children || route._loadedRoutes) {
res.push(this.processRoutes(injectorForChildren, route.children ?? route._loadedRoutes));
}
}
return from(res).pipe(mergeAll());
}
preloadConfig(injector, route) {
return this.preloadingStrategy.preload(route, () => {
let loadedChildren$;
if (route.loadChildren && route.canLoad === void 0) {
loadedChildren$ = this.loader.loadChildren(injector, route);
} else {
loadedChildren$ = of(null);
}
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
if (config === null) {
return of(void 0);
}
route._loadedRoutes = config.routes;
route._loadedInjector = config.injector;
return this.processRoutes(config.injector ?? injector, config.routes);
}));
if (route.loadComponent && !route._loadedComponent) {
const loadComponent$ = this.loader.loadComponent(route);
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
} else {
return recursiveLoadChildren$;
}
});
}
};
_RouterPreloader.ɵfac = function RouterPreloader_Factory(t) {
return new (t || _RouterPreloader)(ɵɵinject(Router), ɵɵinject(Compiler), ɵɵinject(EnvironmentInjector), ɵɵinject(PreloadingStrategy), ɵɵinject(RouterConfigLoader));
};
_RouterPreloader.ɵprov = ɵɵdefineInjectable({
token: _RouterPreloader,
factory: _RouterPreloader.ɵfac,
providedIn: "root"
});
var RouterPreloader = _RouterPreloader;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterPreloader, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: Router
}, {
type: Compiler
}, {
type: EnvironmentInjector
}, {
type: PreloadingStrategy
}, {
type: RouterConfigLoader
}], null);
})();
var ROUTER_SCROLLER = new InjectionToken("");
var _RouterScroller = class _RouterScroller {
/** @nodoc */
constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) {
this.urlSerializer = urlSerializer;
this.transitions = transitions;
this.viewportScroller = viewportScroller;
this.zone = zone;
this.options = options;
this.lastId = 0;
this.lastSource = "imperative";
this.restoredId = 0;
this.store = {};
options.scrollPositionRestoration = options.scrollPositionRestoration || "disabled";
options.anchorScrolling = options.anchorScrolling || "disabled";
}
init() {
if (this.options.scrollPositionRestoration !== "disabled") {
this.viewportScroller.setHistoryScrollRestoration("manual");
}
this.routerEventsSubscription = this.createScrollEvents();
this.scrollEventsSubscription = this.consumeScrollEvents();
}
createScrollEvents() {
return this.transitions.events.subscribe((e) => {
if (e instanceof NavigationStart) {
this.store[this.lastId] = this.viewportScroller.getScrollPosition();
this.lastSource = e.navigationTrigger;
this.restoredId = e.restoredState ? e.restoredState.navigationId : 0;
} else if (e instanceof NavigationEnd) {
this.lastId = e.id;
this.scheduleScrollEvent(e, this.urlSerializer.parse(e.urlAfterRedirects).fragment);
} else if (e instanceof NavigationSkipped && e.code === 0) {
this.lastSource = void 0;
this.restoredId = 0;
this.scheduleScrollEvent(e, this.urlSerializer.parse(e.url).fragment);
}
});
}
consumeScrollEvents() {
return this.transitions.events.subscribe((e) => {
if (!(e instanceof Scroll))
return;
if (e.position) {
if (this.options.scrollPositionRestoration === "top") {
this.viewportScroller.scrollToPosition([0, 0]);
} else if (this.options.scrollPositionRestoration === "enabled") {
this.viewportScroller.scrollToPosition(e.position);
}
} else {
if (e.anchor && this.options.anchorScrolling === "enabled") {
this.viewportScroller.scrollToAnchor(e.anchor);
} else if (this.options.scrollPositionRestoration !== "disabled") {
this.viewportScroller.scrollToPosition([0, 0]);
}
}
});
}
scheduleScrollEvent(routerEvent, anchor) {
this.zone.runOutsideAngular(() => {
setTimeout(() => {
this.zone.run(() => {
this.transitions.events.next(new Scroll(routerEvent, this.lastSource === "popstate" ? this.store[this.restoredId] : null, anchor));
});
}, 0);
});
}
/** @nodoc */
ngOnDestroy() {
this.routerEventsSubscription?.unsubscribe();
this.scrollEventsSubscription?.unsubscribe();
}
};
_RouterScroller.ɵfac = function RouterScroller_Factory(t) {
ɵɵinvalidFactory();
};
_RouterScroller.ɵprov = ɵɵdefineInjectable({
token: _RouterScroller,
factory: _RouterScroller.ɵfac
});
var RouterScroller = _RouterScroller;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterScroller, [{
type: Injectable
}], () => [{
type: UrlSerializer
}, {
type: NavigationTransitions
}, {
type: ViewportScroller
}, {
type: NgZone
}, {
type: void 0
}], null);
})();
function provideRouter(routes, ...features) {
return makeEnvironmentProviders([{
provide: ROUTES,
multi: true,
useValue: routes
}, typeof ngDevMode === "undefined" || ngDevMode ? {
provide: ROUTER_IS_PROVIDED,
useValue: true
} : [], {
provide: ActivatedRoute,
useFactory: rootRoute,
deps: [Router]
}, {
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useFactory: getBootstrapListener
}, features.map((feature) => feature.ɵproviders)]);
}
function rootRoute(router) {
return router.routerState.root;
}
function routerFeature(kind, providers) {
return {
ɵkind: kind,
ɵproviders: providers
};
}
var ROUTER_IS_PROVIDED = new InjectionToken("", {
providedIn: "root",
factory: () => false
});
var routerIsProvidedDevModeCheck = {
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useFactory() {
return () => {
if (!inject(ROUTER_IS_PROVIDED)) {
console.warn("`provideRoutes` was called without `provideRouter` or `RouterModule.forRoot`. This is likely a mistake.");
}
};
}
};
function provideRoutes(routes) {
return [{
provide: ROUTES,
multi: true,
useValue: routes
}, typeof ngDevMode === "undefined" || ngDevMode ? routerIsProvidedDevModeCheck : []];
}
function withInMemoryScrolling(options = {}) {
const providers = [{
provide: ROUTER_SCROLLER,
useFactory: () => {
const viewportScroller = inject(ViewportScroller);
const zone = inject(NgZone);
const transitions = inject(NavigationTransitions);
const urlSerializer = inject(UrlSerializer);
return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, options);
}
}];
return routerFeature(4, providers);
}
function getBootstrapListener() {
const injector = inject(Injector);
return (bootstrappedComponentRef) => {
const ref = injector.get(ApplicationRef);
if (bootstrappedComponentRef !== ref.components[0]) {
return;
}
const router = injector.get(Router);
const bootstrapDone = injector.get(BOOTSTRAP_DONE);
if (injector.get(INITIAL_NAVIGATION) === 1) {
router.initialNavigation();
}
injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
router.resetRootComponentType(ref.componentTypes[0]);
if (!bootstrapDone.closed) {
bootstrapDone.next();
bootstrapDone.complete();
bootstrapDone.unsubscribe();
}
};
}
var BOOTSTRAP_DONE = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "bootstrap done indicator" : "", {
factory: () => {
return new Subject();
}
});
var INITIAL_NAVIGATION = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "initial navigation" : "", {
providedIn: "root",
factory: () => 1
/* InitialNavigation.EnabledNonBlocking */
});
function withEnabledBlockingInitialNavigation() {
const providers = [{
provide: INITIAL_NAVIGATION,
useValue: 0
/* InitialNavigation.EnabledBlocking */
}, {
provide: APP_INITIALIZER,
multi: true,
deps: [Injector],
useFactory: (injector) => {
const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve());
return () => {
return locationInitialized.then(() => {
return new Promise((resolve) => {
const router = injector.get(Router);
const bootstrapDone = injector.get(BOOTSTRAP_DONE);
afterNextNavigation(router, () => {
resolve(true);
});
injector.get(NavigationTransitions).afterPreactivation = () => {
resolve(true);
return bootstrapDone.closed ? of(void 0) : bootstrapDone;
};
router.initialNavigation();
});
});
};
}
}];
return routerFeature(2, providers);
}
function withDisabledInitialNavigation() {
const providers = [{
provide: APP_INITIALIZER,
multi: true,
useFactory: () => {
const router = inject(Router);
return () => {
router.setUpLocationChangeListener();
};
}
}, {
provide: INITIAL_NAVIGATION,
useValue: 2
/* InitialNavigation.Disabled */
}];
return routerFeature(3, providers);
}
function withDebugTracing() {
let providers = [];
if (typeof ngDevMode === "undefined" || ngDevMode) {
providers = [{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useFactory: () => {
const router = inject(Router);
return () => router.events.subscribe((e) => {
console.group?.(`Router Event: ${e.constructor.name}`);
console.log(stringifyEvent(e));
console.log(e);
console.groupEnd?.();
});
}
}];
} else {
providers = [];
}
return routerFeature(1, providers);
}
var ROUTER_PRELOADER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "router preloader" : "");
function withPreloading(preloadingStrategy) {
const providers = [{
provide: ROUTER_PRELOADER,
useExisting: RouterPreloader
}, {
provide: PreloadingStrategy,
useExisting: preloadingStrategy
}];
return routerFeature(0, providers);
}
function withRouterConfig(options) {
const providers = [{
provide: ROUTER_CONFIGURATION,
useValue: options
}];
return routerFeature(5, providers);
}
function withHashLocation() {
const providers = [{
provide: LocationStrategy,
useClass: HashLocationStrategy
}];
return routerFeature(6, providers);
}
function withNavigationErrorHandler(fn) {
const providers = [{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
const injector = inject(EnvironmentInjector);
inject(Router).events.subscribe((e) => {
if (e instanceof NavigationError) {
runInInjectionContext(injector, () => fn(e));
}
});
}
}];
return routerFeature(7, providers);
}
function withComponentInputBinding() {
const providers = [RoutedComponentInputBinder, {
provide: INPUT_BINDER,
useExisting: RoutedComponentInputBinder
}];
return routerFeature(8, providers);
}
function withViewTransitions(options) {
const providers = [{
provide: CREATE_VIEW_TRANSITION,
useValue: createViewTransition
}, {
provide: VIEW_TRANSITION_OPTIONS,
useValue: __spreadValues({
skipNextTransition: !!options?.skipInitialTransition
}, options)
}];
return routerFeature(9, providers);
}
var ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent];
var ROUTER_FORROOT_GUARD = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "router duplicate forRoot guard" : "ROUTER_FORROOT_GUARD");
var ROUTER_PROVIDERS = [
Location,
{
provide: UrlSerializer,
useClass: DefaultUrlSerializer
},
Router,
ChildrenOutletContexts,
{
provide: ActivatedRoute,
useFactory: rootRoute,
deps: [Router]
},
RouterConfigLoader,
// Only used to warn when `provideRoutes` is used without `RouterModule` or `provideRouter`. Can
// be removed when `provideRoutes` is removed.
typeof ngDevMode === "undefined" || ngDevMode ? {
provide: ROUTER_IS_PROVIDED,
useValue: true
} : []
];
var _RouterModule = class _RouterModule {
constructor(guard) {
}
/**
* Creates and configures a module with all the router providers and directives.
* Optionally sets up an application listener to perform an initial navigation.
*
* When registering the NgModule at the root, import as follows:
*
* ```
* @NgModule({
* imports: [RouterModule.forRoot(ROUTES)]
* })
* class MyNgModule {}
* ```
*
* @param routes An array of `Route` objects that define the navigation paths for the application.
* @param config An `ExtraOptions` configuration object that controls how navigation is performed.
* @return The new `NgModule`.
*
*/
static forRoot(routes, config) {
return {
ngModule: _RouterModule,
providers: [ROUTER_PROVIDERS, typeof ngDevMode === "undefined" || ngDevMode ? config?.enableTracing ? withDebugTracing().ɵproviders : [] : [], {
provide: ROUTES,
multi: true,
useValue: routes
}, {
provide: ROUTER_FORROOT_GUARD,
useFactory: provideForRootGuard,
deps: [[Router, new Optional(), new SkipSelf()]]
}, {
provide: ROUTER_CONFIGURATION,
useValue: config ? config : {}
}, config?.useHash ? provideHashLocationStrategy() : providePathLocationStrategy(), provideRouterScroller(), config?.preloadingStrategy ? withPreloading(config.preloadingStrategy).ɵproviders : [], config?.initialNavigation ? provideInitialNavigation(config) : [], config?.bindToComponentInputs ? withComponentInputBinding().ɵproviders : [], config?.enableViewTransitions ? withViewTransitions().ɵproviders : [], provideRouterInitializer()]
};
}
/**
* Creates a module with all the router directives and a provider registering routes,
* without creating a new Router service.
* When registering for submodules and lazy-loaded submodules, create the NgModule as follows:
*
* ```
* @NgModule({
* imports: [RouterModule.forChild(ROUTES)]
* })
* class MyNgModule {}
* ```
*
* @param routes An array of `Route` objects that define the navigation paths for the submodule.
* @return The new NgModule.
*
*/
static forChild(routes) {
return {
ngModule: _RouterModule,
providers: [{
provide: ROUTES,
multi: true,
useValue: routes
}]
};
}
};
_RouterModule.ɵfac = function RouterModule_Factory(t) {
return new (t || _RouterModule)(ɵɵinject(ROUTER_FORROOT_GUARD, 8));
};
_RouterModule.ɵmod = ɵɵdefineNgModule({
type: _RouterModule,
imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent],
exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent]
});
_RouterModule.ɵinj = ɵɵdefineInjector({});
var RouterModule = _RouterModule;
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterModule, [{
type: NgModule,
args: [{
imports: ROUTER_DIRECTIVES,
exports: ROUTER_DIRECTIVES
}]
}], () => [{
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [ROUTER_FORROOT_GUARD]
}]
}], null);
})();
function provideRouterScroller() {
return {
provide: ROUTER_SCROLLER,
useFactory: () => {
const viewportScroller = inject(ViewportScroller);
const zone = inject(NgZone);
const config = inject(ROUTER_CONFIGURATION);
const transitions = inject(NavigationTransitions);
const urlSerializer = inject(UrlSerializer);
if (config.scrollOffset) {
viewportScroller.setOffset(config.scrollOffset);
}
return new RouterScroller(urlSerializer, transitions, viewportScroller, zone, config);
}
};
}
function provideHashLocationStrategy() {
return {
provide: LocationStrategy,
useClass: HashLocationStrategy
};
}
function providePathLocationStrategy() {
return {
provide: LocationStrategy,
useClass: PathLocationStrategy
};
}
function provideForRootGuard(router) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && router) {
throw new RuntimeError(4007, `The Router was provided more than once. This can happen if 'forRoot' is used outside of the root injector. Lazy loaded modules should use RouterModule.forChild() instead.`);
}
return "guarded";
}
function provideInitialNavigation(config) {
return [config.initialNavigation === "disabled" ? withDisabledInitialNavigation().ɵproviders : [], config.initialNavigation === "enabledBlocking" ? withEnabledBlockingInitialNavigation().ɵproviders : []];
}
var ROUTER_INITIALIZER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "Router Initializer" : "");
function provideRouterInitializer() {
return [
// ROUTER_INITIALIZER token should be removed. It's public API but shouldn't be. We can just
// have `getBootstrapListener` directly attached to APP_BOOTSTRAP_LISTENER.
{
provide: ROUTER_INITIALIZER,
useFactory: getBootstrapListener
},
{
provide: APP_BOOTSTRAP_LISTENER,
multi: true,
useExisting: ROUTER_INITIALIZER
}
];
}
function mapToCanMatch(providers) {
return providers.map((provider) => (...params) => inject(provider).canMatch(...params));
}
function mapToCanActivate(providers) {
return providers.map((provider) => (...params) => inject(provider).canActivate(...params));
}
function mapToCanActivateChild(providers) {
return providers.map((provider) => (...params) => inject(provider).canActivateChild(...params));
}
function mapToCanDeactivate(providers) {
return providers.map((provider) => (...params) => inject(provider).canDeactivate(...params));
}
function mapToResolve(provider) {
return (...params) => inject(provider).resolve(...params);
}
var VERSION = new Version("17.0.7");
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,
loadChildren as ɵloadChildren
};
/*! Bundled license information:
@angular/router/fesm2022/router.mjs:
(**
* @license Angular v17.0.7
* (c) 2010-2022 Google LLC. https://angular.io/
* License: MIT
*)
*/
//# sourceMappingURL=@angular_router.js.map