import { Title } from "./chunk-OVEDGMY5.js"; import { HashLocationStrategy, LOCATION_INITIALIZED, Location, LocationStrategy, PathLocationStrategy, ViewportScroller } from "./chunk-PSDIAYZ2.js"; import { APP_BOOTSTRAP_LISTENER, ApplicationRef, Attribute, ChangeDetectorRef, Compiler, Component, Console, ContentChildren, DOCUMENT, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EnvironmentInjector, EventEmitter, HostAttributeToken, HostBinding, HostListener, INTERNAL_APPLICATION_ERROR_HANDLER, IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, Injectable, InjectionToken, Injector, Input, NgModule, NgModuleFactory$1, NgZone, Optional, Output, PendingTasksInternal, Renderer2, RuntimeError, SkipSelf, Version, ViewContainerRef, afterNextRender, booleanAttribute, createEnvironmentInjector, formatRuntimeError, inject, input, isInjectable, isNgModule, isPromise, isStandalone, makeEnvironmentProviders, performanceMarkFeature, provideAppInitializer, publishExternalGlobalUtil, reflectComponentType, runInInjectionContext, setClassMetadata, signal, untracked, ɵɵNgOnChangesFeature, ɵɵattribute, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdirectiveInject, ɵɵelement, ɵɵgetInheritedFactory, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵlistener, ɵɵloadQuery, ɵɵqueryRefresh, ɵɵsanitizeUrlOrResourceUrl } from "./chunk-COCNRMG2.js"; import { defer, isObservable } from "./chunk-576P5TAG.js"; import { BehaviorSubject, ConnectableObservable, EMPTY, EmptyError, Observable, Subject, Subscription, catchError, combineLatest, concat, concatMap, defaultIfEmpty, filter, finalize, first, from, last, map, mergeAll, mergeMap, of, pipe, refCount, scan, startWith, switchMap, take, takeLast, takeUntil, tap, throwError } from "./chunk-2K3BB2X3.js"; import { __async, __spreadProps, __spreadValues } from "./chunk-WDMUDEB6.js"; // node_modules/@angular/router/fesm2022/router2.mjs var PRIMARY_OUTLET = "primary"; var RouteTitleKey = Symbol("RouteTitle"); var ParamsAsMap = class { params; 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[0] === ":"; 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 { root; queryParams; fragment; /** @internal */ _queryParamMap; 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() { this._queryParamMap ??= convertToParamMap(this.queryParams); return this._queryParamMap; } /** @docsNotRequired */ toString() { return DEFAULT_SERIALIZER.serialize(this); } }; var UrlSegmentGroup = class { segments; children; /** The parent node in the url tree */ parent = null; constructor(segments, children) { this.segments = segments; this.children = children; 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 { path; parameters; /** @internal */ _parameterMap; constructor(path, parameters) { this.path = path; this.parameters = parameters; } get 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 { static ɵfac = function UrlSerializer_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _UrlSerializer)(); }; static ɵprov = ɵɵdefineInjectable({ token: _UrlSerializer, factory: () => (() => new DefaultUrlSerializer())(), providedIn: "root" }); }; (() => { (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.entries(params).map(([key, value]) => `;${encodeUriSegment(key)}=${encodeUriSegment(value)}`).join(""); } function serializeQueryParams(params) { const strParams = Object.entries(params).map(([name, value]) => { 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 { url; remaining; 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; 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 ?? PRIMARY_OUTLET] = Object.keys(children).length === 1 && children[PRIMARY_OUTLET] ? 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, child] of Object.entries(segmentGroup.children)) { 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 { isAbsolute; numberOfDoubleDots; commands; 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 { segmentGroup; processChildren; index; 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) { 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 EventType; (function(EventType2) { EventType2[EventType2["NavigationStart"] = 0] = "NavigationStart"; EventType2[EventType2["NavigationEnd"] = 1] = "NavigationEnd"; EventType2[EventType2["NavigationCancel"] = 2] = "NavigationCancel"; EventType2[EventType2["NavigationError"] = 3] = "NavigationError"; EventType2[EventType2["RoutesRecognized"] = 4] = "RoutesRecognized"; EventType2[EventType2["ResolveStart"] = 5] = "ResolveStart"; EventType2[EventType2["ResolveEnd"] = 6] = "ResolveEnd"; EventType2[EventType2["GuardsCheckStart"] = 7] = "GuardsCheckStart"; EventType2[EventType2["GuardsCheckEnd"] = 8] = "GuardsCheckEnd"; EventType2[EventType2["RouteConfigLoadStart"] = 9] = "RouteConfigLoadStart"; EventType2[EventType2["RouteConfigLoadEnd"] = 10] = "RouteConfigLoadEnd"; EventType2[EventType2["ChildActivationStart"] = 11] = "ChildActivationStart"; EventType2[EventType2["ChildActivationEnd"] = 12] = "ChildActivationEnd"; EventType2[EventType2["ActivationStart"] = 13] = "ActivationStart"; EventType2[EventType2["ActivationEnd"] = 14] = "ActivationEnd"; EventType2[EventType2["Scroll"] = 15] = "Scroll"; EventType2[EventType2["NavigationSkipped"] = 16] = "NavigationSkipped"; })(EventType || (EventType = {})); var RouterEvent = class { id; url; constructor(id, url) { this.id = id; this.url = url; } }; var NavigationStart = class extends RouterEvent { type = EventType.NavigationStart; /** * Identifies the call or event that triggered the navigation. * An `imperative` trigger is a call to `router.navigateByUrl()` or `router.navigate()`. * * @see {@link NavigationEnd} * @see {@link NavigationCancel} * @see {@link NavigationError} */ navigationTrigger; /** * The navigation state that was previously supplied to the `pushState` call, * when the navigation is triggered by a `popstate` event. Otherwise null. * * The state object is defined by `NavigationExtras`, and contains any * developer-defined state value, as well as a unique ID that * the router assigns to every router transition/navigation. * * From the perspective of the router, the router never "goes back". * When the user clicks on the back button in the browser, * a new navigation ID is created. * * Use the ID in this previous-state object to differentiate between a newly created * state and one returned to by a `popstate` event, so that you can restore some * remembered state, such as scroll position. * */ restoredState; constructor(id, url, navigationTrigger = "imperative", restoredState = null) { super(id, url); this.navigationTrigger = navigationTrigger; this.restoredState = restoredState; } /** @docsNotRequired */ toString() { return `NavigationStart(id: ${this.id}, url: '${this.url}')`; } }; var NavigationEnd = class extends RouterEvent { urlAfterRedirects; type = EventType.NavigationEnd; constructor(id, url, urlAfterRedirects) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; } /** @docsNotRequired */ toString() { return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`; } }; var NavigationCancellationCode; (function(NavigationCancellationCode2) { NavigationCancellationCode2[NavigationCancellationCode2["Redirect"] = 0] = "Redirect"; NavigationCancellationCode2[NavigationCancellationCode2["SupersededByNewNavigation"] = 1] = "SupersededByNewNavigation"; NavigationCancellationCode2[NavigationCancellationCode2["NoDataFromResolver"] = 2] = "NoDataFromResolver"; NavigationCancellationCode2[NavigationCancellationCode2["GuardRejected"] = 3] = "GuardRejected"; NavigationCancellationCode2[NavigationCancellationCode2["Aborted"] = 4] = "Aborted"; })(NavigationCancellationCode || (NavigationCancellationCode = {})); var NavigationSkippedCode; (function(NavigationSkippedCode2) { NavigationSkippedCode2[NavigationSkippedCode2["IgnoredSameUrlNavigation"] = 0] = "IgnoredSameUrlNavigation"; NavigationSkippedCode2[NavigationSkippedCode2["IgnoredByUrlHandlingStrategy"] = 1] = "IgnoredByUrlHandlingStrategy"; })(NavigationSkippedCode || (NavigationSkippedCode = {})); var NavigationCancel = class extends RouterEvent { reason; code; type = EventType.NavigationCancel; constructor(id, url, reason, code) { super(id, url); this.reason = reason; this.code = code; } /** @docsNotRequired */ toString() { return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; } }; var NavigationSkipped = class extends RouterEvent { reason; code; type = EventType.NavigationSkipped; constructor(id, url, reason, code) { super(id, url); this.reason = reason; this.code = code; } }; var NavigationError = class extends RouterEvent { error; target; type = EventType.NavigationError; constructor(id, url, error, target) { super(id, url); this.error = error; this.target = target; } /** @docsNotRequired */ toString() { return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`; } }; var RoutesRecognized = class extends RouterEvent { urlAfterRedirects; state; type = EventType.RoutesRecognized; constructor(id, url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } /** @docsNotRequired */ toString() { return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } }; var GuardsCheckStart = class extends RouterEvent { urlAfterRedirects; state; type = EventType.GuardsCheckStart; constructor(id, url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } toString() { return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } }; var GuardsCheckEnd = class extends RouterEvent { urlAfterRedirects; state; shouldActivate; type = EventType.GuardsCheckEnd; constructor(id, url, urlAfterRedirects, state, shouldActivate) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; this.shouldActivate = shouldActivate; } toString() { return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`; } }; var ResolveStart = class extends RouterEvent { urlAfterRedirects; state; type = EventType.ResolveStart; constructor(id, url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } toString() { return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } }; var ResolveEnd = class extends RouterEvent { urlAfterRedirects; state; type = EventType.ResolveEnd; constructor(id, url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } toString() { return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } }; var RouteConfigLoadStart = class { route; type = EventType.RouteConfigLoadStart; constructor(route) { this.route = route; } toString() { return `RouteConfigLoadStart(path: ${this.route.path})`; } }; var RouteConfigLoadEnd = class { route; type = EventType.RouteConfigLoadEnd; constructor(route) { this.route = route; } toString() { return `RouteConfigLoadEnd(path: ${this.route.path})`; } }; var ChildActivationStart = class { snapshot; type = EventType.ChildActivationStart; constructor(snapshot) { this.snapshot = snapshot; } toString() { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ""; return `ChildActivationStart(path: '${path}')`; } }; var ChildActivationEnd = class { snapshot; type = EventType.ChildActivationEnd; constructor(snapshot) { this.snapshot = snapshot; } toString() { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ""; return `ChildActivationEnd(path: '${path}')`; } }; var ActivationStart = class { snapshot; type = EventType.ActivationStart; constructor(snapshot) { this.snapshot = snapshot; } toString() { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ""; return `ActivationStart(path: '${path}')`; } }; var ActivationEnd = class { snapshot; type = EventType.ActivationEnd; constructor(snapshot) { this.snapshot = snapshot; } toString() { const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ""; return `ActivationEnd(path: '${path}')`; } }; var Scroll = class { routerEvent; position; anchor; type = EventType.Scroll; constructor(routerEvent, position, anchor) { this.routerEvent = routerEvent; this.position = position; this.anchor = anchor; } 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 { url; navigationBehaviorOptions; constructor(url, navigationBehaviorOptions) { this.url = url; this.navigationBehaviorOptions = navigationBehaviorOptions; } }; function isPublicRouterEvent(e) { return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest); } function stringifyEvent(routerEvent) { switch (routerEvent.type) { case EventType.ActivationEnd: return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`; case EventType.ActivationStart: return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`; case EventType.ChildActivationEnd: return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`; case EventType.ChildActivationStart: return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ""}')`; case EventType.GuardsCheckEnd: return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`; case EventType.GuardsCheckStart: return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; case EventType.NavigationCancel: return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`; case EventType.NavigationSkipped: return `NavigationSkipped(id: ${routerEvent.id}, url: '${routerEvent.url}')`; case EventType.NavigationEnd: return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`; case EventType.NavigationError: return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`; case EventType.NavigationStart: return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`; case EventType.ResolveEnd: return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; case EventType.ResolveStart: return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; case EventType.RouteConfigLoadEnd: return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`; case EventType.RouteConfigLoadStart: return `RouteConfigLoadStart(path: ${routerEvent.route.path})`; case EventType.RoutesRecognized: return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`; case EventType.Scroll: const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null; return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`; } } 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.component && route.loadComponent) { throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`); } if (route.redirectTo) { if (route.component || route.loadComponent) { throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`); } if (route.canMatch || route.canActivate) { throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and ${route.canMatch ? "canMatch" : "canActivate"} cannot be used together.Redirects happen before guards are 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 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 OutletContext = class { rootInjector; outlet = null; route = null; children; attachRef = null; get injector() { return getClosestRouteInjector(this.route?.snapshot) ?? this.rootInjector; } constructor(rootInjector) { this.rootInjector = rootInjector; this.children = new ChildrenOutletContexts(this.rootInjector); } }; var ChildrenOutletContexts = class _ChildrenOutletContexts { rootInjector; // contexts for child outlets, by name. contexts = /* @__PURE__ */ new Map(); /** @docs-private */ constructor(rootInjector) { this.rootInjector = rootInjector; } /** 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.rootInjector); this.contexts.set(childName, context); } return context; } getContext(childName) { return this.contexts.get(childName) || null; } static ɵfac = function ChildrenOutletContexts_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _ChildrenOutletContexts)(ɵɵinject(EnvironmentInjector)); }; static ɵprov = ɵɵdefineInjectable({ token: _ChildrenOutletContexts, factory: _ChildrenOutletContexts.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ChildrenOutletContexts, [{ type: Injectable, args: [{ providedIn: "root" }] }], () => [{ type: EnvironmentInjector }], null); })(); var Tree = class { /** @internal */ _root; 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 { value; children; 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 { snapshot; /** @internal */ constructor(root, snapshot) { super(root); this.snapshot = snapshot; setRouterState(this, root); } toString() { return this.snapshot.toString(); } }; function createEmptyState(rootComponent) { const snapshot = createEmptyStateSnapshot(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(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 { urlSubject; paramsSubject; queryParamsSubject; fragmentSubject; dataSubject; outlet; component; /** The current snapshot of this route */ snapshot; /** @internal */ _futureSnapshot; /** @internal */ _routerState; /** @internal */ _paramMap; /** @internal */ _queryParamMap; /** An Observable of the resolved route title */ title; /** An observable of the URL segments matched by this route. */ url; /** An observable of the matrix parameters scoped to this route. */ params; /** An observable of the query parameters shared by all the routes. */ queryParams; /** An observable of the URL fragment shared by all the routes. */ fragment; /** An observable of the static and resolved data of this route. */ data; /** @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() { 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() { 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: __spreadValues({}, route.params), data: __spreadValues({}, route.data), resolve: __spreadValues(__spreadValues({}, route.data), route._resolvedData ?? {}) }; } if (routeConfig && hasStaticTitle(routeConfig)) { inherited.resolve[RouteTitleKey] = routeConfig.title; } return inherited; } var ActivatedRouteSnapshot = class { url; params; queryParams; fragment; data; outlet; component; /** The configuration used to match this route **/ routeConfig; /** @internal */ _resolve; /** @internal */ _resolvedData; /** @internal */ _routerState; /** @internal */ _paramMap; /** @internal */ _queryParamMap; /** 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() { this._paramMap ??= convertToParamMap(this.params); return this._paramMap; } get 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 { url; /** @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 ROUTER_OUTLET_DATA = new InjectionToken(ngDevMode ? "RouterOutlet data" : ""); var RouterOutlet = class _RouterOutlet { activated = null; /** @internal */ get activatedComponentRef() { return this.activated; } _activatedRoute = null; /** * The name of the outlet * */ name = PRIMARY_OUTLET; activateEvents = new EventEmitter(); deactivateEvents = new EventEmitter(); /** * Emits an attached component instance when the `RouteReuseStrategy` instructs to re-attach a * previously detached subtree. **/ attachEvents = new EventEmitter(); /** * Emits a detached component instance when the `RouteReuseStrategy` instructs to detach the * subtree. */ detachEvents = new EventEmitter(); /** * Data that will be provided to the child injector through the `ROUTER_OUTLET_DATA` token. * * When unset, the value of the token is `undefined` by default. */ routerOutletData = input(...ngDevMode ? [void 0, { debugName: "routerOutletData" }] : []); parentContexts = inject(ChildrenOutletContexts); location = inject(ViewContainerRef); changeDetector = inject(ChangeDetectorRef); inputBinder = inject(INPUT_BINDER, { optional: true }); /** @docs-private */ supportsBindingToComponentInputs = true; /** @docs-private */ 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(); } } /** @docs-private */ ngOnDestroy() { if (this.isTrackedInParentContexts(this.name)) { this.parentContexts.onChildOutletDestroyed(this.name); } this.inputBinder?.unsubscribeFromRouteData(this); } isTrackedInParentContexts(outletName) { return this.parentContexts.getContext(outletName)?.outlet === this; } /** @docs-private */ 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.routerOutletData); this.activated = location.createComponent(component, { index: location.length, injector, environmentInjector }); this.changeDetector.markForCheck(); this.inputBinder?.bindActivatedRouteToOutletComponent(this); this.activateEvents.emit(this.activated.instance); } static ɵfac = function RouterOutlet_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterOutlet)(); }; static ɵdir = ɵɵdefineDirective({ type: _RouterOutlet, selectors: [["router-outlet"]], inputs: { name: "name", routerOutletData: [1, "routerOutletData"] }, outputs: { activateEvents: "activate", deactivateEvents: "deactivate", attachEvents: "attach", detachEvents: "detach" }, exportAs: ["outlet"], features: [ɵɵNgOnChangesFeature] }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterOutlet, [{ type: Directive, args: [{ selector: "router-outlet", exportAs: "outlet" }] }], null, { name: [{ type: Input }], activateEvents: [{ type: Output, args: ["activate"] }], deactivateEvents: [{ type: Output, args: ["deactivate"] }], attachEvents: [{ type: Output, args: ["attach"] }], detachEvents: [{ type: Output, args: ["detach"] }], routerOutletData: [{ type: Input, args: [{ isSignal: true, alias: "routerOutletData", required: false }] }] }); })(); var OutletInjector = class { route; childContexts; parent; outletData; constructor(route, childContexts, parent, outletData) { this.route = route; this.childContexts = childContexts; this.parent = parent; this.outletData = outletData; } get(token, notFoundValue) { if (token === ActivatedRoute) { return this.route; } if (token === ChildrenOutletContexts) { return this.childContexts; } if (token === ROUTER_OUTLET_DATA) { return this.outletData; } return this.parent.get(token, notFoundValue); } }; var INPUT_BINDER = new InjectionToken(""); var RoutedComponentInputBinder = class _RoutedComponentInputBinder { 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); } static ɵfac = function RoutedComponentInputBinder_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RoutedComponentInputBinder)(); }; static ɵprov = ɵɵdefineInjectable({ token: _RoutedComponentInputBinder, factory: _RoutedComponentInputBinder.ɵfac }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RoutedComponentInputBinder, [{ type: Injectable }], null, null); })(); var ɵEmptyOutletComponent = class _ɵEmptyOutletComponent { static ɵfac = function ɵEmptyOutletComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _ɵEmptyOutletComponent)(); }; static ɵcmp = ɵɵdefineComponent({ type: _ɵEmptyOutletComponent, selectors: [["ng-component"]], exportAs: ["emptyRouterOutlet"], decls: 1, vars: 0, template: function _EmptyOutletComponent_Template(rf, ctx) { if (rf & 1) { ɵɵelement(0, "router-outlet"); } }, dependencies: [RouterOutlet], encapsulation: 2 }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ɵEmptyOutletComponent, [{ type: Component, args: [{ template: ``, imports: [RouterOutlet], // Used to avoid component ID collisions with user code. exportAs: "emptyRouterOutlet" }] }], null, null); })(); 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 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 RedirectCommand = class { redirectTo; navigationBehaviorOptions; constructor(redirectTo, navigationBehaviorOptions) { this.redirectTo = redirectTo; this.navigationBehaviorOptions = navigationBehaviorOptions; } }; 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)}"`, NavigationCancellationCode.Redirect); error.url = redirectTo; error.navigationBehaviorOptions = navigationBehaviorOptions; return error; } function navigationCancelingError(message, code) { const error = new Error(`NavigationCancelingError: ${message || ""}`); error[NAVIGATION_CANCELING_ERROR] = true; error.cancellationCode = code; return error; } function isRedirectingNavigationCancelingError(error) { return isNavigationCancelingError(error) && isUrlTree(error.url); } function isNavigationCancelingError(error) { return !!error && error[NAVIGATION_CANCELING_ERROR]; } 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 { routeReuseStrategy; futureState; currState; forwardEvent; inputBindingEnabled; 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 treeNode of Object.values(children)) { this.deactivateRouteAndItsChildren(treeNode, 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 treeNode of Object.values(children)) { this.deactivateRouteAndItsChildren(treeNode, 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 { context.attachRef = null; context.route = future; 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 { path; route; constructor(path) { this.path = path; this.route = this.path[this.path.length - 1]; } }; var CanDeactivate = class { component; route; 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 || isRedirect(result)) { return result; } } return true; }), filter((item) => item !== INITIAL_VALUE), take(1)); }); } function isRedirect(val) { return isUrlTree(val) || val instanceof RedirectCommand; } 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 (typeof result === "boolean") 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 { segmentGroup; constructor(segmentGroup) { this.segmentGroup = segmentGroup || null; } }; var AbsoluteRedirect = class extends Error { urlTree; 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`, NavigationCancellationCode.GuardRejected)); } var ApplyRedirects = class { urlSerializer; urlTree; 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, currentSnapshot, injector) { return getRedirectResult(redirectTo, currentSnapshot, injector).pipe(map((redirect) => { if (redirect instanceof UrlTree) { throw new AbsoluteRedirect(redirect); } const newTree = this.applyRedirectCreateUrlTree(redirect, this.urlSerializer.parse(redirect), segments, posParams); if (redirect[0] === "/") { 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[0] === ":"; 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[0] === ":" ? 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; } }; function getRedirectResult(redirectTo, currentSnapshot, injector) { if (typeof redirectTo === "string") { return of(redirectTo); } const redirectToFn = redirectTo; const { queryParams, fragment, routeConfig, url, outlet, params, data, title } = currentSnapshot; return wrapIntoObservable(runInInjectionContext(injector, () => redirectToFn({ params, data, queryParams, fragment, routeConfig, url, outlet, title }))); } 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, slicedSegments, config, segmentGroup.children)); return { segmentGroup: s2, slicedSegments }; } const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children); return { segmentGroup: s, slicedSegments }; } function addEmptyPathsToChildrenIfNeeded(segmentGroup, 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 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 { injector; configLoader; rootComponentType; config; urlTree; paramsInheritanceStrategy; urlSerializer; applyRedirects; absoluteRedirectCount = 0; allowRedirects = true; 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); } 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, rootSnapshot }) => { const rootNode = new TreeNode(rootSnapshot, children); const routeState = new RouterStateSnapshot("", rootNode); const tree2 = createUrlTreeFromSnapshot(rootSnapshot, [], this.urlTree.queryParams, this.urlTree.fragment); tree2.queryParams = this.urlTree.queryParams; routeState.url = this.urlSerializer.serialize(tree2); return { state: routeState, tree: tree2 }; })); } match(rootSegmentGroup) { const rootSnapshot = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(__spreadValues({}, this.urlTree.queryParams)), this.urlTree.fragment, Object.freeze({}), PRIMARY_OUTLET, this.rootComponentType, null, {}); return this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET, rootSnapshot).pipe(map((children) => { return { children, rootSnapshot }; }), 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; })); } processSegmentGroup(injector, config, segmentGroup, outlet, parentRoute) { if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { return this.processChildren(injector, config, segmentGroup, parentRoute); } return this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true, parentRoute).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, parentRoute) { 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, parentRoute); }), 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, parentRoute) { return from(routes).pipe(concatMap((r) => { return this.processSegmentAgainstRoute(r._injector ?? injector, routes, r, segmentGroup, segments, outlet, allowRedirects, parentRoute).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, parentRoute) { if (getOutlet(route) !== outlet && (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) { return noMatch$1(rawSegment); } if (route.redirectTo === void 0) { return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute); } if (this.allowRedirects && allowRedirects) { return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet, parentRoute); } return noMatch$1(rawSegment); } expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet, parentRoute) { const { matched, parameters, consumedSegments, positionalParamSegments, remainingSegments } = match(segmentGroup, route, segments); if (!matched) return noMatch$1(segmentGroup); if (typeof route.redirectTo === "string" && route.redirectTo[0] === "/") { 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 currentSnapshot = new ActivatedRouteSnapshot(segments, parameters, Object.freeze(__spreadValues({}, this.urlTree.queryParams)), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route)); const inherited = getInherited(currentSnapshot, parentRoute, this.paramsInheritanceStrategy); currentSnapshot.params = Object.freeze(inherited.params); currentSnapshot.data = Object.freeze(inherited.data); const newTree$ = this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments, currentSnapshot, injector); return newTree$.pipe(switchMap((newTree) => this.applyRedirects.lineralizeSegments(route, newTree)), mergeMap((newSegments) => { return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false, parentRoute); })); } matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute) { 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 { parameters, consumedSegments, remainingSegments } = 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 inherited = getInherited(snapshot, parentRoute, this.paramsInheritanceStrategy); snapshot.params = Object.freeze(inherited.params); snapshot.data = Object.freeze(inherited.data); const { segmentGroup, slicedSegments } = split(rawSegment, consumedSegments, remainingSegments, childConfig); if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { return this.processChildren(childInjector, childConfig, segmentGroup, snapshot).pipe(map((children) => { 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, snapshot).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 defer(() => { futureARS.data = getInherited(futureARS, futureARS.parent, paramsInheritanceStrategy).resolve; return resolveNode(resolve, futureARS, futureRSS, injector).pipe(map((resolvedData) => { futureARS._resolvedData = resolvedData; futureARS.data = __spreadValues(__spreadValues({}, futureARS.data), resolvedData); 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) => { if (value instanceof RedirectCommand) { throw redirectingNavigationError(new DefaultUrlSerializer(), value); } data[key] = value; }))), takeLast(1), map(() => 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]; } static ɵfac = function TitleStrategy_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _TitleStrategy)(); }; static ɵprov = ɵɵdefineInjectable({ token: _TitleStrategy, factory: () => (() => inject(DefaultTitleStrategy))(), providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TitleStrategy, [{ type: Injectable, args: [{ providedIn: "root", useFactory: () => inject(DefaultTitleStrategy) }] }], null, null); })(); var DefaultTitleStrategy = class _DefaultTitleStrategy extends TitleStrategy { title; 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); } } static ɵfac = function DefaultTitleStrategy_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _DefaultTitleStrategy)(ɵɵinject(Title)); }; static ɵprov = ɵɵdefineInjectable({ token: _DefaultTitleStrategy, factory: _DefaultTitleStrategy.ɵfac, providedIn: "root" }); }; (() => { (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(ngDevMode ? "ROUTES" : ""); var RouterConfigLoader = class _RouterConfigLoader { componentLoaders = /* @__PURE__ */ new WeakMap(); childrenLoaders = /* @__PURE__ */ new WeakMap(); onLoadStartListener; onLoadEndListener; compiler = inject(Compiler); loadComponent(injector, 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(runInInjectionContext(injector, () => route.loadComponent())).pipe(map(maybeUnwrapDefaultExport), switchMap(maybeResolveResources), 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; } static ɵfac = function RouterConfigLoader_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterConfigLoader)(); }; static ɵprov = ɵɵdefineInjectable({ token: _RouterConfigLoader, factory: _RouterConfigLoader.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterConfigLoader, [{ type: Injectable, args: [{ providedIn: "root" }] }], null, null); })(); function loadChildren(route, compiler, parentInjector, onLoadEndListener) { return wrapIntoObservable(runInInjectionContext(parentInjector, () => route.loadChildren())).pipe(map(maybeUnwrapDefaultExport), switchMap(maybeResolveResources), 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(input2) { return isWrappedDefaultExport(input2) ? input2["default"] : input2; } function maybeResolveResources(value) { if (false) { return resolveComponentResources(fetch).catch((error) => { console.error(error); return Promise.resolve(); }).then(() => value); } return of(value); } var UrlHandlingStrategy = class _UrlHandlingStrategy { static ɵfac = function UrlHandlingStrategy_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _UrlHandlingStrategy)(); }; static ɵprov = ɵɵdefineInjectable({ token: _UrlHandlingStrategy, factory: () => (() => inject(DefaultUrlHandlingStrategy))(), providedIn: "root" }); }; (() => { (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; } static ɵfac = function DefaultUrlHandlingStrategy_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _DefaultUrlHandlingStrategy)(); }; static ɵprov = ɵɵdefineInjectable({ token: _DefaultUrlHandlingStrategy, factory: _DefaultUrlHandlingStrategy.ɵfac, providedIn: "root" }); }; (() => { (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); if (!document.startViewTransition || transitionOptions.skipNextTransition) { transitionOptions.skipNextTransition = false; return new Promise((resolve) => setTimeout(resolve)); } let resolveViewTransitionStarted; const viewTransitionStarted = new Promise((resolve) => { resolveViewTransitionStarted = resolve; }); const transition = document.startViewTransition(() => { resolveViewTransitionStarted(); return createRenderPromise(injector); }); transition.ready.catch((error) => { if (typeof ngDevMode === "undefined" || ngDevMode) { console.error(error); } }); const { onViewTransitionCreated } = transitionOptions; if (onViewTransitionCreated) { runInInjectionContext(injector, () => onViewTransitionCreated({ transition, from: from2, to })); } return viewTransitionStarted; } function createRenderPromise(injector) { return new Promise((resolve) => { afterNextRender({ read: () => setTimeout(resolve) }, { injector }); }); } var NAVIGATION_ERROR_HANDLER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "navigation error handler" : ""); var NavigationTransitions = class _NavigationTransitions { // Some G3 targets expect the navigation object to be mutated (and not getting a new reference on changes). currentNavigation = signal(null, ...ngDevMode ? [{ debugName: "currentNavigation", equal: () => false }] : [{ equal: () => false }]); currentTransition = null; lastSuccessfulNavigation = null; /** * These events are used to communicate back to the Router about the state of the transition. The * Router wants to respond to these events in various ways. Because the `NavigationTransition` * class is not public, this event subject is not publicly exposed. */ events = new Subject(); /** * Used to abort the current transition with an error. */ transitionAbortWithErrorSubject = new Subject(); configLoader = inject(RouterConfigLoader); environmentInjector = inject(EnvironmentInjector); destroyRef = inject(DestroyRef); urlSerializer = inject(UrlSerializer); rootContexts = inject(ChildrenOutletContexts); location = inject(Location); inputBindingEnabled = inject(INPUT_BINDER, { optional: true }) !== null; titleStrategy = inject(TitleStrategy); options = inject(ROUTER_CONFIGURATION, { optional: true }) || {}; paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || "emptyOnly"; urlHandlingStrategy = inject(UrlHandlingStrategy); createViewTransition = inject(CREATE_VIEW_TRANSITION, { optional: true }); navigationErrorHandler = inject(NAVIGATION_ERROR_HANDLER, { optional: true }); navigationId = 0; get hasRequestedNavigation() { return this.navigationId !== 0; } transitions; /** * Hook that enables you to pause navigation after the preactivation phase. * Used by `RouterModule`. * * @internal */ afterPreactivation = () => of(void 0); /** @internal */ rootComponentType = null; destroyed = false; constructor() { 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; this.destroyRef.onDestroy(() => { this.destroyed = true; }); } complete() { this.transitions?.complete(); } handleNavigationRequest(request) { const id = ++this.navigationId; untracked(() => { this.transitions?.next(__spreadProps(__spreadValues({}, request), { extractedUrl: this.urlHandlingStrategy.extract(request.rawUrl), targetSnapshot: null, targetRouterState: null, guards: { canActivateChecks: [], canDeactivateChecks: [] }, guardsResult: null, abortController: new AbortController(), id })); }); } setupNavigations(router) { this.transitions = new BehaviorSubject(null); return this.transitions.pipe( filter((t) => t !== null), // Using switchMap so we cancel executing navigations when a new one comes in switchMap((overallTransitionState) => { let completedOrAborted = false; return of(overallTransitionState).pipe( switchMap((t) => { if (this.navigationId > overallTransitionState.id) { const cancellationReason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : ""; this.cancelNavigationTransition(overallTransitionState, cancellationReason, NavigationCancellationCode.SupersededByNewNavigation); return EMPTY; } this.currentTransition = overallTransitionState; this.currentNavigation.set({ id: t.id, initialUrl: t.rawUrl, extractedUrl: t.extractedUrl, targetBrowserUrl: typeof t.extras.browserUrl === "string" ? this.urlSerializer.parse(t.extras.browserUrl) : t.extras.browserUrl, trigger: t.source, extras: t.extras, previousNavigation: !this.lastSuccessfulNavigation ? null : __spreadProps(__spreadValues({}, this.lastSuccessfulNavigation), { previousNavigation: null }), abort: () => t.abortController.abort() }); 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, NavigationSkippedCode.IgnoredSameUrlNavigation)); t.resolve(false); return EMPTY; } if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) { return of(t).pipe( // Fire NavigationStart event switchMap((t2) => { this.events.next(new NavigationStart(t2.id, this.urlSerializer.serialize(t2.extractedUrl), t2.source, t2.restoredState)); if (t2.id !== this.navigationId) { 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.update((nav) => { nav.finalUrl = t2.urlAfterRedirects; return nav; }); 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(this.rootComponentType).snapshot; this.currentTransition = overallTransitionState = __spreadProps(__spreadValues({}, t), { targetSnapshot, urlAfterRedirects: extractedUrl, extras: __spreadProps(__spreadValues({}, extras), { skipLocationChange: false, replaceUrl: false }) }); this.currentNavigation.update((nav) => { nav.finalUrl = extractedUrl; return nav; }); 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, NavigationSkippedCode.IgnoredByUrlHandlingStrategy)); t.resolve(false); 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 (t.guardsResult && typeof t.guardsResult !== "boolean") { 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, "", NavigationCancellationCode.GuardRejected); return false; } return true; }), // --- RESOLVE --- switchTap((t) => { if (t.guards.canActivateChecks.length === 0) { return void 0; } 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.` : "", 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); })); }), // --- LOAD COMPONENTS --- switchTap((t) => { const loadComponents = (route) => { const loaders = []; if (route.routeConfig?.loadComponent) { const injector = getClosestRouteInjector(route) ?? this.environmentInjector; loaders.push(this.configLoader.loadComponent(injector, 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(null), 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.update((nav) => { nav.targetRouterState = targetRouterState; return nav; }); 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), takeUntil(new Observable((subscriber) => { const abortSignal = overallTransitionState.abortController.signal; const handler = () => subscriber.next(); abortSignal.addEventListener("abort", handler); return () => abortSignal.removeEventListener("abort", handler); }).pipe( // Ignore aborts if we are already completed, canceled, or are in the activation stage (we have targetRouterState) filter(() => !completedOrAborted && !overallTransitionState.targetRouterState), tap(() => { this.cancelNavigationTransition(overallTransitionState, overallTransitionState.abortController.signal.reason + "", NavigationCancellationCode.Aborted); }) )), tap({ next: (t) => { completedOrAborted = true; this.lastSuccessfulNavigation = untracked(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: () => { completedOrAborted = 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.transitionAbortWithErrorSubject.pipe(tap((err) => { throw err; }))), finalize(() => { if (!completedOrAborted) { const cancelationReason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : ""; this.cancelNavigationTransition(overallTransitionState, cancelationReason, NavigationCancellationCode.SupersededByNewNavigation); } if (this.currentTransition?.id === overallTransitionState.id) { this.currentNavigation.set(null); this.currentTransition = null; } }), catchError((e) => { if (this.destroyed) { overallTransitionState.resolve(false); return EMPTY; } completedOrAborted = true; if (isNavigationCancelingError(e)) { this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode)); if (!isRedirectingNavigationCancelingError(e)) { overallTransitionState.resolve(false); } else { this.events.next(new RedirectRequest(e.url, e.navigationBehaviorOptions)); } } else { const navigationError = new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? void 0); try { const navigationErrorHandlerResult = runInInjectionContext(this.environmentInjector, () => this.navigationErrorHandler?.(navigationError)); if (navigationErrorHandlerResult instanceof RedirectCommand) { const { message, cancellationCode } = redirectingNavigationError(this.urlSerializer, navigationErrorHandlerResult); this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), message, cancellationCode)); this.events.next(new RedirectRequest(navigationErrorHandlerResult.redirectTo, navigationErrorHandlerResult.navigationBehaviorOptions)); } else { this.events.next(navigationError); throw e; } } catch (ee) { if (this.options.resolveNavigationPromiseOnError) { overallTransitionState.resolve(false); } else { 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 currentBrowserUrl = this.urlHandlingStrategy.extract(this.urlSerializer.parse(this.location.path(true))); const currentNavigation = untracked(this.currentNavigation); const targetBrowserUrl = currentNavigation?.targetBrowserUrl ?? currentNavigation?.extractedUrl; return currentBrowserUrl.toString() !== targetBrowserUrl?.toString() && !currentNavigation?.extras.skipLocationChange; } static ɵfac = function NavigationTransitions_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _NavigationTransitions)(); }; static ɵprov = ɵɵdefineInjectable({ token: _NavigationTransitions, factory: _NavigationTransitions.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NavigationTransitions, [{ type: Injectable, args: [{ providedIn: "root" }] }], () => [], null); })(); function isBrowserTriggeredNavigation(source) { return source !== IMPERATIVE_NAVIGATION; } var RouteReuseStrategy = class _RouteReuseStrategy { static ɵfac = function RouteReuseStrategy_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouteReuseStrategy)(); }; static ɵprov = ɵɵdefineInjectable({ token: _RouteReuseStrategy, factory: () => (() => inject(DefaultRouteReuseStrategy))(), providedIn: "root" }); }; (() => { (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 { static ɵfac = /* @__PURE__ */ (() => { let ɵDefaultRouteReuseStrategy_BaseFactory; return function DefaultRouteReuseStrategy_Factory(__ngFactoryType__) { return (ɵDefaultRouteReuseStrategy_BaseFactory || (ɵDefaultRouteReuseStrategy_BaseFactory = ɵɵgetInheritedFactory(_DefaultRouteReuseStrategy)))(__ngFactoryType__ || _DefaultRouteReuseStrategy); }; })(); static ɵprov = ɵɵdefineInjectable({ token: _DefaultRouteReuseStrategy, factory: _DefaultRouteReuseStrategy.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DefaultRouteReuseStrategy, [{ type: Injectable, args: [{ providedIn: "root" }] }], null, null); })(); var StateManager = class _StateManager { urlSerializer = inject(UrlSerializer); options = inject(ROUTER_CONFIGURATION, { optional: true }) || {}; canceledNavigationResolution = this.options.canceledNavigationResolution || "replace"; location = inject(Location); urlHandlingStrategy = inject(UrlHandlingStrategy); urlUpdateStrategy = this.options.urlUpdateStrategy || "deferred"; currentUrlTree = new UrlTree(); /** * Returns the currently activated `UrlTree`. * * This `UrlTree` shows only URLs that the `Router` is configured to handle (through * `UrlHandlingStrategy`). * * The value is set after finding the route config tree to activate but before activating the * route. */ getCurrentUrlTree() { return this.currentUrlTree; } rawUrlTree = this.currentUrlTree; /** * Returns a `UrlTree` that is represents what the browser is actually showing. * * In the life of a navigation transition: * 1. When a navigation begins, the raw `UrlTree` is updated to the full URL that's being * navigated to. * 2. During a navigation, redirects are applied, which might only apply to _part_ of the URL (due * to `UrlHandlingStrategy`). * 3. Just before activation, the raw `UrlTree` is updated to include the redirects on top of the * original raw URL. * * Note that this is _only_ here to support `UrlHandlingStrategy.extract` and * `UrlHandlingStrategy.shouldProcessUrl`. Without those APIs, the current `UrlTree` would not * deviated from the raw `UrlTree`. * * For `extract`, a raw `UrlTree` is needed because `extract` may only return part * of the navigation URL. Thus, the current `UrlTree` may only represent _part_ of the browser * URL. When a navigation gets cancelled and the router needs to reset the URL or a new navigation * occurs, it needs to know the _whole_ browser URL, not just the part handled by * `UrlHandlingStrategy`. * For `shouldProcessUrl`, when the return is `false`, the router ignores the navigation but * still updates the raw `UrlTree` with the assumption that the navigation was caused by the * location change listener due to a URL update by the AngularJS router. In this case, the router * still need to know what the browser's URL is for future navigations. */ getRawUrlTree() { return this.rawUrlTree; } createBrowserPath({ finalUrl, initialUrl, targetBrowserUrl }) { const rawUrl = finalUrl !== void 0 ? this.urlHandlingStrategy.merge(finalUrl, initialUrl) : initialUrl; const url = targetBrowserUrl ?? rawUrl; const path = url instanceof UrlTree ? this.urlSerializer.serialize(url) : url; return path; } commitTransition({ targetRouterState, finalUrl, initialUrl }) { if (finalUrl && targetRouterState) { this.currentUrlTree = finalUrl; this.rawUrlTree = this.urlHandlingStrategy.merge(finalUrl, initialUrl); this.routerState = targetRouterState; } else { this.rawUrlTree = initialUrl; } } routerState = createEmptyState(null); /** Returns the current RouterState. */ getRouterState() { return this.routerState; } stateMemento = this.createStateMemento(); updateStateMemento() { this.stateMemento = this.createStateMemento(); } createStateMemento() { return { rawUrlTree: this.rawUrlTree, currentUrlTree: this.currentUrlTree, routerState: this.routerState }; } resetInternalState({ finalUrl }) { this.routerState = this.stateMemento.routerState; this.currentUrlTree = this.stateMemento.currentUrlTree; this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, finalUrl ?? this.rawUrlTree); } static ɵfac = function StateManager_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _StateManager)(); }; static ɵprov = ɵɵdefineInjectable({ token: _StateManager, factory: () => (() => inject(HistoryStateManager))(), providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(StateManager, [{ type: Injectable, args: [{ providedIn: "root", useFactory: () => inject(HistoryStateManager) }] }], null, null); })(); var HistoryStateManager = class _HistoryStateManager extends StateManager { /** * The id of the currently active page in the router. * Updated to the transition's target id on a successful navigation. * * This is used to track what page the router last activated. When an attempted navigation fails, * the router can then use this to compute how to restore the state back to the previously active * page. */ currentPageId = 0; lastSuccessfulId = -1; 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; } registerNonRouterCurrentEntryChangeListener(listener) { return this.location.subscribe((event) => { if (event["type"] === "popstate") { setTimeout(() => { listener(event["url"], event.state, "popstate"); }); } }); } handleRouterEvent(e, currentTransition) { if (e instanceof NavigationStart) { this.updateStateMemento(); } else if (e instanceof NavigationSkipped) { this.commitTransition(currentTransition); } else if (e instanceof RoutesRecognized) { if (this.urlUpdateStrategy === "eager") { if (!currentTransition.extras.skipLocationChange) { this.setBrowserUrl(this.createBrowserPath(currentTransition), currentTransition); } } } else if (e instanceof BeforeActivateRoutes) { this.commitTransition(currentTransition); if (this.urlUpdateStrategy === "deferred" && !currentTransition.extras.skipLocationChange) { this.setBrowserUrl(this.createBrowserPath(currentTransition), currentTransition); } } else if (e instanceof NavigationCancel && e.code !== NavigationCancellationCode.SupersededByNewNavigation && e.code !== NavigationCancellationCode.Redirect) { 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(path, { extras, id }) { const { replaceUrl, state } = extras; if (this.location.isCurrentPathEqualTo(path) || !!replaceUrl) { const currentBrowserPageId = this.browserPageId; const newState = __spreadValues(__spreadValues({}, state), this.generateNgRouterState(id, currentBrowserPageId)); this.location.replaceState(path, "", newState); } else { const newState = __spreadValues(__spreadValues({}, state), this.generateNgRouterState(id, this.browserPageId + 1)); this.location.go(path, "", newState); } } /** * 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.getCurrentUrlTree() === navigation.finalUrl && targetPagePosition === 0) { this.resetInternalState(navigation); this.resetUrlToCurrentUrlTree(); } else ; } else if (this.canceledNavigationResolution === "replace") { if (restoringFromCaughtError) { this.resetInternalState(navigation); } this.resetUrlToCurrentUrlTree(); } } resetUrlToCurrentUrlTree() { this.location.replaceState(this.urlSerializer.serialize(this.getRawUrlTree()), "", this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId)); } generateNgRouterState(navigationId, routerPageId) { if (this.canceledNavigationResolution === "computed") { return { navigationId, ɵrouterPageId: routerPageId }; } return { navigationId }; } static ɵfac = /* @__PURE__ */ (() => { let ɵHistoryStateManager_BaseFactory; return function HistoryStateManager_Factory(__ngFactoryType__) { return (ɵHistoryStateManager_BaseFactory || (ɵHistoryStateManager_BaseFactory = ɵɵgetInheritedFactory(_HistoryStateManager)))(__ngFactoryType__ || _HistoryStateManager); }; })(); static ɵprov = ɵɵdefineInjectable({ token: _HistoryStateManager, factory: _HistoryStateManager.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HistoryStateManager, [{ type: Injectable, args: [{ providedIn: "root" }] }], null, null); })(); 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 0; } const redirecting = e instanceof NavigationCancel ? e.code === NavigationCancellationCode.Redirect || e.code === NavigationCancellationCode.SupersededByNewNavigation : false; return redirecting ? 2 : 1; }), filter( (result) => result !== 2 /* NavigationResult.REDIRECTING */ ), take(1)).subscribe(() => { action(); }); } 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(); } disposed = false; nonRouterCurrentEntryChangeSubscription; console = inject(Console); stateManager = inject(StateManager); options = inject(ROUTER_CONFIGURATION, { optional: true }) || {}; pendingTasks = inject(PendingTasksInternal); urlUpdateStrategy = this.options.urlUpdateStrategy || "deferred"; navigationTransitions = inject(NavigationTransitions); urlSerializer = inject(UrlSerializer); location = inject(Location); urlHandlingStrategy = inject(UrlHandlingStrategy); injector = inject(EnvironmentInjector); /** * The private `Subject` type for the public events exposed in the getter. This is used internally * to push events to. The separate field allows us to expose separate types in the public API * (i.e., an Observable rather than the Subject). */ _events = new Subject(); /** * 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(); } /** * True if at least one navigation event has occurred, * false otherwise. */ navigated = false; /** * A strategy for re-using routes. * * @deprecated Configure using `providers` instead: * `{provide: RouteReuseStrategy, useClass: MyStrategy}`. */ routeReuseStrategy = inject(RouteReuseStrategy); /** * How to handle a navigation request to the current URL. * * * @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead. * @see {@link withRouterConfig} * @see {@link provideRouter} * @see {@link RouterModule} */ onSameUrlNavigation = this.options.onSameUrlNavigation || "ignore"; config = inject(ROUTES, { optional: true })?.flat() ?? []; /** * Indicates whether the application has opted in to binding Router data to component inputs. * * This option is enabled by the `withComponentInputBinding` feature of `provideRouter` or * `bindToComponentInputs` in the `ExtraOptions` of `RouterModule.forRoot`. */ componentInputBindingEnabled = !!inject(INPUT_BINDER, { optional: true }); /** * Signal of the current `Navigation` object when the router is navigating, and `null` when idle. * * Note: The current navigation becomes to null after the NavigationEnd event is emitted. */ currentNavigation = this.navigationTransitions.currentNavigation.asReadonly(); constructor() { this.resetConfig(this.config); this.navigationTransitions.setupNavigations(this).subscribe({ error: (e) => { this.console.warn(ngDevMode ? `Unhandled Navigation Error: ${e}` : e); } }); this.subscribeToNavigationEvents(); } eventsSubscription = new Subscription(); subscribeToNavigationEvents() { const subscription = this.navigationTransitions.events.subscribe((e) => { try { const currentTransition = this.navigationTransitions.currentTransition; const currentNavigation = untracked(this.navigationTransitions.currentNavigation); if (currentTransition !== null && currentNavigation !== null) { this.stateManager.handleRouterEvent(e, currentNavigation); if (e instanceof NavigationCancel && e.code !== NavigationCancellationCode.Redirect && e.code !== NavigationCancellationCode.SupersededByNewNavigation) { this.navigated = true; } else if (e instanceof NavigationEnd) { this.navigated = true; } else if (e instanceof RedirectRequest) { const opts = e.navigationBehaviorOptions; const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl); const extras = __spreadValues({ browserUrl: currentTransition.extras.browserUrl, info: currentTransition.extras.info, 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: currentTransition.extras.replaceUrl || this.urlUpdateStrategy === "eager" || isBrowserTriggeredNavigation(currentTransition.source) }, opts); 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.transitionAbortWithErrorSubject.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() { this.nonRouterCurrentEntryChangeSubscription ??= this.stateManager.registerNonRouterCurrentEntryChangeListener((url, state, source) => { this.navigateToSyncWithBrowser(url, source, state); }); } /** * 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).catch((e) => { if (this.disposed) { return; } this.injector.get(INTERNAL_APPLICATION_ERROR_HANDLER)(e); }); } /** The current URL. */ get url() { return this.serializeUrl(this.currentUrlTree); } /** * Returns the current `Navigation` object when the router is navigating, * and `null` when idle. * * @deprecated 20.2 Use the `currentNavigation` signal instead. */ getCurrentNavigation() { return untracked(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 * * ```ts * 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; } /** @docs-private */ ngOnDestroy() { this.dispose(); } /** Disposes of the router. */ dispose() { this._events.unsubscribe(); 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 ?? this.options.defaultQueryParamsHandling) { 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][0] !== "/") { 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. * * ```ts * 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/routing/common-router-tasks) * */ navigateByUrl(url, extras = { skipLocationChange: false }) { 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, or `false` when navigation * fails. The Promise is rejected when an error occurs if `resolveNavigationPromiseOnError` is * not `true`. * * @usageNotes * * The following calls request navigation to a dynamic route path relative to the current URL. * * ```ts * 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/routing/common-router-tasks) * */ 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 (e) { this.console.warn(formatRuntimeError(4018, ngDevMode && `Error parsing URL ${url}. Falling back to '/' instead. ` + e)); 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.entries(params).reduce((result, [key, value]) => { 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); }); } static ɵfac = function Router_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _Router)(); }; static ɵprov = ɵɵdefineInjectable({ token: _Router, factory: _Router.ɵfac, providedIn: "root" }); }; (() => { (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}`); } } } // node_modules/@angular/router/fesm2022/router_module.mjs var RouterLink = class _RouterLink { router; route; tabIndexAttribute; renderer; el; locationStrategy; /** @nodoc */ reactiveHref = signal(null, ...ngDevMode ? [{ debugName: "reactiveHref" }] : []); /** * Represents an `href` attribute value applied to a host element, * when a host element is an ``/`` tag or a compatible custom element. * For other tags, the value is `null`. */ get href() { return untracked(this.reactiveHref); } /** @deprecated */ set href(value) { this.reactiveHref.set(value); } /** * Represents the `target` attribute on a host element. * This is only used when the host element is * an ``/`` tag or a compatible custom element. */ target; /** * Passed to {@link Router#createUrlTree} as part of the * `UrlCreationOptions`. * @see {@link UrlCreationOptions#queryParams} * @see {@link Router#createUrlTree} */ queryParams; /** * Passed to {@link Router#createUrlTree} as part of the * `UrlCreationOptions`. * @see {@link UrlCreationOptions#fragment} * @see {@link Router#createUrlTree} */ fragment; /** * Passed to {@link Router#createUrlTree} as part of the * `UrlCreationOptions`. * @see {@link UrlCreationOptions#queryParamsHandling} * @see {@link Router#createUrlTree} */ queryParamsHandling; /** * Passed to {@link Router#navigateByUrl} as part of the * `NavigationBehaviorOptions`. * @see {@link NavigationBehaviorOptions#state} * @see {@link Router#navigateByUrl} */ state; /** * Passed to {@link Router#navigateByUrl} as part of the * `NavigationBehaviorOptions`. * @see {@link NavigationBehaviorOptions#info} * @see {@link Router#navigateByUrl} */ info; /** * Passed to {@link Router#createUrlTree} as part of the * `UrlCreationOptions`. * Specify a value here when you do not want to use the default value * for `routerLink`, which is the current activated route. * Note that a value of `undefined` here will use the `routerLink` default. * @see {@link UrlCreationOptions#relativeTo} * @see {@link Router#createUrlTree} */ relativeTo; /** Whether a host element is an ``/`` tag or a compatible custom element. */ isAnchorElement; subscription; /** @internal */ onChanges = new Subject(); applicationErrorHandler = inject(INTERNAL_APPLICATION_ERROR_HANDLER); options = inject(ROUTER_CONFIGURATION, { optional: true }); 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.reactiveHref.set(inject(new HostAttributeToken("href"), { optional: true })); const tagName = el.nativeElement.tagName?.toLowerCase(); this.isAnchorElement = tagName === "a" || tagName === "area" || !!// Avoid breaking in an SSR context where customElements might not be defined. (typeof customElements === "object" && // observedAttributes is an optional static property/getter on a custom element. // The spec states that this must be an array of strings. customElements.get(tagName)?.observedAttributes?.includes?.("href")); if (!this.isAnchorElement) { this.subscribeToNavigationEventsIfNecessary(); } else { this.setTabIndexIfNotOnNativeEl("0"); } } subscribeToNavigationEventsIfNecessary() { if (this.subscription !== void 0 || !this.isAnchorElement) { return; } let createSubcription = this.preserveFragment; const dependsOnRouterState = (handling) => handling === "merge" || handling === "preserve"; createSubcription ||= dependsOnRouterState(this.queryParamsHandling); createSubcription ||= !this.queryParamsHandling && !dependsOnRouterState(this.options?.defaultQueryParamsHandling); if (!createSubcription) { return; } this.subscription = this.router.events.subscribe((s) => { if (s instanceof NavigationEnd) { this.updateHref(); } }); } /** * Passed to {@link Router#createUrlTree} as part of the * `UrlCreationOptions`. * @see {@link UrlCreationOptions#preserveFragment} * @see {@link Router#createUrlTree} */ preserveFragment = false; /** * Passed to {@link Router#navigateByUrl} as part of the * `NavigationBehaviorOptions`. * @see {@link NavigationBehaviorOptions#skipLocationChange} * @see {@link Router#navigateByUrl} */ skipLocationChange = false; /** * Passed to {@link Router#navigateByUrl} as part of the * `NavigationBehaviorOptions`. * @see {@link NavigationBehaviorOptions#replaceUrl} * @see {@link Router#navigateByUrl} */ replaceUrl = false; /** * 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); } /** @docs-private */ // TODO(atscott): Remove changes parameter in major version as a breaking change. ngOnChanges(changes) { if (ngDevMode && isUrlTree(this.routerLinkInput) && (this.fragment !== void 0 || this.queryParams || this.queryParamsHandling || this.preserveFragment || this.relativeTo)) { throw new RuntimeError(4017, "Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value."); } if (this.isAnchorElement) { this.updateHref(); this.subscribeToNavigationEventsIfNecessary(); } this.onChanges.next(this); } routerLinkInput = null; /** * Commands to pass to {@link Router#createUrlTree} or a `UrlTree`. * - **array**: commands to pass to {@link Router#createUrlTree}. * - **string**: shorthand for array of commands with just the string, i.e. `['/route']` * - **UrlTree**: a `UrlTree` for this link rather than creating one from the commands * and other inputs that correspond to properties of `UrlCreationOptions`. * - **null|undefined**: effectively disables the `routerLink` * @see {@link Router#createUrlTree} */ set routerLink(commandsOrUrlTree) { if (commandsOrUrlTree == null) { this.routerLinkInput = null; this.setTabIndexIfNotOnNativeEl(null); } else { if (isUrlTree(commandsOrUrlTree)) { this.routerLinkInput = commandsOrUrlTree; } else { this.routerLinkInput = Array.isArray(commandsOrUrlTree) ? commandsOrUrlTree : [commandsOrUrlTree]; } this.setTabIndexIfNotOnNativeEl("0"); } } /** @docs-private */ onClick(button, ctrlKey, shiftKey, altKey, metaKey) { const urlTree = this.urlTree; if (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, info: this.info }; this.router.navigateByUrl(urlTree, extras)?.catch((e) => { this.applicationErrorHandler(e); }); return !this.isAnchorElement; } /** @docs-private */ ngOnDestroy() { this.subscription?.unsubscribe(); } updateHref() { const urlTree = this.urlTree; this.reactiveHref.set(urlTree !== null && this.locationStrategy ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree)) ?? "" : null); } 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.routerLinkInput === null) { return null; } else if (isUrlTree(this.routerLinkInput)) { return this.routerLinkInput; } return this.router.createUrlTree(this.routerLinkInput, { // 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 }); } static ɵfac = function RouterLink_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterLink)(ɵɵdirectiveInject(Router), ɵɵdirectiveInject(ActivatedRoute), ɵɵinjectAttribute("tabindex"), ɵɵdirectiveInject(Renderer2), ɵɵdirectiveInject(ElementRef), ɵɵdirectiveInject(LocationStrategy)); }; static ɵdir = ɵɵdefineDirective({ type: _RouterLink, selectors: [["", "routerLink", ""]], hostVars: 2, 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("href", ctx.reactiveHref(), ɵɵsanitizeUrlOrResourceUrl)("target", ctx.target); } }, inputs: { target: "target", queryParams: "queryParams", fragment: "fragment", queryParamsHandling: "queryParamsHandling", state: "state", info: "info", relativeTo: "relativeTo", preserveFragment: [2, "preserveFragment", "preserveFragment", booleanAttribute], skipLocationChange: [2, "skipLocationChange", "skipLocationChange", booleanAttribute], replaceUrl: [2, "replaceUrl", "replaceUrl", booleanAttribute], routerLink: "routerLink" }, features: [ɵɵNgOnChangesFeature] }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterLink, [{ type: Directive, args: [{ selector: "[routerLink]", host: { "[attr.href]": "reactiveHref()" } }] }], () => [{ 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 }], info: [{ 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 { router; element; renderer; cdr; link; links; classes = []; routerEventsSubscription; linkInputChangesSubscription; _isActive = false; get isActive() { return this._isActive; } /** * Options to configure how to determine if the router link is active. * * These options are passed to the `Router.isActive()` function. * * @see {@link Router#isActive} */ routerLinkActiveOptions = { exact: false }; /** * Aria-current attribute to apply when the router link is active. * * Possible values: `'page'` | `'step'` | `'location'` | `'date'` | `'time'` | `true` | `false`. * * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current} */ ariaCurrentWhenActive; /** * * You can use the output `isActiveChange` to get notified each time the link becomes * active or inactive. * * Emits: * true -> Route is active * false -> Route is inactive * * ```html * Bob * ``` */ isActiveChange = new EventEmitter(); constructor(router, element, renderer, cdr, link) { this.router = router; this.element = element; this.renderer = renderer; this.cdr = cdr; this.link = link; this.routerEventsSubscription = router.events.subscribe((s) => { if (s instanceof NavigationEnd) { this.update(); } }); } /** @docs-private */ 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); } /** @docs-private */ ngOnChanges(changes) { this.update(); } /** @docs-private */ ngOnDestroy() { this.routerEventsSubscription.unsubscribe(); this.linkInputChangesSubscription?.unsubscribe(); } update() { if (!this.links || !this.router.navigated) return; queueMicrotask(() => { const hasActiveLinks = this.hasActiveLinks(); 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"); } if (this._isActive !== hasActiveLinks) { this._isActive = hasActiveLinks; this.cdr.markForCheck(); 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) => { const urlTree = link.urlTree; return urlTree ? router.isActive(urlTree, options) : false; }; } hasActiveLinks() { const isActiveCheckFn = this.isLinkActive(this.router); return this.link && isActiveCheckFn(this.link) || this.links.some(isActiveCheckFn); } static ɵfac = function RouterLinkActive_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterLinkActive)(ɵɵdirectiveInject(Router), ɵɵdirectiveInject(ElementRef), ɵɵdirectiveInject(Renderer2), ɵɵdirectiveInject(ChangeDetectorRef), ɵɵdirectiveInject(RouterLink, 8)); }; static ɵ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"], features: [ɵɵNgOnChangesFeature] }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterLinkActive, [{ type: Directive, args: [{ selector: "[routerLinkActive]", exportAs: "routerLinkActive" }] }], () => [{ 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))); } static ɵfac = function PreloadAllModules_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _PreloadAllModules)(); }; static ɵprov = ɵɵdefineInjectable({ token: _PreloadAllModules, factory: _PreloadAllModules.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PreloadAllModules, [{ type: Injectable, args: [{ providedIn: "root" }] }], null, null); })(); var NoPreloading = class _NoPreloading { preload(route, fn) { return of(null); } static ɵfac = function NoPreloading_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _NoPreloading)(); }; static ɵprov = ɵɵdefineInjectable({ token: _NoPreloading, factory: _NoPreloading.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NoPreloading, [{ type: Injectable, args: [{ providedIn: "root" }] }], null, null); })(); var RouterPreloader = class _RouterPreloader { router; injector; preloadingStrategy; loader; subscription; constructor(router, 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); } /** @docs-private */ 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(injector, route); return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll()); } else { return recursiveLoadChildren$; } }); } static ɵfac = function RouterPreloader_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterPreloader)(ɵɵinject(Router), ɵɵinject(EnvironmentInjector), ɵɵinject(PreloadingStrategy), ɵɵinject(RouterConfigLoader)); }; static ɵprov = ɵɵdefineInjectable({ token: _RouterPreloader, factory: _RouterPreloader.ɵfac, providedIn: "root" }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterPreloader, [{ type: Injectable, args: [{ providedIn: "root" }] }], () => [{ type: Router }, { type: EnvironmentInjector }, { type: PreloadingStrategy }, { type: RouterConfigLoader }], null); })(); var ROUTER_SCROLLER = new InjectionToken(""); var RouterScroller = class _RouterScroller { urlSerializer; transitions; viewportScroller; zone; options; routerEventsSubscription; scrollEventsSubscription; lastId = 0; lastSource = IMPERATIVE_NAVIGATION; restoredId = 0; store = {}; /** @docs-private */ constructor(urlSerializer, transitions, viewportScroller, zone, options = {}) { this.urlSerializer = urlSerializer; this.transitions = transitions; this.viewportScroller = viewportScroller; this.zone = zone; this.options = options; options.scrollPositionRestoration ||= "disabled"; 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 === NavigationSkippedCode.IgnoredSameUrlNavigation) { 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; const instantScroll = { behavior: "instant" }; if (e.position) { if (this.options.scrollPositionRestoration === "top") { this.viewportScroller.scrollToPosition([0, 0], instantScroll); } else if (this.options.scrollPositionRestoration === "enabled") { this.viewportScroller.scrollToPosition(e.position, instantScroll); } } 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(() => __async(this, null, function* () { yield new Promise((resolve) => { setTimeout(resolve); if (typeof requestAnimationFrame !== "undefined") { requestAnimationFrame(resolve); } }); this.zone.run(() => { this.transitions.events.next(new Scroll(routerEvent, this.lastSource === "popstate" ? this.store[this.restoredId] : null, anchor)); }); })); } /** @docs-private */ ngOnDestroy() { this.routerEventsSubscription?.unsubscribe(); this.scrollEventsSubscription?.unsubscribe(); } static ɵfac = function RouterScroller_Factory(__ngFactoryType__) { ɵɵinvalidFactory(); }; static ɵprov = ɵɵdefineInjectable({ token: _RouterScroller, factory: _RouterScroller.ɵfac }); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterScroller, [{ type: Injectable }], () => [{ type: UrlSerializer }, { type: NavigationTransitions }, { type: ViewportScroller }, { type: NgZone }, { type: void 0 }], null); })(); function getLoadedRoutes(route) { return route._loadedRoutes; } function getRouterInstance(injector) { return injector.get(Router, null, { optional: true }); } function navigateByUrl(router, url) { if (!(router instanceof Router)) { throw new Error("The provided router is not an Angular Router."); } return router.navigateByUrl(url); } function provideRouter(routes, ...features) { if (typeof ngDevMode === "undefined" || ngDevMode) { publishExternalGlobalUtil("ɵgetLoadedRoutes", getLoadedRoutes); publishExternalGlobalUtil("ɵgetRouterInstance", getRouterInstance); publishExternalGlobalUtil("ɵnavigateByUrl", navigateByUrl); } 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, { optional: true })?.setUpPreloading(); injector.get(ROUTER_SCROLLER, null, { optional: true })?.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: IS_ENABLED_BLOCKING_INITIAL_NAVIGATION, useValue: true }, { provide: INITIAL_NAVIGATION, useValue: 0 /* InitialNavigation.EnabledBlocking */ }, provideAppInitializer(() => { const injector = inject(Injector); const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve()); 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 = [provideAppInitializer(() => { inject(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(handler) { const providers = [{ provide: NAVIGATION_ERROR_HANDLER, useValue: handler }]; return routerFeature(7, providers); } function withComponentInputBinding() { const providers = [RoutedComponentInputBinder, { provide: INPUT_BINDER, useExisting: RoutedComponentInputBinder }]; return routerFeature(8, providers); } function withViewTransitions(options) { performanceMarkFeature("NgRouterViewTransitions"); 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" : ""); 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() { if (typeof ngDevMode === "undefined" || ngDevMode) { inject(ROUTER_FORROOT_GUARD, { optional: true }); } } /** * 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: * * ```ts * @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 }, typeof ngDevMode === "undefined" || ngDevMode ? { provide: ROUTER_FORROOT_GUARD, useFactory: provideForRootGuard, deps: [[Router, new Optional(), new SkipSelf()]] } : [], config?.errorHandler ? { provide: NAVIGATION_ERROR_HANDLER, useValue: config.errorHandler } : [], { 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: * * ```ts * @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 }] }; } static ɵfac = function RouterModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || _RouterModule)(); }; static ɵmod = ɵɵdefineNgModule({ type: _RouterModule, imports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent], exports: [RouterOutlet, RouterLink, RouterLinkActive, ɵEmptyOutletComponent] }); static ɵinj = ɵɵdefineInjector({}); }; (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterModule, [{ type: NgModule, args: [{ imports: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES }] }], () => [], 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 (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 } ]; } // node_modules/@angular/router/fesm2022/router.mjs 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("20.3.18"); export { PRIMARY_OUTLET, convertToParamMap, defaultUrlMatcher, UrlTree, UrlSegmentGroup, UrlSegment, UrlSerializer, DefaultUrlSerializer, createUrlTreeFromSnapshot, EventType, RouterEvent, NavigationStart, NavigationEnd, NavigationCancellationCode, NavigationSkippedCode, NavigationCancel, NavigationSkipped, NavigationError, RoutesRecognized, GuardsCheckStart, GuardsCheckEnd, ResolveStart, ResolveEnd, RouteConfigLoadStart, RouteConfigLoadEnd, ChildActivationStart, ChildActivationEnd, ActivationStart, ActivationEnd, Scroll, OutletContext, ChildrenOutletContexts, RouterState, ActivatedRoute, ActivatedRouteSnapshot, RouterStateSnapshot, ROUTER_OUTLET_DATA, RouterOutlet, ɵEmptyOutletComponent, RedirectCommand, TitleStrategy, DefaultTitleStrategy, ROUTER_CONFIGURATION, ROUTES, loadChildren, UrlHandlingStrategy, RouteReuseStrategy, BaseRouteReuseStrategy, afterNextNavigation, Router, RouterLink, RouterLinkActive, PreloadingStrategy, PreloadAllModules, NoPreloading, RouterPreloader, provideRouter, provideRoutes, withInMemoryScrolling, withEnabledBlockingInitialNavigation, withDisabledInitialNavigation, withDebugTracing, withPreloading, withRouterConfig, withHashLocation, withNavigationErrorHandler, withComponentInputBinding, withViewTransitions, ROUTER_PROVIDERS, RouterModule, ROUTER_INITIALIZER, mapToCanMatch, mapToCanActivate, mapToCanActivateChild, mapToCanDeactivate, mapToResolve, VERSION }; /*! Bundled license information: @angular/router/fesm2022/router2.mjs: @angular/router/fesm2022/router_module.mjs: @angular/router/fesm2022/router.mjs: (** * @license Angular v20.3.18 * (c) 2010-2025 Google LLC. https://angular.dev/ * License: MIT *) */ //# sourceMappingURL=chunk-IUZF7AOX.js.map