Files
demo-decoupled/spring-angular-ui/static/browser/main.js
T
2026-09-13 15:58:54 +02:00

38447 lines
1.6 MiB
Plaintext

import {
ANIMATION_MODULE_TYPE,
APP_BOOTSTRAP_LISTENER,
APP_ID,
ApplicationModule,
ApplicationRef,
Attribute,
BehaviorSubject,
CSP_NONCE,
ChangeDetectionScheduler,
ChangeDetectionStrategy,
ChangeDetectorRef,
Compiler,
Component,
ConnectableObservable,
Console,
ContentChild,
ContentChildren,
DEFAULT_CURRENCY_CODE,
DestroyRef,
Directive,
EMPTY,
ENVIRONMENT_INITIALIZER,
ElementRef,
EmptyError,
EnvironmentInjector,
ErrorHandler,
EventEmitter,
Host,
HostAttributeToken,
HostBinding,
HostListener,
IMAGE_CONFIG,
IMAGE_CONFIG_DEFAULTS,
INJECTOR_SCOPE,
Inject,
InjectFlags,
Injectable,
InjectionToken,
Injector,
Input,
IterableDiffers,
KeyValueDiffers,
LOCALE_ID,
LocaleDataIndex,
NgModule,
NgModuleFactory$1,
NgModuleRef$1,
NgZone,
Observable,
Optional,
Output,
PLATFORM_ID,
PLATFORM_INITIALIZER,
PendingTasksInternal,
Pipe,
Renderer2,
RendererFactory2,
RendererStyleFlags2,
ResourceImpl,
ResourceStatus,
RuntimeError,
SecurityContext,
Self,
SkipSelf,
Subject,
Subscription,
TESTABILITY,
TESTABILITY_GETTER,
TemplateRef,
Testability,
TestabilityRegistry,
TracingService,
VERSION,
Version,
ViewChild,
ViewContainerRef,
ViewEncapsulation,
XSS_SECURITY_URL,
__async,
__spreadProps,
__spreadValues,
_global,
_sanitizeHtml,
_sanitizeUrl,
afterNextRender,
afterRender,
allowSanitizationBypassAndThrow,
animationFrameScheduler,
asapScheduler,
assertInInjectionContext,
auditTime,
booleanAttribute,
bypassSanitizationTrustHtml,
bypassSanitizationTrustResourceUrl,
bypassSanitizationTrustScript,
bypassSanitizationTrustStyle,
bypassSanitizationTrustUrl,
catchError,
combineLatest,
computed,
concat,
concatMap,
contentChild,
createComponent,
createEnvironmentInjector,
createNgModule,
createPlatformFactory,
debounceTime,
defaultIfEmpty,
defer,
distinctUntilChanged,
effect,
enableProdMode,
filter,
finalize,
findLocaleData,
first,
forkJoin,
formatRuntimeError,
forwardRef,
from,
getLocalePluralCase,
inject,
input,
isInjectable,
isNgModule,
isObservable,
isPromise,
isSignal,
isStandalone,
isSubscribable,
last,
linkedSignal,
makeEnvironmentProviders,
map,
merge,
mergeAll,
mergeMap,
numberAttribute,
of,
pairwise,
performanceMarkFeature,
pipe,
platformCore,
provideAppInitializer,
refCount,
reflectComponentType,
runInInjectionContext,
scan,
setClassMetadata,
setDocument,
share,
shareReplay,
signal,
skip,
startWith,
stringify,
switchMap,
take,
takeLast,
takeUntil,
takeWhile,
tap,
throwError,
untracked,
unwrapSafeValue,
ɵsetClassDebugInfo,
ɵɵHostDirectivesFeature,
ɵɵInheritDefinitionFeature,
ɵɵNgOnChangesFeature,
ɵɵProvidersFeature,
ɵɵadvance,
ɵɵattribute,
ɵɵclassMap,
ɵɵclassProp,
ɵɵconditional,
ɵɵcontentQuery,
ɵɵcontentQuerySignal,
ɵɵdeclareLet,
ɵɵdefineComponent,
ɵɵdefineDirective,
ɵɵdefineInjectable,
ɵɵdefineInjector,
ɵɵdefineNgModule,
ɵɵdefinePipe,
ɵɵdirectiveInject,
ɵɵelement,
ɵɵelementEnd,
ɵɵelementStart,
ɵɵgetCurrentView,
ɵɵgetInheritedFactory,
ɵɵhostProperty,
ɵɵinject,
ɵɵinjectAttribute,
ɵɵinvalidFactory,
ɵɵlistener,
ɵɵloadQuery,
ɵɵnextContext,
ɵɵprojection,
ɵɵprojectionDef,
ɵɵproperty,
ɵɵpropertyInterpolate1,
ɵɵpureFunction0,
ɵɵqueryAdvance,
ɵɵqueryRefresh,
ɵɵreference,
ɵɵresetView,
ɵɵrestoreView,
ɵɵsanitizeUrlOrResourceUrl,
ɵɵstyleProp,
ɵɵtemplate,
ɵɵtemplateRefExtractor,
ɵɵtext,
ɵɵtextInterpolate,
ɵɵtextInterpolate1,
ɵɵtextInterpolate2,
ɵɵtwoWayBindingSet,
ɵɵtwoWayListener,
ɵɵtwoWayProperty,
ɵɵviewQuery
} from "./chunk-7E6NIDIZ.js";
// node_modules/@angular/common/fesm2022/dom_tokens-rA0ACyx7.mjs
var DOCUMENT = new InjectionToken(ngDevMode ? "DocumentToken" : "");
// node_modules/@angular/common/fesm2022/location-Dq4mJT-A.mjs
var _DOM = null;
function getDOM() {
return _DOM;
}
function setRootDomAdapter(adapter) {
_DOM ??= adapter;
}
var DomAdapter = class {
};
var PlatformLocation = class _PlatformLocation {
historyGo(relativePosition) {
throw new Error(ngDevMode ? "Not implemented" : "");
}
static \u0275fac = function PlatformLocation_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PlatformLocation)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _PlatformLocation,
factory: () => (() => inject(BrowserPlatformLocation))(),
providedIn: "platform"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformLocation, [{
type: Injectable,
args: [{
providedIn: "platform",
useFactory: () => inject(BrowserPlatformLocation)
}]
}], null, null);
})();
var LOCATION_INITIALIZED = new InjectionToken(ngDevMode ? "Location Initialized" : "");
var BrowserPlatformLocation = class _BrowserPlatformLocation extends PlatformLocation {
_location;
_history;
_doc = inject(DOCUMENT);
constructor() {
super();
this._location = window.location;
this._history = window.history;
}
getBaseHrefFromDOM() {
return getDOM().getBaseHref(this._doc);
}
onPopState(fn) {
const window2 = getDOM().getGlobalEventTarget(this._doc, "window");
window2.addEventListener("popstate", fn, false);
return () => window2.removeEventListener("popstate", fn);
}
onHashChange(fn) {
const window2 = getDOM().getGlobalEventTarget(this._doc, "window");
window2.addEventListener("hashchange", fn, false);
return () => window2.removeEventListener("hashchange", fn);
}
get href() {
return this._location.href;
}
get protocol() {
return this._location.protocol;
}
get hostname() {
return this._location.hostname;
}
get port() {
return this._location.port;
}
get pathname() {
return this._location.pathname;
}
get search() {
return this._location.search;
}
get hash() {
return this._location.hash;
}
set pathname(newPath) {
this._location.pathname = newPath;
}
pushState(state, title, url) {
this._history.pushState(state, title, url);
}
replaceState(state, title, url) {
this._history.replaceState(state, title, url);
}
forward() {
this._history.forward();
}
back() {
this._history.back();
}
historyGo(relativePosition = 0) {
this._history.go(relativePosition);
}
getState() {
return this._history.state;
}
static \u0275fac = function BrowserPlatformLocation_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BrowserPlatformLocation)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _BrowserPlatformLocation,
factory: () => (() => new _BrowserPlatformLocation())(),
providedIn: "platform"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BrowserPlatformLocation, [{
type: Injectable,
args: [{
providedIn: "platform",
useFactory: () => new BrowserPlatformLocation()
}]
}], () => [], null);
})();
function joinWithSlash(start, end) {
if (!start) return end;
if (!end) return start;
if (start.endsWith("/")) {
return end.startsWith("/") ? start + end.slice(1) : start + end;
}
return end.startsWith("/") ? start + end : `${start}/${end}`;
}
function stripTrailingSlash(url) {
const pathEndIdx = url.search(/#|\?|$/);
return url[pathEndIdx - 1] === "/" ? url.slice(0, pathEndIdx - 1) + url.slice(pathEndIdx) : url;
}
function normalizeQueryParams(params) {
return params && params[0] !== "?" ? `?${params}` : params;
}
var LocationStrategy = class _LocationStrategy {
historyGo(relativePosition) {
throw new Error(ngDevMode ? "Not implemented" : "");
}
static \u0275fac = function LocationStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _LocationStrategy)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _LocationStrategy,
factory: () => (() => inject(PathLocationStrategy))(),
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(LocationStrategy, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(PathLocationStrategy)
}]
}], null, null);
})();
var APP_BASE_HREF = new InjectionToken(ngDevMode ? "appBaseHref" : "");
var PathLocationStrategy = class _PathLocationStrategy extends LocationStrategy {
_platformLocation;
_baseHref;
_removeListenerFns = [];
constructor(_platformLocation, href) {
super();
this._platformLocation = _platformLocation;
this._baseHref = href ?? this._platformLocation.getBaseHrefFromDOM() ?? inject(DOCUMENT).location?.origin ?? "";
}
/** @docs-private */
ngOnDestroy() {
while (this._removeListenerFns.length) {
this._removeListenerFns.pop()();
}
}
onPopState(fn) {
this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));
}
getBaseHref() {
return this._baseHref;
}
prepareExternalUrl(internal) {
return joinWithSlash(this._baseHref, internal);
}
path(includeHash = false) {
const pathname = this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search);
const hash = this._platformLocation.hash;
return hash && includeHash ? `${pathname}${hash}` : pathname;
}
pushState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.pushState(state, title, externalUrl);
}
replaceState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.replaceState(state, title, externalUrl);
}
forward() {
this._platformLocation.forward();
}
back() {
this._platformLocation.back();
}
getState() {
return this._platformLocation.getState();
}
historyGo(relativePosition = 0) {
this._platformLocation.historyGo?.(relativePosition);
}
static \u0275fac = function PathLocationStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PathLocationStrategy)(\u0275\u0275inject(PlatformLocation), \u0275\u0275inject(APP_BASE_HREF, 8));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _PathLocationStrategy,
factory: _PathLocationStrategy.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PathLocationStrategy, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: PlatformLocation
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [APP_BASE_HREF]
}]
}], null);
})();
var Location = class _Location {
/** @internal */
_subject = new Subject();
/** @internal */
_basePath;
/** @internal */
_locationStrategy;
/** @internal */
_urlChangeListeners = [];
/** @internal */
_urlChangeSubscription = null;
constructor(locationStrategy) {
this._locationStrategy = locationStrategy;
const baseHref = this._locationStrategy.getBaseHref();
this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));
this._locationStrategy.onPopState((ev) => {
this._subject.next({
"url": this.path(true),
"pop": true,
"state": ev.state,
"type": ev.type
});
});
}
/** @docs-private */
ngOnDestroy() {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeListeners = [];
}
/**
* Normalizes the URL path for this location.
*
* @param includeHash True to include an anchor fragment in the path.
*
* @returns The normalized URL path.
*/
// TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is
// removed.
path(includeHash = false) {
return this.normalize(this._locationStrategy.path(includeHash));
}
/**
* Reports the current state of the location history.
* @returns The current value of the `history.state` object.
*/
getState() {
return this._locationStrategy.getState();
}
/**
* Normalizes the given path and compares to the current normalized path.
*
* @param path The given URL path.
* @param query Query parameters.
*
* @returns True if the given URL path is equal to the current normalized path, false
* otherwise.
*/
isCurrentPathEqualTo(path, query = "") {
return this.path() == this.normalize(path + normalizeQueryParams(query));
}
/**
* Normalizes a URL path by stripping any trailing slashes.
*
* @param url String representing a URL.
*
* @returns The normalized URL string.
*/
normalize(url) {
return _Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));
}
/**
* Normalizes an external URL path.
* If the given URL doesn't begin with a leading slash (`'/'`), adds one
* before normalizing. Adds a hash if `HashLocationStrategy` is
* in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
*
* @param url String representing a URL.
*
* @returns A normalized platform-specific URL.
*/
prepareExternalUrl(url) {
if (url && url[0] !== "/") {
url = "/" + url;
}
return this._locationStrategy.prepareExternalUrl(url);
}
// TODO: rename this method to pushState
/**
* Changes the browser's URL to a normalized version of a given URL, and pushes a
* new item onto the platform's history.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*
*/
go(path, query = "", state = null) {
this._locationStrategy.pushState(state, "", path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Changes the browser's URL to a normalized version of the given URL, and replaces
* the top item on the platform's history stack.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*/
replaceState(path, query = "", state = null) {
this._locationStrategy.replaceState(state, "", path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Navigates forward in the platform's history.
*/
forward() {
this._locationStrategy.forward();
}
/**
* Navigates back in the platform's history.
*/
back() {
this._locationStrategy.back();
}
/**
* Navigate to a specific page from session history, identified by its relative position to the
* current page.
*
* @param relativePosition Position of the target page in the history relative to the current
* page.
* A negative value moves backwards, a positive value moves forwards, e.g. `location.historyGo(2)`
* moves forward two pages and `location.historyGo(-2)` moves back two pages. When we try to go
* beyond what's stored in the history session, we stay in the current page. Same behaviour occurs
* when `relativePosition` equals 0.
* @see https://developer.mozilla.org/en-US/docs/Web/API/History_API#Moving_to_a_specific_point_in_history
*/
historyGo(relativePosition = 0) {
this._locationStrategy.historyGo?.(relativePosition);
}
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param fn The change handler function, which take a URL and a location history state.
* @returns A function that, when executed, unregisters a URL change listener.
*/
onUrlChange(fn) {
this._urlChangeListeners.push(fn);
this._urlChangeSubscription ??= this.subscribe((v) => {
this._notifyUrlChangeListeners(v.url, v.state);
});
return () => {
const fnIndex = this._urlChangeListeners.indexOf(fn);
this._urlChangeListeners.splice(fnIndex, 1);
if (this._urlChangeListeners.length === 0) {
this._urlChangeSubscription?.unsubscribe();
this._urlChangeSubscription = null;
}
};
}
/** @internal */
_notifyUrlChangeListeners(url = "", state) {
this._urlChangeListeners.forEach((fn) => fn(url, state));
}
/**
* Subscribes to the platform's `popState` events.
*
* Note: `Location.go()` does not trigger the `popState` event in the browser. Use
* `Location.onUrlChange()` to subscribe to URL changes instead.
*
* @param value Event that is triggered when the state history changes.
* @param exception The exception to throw.
*
* @see [onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate)
*
* @returns Subscribed events.
*/
subscribe(onNext, onThrow, onReturn) {
return this._subject.subscribe({
next: onNext,
error: onThrow ?? void 0,
complete: onReturn ?? void 0
});
}
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param params String of URL parameters.
*
* @returns The normalized URL parameters string.
*/
static normalizeQueryParams = normalizeQueryParams;
/**
* Joins two parts of a URL with a slash if needed.
*
* @param start URL string
* @param end URL string
*
*
* @returns The joined URL string.
*/
static joinWithSlash = joinWithSlash;
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param url URL string.
*
* @returns The URL string, modified if needed.
*/
static stripTrailingSlash = stripTrailingSlash;
static \u0275fac = function Location_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Location)(\u0275\u0275inject(LocationStrategy));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Location,
factory: () => createLocation(),
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Location, [{
type: Injectable,
args: [{
providedIn: "root",
// See #23917
useFactory: createLocation
}]
}], () => [{
type: LocationStrategy
}], null);
})();
function createLocation() {
return new Location(\u0275\u0275inject(LocationStrategy));
}
function _stripBasePath(basePath, url) {
if (!basePath || !url.startsWith(basePath)) {
return url;
}
const strippedUrl = url.substring(basePath.length);
if (strippedUrl === "" || ["/", ";", "?", "#"].includes(strippedUrl[0])) {
return strippedUrl;
}
return url;
}
function _stripIndexHtml(url) {
return url.replace(/\/index.html$/, "");
}
function _stripOrigin(baseHref) {
const isAbsoluteUrl2 = new RegExp("^(https?:)?//").test(baseHref);
if (isAbsoluteUrl2) {
const [, pathname] = baseHref.split(/\/\/[^\/]+/);
return pathname;
}
return baseHref;
}
// node_modules/@angular/common/fesm2022/common_module-Dx7dWex5.mjs
var HashLocationStrategy = class _HashLocationStrategy extends LocationStrategy {
_platformLocation;
_baseHref = "";
_removeListenerFns = [];
constructor(_platformLocation, _baseHref) {
super();
this._platformLocation = _platformLocation;
if (_baseHref != null) {
this._baseHref = _baseHref;
}
}
/** @docs-private */
ngOnDestroy() {
while (this._removeListenerFns.length) {
this._removeListenerFns.pop()();
}
}
onPopState(fn) {
this._removeListenerFns.push(this._platformLocation.onPopState(fn), this._platformLocation.onHashChange(fn));
}
getBaseHref() {
return this._baseHref;
}
path(includeHash = false) {
const path = this._platformLocation.hash ?? "#";
return path.length > 0 ? path.substring(1) : path;
}
prepareExternalUrl(internal) {
const url = joinWithSlash(this._baseHref, internal);
return url.length > 0 ? "#" + url : url;
}
pushState(state, title, path, queryParams) {
const url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams)) || this._platformLocation.pathname;
this._platformLocation.pushState(state, title, url);
}
replaceState(state, title, path, queryParams) {
const url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams)) || this._platformLocation.pathname;
this._platformLocation.replaceState(state, title, url);
}
forward() {
this._platformLocation.forward();
}
back() {
this._platformLocation.back();
}
getState() {
return this._platformLocation.getState();
}
historyGo(relativePosition = 0) {
this._platformLocation.historyGo?.(relativePosition);
}
static \u0275fac = function HashLocationStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HashLocationStrategy)(\u0275\u0275inject(PlatformLocation), \u0275\u0275inject(APP_BASE_HREF, 8));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HashLocationStrategy,
factory: _HashLocationStrategy.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HashLocationStrategy, [{
type: Injectable
}], () => [{
type: PlatformLocation
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [APP_BASE_HREF]
}]
}], null);
})();
var CURRENCIES_EN = {
"ADP": [void 0, void 0, 0],
"AFN": [void 0, "\u060B", 0],
"ALL": [void 0, void 0, 0],
"AMD": [void 0, "\u058F", 2],
"AOA": [void 0, "Kz"],
"ARS": [void 0, "$"],
"AUD": ["A$", "$"],
"AZN": [void 0, "\u20BC"],
"BAM": [void 0, "KM"],
"BBD": [void 0, "$"],
"BDT": [void 0, "\u09F3"],
"BHD": [void 0, void 0, 3],
"BIF": [void 0, void 0, 0],
"BMD": [void 0, "$"],
"BND": [void 0, "$"],
"BOB": [void 0, "Bs"],
"BRL": ["R$"],
"BSD": [void 0, "$"],
"BWP": [void 0, "P"],
"BYN": [void 0, void 0, 2],
"BYR": [void 0, void 0, 0],
"BZD": [void 0, "$"],
"CAD": ["CA$", "$", 2],
"CHF": [void 0, void 0, 2],
"CLF": [void 0, void 0, 4],
"CLP": [void 0, "$", 0],
"CNY": ["CN\xA5", "\xA5"],
"COP": [void 0, "$", 2],
"CRC": [void 0, "\u20A1", 2],
"CUC": [void 0, "$"],
"CUP": [void 0, "$"],
"CZK": [void 0, "K\u010D", 2],
"DJF": [void 0, void 0, 0],
"DKK": [void 0, "kr", 2],
"DOP": [void 0, "$"],
"EGP": [void 0, "E\xA3"],
"ESP": [void 0, "\u20A7", 0],
"EUR": ["\u20AC"],
"FJD": [void 0, "$"],
"FKP": [void 0, "\xA3"],
"GBP": ["\xA3"],
"GEL": [void 0, "\u20BE"],
"GHS": [void 0, "GH\u20B5"],
"GIP": [void 0, "\xA3"],
"GNF": [void 0, "FG", 0],
"GTQ": [void 0, "Q"],
"GYD": [void 0, "$", 2],
"HKD": ["HK$", "$"],
"HNL": [void 0, "L"],
"HRK": [void 0, "kn"],
"HUF": [void 0, "Ft", 2],
"IDR": [void 0, "Rp", 2],
"ILS": ["\u20AA"],
"INR": ["\u20B9"],
"IQD": [void 0, void 0, 0],
"IRR": [void 0, void 0, 0],
"ISK": [void 0, "kr", 0],
"ITL": [void 0, void 0, 0],
"JMD": [void 0, "$"],
"JOD": [void 0, void 0, 3],
"JPY": ["\xA5", void 0, 0],
"KHR": [void 0, "\u17DB"],
"KMF": [void 0, "CF", 0],
"KPW": [void 0, "\u20A9", 0],
"KRW": ["\u20A9", void 0, 0],
"KWD": [void 0, void 0, 3],
"KYD": [void 0, "$"],
"KZT": [void 0, "\u20B8"],
"LAK": [void 0, "\u20AD", 0],
"LBP": [void 0, "L\xA3", 0],
"LKR": [void 0, "Rs"],
"LRD": [void 0, "$"],
"LTL": [void 0, "Lt"],
"LUF": [void 0, void 0, 0],
"LVL": [void 0, "Ls"],
"LYD": [void 0, void 0, 3],
"MGA": [void 0, "Ar", 0],
"MGF": [void 0, void 0, 0],
"MMK": [void 0, "K", 0],
"MNT": [void 0, "\u20AE", 2],
"MRO": [void 0, void 0, 0],
"MUR": [void 0, "Rs", 2],
"MXN": ["MX$", "$"],
"MYR": [void 0, "RM"],
"NAD": [void 0, "$"],
"NGN": [void 0, "\u20A6"],
"NIO": [void 0, "C$"],
"NOK": [void 0, "kr", 2],
"NPR": [void 0, "Rs"],
"NZD": ["NZ$", "$"],
"OMR": [void 0, void 0, 3],
"PHP": ["\u20B1"],
"PKR": [void 0, "Rs", 2],
"PLN": [void 0, "z\u0142"],
"PYG": [void 0, "\u20B2", 0],
"RON": [void 0, "lei"],
"RSD": [void 0, void 0, 0],
"RUB": [void 0, "\u20BD"],
"RWF": [void 0, "RF", 0],
"SBD": [void 0, "$"],
"SEK": [void 0, "kr", 2],
"SGD": [void 0, "$"],
"SHP": [void 0, "\xA3"],
"SLE": [void 0, void 0, 2],
"SLL": [void 0, void 0, 0],
"SOS": [void 0, void 0, 0],
"SRD": [void 0, "$"],
"SSP": [void 0, "\xA3"],
"STD": [void 0, void 0, 0],
"STN": [void 0, "Db"],
"SYP": [void 0, "\xA3", 0],
"THB": [void 0, "\u0E3F"],
"TMM": [void 0, void 0, 0],
"TND": [void 0, void 0, 3],
"TOP": [void 0, "T$"],
"TRL": [void 0, void 0, 0],
"TRY": [void 0, "\u20BA"],
"TTD": [void 0, "$"],
"TWD": ["NT$", "$", 2],
"TZS": [void 0, void 0, 2],
"UAH": [void 0, "\u20B4"],
"UGX": [void 0, void 0, 0],
"USD": ["$"],
"UYI": [void 0, void 0, 0],
"UYU": [void 0, "$"],
"UYW": [void 0, void 0, 4],
"UZS": [void 0, void 0, 2],
"VEF": [void 0, "Bs", 2],
"VND": ["\u20AB", void 0, 0],
"VUV": [void 0, void 0, 0],
"XAF": ["FCFA", void 0, 0],
"XCD": ["EC$", "$"],
"XOF": ["F\u202FCFA", void 0, 0],
"XPF": ["CFPF", void 0, 0],
"XXX": ["\xA4"],
"YER": [void 0, void 0, 0],
"ZAR": [void 0, "R"],
"ZMK": [void 0, void 0, 0],
"ZMW": [void 0, "ZK"],
"ZWD": [void 0, void 0, 0]
};
var NumberFormatStyle;
(function(NumberFormatStyle2) {
NumberFormatStyle2[NumberFormatStyle2["Decimal"] = 0] = "Decimal";
NumberFormatStyle2[NumberFormatStyle2["Percent"] = 1] = "Percent";
NumberFormatStyle2[NumberFormatStyle2["Currency"] = 2] = "Currency";
NumberFormatStyle2[NumberFormatStyle2["Scientific"] = 3] = "Scientific";
})(NumberFormatStyle || (NumberFormatStyle = {}));
var Plural;
(function(Plural2) {
Plural2[Plural2["Zero"] = 0] = "Zero";
Plural2[Plural2["One"] = 1] = "One";
Plural2[Plural2["Two"] = 2] = "Two";
Plural2[Plural2["Few"] = 3] = "Few";
Plural2[Plural2["Many"] = 4] = "Many";
Plural2[Plural2["Other"] = 5] = "Other";
})(Plural || (Plural = {}));
var FormStyle;
(function(FormStyle2) {
FormStyle2[FormStyle2["Format"] = 0] = "Format";
FormStyle2[FormStyle2["Standalone"] = 1] = "Standalone";
})(FormStyle || (FormStyle = {}));
var TranslationWidth;
(function(TranslationWidth2) {
TranslationWidth2[TranslationWidth2["Narrow"] = 0] = "Narrow";
TranslationWidth2[TranslationWidth2["Abbreviated"] = 1] = "Abbreviated";
TranslationWidth2[TranslationWidth2["Wide"] = 2] = "Wide";
TranslationWidth2[TranslationWidth2["Short"] = 3] = "Short";
})(TranslationWidth || (TranslationWidth = {}));
var FormatWidth;
(function(FormatWidth2) {
FormatWidth2[FormatWidth2["Short"] = 0] = "Short";
FormatWidth2[FormatWidth2["Medium"] = 1] = "Medium";
FormatWidth2[FormatWidth2["Long"] = 2] = "Long";
FormatWidth2[FormatWidth2["Full"] = 3] = "Full";
})(FormatWidth || (FormatWidth = {}));
var NumberSymbol = {
/**
* Decimal separator.
* For `en-US`, the dot character.
* Example: 2,345`.`67
*/
Decimal: 0,
/**
* Grouping separator, typically for thousands.
* For `en-US`, the comma character.
* Example: 2`,`345.67
*/
Group: 1,
/**
* List-item separator.
* Example: "one, two, and three"
*/
List: 2,
/**
* Sign for percentage (out of 100).
* Example: 23.4%
*/
PercentSign: 3,
/**
* Sign for positive numbers.
* Example: +23
*/
PlusSign: 4,
/**
* Sign for negative numbers.
* Example: -23
*/
MinusSign: 5,
/**
* Computer notation for exponential value (n times a power of 10).
* Example: 1.2E3
*/
Exponential: 6,
/**
* Human-readable format of exponential.
* Example: 1.2x103
*/
SuperscriptingExponent: 7,
/**
* Sign for permille (out of 1000).
* Example: 23.4‰
*/
PerMille: 8,
/**
* Infinity, can be used with plus and minus.
* Example: ∞, +∞, -∞
*/
Infinity: 9,
/**
* Not a number.
* Example: NaN
*/
NaN: 10,
/**
* Symbol used between time units.
* Example: 10:52
*/
TimeSeparator: 11,
/**
* Decimal separator for currency values (fallback to `Decimal`).
* Example: $2,345.67
*/
CurrencyDecimal: 12,
/**
* Group separator for currency values (fallback to `Group`).
* Example: $2,345.67
*/
CurrencyGroup: 13
};
var WeekDay;
(function(WeekDay2) {
WeekDay2[WeekDay2["Sunday"] = 0] = "Sunday";
WeekDay2[WeekDay2["Monday"] = 1] = "Monday";
WeekDay2[WeekDay2["Tuesday"] = 2] = "Tuesday";
WeekDay2[WeekDay2["Wednesday"] = 3] = "Wednesday";
WeekDay2[WeekDay2["Thursday"] = 4] = "Thursday";
WeekDay2[WeekDay2["Friday"] = 5] = "Friday";
WeekDay2[WeekDay2["Saturday"] = 6] = "Saturday";
})(WeekDay || (WeekDay = {}));
function getLocaleId(locale) {
return findLocaleData(locale)[LocaleDataIndex.LocaleId];
}
function getLocaleDayPeriods(locale, formStyle, width) {
const data = findLocaleData(locale);
const amPmData = [data[LocaleDataIndex.DayPeriodsFormat], data[LocaleDataIndex.DayPeriodsStandalone]];
const amPm = getLastDefinedValue(amPmData, formStyle);
return getLastDefinedValue(amPm, width);
}
function getLocaleDayNames(locale, formStyle, width) {
const data = findLocaleData(locale);
const daysData = [data[LocaleDataIndex.DaysFormat], data[LocaleDataIndex.DaysStandalone]];
const days = getLastDefinedValue(daysData, formStyle);
return getLastDefinedValue(days, width);
}
function getLocaleMonthNames(locale, formStyle, width) {
const data = findLocaleData(locale);
const monthsData = [data[LocaleDataIndex.MonthsFormat], data[LocaleDataIndex.MonthsStandalone]];
const months = getLastDefinedValue(monthsData, formStyle);
return getLastDefinedValue(months, width);
}
function getLocaleEraNames(locale, width) {
const data = findLocaleData(locale);
const erasData = data[LocaleDataIndex.Eras];
return getLastDefinedValue(erasData, width);
}
function getLocaleDateFormat(locale, width) {
const data = findLocaleData(locale);
return getLastDefinedValue(data[LocaleDataIndex.DateFormat], width);
}
function getLocaleTimeFormat(locale, width) {
const data = findLocaleData(locale);
return getLastDefinedValue(data[LocaleDataIndex.TimeFormat], width);
}
function getLocaleDateTimeFormat(locale, width) {
const data = findLocaleData(locale);
const dateTimeFormatData = data[LocaleDataIndex.DateTimeFormat];
return getLastDefinedValue(dateTimeFormatData, width);
}
function getLocaleNumberSymbol(locale, symbol) {
const data = findLocaleData(locale);
const res = data[LocaleDataIndex.NumberSymbols][symbol];
if (typeof res === "undefined") {
if (symbol === NumberSymbol.CurrencyDecimal) {
return data[LocaleDataIndex.NumberSymbols][NumberSymbol.Decimal];
} else if (symbol === NumberSymbol.CurrencyGroup) {
return data[LocaleDataIndex.NumberSymbols][NumberSymbol.Group];
}
}
return res;
}
function getLocaleNumberFormat(locale, type) {
const data = findLocaleData(locale);
return data[LocaleDataIndex.NumberFormats][type];
}
function getLocaleCurrencies(locale) {
const data = findLocaleData(locale);
return data[LocaleDataIndex.Currencies];
}
var getLocalePluralCase2 = getLocalePluralCase;
function checkFullData(data) {
if (!data[LocaleDataIndex.ExtraData]) {
throw new Error(`Missing extra locale data for the locale "${data[LocaleDataIndex.LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`);
}
}
function getLocaleExtraDayPeriodRules(locale) {
const data = findLocaleData(locale);
checkFullData(data);
const rules = data[LocaleDataIndex.ExtraData][
2
/* ɵExtraLocaleDataIndex.ExtraDayPeriodsRules */
] || [];
return rules.map((rule) => {
if (typeof rule === "string") {
return extractTime(rule);
}
return [extractTime(rule[0]), extractTime(rule[1])];
});
}
function getLocaleExtraDayPeriods(locale, formStyle, width) {
const data = findLocaleData(locale);
checkFullData(data);
const dayPeriodsData = [data[LocaleDataIndex.ExtraData][
0
/* ɵExtraLocaleDataIndex.ExtraDayPeriodFormats */
], data[LocaleDataIndex.ExtraData][
1
/* ɵExtraLocaleDataIndex.ExtraDayPeriodStandalone */
]];
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
return getLastDefinedValue(dayPeriods, width) || [];
}
function getLastDefinedValue(data, index) {
for (let i = index; i > -1; i--) {
if (typeof data[i] !== "undefined") {
return data[i];
}
}
throw new Error("Locale data API: locale data undefined");
}
function extractTime(time) {
const [h, m] = time.split(":");
return {
hours: +h,
minutes: +m
};
}
function getCurrencySymbol(code, format, locale = "en") {
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
const symbolNarrow = currency[
1
/* ɵCurrencyIndex.SymbolNarrow */
];
if (format === "narrow" && typeof symbolNarrow === "string") {
return symbolNarrow;
}
return currency[
0
/* ɵCurrencyIndex.Symbol */
] || code;
}
var DEFAULT_NB_OF_CURRENCY_DIGITS = 2;
function getNumberOfCurrencyDigits(code) {
let digits;
const currency = CURRENCIES_EN[code];
if (currency) {
digits = currency[
2
/* ɵCurrencyIndex.NbOfDigits */
];
}
return typeof digits === "number" ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;
}
var ISO8601_DATE_REGEX = /^(\d{4,})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
var NAMED_FORMATS = {};
var DATE_FORMATS_SPLIT = /((?:[^BEGHLMOSWYZabcdhmswyz']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|Y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|c{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
function formatDate(value, format, locale, timezone) {
let date = toDate(value);
const namedFormat = getNamedFormat(locale, format);
format = namedFormat || format;
let parts = [];
let match2;
while (format) {
match2 = DATE_FORMATS_SPLIT.exec(format);
if (match2) {
parts = parts.concat(match2.slice(1));
const part = parts.pop();
if (!part) {
break;
}
format = part;
} else {
parts.push(format);
break;
}
}
let dateTimezoneOffset = date.getTimezoneOffset();
if (timezone) {
dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
date = convertTimezoneToLocal(date, timezone);
}
let text = "";
parts.forEach((value2) => {
const dateFormatter = getDateFormatter(value2);
text += dateFormatter ? dateFormatter(date, locale, dateTimezoneOffset) : value2 === "''" ? "'" : value2.replace(/(^'|'$)/g, "").replace(/''/g, "'");
});
return text;
}
function createDate(year, month, date) {
const newDate = /* @__PURE__ */ new Date(0);
newDate.setFullYear(year, month, date);
newDate.setHours(0, 0, 0);
return newDate;
}
function getNamedFormat(locale, format) {
const localeId = getLocaleId(locale);
NAMED_FORMATS[localeId] ??= {};
if (NAMED_FORMATS[localeId][format]) {
return NAMED_FORMATS[localeId][format];
}
let formatValue = "";
switch (format) {
case "shortDate":
formatValue = getLocaleDateFormat(locale, FormatWidth.Short);
break;
case "mediumDate":
formatValue = getLocaleDateFormat(locale, FormatWidth.Medium);
break;
case "longDate":
formatValue = getLocaleDateFormat(locale, FormatWidth.Long);
break;
case "fullDate":
formatValue = getLocaleDateFormat(locale, FormatWidth.Full);
break;
case "shortTime":
formatValue = getLocaleTimeFormat(locale, FormatWidth.Short);
break;
case "mediumTime":
formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium);
break;
case "longTime":
formatValue = getLocaleTimeFormat(locale, FormatWidth.Long);
break;
case "fullTime":
formatValue = getLocaleTimeFormat(locale, FormatWidth.Full);
break;
case "short":
const shortTime = getNamedFormat(locale, "shortTime");
const shortDate = getNamedFormat(locale, "shortDate");
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]);
break;
case "medium":
const mediumTime = getNamedFormat(locale, "mediumTime");
const mediumDate = getNamedFormat(locale, "mediumDate");
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]);
break;
case "long":
const longTime = getNamedFormat(locale, "longTime");
const longDate = getNamedFormat(locale, "longDate");
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]);
break;
case "full":
const fullTime = getNamedFormat(locale, "fullTime");
const fullDate = getNamedFormat(locale, "fullDate");
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]);
break;
}
if (formatValue) {
NAMED_FORMATS[localeId][format] = formatValue;
}
return formatValue;
}
function formatDateTime(str, opt_values) {
if (opt_values) {
str = str.replace(/\{([^}]+)}/g, function(match2, key) {
return opt_values != null && key in opt_values ? opt_values[key] : match2;
});
}
return str;
}
function padNumber(num, digits, minusSign = "-", trim, negWrap) {
let neg = "";
if (num < 0 || negWrap && num <= 0) {
if (negWrap) {
num = -num + 1;
} else {
num = -num;
neg = minusSign;
}
}
let strNum = String(num);
while (strNum.length < digits) {
strNum = "0" + strNum;
}
if (trim) {
strNum = strNum.slice(strNum.length - digits);
}
return neg + strNum;
}
function formatFractionalSeconds(milliseconds, digits) {
const strMs = padNumber(milliseconds, 3);
return strMs.substring(0, digits);
}
function dateGetter(name, size, offset = 0, trim = false, negWrap = false) {
return function(date, locale) {
let part = getDatePart(name, date);
if (offset > 0 || part > -offset) {
part += offset;
}
if (name === 3) {
if (part === 0 && offset === -12) {
part = 12;
}
} else if (name === 6) {
return formatFractionalSeconds(part, size);
}
const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
return padNumber(part, size, localeMinus, trim, negWrap);
};
}
function getDatePart(part, date) {
switch (part) {
case 0:
return date.getFullYear();
case 1:
return date.getMonth();
case 2:
return date.getDate();
case 3:
return date.getHours();
case 4:
return date.getMinutes();
case 5:
return date.getSeconds();
case 6:
return date.getMilliseconds();
case 7:
return date.getDay();
default:
throw new Error(`Unknown DateType value "${part}".`);
}
}
function dateStrGetter(name, width, form = FormStyle.Format, extended = false) {
return function(date, locale) {
return getDateTranslation(date, locale, name, width, form, extended);
};
}
function getDateTranslation(date, locale, name, width, form, extended) {
switch (name) {
case 2:
return getLocaleMonthNames(locale, form, width)[date.getMonth()];
case 1:
return getLocaleDayNames(locale, form, width)[date.getDay()];
case 0:
const currentHours = date.getHours();
const currentMinutes = date.getMinutes();
if (extended) {
const rules = getLocaleExtraDayPeriodRules(locale);
const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);
const index = rules.findIndex((rule) => {
if (Array.isArray(rule)) {
const [from2, to] = rule;
const afterFrom = currentHours >= from2.hours && currentMinutes >= from2.minutes;
const beforeTo = currentHours < to.hours || currentHours === to.hours && currentMinutes < to.minutes;
if (from2.hours < to.hours) {
if (afterFrom && beforeTo) {
return true;
}
} else if (afterFrom || beforeTo) {
return true;
}
} else {
if (rule.hours === currentHours && rule.minutes === currentMinutes) {
return true;
}
}
return false;
});
if (index !== -1) {
return dayPeriods[index];
}
}
return getLocaleDayPeriods(locale, form, width)[currentHours < 12 ? 0 : 1];
case 3:
return getLocaleEraNames(locale, width)[date.getFullYear() <= 0 ? 0 : 1];
default:
const unexpected = name;
throw new Error(`unexpected translation type ${unexpected}`);
}
}
function timeZoneGetter(width) {
return function(date, locale, offset) {
const zone = -1 * offset;
const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60);
switch (width) {
case 0:
return (zone >= 0 ? "+" : "") + padNumber(hours, 2, minusSign) + padNumber(Math.abs(zone % 60), 2, minusSign);
case 1:
return "GMT" + (zone >= 0 ? "+" : "") + padNumber(hours, 1, minusSign);
case 2:
return "GMT" + (zone >= 0 ? "+" : "") + padNumber(hours, 2, minusSign) + ":" + padNumber(Math.abs(zone % 60), 2, minusSign);
case 3:
if (offset === 0) {
return "Z";
} else {
return (zone >= 0 ? "+" : "") + padNumber(hours, 2, minusSign) + ":" + padNumber(Math.abs(zone % 60), 2, minusSign);
}
default:
throw new Error(`Unknown zone width "${width}"`);
}
};
}
var JANUARY = 0;
var THURSDAY = 4;
function getFirstThursdayOfYear(year) {
const firstDayOfYear = createDate(year, JANUARY, 1).getDay();
return createDate(year, 0, 1 + (firstDayOfYear <= THURSDAY ? THURSDAY : THURSDAY + 7) - firstDayOfYear);
}
function getThursdayThisIsoWeek(datetime) {
const currentDay = datetime.getDay();
const deltaToThursday = currentDay === 0 ? -3 : THURSDAY - currentDay;
return createDate(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + deltaToThursday);
}
function weekGetter(size, monthBased = false) {
return function(date, locale) {
let result;
if (monthBased) {
const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1;
const today = date.getDate();
result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7);
} else {
const thisThurs = getThursdayThisIsoWeek(date);
const firstThurs = getFirstThursdayOfYear(thisThurs.getFullYear());
const diff = thisThurs.getTime() - firstThurs.getTime();
result = 1 + Math.round(diff / 6048e5);
}
return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
};
}
function weekNumberingYearGetter(size, trim = false) {
return function(date, locale) {
const thisThurs = getThursdayThisIsoWeek(date);
const weekNumberingYear = thisThurs.getFullYear();
return padNumber(weekNumberingYear, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign), trim);
};
}
var DATE_FORMATS = {};
function getDateFormatter(format) {
if (DATE_FORMATS[format]) {
return DATE_FORMATS[format];
}
let formatter;
switch (format) {
// Era name (AD/BC)
case "G":
case "GG":
case "GGG":
formatter = dateStrGetter(3, TranslationWidth.Abbreviated);
break;
case "GGGG":
formatter = dateStrGetter(3, TranslationWidth.Wide);
break;
case "GGGGG":
formatter = dateStrGetter(3, TranslationWidth.Narrow);
break;
// 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199)
case "y":
formatter = dateGetter(0, 1, 0, false, true);
break;
// 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
case "yy":
formatter = dateGetter(0, 2, 0, true, true);
break;
// 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10)
case "yyy":
formatter = dateGetter(0, 3, 0, false, true);
break;
// 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010)
case "yyyy":
formatter = dateGetter(0, 4, 0, false, true);
break;
// 1 digit representation of the week-numbering year, e.g. (AD 1 => 1, AD 199 => 199)
case "Y":
formatter = weekNumberingYearGetter(1);
break;
// 2 digit representation of the week-numbering year, padded (00-99). (e.g. AD 2001 => 01, AD
// 2010 => 10)
case "YY":
formatter = weekNumberingYearGetter(2, true);
break;
// 3 digit representation of the week-numbering year, padded (000-999). (e.g. AD 1 => 001, AD
// 2010 => 2010)
case "YYY":
formatter = weekNumberingYearGetter(3);
break;
// 4 digit representation of the week-numbering year (e.g. AD 1 => 0001, AD 2010 => 2010)
case "YYYY":
formatter = weekNumberingYearGetter(4);
break;
// Month of the year (1-12), numeric
case "M":
case "L":
formatter = dateGetter(1, 1, 1);
break;
case "MM":
case "LL":
formatter = dateGetter(1, 2, 1);
break;
// Month of the year (January, ...), string, format
case "MMM":
formatter = dateStrGetter(2, TranslationWidth.Abbreviated);
break;
case "MMMM":
formatter = dateStrGetter(2, TranslationWidth.Wide);
break;
case "MMMMM":
formatter = dateStrGetter(2, TranslationWidth.Narrow);
break;
// Month of the year (January, ...), string, standalone
case "LLL":
formatter = dateStrGetter(2, TranslationWidth.Abbreviated, FormStyle.Standalone);
break;
case "LLLL":
formatter = dateStrGetter(2, TranslationWidth.Wide, FormStyle.Standalone);
break;
case "LLLLL":
formatter = dateStrGetter(2, TranslationWidth.Narrow, FormStyle.Standalone);
break;
// Week of the year (1, ... 52)
case "w":
formatter = weekGetter(1);
break;
case "ww":
formatter = weekGetter(2);
break;
// Week of the month (1, ...)
case "W":
formatter = weekGetter(1, true);
break;
// Day of the month (1-31)
case "d":
formatter = dateGetter(2, 1);
break;
case "dd":
formatter = dateGetter(2, 2);
break;
// Day of the Week StandAlone (1, 1, Mon, Monday, M, Mo)
case "c":
case "cc":
formatter = dateGetter(7, 1);
break;
case "ccc":
formatter = dateStrGetter(1, TranslationWidth.Abbreviated, FormStyle.Standalone);
break;
case "cccc":
formatter = dateStrGetter(1, TranslationWidth.Wide, FormStyle.Standalone);
break;
case "ccccc":
formatter = dateStrGetter(1, TranslationWidth.Narrow, FormStyle.Standalone);
break;
case "cccccc":
formatter = dateStrGetter(1, TranslationWidth.Short, FormStyle.Standalone);
break;
// Day of the Week
case "E":
case "EE":
case "EEE":
formatter = dateStrGetter(1, TranslationWidth.Abbreviated);
break;
case "EEEE":
formatter = dateStrGetter(1, TranslationWidth.Wide);
break;
case "EEEEE":
formatter = dateStrGetter(1, TranslationWidth.Narrow);
break;
case "EEEEEE":
formatter = dateStrGetter(1, TranslationWidth.Short);
break;
// Generic period of the day (am-pm)
case "a":
case "aa":
case "aaa":
formatter = dateStrGetter(0, TranslationWidth.Abbreviated);
break;
case "aaaa":
formatter = dateStrGetter(0, TranslationWidth.Wide);
break;
case "aaaaa":
formatter = dateStrGetter(0, TranslationWidth.Narrow);
break;
// Extended period of the day (midnight, at night, ...), standalone
case "b":
case "bb":
case "bbb":
formatter = dateStrGetter(0, TranslationWidth.Abbreviated, FormStyle.Standalone, true);
break;
case "bbbb":
formatter = dateStrGetter(0, TranslationWidth.Wide, FormStyle.Standalone, true);
break;
case "bbbbb":
formatter = dateStrGetter(0, TranslationWidth.Narrow, FormStyle.Standalone, true);
break;
// Extended period of the day (midnight, night, ...), standalone
case "B":
case "BB":
case "BBB":
formatter = dateStrGetter(0, TranslationWidth.Abbreviated, FormStyle.Format, true);
break;
case "BBBB":
formatter = dateStrGetter(0, TranslationWidth.Wide, FormStyle.Format, true);
break;
case "BBBBB":
formatter = dateStrGetter(0, TranslationWidth.Narrow, FormStyle.Format, true);
break;
// Hour in AM/PM, (1-12)
case "h":
formatter = dateGetter(3, 1, -12);
break;
case "hh":
formatter = dateGetter(3, 2, -12);
break;
// Hour of the day (0-23)
case "H":
formatter = dateGetter(3, 1);
break;
// Hour in day, padded (00-23)
case "HH":
formatter = dateGetter(3, 2);
break;
// Minute of the hour (0-59)
case "m":
formatter = dateGetter(4, 1);
break;
case "mm":
formatter = dateGetter(4, 2);
break;
// Second of the minute (0-59)
case "s":
formatter = dateGetter(5, 1);
break;
case "ss":
formatter = dateGetter(5, 2);
break;
// Fractional second
case "S":
formatter = dateGetter(6, 1);
break;
case "SS":
formatter = dateGetter(6, 2);
break;
case "SSS":
formatter = dateGetter(6, 3);
break;
// Timezone ISO8601 short format (-0430)
case "Z":
case "ZZ":
case "ZZZ":
formatter = timeZoneGetter(
0
/* ZoneWidth.Short */
);
break;
// Timezone ISO8601 extended format (-04:30)
case "ZZZZZ":
formatter = timeZoneGetter(
3
/* ZoneWidth.Extended */
);
break;
// Timezone GMT short format (GMT+4)
case "O":
case "OO":
case "OOO":
// Should be location, but fallback to format O instead because we don't have the data yet
case "z":
case "zz":
case "zzz":
formatter = timeZoneGetter(
1
/* ZoneWidth.ShortGMT */
);
break;
// Timezone GMT long format (GMT+0430)
case "OOOO":
case "ZZZZ":
// Should be location, but fallback to format O instead because we don't have the data yet
case "zzzz":
formatter = timeZoneGetter(
2
/* ZoneWidth.Long */
);
break;
default:
return null;
}
DATE_FORMATS[format] = formatter;
return formatter;
}
function timezoneToOffset(timezone, fallback) {
timezone = timezone.replace(/:/g, "");
const requestedTimezoneOffset = Date.parse("Jan 01, 1970 00:00:00 " + timezone) / 6e4;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
function addDateMinutes(date, minutes) {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + minutes);
return date;
}
function convertTimezoneToLocal(date, timezone, reverse) {
const reverseValue = -1;
const dateTimezoneOffset = date.getTimezoneOffset();
const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset));
}
function toDate(value) {
if (isDate(value)) {
return value;
}
if (typeof value === "number" && !isNaN(value)) {
return new Date(value);
}
if (typeof value === "string") {
value = value.trim();
if (/^(\d{4}(-\d{1,2}(-\d{1,2})?)?)$/.test(value)) {
const [y, m = 1, d = 1] = value.split("-").map((val) => +val);
return createDate(y, m - 1, d);
}
const parsedNb = parseFloat(value);
if (!isNaN(value - parsedNb)) {
return new Date(parsedNb);
}
let match2;
if (match2 = value.match(ISO8601_DATE_REGEX)) {
return isoStringToDate(match2);
}
}
const date = new Date(value);
if (!isDate(date)) {
throw new Error(`Unable to convert "${value}" into a date`);
}
return date;
}
function isoStringToDate(match2) {
const date = /* @__PURE__ */ new Date(0);
let tzHour = 0;
let tzMin = 0;
const dateSetter = match2[8] ? date.setUTCFullYear : date.setFullYear;
const timeSetter = match2[8] ? date.setUTCHours : date.setHours;
if (match2[9]) {
tzHour = Number(match2[9] + match2[10]);
tzMin = Number(match2[9] + match2[11]);
}
dateSetter.call(date, Number(match2[1]), Number(match2[2]) - 1, Number(match2[3]));
const h = Number(match2[4] || 0) - tzHour;
const m = Number(match2[5] || 0) - tzMin;
const s = Number(match2[6] || 0);
const ms = Math.floor(parseFloat("0." + (match2[7] || 0)) * 1e3);
timeSetter.call(date, h, m, s, ms);
return date;
}
function isDate(value) {
return value instanceof Date && !isNaN(value.valueOf());
}
var NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
var MAX_DIGITS = 22;
var DECIMAL_SEP = ".";
var ZERO_CHAR = "0";
var PATTERN_SEP = ";";
var GROUP_SEP = ",";
var DIGIT_CHAR = "#";
var CURRENCY_CHAR = "\xA4";
var PERCENT_CHAR = "%";
function formatNumberToLocaleString(value, pattern, locale, groupSymbol, decimalSymbol, digitsInfo, isPercent = false) {
let formattedText = "";
let isZero = false;
if (!isFinite(value)) {
formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity);
} else {
let parsedNumber = parseNumber(value);
if (isPercent) {
parsedNumber = toPercent(parsedNumber);
}
let minInt = pattern.minInt;
let minFraction = pattern.minFrac;
let maxFraction = pattern.maxFrac;
if (digitsInfo) {
const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);
if (parts === null) {
throw new Error(`${digitsInfo} is not a valid digit info`);
}
const minIntPart = parts[1];
const minFractionPart = parts[3];
const maxFractionPart = parts[5];
if (minIntPart != null) {
minInt = parseIntAutoRadix(minIntPart);
}
if (minFractionPart != null) {
minFraction = parseIntAutoRadix(minFractionPart);
}
if (maxFractionPart != null) {
maxFraction = parseIntAutoRadix(maxFractionPart);
} else if (minFractionPart != null && minFraction > maxFraction) {
maxFraction = minFraction;
}
}
roundNumber(parsedNumber, minFraction, maxFraction);
let digits = parsedNumber.digits;
let integerLen = parsedNumber.integerLen;
const exponent = parsedNumber.exponent;
let decimals = [];
isZero = digits.every((d) => !d);
for (; integerLen < minInt; integerLen++) {
digits.unshift(0);
}
for (; integerLen < 0; integerLen++) {
digits.unshift(0);
}
if (integerLen > 0) {
decimals = digits.splice(integerLen, digits.length);
} else {
decimals = digits;
digits = [0];
}
const groups = [];
if (digits.length >= pattern.lgSize) {
groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(""));
}
while (digits.length > pattern.gSize) {
groups.unshift(digits.splice(-pattern.gSize, digits.length).join(""));
}
if (digits.length) {
groups.unshift(digits.join(""));
}
formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));
if (decimals.length) {
formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join("");
}
if (exponent) {
formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + "+" + exponent;
}
}
if (value < 0 && !isZero) {
formattedText = pattern.negPre + formattedText + pattern.negSuf;
} else {
formattedText = pattern.posPre + formattedText + pattern.posSuf;
}
return formattedText;
}
function formatCurrency(value, locale, currency, currencyCode, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
pattern.minFrac = getNumberOfCurrencyDigits(currencyCode);
pattern.maxFrac = pattern.minFrac;
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo);
return res.replace(CURRENCY_CHAR, currency).replace(CURRENCY_CHAR, "").trim();
}
function formatPercent(value, locale, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true);
return res.replace(new RegExp(PERCENT_CHAR, "g"), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));
}
function formatNumber(value, locale, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
return formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo);
}
function parseNumberFormat(format, minusSign = "-") {
const p = {
minInt: 1,
minFrac: 0,
maxFrac: 0,
posPre: "",
posSuf: "",
negPre: "",
negSuf: "",
gSize: 0,
lgSize: 0
};
const patternParts = format.split(PATTERN_SEP);
const positive = patternParts[0];
const negative = patternParts[1];
const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ? positive.split(DECIMAL_SEP) : [positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1), positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1)], integer = positiveParts[0], fraction = positiveParts[1] || "";
p.posPre = integer.substring(0, integer.indexOf(DIGIT_CHAR));
for (let i = 0; i < fraction.length; i++) {
const ch = fraction.charAt(i);
if (ch === ZERO_CHAR) {
p.minFrac = p.maxFrac = i + 1;
} else if (ch === DIGIT_CHAR) {
p.maxFrac = i + 1;
} else {
p.posSuf += ch;
}
}
const groups = integer.split(GROUP_SEP);
p.gSize = groups[1] ? groups[1].length : 0;
p.lgSize = groups[2] || groups[1] ? (groups[2] || groups[1]).length : 0;
if (negative) {
const trunkLen = positive.length - p.posPre.length - p.posSuf.length, pos = negative.indexOf(DIGIT_CHAR);
p.negPre = negative.substring(0, pos).replace(/'/g, "");
p.negSuf = negative.slice(pos + trunkLen).replace(/'/g, "");
} else {
p.negPre = minusSign + p.posPre;
p.negSuf = p.posSuf;
}
return p;
}
function toPercent(parsedNumber) {
if (parsedNumber.digits[0] === 0) {
return parsedNumber;
}
const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen;
if (parsedNumber.exponent) {
parsedNumber.exponent += 2;
} else {
if (fractionLen === 0) {
parsedNumber.digits.push(0, 0);
} else if (fractionLen === 1) {
parsedNumber.digits.push(0);
}
parsedNumber.integerLen += 2;
}
return parsedNumber;
}
function parseNumber(num) {
let numStr = Math.abs(num) + "";
let exponent = 0, digits, integerLen;
let i, j, zeros;
if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) {
numStr = numStr.replace(DECIMAL_SEP, "");
}
if ((i = numStr.search(/e/i)) > 0) {
if (integerLen < 0) integerLen = i;
integerLen += +numStr.slice(i + 1);
numStr = numStr.substring(0, i);
} else if (integerLen < 0) {
integerLen = numStr.length;
}
for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) {
}
if (i === (zeros = numStr.length)) {
digits = [0];
integerLen = 1;
} else {
zeros--;
while (numStr.charAt(zeros) === ZERO_CHAR) zeros--;
integerLen -= i;
digits = [];
for (j = 0; i <= zeros; i++, j++) {
digits[j] = Number(numStr.charAt(i));
}
}
if (integerLen > MAX_DIGITS) {
digits = digits.splice(0, MAX_DIGITS - 1);
exponent = integerLen - 1;
integerLen = 1;
}
return {
digits,
exponent,
integerLen
};
}
function roundNumber(parsedNumber, minFrac, maxFrac) {
if (minFrac > maxFrac) {
throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`);
}
let digits = parsedNumber.digits;
let fractionLen = digits.length - parsedNumber.integerLen;
const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac);
let roundAt = fractionSize + parsedNumber.integerLen;
let digit = digits[roundAt];
if (roundAt > 0) {
digits.splice(Math.max(parsedNumber.integerLen, roundAt));
for (let j = roundAt; j < digits.length; j++) {
digits[j] = 0;
}
} else {
fractionLen = Math.max(0, fractionLen);
parsedNumber.integerLen = 1;
digits.length = Math.max(1, roundAt = fractionSize + 1);
digits[0] = 0;
for (let i = 1; i < roundAt; i++) digits[i] = 0;
}
if (digit >= 5) {
if (roundAt - 1 < 0) {
for (let k = 0; k > roundAt; k--) {
digits.unshift(0);
parsedNumber.integerLen++;
}
digits.unshift(1);
parsedNumber.integerLen++;
} else {
digits[roundAt - 1]++;
}
}
for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0);
let dropTrailingZeros = fractionSize !== 0;
const minLen = minFrac + parsedNumber.integerLen;
const carry = digits.reduceRight(function(carry2, d, i, digits2) {
d = d + carry2;
digits2[i] = d < 10 ? d : d - 10;
if (dropTrailingZeros) {
if (digits2[i] === 0 && i >= minLen) {
digits2.pop();
} else {
dropTrailingZeros = false;
}
}
return d >= 10 ? 1 : 0;
}, 0);
if (carry) {
digits.unshift(carry);
parsedNumber.integerLen++;
}
}
function parseIntAutoRadix(text) {
const result = parseInt(text);
if (isNaN(result)) {
throw new Error("Invalid integer literal when parsing " + text);
}
return result;
}
var NgLocalization = class _NgLocalization {
static \u0275fac = function NgLocalization_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgLocalization)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _NgLocalization,
factory: function NgLocalization_Factory(__ngFactoryType__) {
let __ngConditionalFactory__ = null;
if (__ngFactoryType__) {
__ngConditionalFactory__ = new __ngFactoryType__();
} else {
__ngConditionalFactory__ = ((locale) => new NgLocaleLocalization(locale))(\u0275\u0275inject(LOCALE_ID));
}
return __ngConditionalFactory__;
},
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgLocalization, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: (locale) => new NgLocaleLocalization(locale),
deps: [LOCALE_ID]
}]
}], null, null);
})();
function getPluralCategory(value, cases, ngLocalization, locale) {
let key = `=${value}`;
if (cases.indexOf(key) > -1) {
return key;
}
key = ngLocalization.getPluralCategory(value, locale);
if (cases.indexOf(key) > -1) {
return key;
}
if (cases.indexOf("other") > -1) {
return "other";
}
throw new Error(`No plural message found for value "${value}"`);
}
var NgLocaleLocalization = class _NgLocaleLocalization extends NgLocalization {
locale;
constructor(locale) {
super();
this.locale = locale;
}
getPluralCategory(value, locale) {
const plural = getLocalePluralCase2(locale || this.locale)(value);
switch (plural) {
case Plural.Zero:
return "zero";
case Plural.One:
return "one";
case Plural.Two:
return "two";
case Plural.Few:
return "few";
case Plural.Many:
return "many";
default:
return "other";
}
}
static \u0275fac = function NgLocaleLocalization_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgLocaleLocalization)(\u0275\u0275inject(LOCALE_ID));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _NgLocaleLocalization,
factory: _NgLocaleLocalization.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgLocaleLocalization, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [LOCALE_ID]
}]
}], null);
})();
var WS_REGEXP = /\s+/;
var EMPTY_ARRAY = [];
var NgClass = class _NgClass {
_ngEl;
_renderer;
initialClasses = EMPTY_ARRAY;
rawClass;
stateMap = /* @__PURE__ */ new Map();
constructor(_ngEl, _renderer) {
this._ngEl = _ngEl;
this._renderer = _renderer;
}
set klass(value) {
this.initialClasses = value != null ? value.trim().split(WS_REGEXP) : EMPTY_ARRAY;
}
set ngClass(value) {
this.rawClass = typeof value === "string" ? value.trim().split(WS_REGEXP) : value;
}
/*
The NgClass directive uses the custom change detection algorithm for its inputs. The custom
algorithm is necessary since inputs are represented as complex object or arrays that need to be
deeply-compared.
This algorithm is perf-sensitive since NgClass is used very frequently and its poor performance
might negatively impact runtime performance of the entire change detection cycle. The design of
this algorithm is making sure that:
- there is no unnecessary DOM manipulation (CSS classes are added / removed from the DOM only when
needed), even if references to bound objects change;
- there is no memory allocation if nothing changes (even relatively modest memory allocation
during the change detection cycle can result in GC pauses for some of the CD cycles).
The algorithm works by iterating over the set of bound classes, staring with [class] binding and
then going over [ngClass] binding. For each CSS class name:
- check if it was seen before (this information is tracked in the state map) and if its value
changed;
- mark it as "touched" - names that are not marked are not present in the latest set of binding
and we can remove such class name from the internal data structures;
After iteration over all the CSS class names we've got data structure with all the information
necessary to synchronize changes to the DOM - it is enough to iterate over the state map, flush
changes to the DOM and reset internal data structures so those are ready for the next change
detection cycle.
*/
ngDoCheck() {
for (const klass of this.initialClasses) {
this._updateState(klass, true);
}
const rawClass = this.rawClass;
if (Array.isArray(rawClass) || rawClass instanceof Set) {
for (const klass of rawClass) {
this._updateState(klass, true);
}
} else if (rawClass != null) {
for (const klass of Object.keys(rawClass)) {
this._updateState(klass, Boolean(rawClass[klass]));
}
}
this._applyStateDiff();
}
_updateState(klass, nextEnabled) {
const state = this.stateMap.get(klass);
if (state !== void 0) {
if (state.enabled !== nextEnabled) {
state.changed = true;
state.enabled = nextEnabled;
}
state.touched = true;
} else {
this.stateMap.set(klass, {
enabled: nextEnabled,
changed: true,
touched: true
});
}
}
_applyStateDiff() {
for (const stateEntry of this.stateMap) {
const klass = stateEntry[0];
const state = stateEntry[1];
if (state.changed) {
this._toggleClass(klass, state.enabled);
state.changed = false;
} else if (!state.touched) {
if (state.enabled) {
this._toggleClass(klass, false);
}
this.stateMap.delete(klass);
}
state.touched = false;
}
}
_toggleClass(klass, enabled) {
if (ngDevMode) {
if (typeof klass !== "string") {
throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${stringify(klass)}`);
}
}
klass = klass.trim();
if (klass.length > 0) {
klass.split(WS_REGEXP).forEach((klass2) => {
if (enabled) {
this._renderer.addClass(this._ngEl.nativeElement, klass2);
} else {
this._renderer.removeClass(this._ngEl.nativeElement, klass2);
}
});
}
}
static \u0275fac = function NgClass_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgClass)(\u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(Renderer2));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgClass,
selectors: [["", "ngClass", ""]],
inputs: {
klass: [0, "class", "klass"],
ngClass: "ngClass"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgClass, [{
type: Directive,
args: [{
selector: "[ngClass]"
}]
}], () => [{
type: ElementRef
}, {
type: Renderer2
}], {
klass: [{
type: Input,
args: ["class"]
}],
ngClass: [{
type: Input,
args: ["ngClass"]
}]
});
})();
var NgComponentOutlet = class _NgComponentOutlet {
_viewContainerRef;
// TODO(crisbeto): this should be `Type<T>`, but doing so broke a few
// targets in a TGP so we need to do it in a major version.
/** Component that should be rendered in the outlet. */
ngComponentOutlet = null;
ngComponentOutletInputs;
ngComponentOutletInjector;
ngComponentOutletContent;
ngComponentOutletNgModule;
/**
* @deprecated This input is deprecated, use `ngComponentOutletNgModule` instead.
*/
ngComponentOutletNgModuleFactory;
_componentRef;
_moduleRef;
/**
* A helper data structure that allows us to track inputs that were part of the
* ngComponentOutletInputs expression. Tracking inputs is necessary for proper removal of ones
* that are no longer referenced.
*/
_inputsUsed = /* @__PURE__ */ new Map();
/**
* Gets the instance of the currently-rendered component.
* Will be null if no component has been rendered.
*/
get componentInstance() {
return this._componentRef?.instance ?? null;
}
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
}
_needToReCreateNgModuleInstance(changes) {
return changes["ngComponentOutletNgModule"] !== void 0 || changes["ngComponentOutletNgModuleFactory"] !== void 0;
}
_needToReCreateComponentInstance(changes) {
return changes["ngComponentOutlet"] !== void 0 || changes["ngComponentOutletContent"] !== void 0 || changes["ngComponentOutletInjector"] !== void 0 || this._needToReCreateNgModuleInstance(changes);
}
/** @docs-private */
ngOnChanges(changes) {
if (this._needToReCreateComponentInstance(changes)) {
this._viewContainerRef.clear();
this._inputsUsed.clear();
this._componentRef = void 0;
if (this.ngComponentOutlet) {
const injector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
if (this._needToReCreateNgModuleInstance(changes)) {
this._moduleRef?.destroy();
if (this.ngComponentOutletNgModule) {
this._moduleRef = createNgModule(this.ngComponentOutletNgModule, getParentInjector(injector));
} else if (this.ngComponentOutletNgModuleFactory) {
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(getParentInjector(injector));
} else {
this._moduleRef = void 0;
}
}
this._componentRef = this._viewContainerRef.createComponent(this.ngComponentOutlet, {
injector,
ngModuleRef: this._moduleRef,
projectableNodes: this.ngComponentOutletContent
});
}
}
}
/** @docs-private */
ngDoCheck() {
if (this._componentRef) {
if (this.ngComponentOutletInputs) {
for (const inputName of Object.keys(this.ngComponentOutletInputs)) {
this._inputsUsed.set(inputName, true);
}
}
this._applyInputStateDiff(this._componentRef);
}
}
/** @docs-private */
ngOnDestroy() {
this._moduleRef?.destroy();
}
_applyInputStateDiff(componentRef) {
for (const [inputName, touched] of this._inputsUsed) {
if (!touched) {
componentRef.setInput(inputName, void 0);
this._inputsUsed.delete(inputName);
} else {
componentRef.setInput(inputName, this.ngComponentOutletInputs[inputName]);
this._inputsUsed.set(inputName, false);
}
}
}
static \u0275fac = function NgComponentOutlet_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgComponentOutlet)(\u0275\u0275directiveInject(ViewContainerRef));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgComponentOutlet,
selectors: [["", "ngComponentOutlet", ""]],
inputs: {
ngComponentOutlet: "ngComponentOutlet",
ngComponentOutletInputs: "ngComponentOutletInputs",
ngComponentOutletInjector: "ngComponentOutletInjector",
ngComponentOutletContent: "ngComponentOutletContent",
ngComponentOutletNgModule: "ngComponentOutletNgModule",
ngComponentOutletNgModuleFactory: "ngComponentOutletNgModuleFactory"
},
exportAs: ["ngComponentOutlet"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgComponentOutlet, [{
type: Directive,
args: [{
selector: "[ngComponentOutlet]",
exportAs: "ngComponentOutlet"
}]
}], () => [{
type: ViewContainerRef
}], {
ngComponentOutlet: [{
type: Input
}],
ngComponentOutletInputs: [{
type: Input
}],
ngComponentOutletInjector: [{
type: Input
}],
ngComponentOutletContent: [{
type: Input
}],
ngComponentOutletNgModule: [{
type: Input
}],
ngComponentOutletNgModuleFactory: [{
type: Input
}]
});
})();
function getParentInjector(injector) {
const parentNgModule = injector.get(NgModuleRef$1);
return parentNgModule.injector;
}
var NgForOfContext = class {
$implicit;
ngForOf;
index;
count;
constructor($implicit, ngForOf, index, count) {
this.$implicit = $implicit;
this.ngForOf = ngForOf;
this.index = index;
this.count = count;
}
// Indicates whether this is the first item in the collection.
get first() {
return this.index === 0;
}
// Indicates whether this is the last item in the collection.
get last() {
return this.index === this.count - 1;
}
// Indicates whether an index of this item in the collection is even.
get even() {
return this.index % 2 === 0;
}
// Indicates whether an index of this item in the collection is odd.
get odd() {
return !this.even;
}
};
var NgForOf = class _NgForOf {
_viewContainer;
_template;
_differs;
/**
* The value of the iterable expression, which can be used as a
* [template input variable](guide/directives/structural-directives#shorthand).
*/
set ngForOf(ngForOf) {
this._ngForOf = ngForOf;
this._ngForOfDirty = true;
}
/**
* Specifies a custom `TrackByFunction` to compute the identity of items in an iterable.
*
* If a custom `TrackByFunction` is not provided, `NgForOf` will use the item's [object
* identity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)
* as the key.
*
* `NgForOf` uses the computed key to associate items in an iterable with DOM elements
* it produces for these items.
*
* A custom `TrackByFunction` is useful to provide good user experience in cases when items in an
* iterable rendered using `NgForOf` have a natural identifier (for example, custom ID or a
* primary key), and this iterable could be updated with new object instances that still
* represent the same underlying entity (for example, when data is re-fetched from the server,
* and the iterable is recreated and re-rendered, but most of the data is still the same).
*
* @see {@link TrackByFunction}
*/
set ngForTrackBy(fn) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && fn != null && typeof fn !== "function") {
console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
}
this._trackByFn = fn;
}
get ngForTrackBy() {
return this._trackByFn;
}
_ngForOf = null;
_ngForOfDirty = true;
_differ = null;
// waiting for microsoft/typescript#43662 to allow the return type `TrackByFunction|undefined` for
// the getter
_trackByFn;
constructor(_viewContainer, _template, _differs) {
this._viewContainer = _viewContainer;
this._template = _template;
this._differs = _differs;
}
/**
* A reference to the template that is stamped out for each item in the iterable.
* @see [template reference variable](guide/templates/variables#template-reference-variables)
*/
set ngForTemplate(value) {
if (value) {
this._template = value;
}
}
/**
* Applies the changes when needed.
* @docs-private
*/
ngDoCheck() {
if (this._ngForOfDirty) {
this._ngForOfDirty = false;
const value = this._ngForOf;
if (!this._differ && value) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
try {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
} catch {
let errorMessage = `Cannot find a differ supporting object '${value}' of type '${getTypeName(value)}'. NgFor only supports binding to Iterables, such as Arrays.`;
if (typeof value === "object") {
errorMessage += " Did you mean to use the keyvalue pipe?";
}
throw new RuntimeError(-2200, errorMessage);
}
} else {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
}
}
}
if (this._differ) {
const changes = this._differ.diff(this._ngForOf);
if (changes) this._applyChanges(changes);
}
}
_applyChanges(changes) {
const viewContainer = this._viewContainer;
changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
if (item.previousIndex == null) {
viewContainer.createEmbeddedView(this._template, new NgForOfContext(item.item, this._ngForOf, -1, -1), currentIndex === null ? void 0 : currentIndex);
} else if (currentIndex == null) {
viewContainer.remove(adjustedPreviousIndex === null ? void 0 : adjustedPreviousIndex);
} else if (adjustedPreviousIndex !== null) {
const view = viewContainer.get(adjustedPreviousIndex);
viewContainer.move(view, currentIndex);
applyViewChange(view, item);
}
});
for (let i = 0, ilen = viewContainer.length; i < ilen; i++) {
const viewRef = viewContainer.get(i);
const context = viewRef.context;
context.index = i;
context.count = ilen;
context.ngForOf = this._ngForOf;
}
changes.forEachIdentityChange((record) => {
const viewRef = viewContainer.get(record.currentIndex);
applyViewChange(viewRef, record);
});
}
/**
* Asserts the correct type of the context for the template that `NgForOf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgForOf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard(dir, ctx) {
return true;
}
static \u0275fac = function NgForOf_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgForOf)(\u0275\u0275directiveInject(ViewContainerRef), \u0275\u0275directiveInject(TemplateRef), \u0275\u0275directiveInject(IterableDiffers));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgForOf,
selectors: [["", "ngFor", "", "ngForOf", ""]],
inputs: {
ngForOf: "ngForOf",
ngForTrackBy: "ngForTrackBy",
ngForTemplate: "ngForTemplate"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgForOf, [{
type: Directive,
args: [{
selector: "[ngFor][ngForOf]"
}]
}], () => [{
type: ViewContainerRef
}, {
type: TemplateRef
}, {
type: IterableDiffers
}], {
ngForOf: [{
type: Input
}],
ngForTrackBy: [{
type: Input
}],
ngForTemplate: [{
type: Input
}]
});
})();
function applyViewChange(view, record) {
view.context.$implicit = record.item;
}
function getTypeName(type) {
return type["name"] || typeof type;
}
var NgIf = class _NgIf {
_viewContainer;
_context = new NgIfContext();
_thenTemplateRef = null;
_elseTemplateRef = null;
_thenViewRef = null;
_elseViewRef = null;
constructor(_viewContainer, templateRef) {
this._viewContainer = _viewContainer;
this._thenTemplateRef = templateRef;
}
/**
* The Boolean expression to evaluate as the condition for showing a template.
*/
set ngIf(condition) {
this._context.$implicit = this._context.ngIf = condition;
this._updateView();
}
/**
* A template to show if the condition expression evaluates to true.
*/
set ngIfThen(templateRef) {
assertTemplate(templateRef, (typeof ngDevMode === "undefined" || ngDevMode) && "ngIfThen");
this._thenTemplateRef = templateRef;
this._thenViewRef = null;
this._updateView();
}
/**
* A template to show if the condition expression evaluates to false.
*/
set ngIfElse(templateRef) {
assertTemplate(templateRef, (typeof ngDevMode === "undefined" || ngDevMode) && "ngIfElse");
this._elseTemplateRef = templateRef;
this._elseViewRef = null;
this._updateView();
}
_updateView() {
if (this._context.$implicit) {
if (!this._thenViewRef) {
this._viewContainer.clear();
this._elseViewRef = null;
if (this._thenTemplateRef) {
this._thenViewRef = this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
}
}
} else {
if (!this._elseViewRef) {
this._viewContainer.clear();
this._thenViewRef = null;
if (this._elseTemplateRef) {
this._elseViewRef = this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
}
}
}
}
/** @internal */
static ngIfUseIfTypeGuard;
/**
* Assert the correct type of the expression bound to the `ngIf` input within the template.
*
* The presence of this static field is a signal to the Ivy template type check compiler that
* when the `NgIf` structural directive renders its template, the type of the expression bound
* to `ngIf` should be narrowed in some way. For `NgIf`, the binding expression itself is used to
* narrow its type, which allows the strictNullChecks feature of TypeScript to work with `NgIf`.
*/
static ngTemplateGuard_ngIf;
/**
* Asserts the correct type of the context for the template that `NgIf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgIf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard(dir, ctx) {
return true;
}
static \u0275fac = function NgIf_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgIf)(\u0275\u0275directiveInject(ViewContainerRef), \u0275\u0275directiveInject(TemplateRef));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgIf,
selectors: [["", "ngIf", ""]],
inputs: {
ngIf: "ngIf",
ngIfThen: "ngIfThen",
ngIfElse: "ngIfElse"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgIf, [{
type: Directive,
args: [{
selector: "[ngIf]"
}]
}], () => [{
type: ViewContainerRef
}, {
type: TemplateRef
}], {
ngIf: [{
type: Input
}],
ngIfThen: [{
type: Input
}],
ngIfElse: [{
type: Input
}]
});
})();
var NgIfContext = class {
$implicit = null;
ngIf = null;
};
function assertTemplate(templateRef, property) {
if (templateRef && !templateRef.createEmbeddedView) {
throw new RuntimeError(2020, (typeof ngDevMode === "undefined" || ngDevMode) && `${property} must be a TemplateRef, but received '${stringify(templateRef)}'.`);
}
}
var SwitchView = class {
_viewContainerRef;
_templateRef;
_created = false;
constructor(_viewContainerRef, _templateRef) {
this._viewContainerRef = _viewContainerRef;
this._templateRef = _templateRef;
}
create() {
this._created = true;
this._viewContainerRef.createEmbeddedView(this._templateRef);
}
destroy() {
this._created = false;
this._viewContainerRef.clear();
}
enforceState(created) {
if (created && !this._created) {
this.create();
} else if (!created && this._created) {
this.destroy();
}
}
};
var NgSwitch = class _NgSwitch {
_defaultViews = [];
_defaultUsed = false;
_caseCount = 0;
_lastCaseCheckIndex = 0;
_lastCasesMatched = false;
_ngSwitch;
set ngSwitch(newValue) {
this._ngSwitch = newValue;
if (this._caseCount === 0) {
this._updateDefaultCases(true);
}
}
/** @internal */
_addCase() {
return this._caseCount++;
}
/** @internal */
_addDefault(view) {
this._defaultViews.push(view);
}
/** @internal */
_matchCase(value) {
const matched = value === this._ngSwitch;
this._lastCasesMatched ||= matched;
this._lastCaseCheckIndex++;
if (this._lastCaseCheckIndex === this._caseCount) {
this._updateDefaultCases(!this._lastCasesMatched);
this._lastCaseCheckIndex = 0;
this._lastCasesMatched = false;
}
return matched;
}
_updateDefaultCases(useDefault) {
if (this._defaultViews.length > 0 && useDefault !== this._defaultUsed) {
this._defaultUsed = useDefault;
for (const defaultView of this._defaultViews) {
defaultView.enforceState(useDefault);
}
}
}
static \u0275fac = function NgSwitch_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgSwitch)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgSwitch,
selectors: [["", "ngSwitch", ""]],
inputs: {
ngSwitch: "ngSwitch"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgSwitch, [{
type: Directive,
args: [{
selector: "[ngSwitch]"
}]
}], null, {
ngSwitch: [{
type: Input
}]
});
})();
var NgSwitchCase = class _NgSwitchCase {
ngSwitch;
_view;
/**
* Stores the HTML template to be selected on match.
*/
ngSwitchCase;
constructor(viewContainer, templateRef, ngSwitch) {
this.ngSwitch = ngSwitch;
if ((typeof ngDevMode === "undefined" || ngDevMode) && !ngSwitch) {
throwNgSwitchProviderNotFoundError("ngSwitchCase", "NgSwitchCase");
}
ngSwitch._addCase();
this._view = new SwitchView(viewContainer, templateRef);
}
/**
* Performs case matching. For internal use only.
* @docs-private
*/
ngDoCheck() {
this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase));
}
static \u0275fac = function NgSwitchCase_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgSwitchCase)(\u0275\u0275directiveInject(ViewContainerRef), \u0275\u0275directiveInject(TemplateRef), \u0275\u0275directiveInject(NgSwitch, 9));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgSwitchCase,
selectors: [["", "ngSwitchCase", ""]],
inputs: {
ngSwitchCase: "ngSwitchCase"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgSwitchCase, [{
type: Directive,
args: [{
selector: "[ngSwitchCase]"
}]
}], () => [{
type: ViewContainerRef
}, {
type: TemplateRef
}, {
type: NgSwitch,
decorators: [{
type: Optional
}, {
type: Host
}]
}], {
ngSwitchCase: [{
type: Input
}]
});
})();
var NgSwitchDefault = class _NgSwitchDefault {
constructor(viewContainer, templateRef, ngSwitch) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && !ngSwitch) {
throwNgSwitchProviderNotFoundError("ngSwitchDefault", "NgSwitchDefault");
}
ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
}
static \u0275fac = function NgSwitchDefault_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgSwitchDefault)(\u0275\u0275directiveInject(ViewContainerRef), \u0275\u0275directiveInject(TemplateRef), \u0275\u0275directiveInject(NgSwitch, 9));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgSwitchDefault,
selectors: [["", "ngSwitchDefault", ""]]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgSwitchDefault, [{
type: Directive,
args: [{
selector: "[ngSwitchDefault]"
}]
}], () => [{
type: ViewContainerRef
}, {
type: TemplateRef
}, {
type: NgSwitch,
decorators: [{
type: Optional
}, {
type: Host
}]
}], null);
})();
function throwNgSwitchProviderNotFoundError(attrName, directiveName) {
throw new RuntimeError(2e3, `An element with the "${attrName}" attribute (matching the "${directiveName}" directive) must be located inside an element with the "ngSwitch" attribute (matching "NgSwitch" directive)`);
}
var NgPlural = class _NgPlural {
_localization;
_activeView;
_caseViews = {};
constructor(_localization) {
this._localization = _localization;
}
set ngPlural(value) {
this._updateView(value);
}
addCase(value, switchView) {
this._caseViews[value] = switchView;
}
_updateView(switchValue) {
this._clearViews();
const cases = Object.keys(this._caseViews);
const key = getPluralCategory(switchValue, cases, this._localization);
this._activateView(this._caseViews[key]);
}
_clearViews() {
if (this._activeView) this._activeView.destroy();
}
_activateView(view) {
if (view) {
this._activeView = view;
this._activeView.create();
}
}
static \u0275fac = function NgPlural_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgPlural)(\u0275\u0275directiveInject(NgLocalization));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgPlural,
selectors: [["", "ngPlural", ""]],
inputs: {
ngPlural: "ngPlural"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgPlural, [{
type: Directive,
args: [{
selector: "[ngPlural]"
}]
}], () => [{
type: NgLocalization
}], {
ngPlural: [{
type: Input
}]
});
})();
var NgPluralCase = class _NgPluralCase {
value;
constructor(value, template, viewContainer, ngPlural) {
this.value = value;
const isANumber = !isNaN(Number(value));
ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));
}
static \u0275fac = function NgPluralCase_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgPluralCase)(\u0275\u0275injectAttribute("ngPluralCase"), \u0275\u0275directiveInject(TemplateRef), \u0275\u0275directiveInject(ViewContainerRef), \u0275\u0275directiveInject(NgPlural, 1));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgPluralCase,
selectors: [["", "ngPluralCase", ""]]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgPluralCase, [{
type: Directive,
args: [{
selector: "[ngPluralCase]"
}]
}], () => [{
type: void 0,
decorators: [{
type: Attribute,
args: ["ngPluralCase"]
}]
}, {
type: TemplateRef
}, {
type: ViewContainerRef
}, {
type: NgPlural,
decorators: [{
type: Host
}]
}], null);
})();
var NgStyle = class _NgStyle {
_ngEl;
_differs;
_renderer;
_ngStyle = null;
_differ = null;
constructor(_ngEl, _differs, _renderer) {
this._ngEl = _ngEl;
this._differs = _differs;
this._renderer = _renderer;
}
set ngStyle(values) {
this._ngStyle = values;
if (!this._differ && values) {
this._differ = this._differs.find(values).create();
}
}
ngDoCheck() {
if (this._differ) {
const changes = this._differ.diff(this._ngStyle);
if (changes) {
this._applyChanges(changes);
}
}
}
_setStyle(nameAndUnit, value) {
const [name, unit] = nameAndUnit.split(".");
const flags = name.indexOf("-") === -1 ? void 0 : RendererStyleFlags2.DashCase;
if (value != null) {
this._renderer.setStyle(this._ngEl.nativeElement, name, unit ? `${value}${unit}` : value, flags);
} else {
this._renderer.removeStyle(this._ngEl.nativeElement, name, flags);
}
}
_applyChanges(changes) {
changes.forEachRemovedItem((record) => this._setStyle(record.key, null));
changes.forEachAddedItem((record) => this._setStyle(record.key, record.currentValue));
changes.forEachChangedItem((record) => this._setStyle(record.key, record.currentValue));
}
static \u0275fac = function NgStyle_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgStyle)(\u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(KeyValueDiffers), \u0275\u0275directiveInject(Renderer2));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgStyle,
selectors: [["", "ngStyle", ""]],
inputs: {
ngStyle: "ngStyle"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgStyle, [{
type: Directive,
args: [{
selector: "[ngStyle]"
}]
}], () => [{
type: ElementRef
}, {
type: KeyValueDiffers
}, {
type: Renderer2
}], {
ngStyle: [{
type: Input,
args: ["ngStyle"]
}]
});
})();
var NgTemplateOutlet = class _NgTemplateOutlet {
_viewContainerRef;
_viewRef = null;
/**
* A context object to attach to the {@link EmbeddedViewRef}. This should be an
* object, the object's keys will be available for binding by the local template `let`
* declarations.
* Using the key `$implicit` in the context object will set its value as default.
*/
ngTemplateOutletContext = null;
/**
* A string defining the template reference and optionally the context object for the template.
*/
ngTemplateOutlet = null;
/** Injector to be used within the embedded view. */
ngTemplateOutletInjector = null;
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
}
ngOnChanges(changes) {
if (this._shouldRecreateView(changes)) {
const viewContainerRef = this._viewContainerRef;
if (this._viewRef) {
viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
}
if (!this.ngTemplateOutlet) {
this._viewRef = null;
return;
}
const viewContext = this._createContextForwardProxy();
this._viewRef = viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, viewContext, {
injector: this.ngTemplateOutletInjector ?? void 0
});
}
}
/**
* We need to re-create existing embedded view if either is true:
* - the outlet changed.
* - the injector changed.
*/
_shouldRecreateView(changes) {
return !!changes["ngTemplateOutlet"] || !!changes["ngTemplateOutletInjector"];
}
/**
* For a given outlet instance, we create a proxy object that delegates
* to the user-specified context. This allows changing, or swapping out
* the context object completely without having to destroy/re-create the view.
*/
_createContextForwardProxy() {
return new Proxy({}, {
set: (_target, prop, newValue) => {
if (!this.ngTemplateOutletContext) {
return false;
}
return Reflect.set(this.ngTemplateOutletContext, prop, newValue);
},
get: (_target, prop, receiver) => {
if (!this.ngTemplateOutletContext) {
return void 0;
}
return Reflect.get(this.ngTemplateOutletContext, prop, receiver);
}
});
}
static \u0275fac = function NgTemplateOutlet_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgTemplateOutlet)(\u0275\u0275directiveInject(ViewContainerRef));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgTemplateOutlet,
selectors: [["", "ngTemplateOutlet", ""]],
inputs: {
ngTemplateOutletContext: "ngTemplateOutletContext",
ngTemplateOutlet: "ngTemplateOutlet",
ngTemplateOutletInjector: "ngTemplateOutletInjector"
},
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgTemplateOutlet, [{
type: Directive,
args: [{
selector: "[ngTemplateOutlet]"
}]
}], () => [{
type: ViewContainerRef
}], {
ngTemplateOutletContext: [{
type: Input
}],
ngTemplateOutlet: [{
type: Input
}],
ngTemplateOutletInjector: [{
type: Input
}]
});
})();
var COMMON_DIRECTIVES = [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase];
function invalidPipeArgumentError(type, value) {
return new RuntimeError(2100, ngDevMode && `InvalidPipeArgument: '${value}' for pipe '${stringify(type)}'`);
}
var SubscribableStrategy = class {
createSubscription(async, updateLatestValue) {
return untracked(() => async.subscribe({
next: updateLatestValue,
error: (e) => {
throw e;
}
}));
}
dispose(subscription) {
untracked(() => subscription.unsubscribe());
}
};
var PromiseStrategy = class {
createSubscription(async, updateLatestValue) {
async.then(
// Using optional chaining because we may have set it to `null`; since the promise
// is async, the view might be destroyed by the time the promise resolves.
(v) => updateLatestValue?.(v),
(e) => {
throw e;
}
);
return {
unsubscribe: () => {
updateLatestValue = null;
}
};
}
dispose(subscription) {
subscription.unsubscribe();
}
};
var _promiseStrategy = new PromiseStrategy();
var _subscribableStrategy = new SubscribableStrategy();
var AsyncPipe = class _AsyncPipe {
_ref;
_latestValue = null;
markForCheckOnValueUpdate = true;
_subscription = null;
_obj = null;
_strategy = null;
constructor(ref) {
this._ref = ref;
}
ngOnDestroy() {
if (this._subscription) {
this._dispose();
}
this._ref = null;
}
transform(obj) {
if (!this._obj) {
if (obj) {
try {
this.markForCheckOnValueUpdate = false;
this._subscribe(obj);
} finally {
this.markForCheckOnValueUpdate = true;
}
}
return this._latestValue;
}
if (obj !== this._obj) {
this._dispose();
return this.transform(obj);
}
return this._latestValue;
}
_subscribe(obj) {
this._obj = obj;
this._strategy = this._selectStrategy(obj);
this._subscription = this._strategy.createSubscription(obj, (value) => this._updateLatestValue(obj, value));
}
_selectStrategy(obj) {
if (isPromise(obj)) {
return _promiseStrategy;
}
if (isSubscribable(obj)) {
return _subscribableStrategy;
}
throw invalidPipeArgumentError(_AsyncPipe, obj);
}
_dispose() {
this._strategy.dispose(this._subscription);
this._latestValue = null;
this._subscription = null;
this._obj = null;
}
_updateLatestValue(async, value) {
if (async === this._obj) {
this._latestValue = value;
if (this.markForCheckOnValueUpdate) {
this._ref?.markForCheck();
}
}
}
static \u0275fac = function AsyncPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AsyncPipe)(\u0275\u0275directiveInject(ChangeDetectorRef, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "async",
type: _AsyncPipe,
pure: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AsyncPipe, [{
type: Pipe,
args: [{
name: "async",
pure: false
}]
}], () => [{
type: ChangeDetectorRef
}], null);
})();
var LowerCasePipe = class _LowerCasePipe {
transform(value) {
if (value == null) return null;
if (typeof value !== "string") {
throw invalidPipeArgumentError(_LowerCasePipe, value);
}
return value.toLowerCase();
}
static \u0275fac = function LowerCasePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _LowerCasePipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "lowercase",
type: _LowerCasePipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(LowerCasePipe, [{
type: Pipe,
args: [{
name: "lowercase"
}]
}], null, null);
})();
var unicodeWordMatch = /(?:[0-9A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])\S*/g;
var TitleCasePipe = class _TitleCasePipe {
transform(value) {
if (value == null) return null;
if (typeof value !== "string") {
throw invalidPipeArgumentError(_TitleCasePipe, value);
}
return value.replace(unicodeWordMatch, (txt) => txt[0].toUpperCase() + txt.slice(1).toLowerCase());
}
static \u0275fac = function TitleCasePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TitleCasePipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "titlecase",
type: _TitleCasePipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TitleCasePipe, [{
type: Pipe,
args: [{
name: "titlecase"
}]
}], null, null);
})();
var UpperCasePipe = class _UpperCasePipe {
transform(value) {
if (value == null) return null;
if (typeof value !== "string") {
throw invalidPipeArgumentError(_UpperCasePipe, value);
}
return value.toUpperCase();
}
static \u0275fac = function UpperCasePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _UpperCasePipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "uppercase",
type: _UpperCasePipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(UpperCasePipe, [{
type: Pipe,
args: [{
name: "uppercase"
}]
}], null, null);
})();
var DEFAULT_DATE_FORMAT = "mediumDate";
var DATE_PIPE_DEFAULT_TIMEZONE = new InjectionToken(ngDevMode ? "DATE_PIPE_DEFAULT_TIMEZONE" : "");
var DATE_PIPE_DEFAULT_OPTIONS = new InjectionToken(ngDevMode ? "DATE_PIPE_DEFAULT_OPTIONS" : "");
var DatePipe = class _DatePipe {
locale;
defaultTimezone;
defaultOptions;
constructor(locale, defaultTimezone, defaultOptions) {
this.locale = locale;
this.defaultTimezone = defaultTimezone;
this.defaultOptions = defaultOptions;
}
transform(value, format, timezone, locale) {
if (value == null || value === "" || value !== value) return null;
try {
const _format = format ?? this.defaultOptions?.dateFormat ?? DEFAULT_DATE_FORMAT;
const _timezone = timezone ?? this.defaultOptions?.timezone ?? this.defaultTimezone ?? void 0;
return formatDate(value, _format, locale || this.locale, _timezone);
} catch (error) {
throw invalidPipeArgumentError(_DatePipe, error.message);
}
}
static \u0275fac = function DatePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DatePipe)(\u0275\u0275directiveInject(LOCALE_ID, 16), \u0275\u0275directiveInject(DATE_PIPE_DEFAULT_TIMEZONE, 24), \u0275\u0275directiveInject(DATE_PIPE_DEFAULT_OPTIONS, 24));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "date",
type: _DatePipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DatePipe, [{
type: Pipe,
args: [{
name: "date"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [LOCALE_ID]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [DATE_PIPE_DEFAULT_TIMEZONE]
}, {
type: Optional
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [DATE_PIPE_DEFAULT_OPTIONS]
}, {
type: Optional
}]
}], null);
})();
var _INTERPOLATION_REGEXP = /#/g;
var I18nPluralPipe = class _I18nPluralPipe {
_localization;
constructor(_localization) {
this._localization = _localization;
}
/**
* @param value the number to be formatted
* @param pluralMap an object that mimics the ICU format, see
* https://unicode-org.github.io/icu/userguide/format_parse/messages/.
* @param locale a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
* default).
*/
transform(value, pluralMap, locale) {
if (value == null) return "";
if (typeof pluralMap !== "object" || pluralMap === null) {
throw invalidPipeArgumentError(_I18nPluralPipe, pluralMap);
}
const key = getPluralCategory(value, Object.keys(pluralMap), this._localization, locale);
return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString());
}
static \u0275fac = function I18nPluralPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _I18nPluralPipe)(\u0275\u0275directiveInject(NgLocalization, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "i18nPlural",
type: _I18nPluralPipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(I18nPluralPipe, [{
type: Pipe,
args: [{
name: "i18nPlural"
}]
}], () => [{
type: NgLocalization
}], null);
})();
var I18nSelectPipe = class _I18nSelectPipe {
/**
* @param value a string to be internationalized.
* @param mapping an object that indicates the text that should be displayed
* for different values of the provided `value`.
*/
transform(value, mapping) {
if (value == null) return "";
if (typeof mapping !== "object" || typeof value !== "string") {
throw invalidPipeArgumentError(_I18nSelectPipe, mapping);
}
if (mapping.hasOwnProperty(value)) {
return mapping[value];
}
if (mapping.hasOwnProperty("other")) {
return mapping["other"];
}
return "";
}
static \u0275fac = function I18nSelectPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _I18nSelectPipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "i18nSelect",
type: _I18nSelectPipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(I18nSelectPipe, [{
type: Pipe,
args: [{
name: "i18nSelect"
}]
}], null, null);
})();
var JsonPipe = class _JsonPipe {
/**
* @param value A value of any type to convert into a JSON-format string.
*/
transform(value) {
return JSON.stringify(value, null, 2);
}
static \u0275fac = function JsonPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _JsonPipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "json",
type: _JsonPipe,
pure: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(JsonPipe, [{
type: Pipe,
args: [{
name: "json",
pure: false
}]
}], null, null);
})();
function makeKeyValuePair(key, value) {
return {
key,
value
};
}
var KeyValuePipe = class _KeyValuePipe {
differs;
constructor(differs) {
this.differs = differs;
}
differ;
keyValues = [];
compareFn = defaultComparator;
transform(input2, compareFn = defaultComparator) {
if (!input2 || !(input2 instanceof Map) && typeof input2 !== "object") {
return null;
}
this.differ ??= this.differs.find(input2).create();
const differChanges = this.differ.diff(input2);
const compareFnChanged = compareFn !== this.compareFn;
if (differChanges) {
this.keyValues = [];
differChanges.forEachItem((r) => {
this.keyValues.push(makeKeyValuePair(r.key, r.currentValue));
});
}
if (differChanges || compareFnChanged) {
if (compareFn) {
this.keyValues.sort(compareFn);
}
this.compareFn = compareFn;
}
return this.keyValues;
}
static \u0275fac = function KeyValuePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _KeyValuePipe)(\u0275\u0275directiveInject(KeyValueDiffers, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "keyvalue",
type: _KeyValuePipe,
pure: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(KeyValuePipe, [{
type: Pipe,
args: [{
name: "keyvalue",
pure: false
}]
}], () => [{
type: KeyValueDiffers
}], null);
})();
function defaultComparator(keyValueA, keyValueB) {
const a = keyValueA.key;
const b = keyValueB.key;
if (a === b) return 0;
if (a == null) return 1;
if (b == null) return -1;
if (typeof a == "string" && typeof b == "string") {
return a < b ? -1 : 1;
}
if (typeof a == "number" && typeof b == "number") {
return a - b;
}
if (typeof a == "boolean" && typeof b == "boolean") {
return a < b ? -1 : 1;
}
const aString = String(a);
const bString = String(b);
return aString == bString ? 0 : aString < bString ? -1 : 1;
}
var DecimalPipe = class _DecimalPipe {
_locale;
constructor(_locale) {
this._locale = _locale;
}
transform(value, digitsInfo, locale) {
if (!isValue(value)) return null;
locale ||= this._locale;
try {
const num = strToNumber(value);
return formatNumber(num, locale, digitsInfo);
} catch (error) {
throw invalidPipeArgumentError(_DecimalPipe, error.message);
}
}
static \u0275fac = function DecimalPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DecimalPipe)(\u0275\u0275directiveInject(LOCALE_ID, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "number",
type: _DecimalPipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DecimalPipe, [{
type: Pipe,
args: [{
name: "number"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [LOCALE_ID]
}]
}], null);
})();
var PercentPipe = class _PercentPipe {
_locale;
constructor(_locale) {
this._locale = _locale;
}
/**
*
* @param value The number to be formatted as a percentage.
* @param digitsInfo Decimal representation options, specified by a string
* in the following format:<br>
* <code>{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}</code>.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `0`.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n/locale-id).
*/
transform(value, digitsInfo, locale) {
if (!isValue(value)) return null;
locale ||= this._locale;
try {
const num = strToNumber(value);
return formatPercent(num, locale, digitsInfo);
} catch (error) {
throw invalidPipeArgumentError(_PercentPipe, error.message);
}
}
static \u0275fac = function PercentPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PercentPipe)(\u0275\u0275directiveInject(LOCALE_ID, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "percent",
type: _PercentPipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PercentPipe, [{
type: Pipe,
args: [{
name: "percent"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [LOCALE_ID]
}]
}], null);
})();
var CurrencyPipe = class _CurrencyPipe {
_locale;
_defaultCurrencyCode;
constructor(_locale, _defaultCurrencyCode = "USD") {
this._locale = _locale;
this._defaultCurrencyCode = _defaultCurrencyCode;
}
transform(value, currencyCode = this._defaultCurrencyCode, display = "symbol", digitsInfo, locale) {
if (!isValue(value)) return null;
locale ||= this._locale;
if (typeof display === "boolean") {
if ((typeof ngDevMode === "undefined" || ngDevMode) && console && console.warn) {
console.warn(`Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".`);
}
display = display ? "symbol" : "code";
}
let currency = currencyCode || this._defaultCurrencyCode;
if (display !== "code") {
if (display === "symbol" || display === "symbol-narrow") {
currency = getCurrencySymbol(currency, display === "symbol" ? "wide" : "narrow", locale);
} else {
currency = display;
}
}
try {
const num = strToNumber(value);
return formatCurrency(num, locale, currency, currencyCode, digitsInfo);
} catch (error) {
throw invalidPipeArgumentError(_CurrencyPipe, error.message);
}
}
static \u0275fac = function CurrencyPipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CurrencyPipe)(\u0275\u0275directiveInject(LOCALE_ID, 16), \u0275\u0275directiveInject(DEFAULT_CURRENCY_CODE, 16));
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "currency",
type: _CurrencyPipe,
pure: true
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CurrencyPipe, [{
type: Pipe,
args: [{
name: "currency"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [LOCALE_ID]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [DEFAULT_CURRENCY_CODE]
}]
}], null);
})();
function isValue(value) {
return !(value == null || value === "" || value !== value);
}
function strToNumber(value) {
if (typeof value === "string" && !isNaN(Number(value) - parseFloat(value))) {
return Number(value);
}
if (typeof value !== "number") {
throw new Error(`${value} is not a number`);
}
return value;
}
var SlicePipe = class _SlicePipe {
transform(value, start, end) {
if (value == null) return null;
const supports = typeof value === "string" || Array.isArray(value);
if (!supports) {
throw invalidPipeArgumentError(_SlicePipe, value);
}
return value.slice(start, end);
}
static \u0275fac = function SlicePipe_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _SlicePipe)();
};
static \u0275pipe = /* @__PURE__ */ \u0275\u0275definePipe({
name: "slice",
type: _SlicePipe,
pure: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SlicePipe, [{
type: Pipe,
args: [{
name: "slice",
pure: false
}]
}], null, null);
})();
var COMMON_PIPES = [AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe];
var CommonModule = class _CommonModule {
static \u0275fac = function CommonModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CommonModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _CommonModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CommonModule, [{
type: NgModule,
args: [{
imports: [COMMON_DIRECTIVES, COMMON_PIPES],
exports: [COMMON_DIRECTIVES, COMMON_PIPES]
}]
}], null, null);
})();
// node_modules/@angular/common/fesm2022/xhr-BfNfxNDv.mjs
function parseCookieValue(cookieStr, name) {
name = encodeURIComponent(name);
for (const cookie of cookieStr.split(";")) {
const eqIndex = cookie.indexOf("=");
const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ""] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];
if (cookieName.trim() === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
var PLATFORM_BROWSER_ID = "browser";
var PLATFORM_SERVER_ID = "server";
function isPlatformBrowser(platformId) {
return platformId === PLATFORM_BROWSER_ID;
}
function isPlatformServer(platformId) {
return platformId === PLATFORM_SERVER_ID;
}
var XhrFactory = class {
};
// node_modules/@angular/common/fesm2022/common.mjs
var VERSION2 = new Version("19.2.11");
var ViewportScroller = class _ViewportScroller {
// De-sugared tree-shakable injection
// See #23917
/** @nocollapse */
static \u0275prov = (
/** @pureOrBreakMyCode */
/* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ViewportScroller,
providedIn: "root",
factory: () => false ? new NullViewportScroller() : new BrowserViewportScroller(inject(DOCUMENT), window)
})
);
};
var BrowserViewportScroller = class {
document;
window;
offset = () => [0, 0];
constructor(document2, window2) {
this.document = document2;
this.window = window2;
}
/**
* Configures the top offset used when scrolling to an anchor.
* @param offset A position in screen coordinates (a tuple with x and y values)
* or a function that returns the top offset position.
*
*/
setOffset(offset) {
if (Array.isArray(offset)) {
this.offset = () => offset;
} else {
this.offset = offset;
}
}
/**
* Retrieves the current scroll position.
* @returns The position in screen coordinates.
*/
getScrollPosition() {
return [this.window.scrollX, this.window.scrollY];
}
/**
* Sets the scroll position.
* @param position The new position in screen coordinates.
*/
scrollToPosition(position) {
this.window.scrollTo(position[0], position[1]);
}
/**
* Scrolls to an element and attempts to focus the element.
*
* Note that the function name here is misleading in that the target string may be an ID for a
* non-anchor element.
*
* @param target The ID of an element or name of the anchor.
*
* @see https://html.spec.whatwg.org/#the-indicated-part-of-the-document
* @see https://html.spec.whatwg.org/#scroll-to-fragid
*/
scrollToAnchor(target) {
const elSelected = findAnchorFromDocument(this.document, target);
if (elSelected) {
this.scrollToElement(elSelected);
elSelected.focus();
}
}
/**
* Disables automatic scroll restoration provided by the browser.
*/
setHistoryScrollRestoration(scrollRestoration) {
this.window.history.scrollRestoration = scrollRestoration;
}
/**
* Scrolls to an element using the native offset and the specified offset set on this scroller.
*
* The offset can be used when we know that there is a floating header and scrolling naively to an
* element (ex: `scrollIntoView`) leaves the element hidden behind the floating header.
*/
scrollToElement(el) {
const rect = el.getBoundingClientRect();
const left = rect.left + this.window.pageXOffset;
const top = rect.top + this.window.pageYOffset;
const offset = this.offset();
this.window.scrollTo(left - offset[0], top - offset[1]);
}
};
function findAnchorFromDocument(document2, target) {
const documentResult = document2.getElementById(target) || document2.getElementsByName(target)[0];
if (documentResult) {
return documentResult;
}
if (typeof document2.createTreeWalker === "function" && document2.body && typeof document2.body.attachShadow === "function") {
const treeWalker = document2.createTreeWalker(document2.body, NodeFilter.SHOW_ELEMENT);
let currentNode = treeWalker.currentNode;
while (currentNode) {
const shadowRoot = currentNode.shadowRoot;
if (shadowRoot) {
const result = shadowRoot.getElementById(target) || shadowRoot.querySelector(`[name="${target}"]`);
if (result) {
return result;
}
}
currentNode = treeWalker.nextNode();
}
}
return null;
}
var PLACEHOLDER_QUALITY = "20";
function getUrl(src, win) {
return isAbsoluteUrl(src) ? new URL(src) : new URL(src, win.location.href);
}
function isAbsoluteUrl(src) {
return /^https?:\/\//.test(src);
}
function extractHostname(url) {
return isAbsoluteUrl(url) ? new URL(url).hostname : url;
}
function isValidPath(path) {
const isString = typeof path === "string";
if (!isString || path.trim() === "") {
return false;
}
try {
const url = new URL(path);
return true;
} catch {
return false;
}
}
function normalizePath(path) {
return path.endsWith("/") ? path.slice(0, -1) : path;
}
function normalizeSrc(src) {
return src.startsWith("/") ? src.slice(1) : src;
}
var noopImageLoader = (config) => config.src;
var IMAGE_LOADER = new InjectionToken(ngDevMode ? "ImageLoader" : "", {
providedIn: "root",
factory: () => noopImageLoader
});
function createImageLoader(buildUrlFn, exampleUrls) {
return function provideImageLoader(path) {
if (!isValidPath(path)) {
throwInvalidPathError(path, exampleUrls || []);
}
path = normalizePath(path);
const loaderFn = (config) => {
if (isAbsoluteUrl(config.src)) {
throwUnexpectedAbsoluteUrlError(path, config.src);
}
return buildUrlFn(path, __spreadProps(__spreadValues({}, config), {
src: normalizeSrc(config.src)
}));
};
const providers = [{
provide: IMAGE_LOADER,
useValue: loaderFn
}];
return providers;
};
}
function throwInvalidPathError(path, exampleUrls) {
throw new RuntimeError(2959, ngDevMode && `Image loader has detected an invalid path (\`${path}\`). To fix this, supply a path using one of the following formats: ${exampleUrls.join(" or ")}`);
}
function throwUnexpectedAbsoluteUrlError(path, url) {
throw new RuntimeError(2959, ngDevMode && `Image loader has detected a \`<img>\` tag with an invalid \`ngSrc\` attribute: ${url}. This image loader expects \`ngSrc\` to be a relative URL - however the provided value is an absolute URL. To fix this, provide \`ngSrc\` as a path relative to the base URL configured for this loader (\`${path}\`).`);
}
var provideCloudflareLoader = createImageLoader(createCloudflareUrl, ngDevMode ? ["https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>"] : void 0);
function createCloudflareUrl(path, config) {
let params = `format=auto`;
if (config.width) {
params += `,width=${config.width}`;
}
if (config.isPlaceholder) {
params += `,quality=${PLACEHOLDER_QUALITY}`;
}
return `${path}/cdn-cgi/image/${params}/${config.src}`;
}
var cloudinaryLoaderInfo = {
name: "Cloudinary",
testUrl: isCloudinaryUrl
};
var CLOUDINARY_LOADER_REGEX = /https?\:\/\/[^\/]+\.cloudinary\.com\/.+/;
function isCloudinaryUrl(url) {
return CLOUDINARY_LOADER_REGEX.test(url);
}
var provideCloudinaryLoader = createImageLoader(createCloudinaryUrl, ngDevMode ? ["https://res.cloudinary.com/mysite", "https://mysite.cloudinary.com", "https://subdomain.mysite.com"] : void 0);
function createCloudinaryUrl(path, config) {
const quality = config.isPlaceholder ? "q_auto:low" : "q_auto";
let params = `f_auto,${quality}`;
if (config.width) {
params += `,w_${config.width}`;
}
if (config.loaderParams?.["rounded"]) {
params += `,r_max`;
}
return `${path}/image/upload/${params}/${config.src}`;
}
var imageKitLoaderInfo = {
name: "ImageKit",
testUrl: isImageKitUrl
};
var IMAGE_KIT_LOADER_REGEX = /https?\:\/\/[^\/]+\.imagekit\.io\/.+/;
function isImageKitUrl(url) {
return IMAGE_KIT_LOADER_REGEX.test(url);
}
var provideImageKitLoader = createImageLoader(createImagekitUrl, ngDevMode ? ["https://ik.imagekit.io/mysite", "https://subdomain.mysite.com"] : void 0);
function createImagekitUrl(path, config) {
const {
src,
width
} = config;
const params = [];
if (width) {
params.push(`w-${width}`);
}
if (config.isPlaceholder) {
params.push(`q-${PLACEHOLDER_QUALITY}`);
}
const urlSegments = params.length ? [path, `tr:${params.join(",")}`, src] : [path, src];
const url = new URL(urlSegments.join("/"));
return url.href;
}
var imgixLoaderInfo = {
name: "Imgix",
testUrl: isImgixUrl
};
var IMGIX_LOADER_REGEX = /https?\:\/\/[^\/]+\.imgix\.net\/.+/;
function isImgixUrl(url) {
return IMGIX_LOADER_REGEX.test(url);
}
var provideImgixLoader = createImageLoader(createImgixUrl, ngDevMode ? ["https://somepath.imgix.net/"] : void 0);
function createImgixUrl(path, config) {
const url = new URL(`${path}/${config.src}`);
url.searchParams.set("auto", "format");
if (config.width) {
url.searchParams.set("w", config.width.toString());
}
if (config.isPlaceholder) {
url.searchParams.set("q", PLACEHOLDER_QUALITY);
}
return url.href;
}
var netlifyLoaderInfo = {
name: "Netlify",
testUrl: isNetlifyUrl
};
var NETLIFY_LOADER_REGEX = /https?\:\/\/[^\/]+\.netlify\.app\/.+/;
function isNetlifyUrl(url) {
return NETLIFY_LOADER_REGEX.test(url);
}
function imgDirectiveDetails(ngSrc, includeNgSrc = true) {
const ngSrcInfo = includeNgSrc ? `(activated on an <img> element with the \`ngSrc="${ngSrc}"\`) ` : "";
return `The NgOptimizedImage directive ${ngSrcInfo}has detected that`;
}
function assertDevMode(checkName) {
if (!ngDevMode) {
throw new RuntimeError(2958, `Unexpected invocation of the ${checkName} in the prod mode. Please make sure that the prod mode is enabled for production builds.`);
}
}
var LCPImageObserver = class _LCPImageObserver {
// Map of full image URLs -> original `ngSrc` values.
images = /* @__PURE__ */ new Map();
window = null;
observer = null;
constructor() {
const isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
assertDevMode("LCP checker");
const win = inject(DOCUMENT).defaultView;
if (isBrowser && typeof PerformanceObserver !== "undefined") {
this.window = win;
this.observer = this.initPerformanceObserver();
}
}
/**
* Inits PerformanceObserver and subscribes to LCP events.
* Based on https://web.dev/lcp/#measure-lcp-in-javascript
*/
initPerformanceObserver() {
const observer = new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
if (entries.length === 0) return;
const lcpElement = entries[entries.length - 1];
const imgSrc = lcpElement.element?.src ?? "";
if (imgSrc.startsWith("data:") || imgSrc.startsWith("blob:")) return;
const img = this.images.get(imgSrc);
if (!img) return;
if (!img.priority && !img.alreadyWarnedPriority) {
img.alreadyWarnedPriority = true;
logMissingPriorityError(imgSrc);
}
if (img.modified && !img.alreadyWarnedModified) {
img.alreadyWarnedModified = true;
logModifiedWarning(imgSrc);
}
});
observer.observe({
type: "largest-contentful-paint",
buffered: true
});
return observer;
}
registerImage(rewrittenSrc, originalNgSrc, isPriority) {
if (!this.observer) return;
const newObservedImageState = {
priority: isPriority,
modified: false,
alreadyWarnedModified: false,
alreadyWarnedPriority: false
};
this.images.set(getUrl(rewrittenSrc, this.window).href, newObservedImageState);
}
unregisterImage(rewrittenSrc) {
if (!this.observer) return;
this.images.delete(getUrl(rewrittenSrc, this.window).href);
}
updateImage(originalSrc, newSrc) {
if (!this.observer) return;
const originalUrl = getUrl(originalSrc, this.window).href;
const img = this.images.get(originalUrl);
if (img) {
img.modified = true;
this.images.set(getUrl(newSrc, this.window).href, img);
this.images.delete(originalUrl);
}
}
ngOnDestroy() {
if (!this.observer) return;
this.observer.disconnect();
this.images.clear();
}
static \u0275fac = function LCPImageObserver_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _LCPImageObserver)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _LCPImageObserver,
factory: _LCPImageObserver.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(LCPImageObserver, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function logMissingPriorityError(ngSrc) {
const directiveDetails = imgDirectiveDetails(ngSrc);
console.error(formatRuntimeError(2955, `${directiveDetails} this image is the Largest Contentful Paint (LCP) element but was not marked "priority". This image should be marked "priority" in order to prioritize its loading. To fix this, add the "priority" attribute.`));
}
function logModifiedWarning(ngSrc) {
const directiveDetails = imgDirectiveDetails(ngSrc);
console.warn(formatRuntimeError(2964, `${directiveDetails} this image is the Largest Contentful Paint (LCP) element and has had its "ngSrc" attribute modified. This can cause slower loading performance. It is recommended not to modify the "ngSrc" property on any image which could be the LCP element.`));
}
var INTERNAL_PRECONNECT_CHECK_BLOCKLIST = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0"]);
var PRECONNECT_CHECK_BLOCKLIST = new InjectionToken(ngDevMode ? "PRECONNECT_CHECK_BLOCKLIST" : "");
var PreconnectLinkChecker = class _PreconnectLinkChecker {
document = inject(DOCUMENT);
/**
* Set of <link rel="preconnect"> tags found on this page.
* The `null` value indicates that there was no DOM query operation performed.
*/
preconnectLinks = null;
/*
* Keep track of all already seen origin URLs to avoid repeating the same check.
*/
alreadySeen = /* @__PURE__ */ new Set();
window = this.document.defaultView;
blocklist = new Set(INTERNAL_PRECONNECT_CHECK_BLOCKLIST);
constructor() {
assertDevMode("preconnect link checker");
const blocklist = inject(PRECONNECT_CHECK_BLOCKLIST, {
optional: true
});
if (blocklist) {
this.populateBlocklist(blocklist);
}
}
populateBlocklist(origins) {
if (Array.isArray(origins)) {
deepForEach(origins, (origin) => {
this.blocklist.add(extractHostname(origin));
});
} else {
this.blocklist.add(extractHostname(origins));
}
}
/**
* Checks that a preconnect resource hint exists in the head for the
* given src.
*
* @param rewrittenSrc src formatted with loader
* @param originalNgSrc ngSrc value
*/
assertPreconnect(rewrittenSrc, originalNgSrc) {
if (false) return;
const imgUrl = getUrl(rewrittenSrc, this.window);
if (this.blocklist.has(imgUrl.hostname) || this.alreadySeen.has(imgUrl.origin)) return;
this.alreadySeen.add(imgUrl.origin);
this.preconnectLinks ??= this.queryPreconnectLinks();
if (!this.preconnectLinks.has(imgUrl.origin)) {
console.warn(formatRuntimeError(2956, `${imgDirectiveDetails(originalNgSrc)} there is no preconnect tag present for this image. Preconnecting to the origin(s) that serve priority images ensures that these images are delivered as soon as possible. To fix this, please add the following element into the <head> of the document:
<link rel="preconnect" href="${imgUrl.origin}">`));
}
}
queryPreconnectLinks() {
const preconnectUrls = /* @__PURE__ */ new Set();
const links = this.document.querySelectorAll("link[rel=preconnect]");
for (const link of links) {
const url = getUrl(link.href, this.window);
preconnectUrls.add(url.origin);
}
return preconnectUrls;
}
ngOnDestroy() {
this.preconnectLinks?.clear();
this.alreadySeen.clear();
}
static \u0275fac = function PreconnectLinkChecker_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PreconnectLinkChecker)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _PreconnectLinkChecker,
factory: _PreconnectLinkChecker.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PreconnectLinkChecker, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function deepForEach(input2, fn) {
for (let value of input2) {
Array.isArray(value) ? deepForEach(value, fn) : fn(value);
}
}
var DEFAULT_PRELOADED_IMAGES_LIMIT = 5;
var PRELOADED_IMAGES = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "NG_OPTIMIZED_PRELOADED_IMAGES" : "", {
providedIn: "root",
factory: () => /* @__PURE__ */ new Set()
});
var PreloadLinkCreator = class _PreloadLinkCreator {
preloadedImages = inject(PRELOADED_IMAGES);
document = inject(DOCUMENT);
errorShown = false;
/**
* @description Add a preload `<link>` to the `<head>` of the `index.html` that is served from the
* server while using Angular Universal and SSR to kick off image loads for high priority images.
*
* The `sizes` (passed in from the user) and `srcset` (parsed and formatted from `ngSrcset`)
* properties used to set the corresponding attributes, `imagesizes` and `imagesrcset`
* respectively, on the preload `<link>` tag so that the correctly sized image is preloaded from
* the CDN.
*
* {@link https://web.dev/preload-responsive-images/#imagesrcset-and-imagesizes}
*
* @param renderer The `Renderer2` passed in from the directive
* @param src The original src of the image that is set on the `ngSrc` input.
* @param srcset The parsed and formatted srcset created from the `ngSrcset` input
* @param sizes The value of the `sizes` attribute passed in to the `<img>` tag
*/
createPreloadLinkTag(renderer, src, srcset, sizes) {
if (ngDevMode && !this.errorShown && this.preloadedImages.size >= DEFAULT_PRELOADED_IMAGES_LIMIT) {
this.errorShown = true;
console.warn(formatRuntimeError(2961, `The \`NgOptimizedImage\` directive has detected that more than ${DEFAULT_PRELOADED_IMAGES_LIMIT} images were marked as priority. This might negatively affect an overall performance of the page. To fix this, remove the "priority" attribute from images with less priority.`));
}
if (this.preloadedImages.has(src)) {
return;
}
this.preloadedImages.add(src);
const preload = renderer.createElement("link");
renderer.setAttribute(preload, "as", "image");
renderer.setAttribute(preload, "href", src);
renderer.setAttribute(preload, "rel", "preload");
renderer.setAttribute(preload, "fetchpriority", "high");
if (sizes) {
renderer.setAttribute(preload, "imageSizes", sizes);
}
if (srcset) {
renderer.setAttribute(preload, "imageSrcset", srcset);
}
renderer.appendChild(this.document.head, preload);
}
static \u0275fac = function PreloadLinkCreator_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PreloadLinkCreator)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _PreloadLinkCreator,
factory: _PreloadLinkCreator.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PreloadLinkCreator, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var BASE64_IMG_MAX_LENGTH_IN_ERROR = 50;
var VALID_WIDTH_DESCRIPTOR_SRCSET = /^((\s*\d+w\s*(,|$)){1,})$/;
var VALID_DENSITY_DESCRIPTOR_SRCSET = /^((\s*\d+(\.\d+)?x\s*(,|$)){1,})$/;
var ABSOLUTE_SRCSET_DENSITY_CAP = 3;
var RECOMMENDED_SRCSET_DENSITY_CAP = 2;
var DENSITY_SRCSET_MULTIPLIERS = [1, 2];
var VIEWPORT_BREAKPOINT_CUTOFF = 640;
var ASPECT_RATIO_TOLERANCE = 0.1;
var OVERSIZED_IMAGE_TOLERANCE = 1e3;
var FIXED_SRCSET_WIDTH_LIMIT = 1920;
var FIXED_SRCSET_HEIGHT_LIMIT = 1080;
var PLACEHOLDER_BLUR_AMOUNT = 15;
var PLACEHOLDER_DIMENSION_LIMIT = 1e3;
var DATA_URL_WARN_LIMIT = 4e3;
var DATA_URL_ERROR_LIMIT = 1e4;
var BUILT_IN_LOADERS = [imgixLoaderInfo, imageKitLoaderInfo, cloudinaryLoaderInfo, netlifyLoaderInfo];
var PRIORITY_COUNT_THRESHOLD = 10;
var IMGS_WITH_PRIORITY_ATTR_COUNT = 0;
var NgOptimizedImage = class _NgOptimizedImage {
imageLoader = inject(IMAGE_LOADER);
config = processConfig(inject(IMAGE_CONFIG));
renderer = inject(Renderer2);
imgElement = inject(ElementRef).nativeElement;
injector = inject(Injector);
// An LCP image observer should be injected only in development mode.
// Do not assign it to `null` to avoid having a redundant property in the production bundle.
lcpObserver;
/**
* Calculate the rewritten `src` once and store it.
* This is needed to avoid repetitive calculations and make sure the directive cleanup in the
* `ngOnDestroy` does not rely on the `IMAGE_LOADER` logic (which in turn can rely on some other
* instance that might be already destroyed).
*/
_renderedSrc = null;
/**
* Name of the source image.
* Image name will be processed by the image loader and the final URL will be applied as the `src`
* property of the image.
*/
ngSrc;
/**
* A comma separated list of width or density descriptors.
* The image name will be taken from `ngSrc` and combined with the list of width or density
* descriptors to generate the final `srcset` property of the image.
*
* Example:
* ```html
* <img ngSrc="hello.jpg" ngSrcset="100w, 200w" /> =>
* <img src="path/hello.jpg" srcset="path/hello.jpg?w=100 100w, path/hello.jpg?w=200 200w" />
* ```
*/
ngSrcset;
/**
* The base `sizes` attribute passed through to the `<img>` element.
* Providing sizes causes the image to create an automatic responsive srcset.
*/
sizes;
/**
* For responsive images: the intrinsic width of the image in pixels.
* For fixed size images: the desired rendered width of the image in pixels.
*/
width;
/**
* For responsive images: the intrinsic height of the image in pixels.
* For fixed size images: the desired rendered height of the image in pixels.
*/
height;
/**
* The desired loading behavior (lazy, eager, or auto). Defaults to `lazy`,
* which is recommended for most images.
*
* Warning: Setting images as loading="eager" or loading="auto" marks them
* as non-priority images and can hurt loading performance. For images which
* may be the LCP element, use the `priority` attribute instead of `loading`.
*/
loading;
/**
* Indicates whether this image should have a high priority.
*/
priority = false;
/**
* Data to pass through to custom loaders.
*/
loaderParams;
/**
* Disables automatic srcset generation for this image.
*/
disableOptimizedSrcset = false;
/**
* Sets the image to "fill mode", which eliminates the height/width requirement and adds
* styles such that the image fills its containing element.
*/
fill = false;
/**
* A URL or data URL for an image to be used as a placeholder while this image loads.
*/
placeholder;
/**
* Configuration object for placeholder settings. Options:
* * blur: Setting this to false disables the automatic CSS blur.
*/
placeholderConfig;
/**
* Value of the `src` attribute if set on the host `<img>` element.
* This input is exclusively read to assert that `src` is not set in conflict
* with `ngSrc` and that images don't start to load until a lazy loading strategy is set.
* @internal
*/
src;
/**
* Value of the `srcset` attribute if set on the host `<img>` element.
* This input is exclusively read to assert that `srcset` is not set in conflict
* with `ngSrcset` and that images don't start to load until a lazy loading strategy is set.
* @internal
*/
srcset;
constructor() {
if (ngDevMode) {
this.lcpObserver = this.injector.get(LCPImageObserver);
const destroyRef = inject(DestroyRef);
destroyRef.onDestroy(() => {
if (!this.priority && this._renderedSrc !== null) {
this.lcpObserver.unregisterImage(this._renderedSrc);
}
});
}
}
/** @docs-private */
ngOnInit() {
performanceMarkFeature("NgOptimizedImage");
if (ngDevMode) {
const ngZone = this.injector.get(NgZone);
assertNonEmptyInput(this, "ngSrc", this.ngSrc);
assertValidNgSrcset(this, this.ngSrcset);
assertNoConflictingSrc(this);
if (this.ngSrcset) {
assertNoConflictingSrcset(this);
}
assertNotBase64Image(this);
assertNotBlobUrl(this);
if (this.fill) {
assertEmptyWidthAndHeight(this);
ngZone.runOutsideAngular(() => assertNonZeroRenderedHeight(this, this.imgElement, this.renderer));
} else {
assertNonEmptyWidthAndHeight(this);
if (this.height !== void 0) {
assertGreaterThanZero(this, this.height, "height");
}
if (this.width !== void 0) {
assertGreaterThanZero(this, this.width, "width");
}
ngZone.runOutsideAngular(() => assertNoImageDistortion(this, this.imgElement, this.renderer));
}
assertValidLoadingInput(this);
if (!this.ngSrcset) {
assertNoComplexSizes(this);
}
assertValidPlaceholder(this, this.imageLoader);
assertNotMissingBuiltInLoader(this.ngSrc, this.imageLoader);
assertNoNgSrcsetWithoutLoader(this, this.imageLoader);
assertNoLoaderParamsWithoutLoader(this, this.imageLoader);
ngZone.runOutsideAngular(() => {
this.lcpObserver.registerImage(this.getRewrittenSrc(), this.ngSrc, this.priority);
});
if (this.priority) {
const checker = this.injector.get(PreconnectLinkChecker);
checker.assertPreconnect(this.getRewrittenSrc(), this.ngSrc);
if (true) {
const applicationRef = this.injector.get(ApplicationRef);
assetPriorityCountBelowThreshold(applicationRef);
}
}
}
if (this.placeholder) {
this.removePlaceholderOnLoad(this.imgElement);
}
this.setHostAttributes();
}
setHostAttributes() {
if (this.fill) {
this.sizes ||= "100vw";
} else {
this.setHostAttribute("width", this.width.toString());
this.setHostAttribute("height", this.height.toString());
}
this.setHostAttribute("loading", this.getLoadingBehavior());
this.setHostAttribute("fetchpriority", this.getFetchPriority());
this.setHostAttribute("ng-img", "true");
const rewrittenSrcset = this.updateSrcAndSrcset();
if (this.sizes) {
if (this.getLoadingBehavior() === "lazy") {
this.setHostAttribute("sizes", "auto, " + this.sizes);
} else {
this.setHostAttribute("sizes", this.sizes);
}
} else {
if (this.ngSrcset && VALID_WIDTH_DESCRIPTOR_SRCSET.test(this.ngSrcset) && this.getLoadingBehavior() === "lazy") {
this.setHostAttribute("sizes", "auto, 100vw");
}
}
if (false) {
const preloadLinkCreator = this.injector.get(PreloadLinkCreator);
preloadLinkCreator.createPreloadLinkTag(this.renderer, this.getRewrittenSrc(), rewrittenSrcset, this.sizes);
}
}
/** @docs-private */
ngOnChanges(changes) {
if (ngDevMode) {
assertNoPostInitInputChange(this, changes, ["ngSrcset", "width", "height", "priority", "fill", "loading", "sizes", "loaderParams", "disableOptimizedSrcset"]);
}
if (changes["ngSrc"] && !changes["ngSrc"].isFirstChange()) {
const oldSrc = this._renderedSrc;
this.updateSrcAndSrcset(true);
if (ngDevMode) {
const newSrc = this._renderedSrc;
if (oldSrc && newSrc && oldSrc !== newSrc) {
const ngZone = this.injector.get(NgZone);
ngZone.runOutsideAngular(() => {
this.lcpObserver.updateImage(oldSrc, newSrc);
});
}
}
}
if (ngDevMode && changes["placeholder"]?.currentValue && true && true) {
assertPlaceholderDimensions(this, this.imgElement);
}
}
callImageLoader(configWithoutCustomParams) {
let augmentedConfig = configWithoutCustomParams;
if (this.loaderParams) {
augmentedConfig.loaderParams = this.loaderParams;
}
return this.imageLoader(augmentedConfig);
}
getLoadingBehavior() {
if (!this.priority && this.loading !== void 0) {
return this.loading;
}
return this.priority ? "eager" : "lazy";
}
getFetchPriority() {
return this.priority ? "high" : "auto";
}
getRewrittenSrc() {
if (!this._renderedSrc) {
const imgConfig = {
src: this.ngSrc
};
this._renderedSrc = this.callImageLoader(imgConfig);
}
return this._renderedSrc;
}
getRewrittenSrcset() {
const widthSrcSet = VALID_WIDTH_DESCRIPTOR_SRCSET.test(this.ngSrcset);
const finalSrcs = this.ngSrcset.split(",").filter((src) => src !== "").map((srcStr) => {
srcStr = srcStr.trim();
const width = widthSrcSet ? parseFloat(srcStr) : parseFloat(srcStr) * this.width;
return `${this.callImageLoader({
src: this.ngSrc,
width
})} ${srcStr}`;
});
return finalSrcs.join(", ");
}
getAutomaticSrcset() {
if (this.sizes) {
return this.getResponsiveSrcset();
} else {
return this.getFixedSrcset();
}
}
getResponsiveSrcset() {
const {
breakpoints
} = this.config;
let filteredBreakpoints = breakpoints;
if (this.sizes?.trim() === "100vw") {
filteredBreakpoints = breakpoints.filter((bp) => bp >= VIEWPORT_BREAKPOINT_CUTOFF);
}
const finalSrcs = filteredBreakpoints.map((bp) => `${this.callImageLoader({
src: this.ngSrc,
width: bp
})} ${bp}w`);
return finalSrcs.join(", ");
}
updateSrcAndSrcset(forceSrcRecalc = false) {
if (forceSrcRecalc) {
this._renderedSrc = null;
}
const rewrittenSrc = this.getRewrittenSrc();
this.setHostAttribute("src", rewrittenSrc);
let rewrittenSrcset = void 0;
if (this.ngSrcset) {
rewrittenSrcset = this.getRewrittenSrcset();
} else if (this.shouldGenerateAutomaticSrcset()) {
rewrittenSrcset = this.getAutomaticSrcset();
}
if (rewrittenSrcset) {
this.setHostAttribute("srcset", rewrittenSrcset);
}
return rewrittenSrcset;
}
getFixedSrcset() {
const finalSrcs = DENSITY_SRCSET_MULTIPLIERS.map((multiplier) => `${this.callImageLoader({
src: this.ngSrc,
width: this.width * multiplier
})} ${multiplier}x`);
return finalSrcs.join(", ");
}
shouldGenerateAutomaticSrcset() {
let oversizedImage = false;
if (!this.sizes) {
oversizedImage = this.width > FIXED_SRCSET_WIDTH_LIMIT || this.height > FIXED_SRCSET_HEIGHT_LIMIT;
}
return !this.disableOptimizedSrcset && !this.srcset && this.imageLoader !== noopImageLoader && !oversizedImage;
}
/**
* Returns an image url formatted for use with the CSS background-image property. Expects one of:
* * A base64 encoded image, which is wrapped and passed through.
* * A boolean. If true, calls the image loader to generate a small placeholder url.
*/
generatePlaceholder(placeholderInput) {
const {
placeholderResolution
} = this.config;
if (placeholderInput === true) {
return `url(${this.callImageLoader({
src: this.ngSrc,
width: placeholderResolution,
isPlaceholder: true
})})`;
} else if (typeof placeholderInput === "string") {
return `url(${placeholderInput})`;
}
return null;
}
/**
* Determines if blur should be applied, based on an optional boolean
* property `blur` within the optional configuration object `placeholderConfig`.
*/
shouldBlurPlaceholder(placeholderConfig) {
if (!placeholderConfig || !placeholderConfig.hasOwnProperty("blur")) {
return true;
}
return Boolean(placeholderConfig.blur);
}
removePlaceholderOnLoad(img) {
const callback = () => {
const changeDetectorRef = this.injector.get(ChangeDetectorRef);
removeLoadListenerFn();
removeErrorListenerFn();
this.placeholder = false;
changeDetectorRef.markForCheck();
};
const removeLoadListenerFn = this.renderer.listen(img, "load", callback);
const removeErrorListenerFn = this.renderer.listen(img, "error", callback);
callOnLoadIfImageIsLoaded(img, callback);
}
setHostAttribute(name, value) {
this.renderer.setAttribute(this.imgElement, name, value);
}
static \u0275fac = function NgOptimizedImage_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgOptimizedImage)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgOptimizedImage,
selectors: [["img", "ngSrc", ""]],
hostVars: 18,
hostBindings: function NgOptimizedImage_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275styleProp("position", ctx.fill ? "absolute" : null)("width", ctx.fill ? "100%" : null)("height", ctx.fill ? "100%" : null)("inset", ctx.fill ? "0" : null)("background-size", ctx.placeholder ? "cover" : null)("background-position", ctx.placeholder ? "50% 50%" : null)("background-repeat", ctx.placeholder ? "no-repeat" : null)("background-image", ctx.placeholder ? ctx.generatePlaceholder(ctx.placeholder) : null)("filter", ctx.placeholder && ctx.shouldBlurPlaceholder(ctx.placeholderConfig) ? "blur(15px)" : null);
}
},
inputs: {
ngSrc: [2, "ngSrc", "ngSrc", unwrapSafeUrl],
ngSrcset: "ngSrcset",
sizes: "sizes",
width: [2, "width", "width", numberAttribute],
height: [2, "height", "height", numberAttribute],
loading: "loading",
priority: [2, "priority", "priority", booleanAttribute],
loaderParams: "loaderParams",
disableOptimizedSrcset: [2, "disableOptimizedSrcset", "disableOptimizedSrcset", booleanAttribute],
fill: [2, "fill", "fill", booleanAttribute],
placeholder: [2, "placeholder", "placeholder", booleanOrUrlAttribute],
placeholderConfig: "placeholderConfig",
src: "src",
srcset: "srcset"
},
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgOptimizedImage, [{
type: Directive,
args: [{
selector: "img[ngSrc]",
host: {
"[style.position]": 'fill ? "absolute" : null',
"[style.width]": 'fill ? "100%" : null',
"[style.height]": 'fill ? "100%" : null',
"[style.inset]": 'fill ? "0" : null',
"[style.background-size]": 'placeholder ? "cover" : null',
"[style.background-position]": 'placeholder ? "50% 50%" : null',
"[style.background-repeat]": 'placeholder ? "no-repeat" : null',
"[style.background-image]": "placeholder ? generatePlaceholder(placeholder) : null",
"[style.filter]": `placeholder && shouldBlurPlaceholder(placeholderConfig) ? "blur(${PLACEHOLDER_BLUR_AMOUNT}px)" : null`
}
}]
}], () => [], {
ngSrc: [{
type: Input,
args: [{
required: true,
transform: unwrapSafeUrl
}]
}],
ngSrcset: [{
type: Input
}],
sizes: [{
type: Input
}],
width: [{
type: Input,
args: [{
transform: numberAttribute
}]
}],
height: [{
type: Input,
args: [{
transform: numberAttribute
}]
}],
loading: [{
type: Input
}],
priority: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
loaderParams: [{
type: Input
}],
disableOptimizedSrcset: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
fill: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
placeholder: [{
type: Input,
args: [{
transform: booleanOrUrlAttribute
}]
}],
placeholderConfig: [{
type: Input
}],
src: [{
type: Input
}],
srcset: [{
type: Input
}]
});
})();
function processConfig(config) {
let sortedBreakpoints = {};
if (config.breakpoints) {
sortedBreakpoints.breakpoints = config.breakpoints.sort((a, b) => a - b);
}
return Object.assign({}, IMAGE_CONFIG_DEFAULTS, config, sortedBreakpoints);
}
function assertNoConflictingSrc(dir) {
if (dir.src) {
throw new RuntimeError(2950, `${imgDirectiveDetails(dir.ngSrc)} both \`src\` and \`ngSrc\` have been set. Supplying both of these attributes breaks lazy loading. The NgOptimizedImage directive sets \`src\` itself based on the value of \`ngSrc\`. To fix this, please remove the \`src\` attribute.`);
}
}
function assertNoConflictingSrcset(dir) {
if (dir.srcset) {
throw new RuntimeError(2951, `${imgDirectiveDetails(dir.ngSrc)} both \`srcset\` and \`ngSrcset\` have been set. Supplying both of these attributes breaks lazy loading. The NgOptimizedImage directive sets \`srcset\` itself based on the value of \`ngSrcset\`. To fix this, please remove the \`srcset\` attribute.`);
}
}
function assertNotBase64Image(dir) {
let ngSrc = dir.ngSrc.trim();
if (ngSrc.startsWith("data:")) {
if (ngSrc.length > BASE64_IMG_MAX_LENGTH_IN_ERROR) {
ngSrc = ngSrc.substring(0, BASE64_IMG_MAX_LENGTH_IN_ERROR) + "...";
}
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc, false)} \`ngSrc\` is a Base64-encoded string (${ngSrc}). NgOptimizedImage does not support Base64-encoded strings. To fix this, disable the NgOptimizedImage directive for this element by removing \`ngSrc\` and using a standard \`src\` attribute instead.`);
}
}
function assertNoComplexSizes(dir) {
let sizes = dir.sizes;
if (sizes?.match(/((\)|,)\s|^)\d+px/)) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc, false)} \`sizes\` was set to a string including pixel values. For automatic \`srcset\` generation, \`sizes\` must only include responsive values, such as \`sizes="50vw"\` or \`sizes="(min-width: 768px) 50vw, 100vw"\`. To fix this, modify the \`sizes\` attribute, or provide your own \`ngSrcset\` value directly.`);
}
}
function assertValidPlaceholder(dir, imageLoader) {
assertNoPlaceholderConfigWithoutPlaceholder(dir);
assertNoRelativePlaceholderWithoutLoader(dir, imageLoader);
assertNoOversizedDataUrl(dir);
}
function assertNoPlaceholderConfigWithoutPlaceholder(dir) {
if (dir.placeholderConfig && !dir.placeholder) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc, false)} \`placeholderConfig\` options were provided for an image that does not use the \`placeholder\` attribute, and will have no effect.`);
}
}
function assertNoRelativePlaceholderWithoutLoader(dir, imageLoader) {
if (dir.placeholder === true && imageLoader === noopImageLoader) {
throw new RuntimeError(2963, `${imgDirectiveDetails(dir.ngSrc)} the \`placeholder\` attribute is set to true but no image loader is configured (i.e. the default one is being used), which would result in the same image being used for the primary image and its placeholder. To fix this, provide a loader or remove the \`placeholder\` attribute from the image.`);
}
}
function assertNoOversizedDataUrl(dir) {
if (dir.placeholder && typeof dir.placeholder === "string" && dir.placeholder.startsWith("data:")) {
if (dir.placeholder.length > DATA_URL_ERROR_LIMIT) {
throw new RuntimeError(2965, `${imgDirectiveDetails(dir.ngSrc)} the \`placeholder\` attribute is set to a data URL which is longer than ${DATA_URL_ERROR_LIMIT} characters. This is strongly discouraged, as large inline placeholders directly increase the bundle size of Angular and hurt page load performance. To fix this, generate a smaller data URL placeholder.`);
}
if (dir.placeholder.length > DATA_URL_WARN_LIMIT) {
console.warn(formatRuntimeError(2965, `${imgDirectiveDetails(dir.ngSrc)} the \`placeholder\` attribute is set to a data URL which is longer than ${DATA_URL_WARN_LIMIT} characters. This is discouraged, as large inline placeholders directly increase the bundle size of Angular and hurt page load performance. For better loading performance, generate a smaller data URL placeholder.`));
}
}
}
function assertNotBlobUrl(dir) {
const ngSrc = dir.ngSrc.trim();
if (ngSrc.startsWith("blob:")) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} \`ngSrc\` was set to a blob URL (${ngSrc}). Blob URLs are not supported by the NgOptimizedImage directive. To fix this, disable the NgOptimizedImage directive for this element by removing \`ngSrc\` and using a regular \`src\` attribute instead.`);
}
}
function assertNonEmptyInput(dir, name, value) {
const isString = typeof value === "string";
const isEmptyString = isString && value.trim() === "";
if (!isString || isEmptyString) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} \`${name}\` has an invalid value (\`${value}\`). To fix this, change the value to a non-empty string.`);
}
}
function assertValidNgSrcset(dir, value) {
if (value == null) return;
assertNonEmptyInput(dir, "ngSrcset", value);
const stringVal = value;
const isValidWidthDescriptor = VALID_WIDTH_DESCRIPTOR_SRCSET.test(stringVal);
const isValidDensityDescriptor = VALID_DENSITY_DESCRIPTOR_SRCSET.test(stringVal);
if (isValidDensityDescriptor) {
assertUnderDensityCap(dir, stringVal);
}
const isValidSrcset = isValidWidthDescriptor || isValidDensityDescriptor;
if (!isValidSrcset) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} \`ngSrcset\` has an invalid value (\`${value}\`). To fix this, supply \`ngSrcset\` using a comma-separated list of one or more width descriptors (e.g. "100w, 200w") or density descriptors (e.g. "1x, 2x").`);
}
}
function assertUnderDensityCap(dir, value) {
const underDensityCap = value.split(",").every((num) => num === "" || parseFloat(num) <= ABSOLUTE_SRCSET_DENSITY_CAP);
if (!underDensityCap) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the \`ngSrcset\` contains an unsupported image density:\`${value}\`. NgOptimizedImage generally recommends a max image density of ${RECOMMENDED_SRCSET_DENSITY_CAP}x but supports image densities up to ${ABSOLUTE_SRCSET_DENSITY_CAP}x. The human eye cannot distinguish between image densities greater than ${RECOMMENDED_SRCSET_DENSITY_CAP}x - which makes them unnecessary for most use cases. Images that will be pinch-zoomed are typically the primary use case for ${ABSOLUTE_SRCSET_DENSITY_CAP}x images. Please remove the high density descriptor and try again.`);
}
}
function postInitInputChangeError(dir, inputName) {
let reason;
if (inputName === "width" || inputName === "height") {
reason = `Changing \`${inputName}\` may result in different attribute value applied to the underlying image element and cause layout shifts on a page.`;
} else {
reason = `Changing the \`${inputName}\` would have no effect on the underlying image element, because the resource loading has already occurred.`;
}
return new RuntimeError(2953, `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` was updated after initialization. The NgOptimizedImage directive will not react to this input change. ${reason} To fix this, either switch \`${inputName}\` to a static value or wrap the image element in an @if that is gated on the necessary value.`);
}
function assertNoPostInitInputChange(dir, changes, inputs) {
inputs.forEach((input2) => {
const isUpdated = changes.hasOwnProperty(input2);
if (isUpdated && !changes[input2].isFirstChange()) {
if (input2 === "ngSrc") {
dir = {
ngSrc: changes[input2].previousValue
};
}
throw postInitInputChangeError(dir, input2);
}
});
}
function assertGreaterThanZero(dir, inputValue, inputName) {
const validNumber = typeof inputValue === "number" && inputValue > 0;
const validString = typeof inputValue === "string" && /^\d+$/.test(inputValue.trim()) && parseInt(inputValue) > 0;
if (!validNumber && !validString) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} \`${inputName}\` has an invalid value. To fix this, provide \`${inputName}\` as a number greater than 0.`);
}
}
function assertNoImageDistortion(dir, img, renderer) {
const callback = () => {
removeLoadListenerFn();
removeErrorListenerFn();
const computedStyle = window.getComputedStyle(img);
let renderedWidth = parseFloat(computedStyle.getPropertyValue("width"));
let renderedHeight = parseFloat(computedStyle.getPropertyValue("height"));
const boxSizing = computedStyle.getPropertyValue("box-sizing");
if (boxSizing === "border-box") {
const paddingTop = computedStyle.getPropertyValue("padding-top");
const paddingRight = computedStyle.getPropertyValue("padding-right");
const paddingBottom = computedStyle.getPropertyValue("padding-bottom");
const paddingLeft = computedStyle.getPropertyValue("padding-left");
renderedWidth -= parseFloat(paddingRight) + parseFloat(paddingLeft);
renderedHeight -= parseFloat(paddingTop) + parseFloat(paddingBottom);
}
const renderedAspectRatio = renderedWidth / renderedHeight;
const nonZeroRenderedDimensions = renderedWidth !== 0 && renderedHeight !== 0;
const intrinsicWidth = img.naturalWidth;
const intrinsicHeight = img.naturalHeight;
const intrinsicAspectRatio = intrinsicWidth / intrinsicHeight;
const suppliedWidth = dir.width;
const suppliedHeight = dir.height;
const suppliedAspectRatio = suppliedWidth / suppliedHeight;
const inaccurateDimensions = Math.abs(suppliedAspectRatio - intrinsicAspectRatio) > ASPECT_RATIO_TOLERANCE;
const stylingDistortion = nonZeroRenderedDimensions && Math.abs(intrinsicAspectRatio - renderedAspectRatio) > ASPECT_RATIO_TOLERANCE;
if (inaccurateDimensions) {
console.warn(formatRuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the image does not match the aspect ratio indicated by the width and height attributes.
Intrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h (aspect-ratio: ${round(intrinsicAspectRatio)}).
Supplied width and height attributes: ${suppliedWidth}w x ${suppliedHeight}h (aspect-ratio: ${round(suppliedAspectRatio)}).
To fix this, update the width and height attributes.`));
} else if (stylingDistortion) {
console.warn(formatRuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the aspect ratio of the rendered image does not match the image's intrinsic aspect ratio.
Intrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h (aspect-ratio: ${round(intrinsicAspectRatio)}).
Rendered image size: ${renderedWidth}w x ${renderedHeight}h (aspect-ratio: ${round(renderedAspectRatio)}).
This issue can occur if "width" and "height" attributes are added to an image without updating the corresponding image styling. To fix this, adjust image styling. In most cases, adding "height: auto" or "width: auto" to the image styling will fix this issue.`));
} else if (!dir.ngSrcset && nonZeroRenderedDimensions) {
const recommendedWidth = RECOMMENDED_SRCSET_DENSITY_CAP * renderedWidth;
const recommendedHeight = RECOMMENDED_SRCSET_DENSITY_CAP * renderedHeight;
const oversizedWidth = intrinsicWidth - recommendedWidth >= OVERSIZED_IMAGE_TOLERANCE;
const oversizedHeight = intrinsicHeight - recommendedHeight >= OVERSIZED_IMAGE_TOLERANCE;
if (oversizedWidth || oversizedHeight) {
console.warn(formatRuntimeError(2960, `${imgDirectiveDetails(dir.ngSrc)} the intrinsic image is significantly larger than necessary.
Rendered image size: ${renderedWidth}w x ${renderedHeight}h.
Intrinsic image size: ${intrinsicWidth}w x ${intrinsicHeight}h.
Recommended intrinsic image size: ${recommendedWidth}w x ${recommendedHeight}h.
Note: Recommended intrinsic image size is calculated assuming a maximum DPR of ${RECOMMENDED_SRCSET_DENSITY_CAP}. To improve loading time, resize the image or consider using the "ngSrcset" and "sizes" attributes.`));
}
}
};
const removeLoadListenerFn = renderer.listen(img, "load", callback);
const removeErrorListenerFn = renderer.listen(img, "error", () => {
removeLoadListenerFn();
removeErrorListenerFn();
});
callOnLoadIfImageIsLoaded(img, callback);
}
function assertNonEmptyWidthAndHeight(dir) {
let missingAttributes = [];
if (dir.width === void 0) missingAttributes.push("width");
if (dir.height === void 0) missingAttributes.push("height");
if (missingAttributes.length > 0) {
throw new RuntimeError(2954, `${imgDirectiveDetails(dir.ngSrc)} these required attributes are missing: ${missingAttributes.map((attr) => `"${attr}"`).join(", ")}. Including "width" and "height" attributes will prevent image-related layout shifts. To fix this, include "width" and "height" attributes on the image tag or turn on "fill" mode with the \`fill\` attribute.`);
}
}
function assertEmptyWidthAndHeight(dir) {
if (dir.width || dir.height) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the attributes \`height\` and/or \`width\` are present along with the \`fill\` attribute. Because \`fill\` mode causes an image to fill its containing element, the size attributes have no effect and should be removed.`);
}
}
function assertNonZeroRenderedHeight(dir, img, renderer) {
const callback = () => {
removeLoadListenerFn();
removeErrorListenerFn();
const renderedHeight = img.clientHeight;
if (dir.fill && renderedHeight === 0) {
console.warn(formatRuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the height of the fill-mode image is zero. This is likely because the containing element does not have the CSS 'position' property set to one of the following: "relative", "fixed", or "absolute". To fix this problem, make sure the container element has the CSS 'position' property defined and the height of the element is not zero.`));
}
};
const removeLoadListenerFn = renderer.listen(img, "load", callback);
const removeErrorListenerFn = renderer.listen(img, "error", () => {
removeLoadListenerFn();
removeErrorListenerFn();
});
callOnLoadIfImageIsLoaded(img, callback);
}
function assertValidLoadingInput(dir) {
if (dir.loading && dir.priority) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute was used on an image that was marked "priority". Setting \`loading\` on priority images is not allowed because these images will always be eagerly loaded. To fix this, remove the \u201Cloading\u201D attribute from the priority image.`);
}
const validInputs = ["auto", "eager", "lazy"];
if (typeof dir.loading === "string" && !validInputs.includes(dir.loading)) {
throw new RuntimeError(2952, `${imgDirectiveDetails(dir.ngSrc)} the \`loading\` attribute has an invalid value (\`${dir.loading}\`). To fix this, provide a valid value ("lazy", "eager", or "auto").`);
}
}
function assertNotMissingBuiltInLoader(ngSrc, imageLoader) {
if (imageLoader === noopImageLoader) {
let builtInLoaderName = "";
for (const loader of BUILT_IN_LOADERS) {
if (loader.testUrl(ngSrc)) {
builtInLoaderName = loader.name;
break;
}
}
if (builtInLoaderName) {
console.warn(formatRuntimeError(2962, `NgOptimizedImage: It looks like your images may be hosted on the ${builtInLoaderName} CDN, but your app is not using Angular's built-in loader for that CDN. We recommend switching to use the built-in by calling \`provide${builtInLoaderName}Loader()\` in your \`providers\` and passing it your instance's base URL. If you don't want to use the built-in loader, define a custom loader function using IMAGE_LOADER to silence this warning.`));
}
}
}
function assertNoNgSrcsetWithoutLoader(dir, imageLoader) {
if (dir.ngSrcset && imageLoader === noopImageLoader) {
console.warn(formatRuntimeError(2963, `${imgDirectiveDetails(dir.ngSrc)} the \`ngSrcset\` attribute is present but no image loader is configured (i.e. the default one is being used), which would result in the same image being used for all configured sizes. To fix this, provide a loader or remove the \`ngSrcset\` attribute from the image.`));
}
}
function assertNoLoaderParamsWithoutLoader(dir, imageLoader) {
if (dir.loaderParams && imageLoader === noopImageLoader) {
console.warn(formatRuntimeError(2963, `${imgDirectiveDetails(dir.ngSrc)} the \`loaderParams\` attribute is present but no image loader is configured (i.e. the default one is being used), which means that the loaderParams data will not be consumed and will not affect the URL. To fix this, provide a custom loader or remove the \`loaderParams\` attribute from the image.`));
}
}
function assetPriorityCountBelowThreshold(appRef) {
return __async(this, null, function* () {
if (IMGS_WITH_PRIORITY_ATTR_COUNT === 0) {
IMGS_WITH_PRIORITY_ATTR_COUNT++;
yield appRef.whenStable();
if (IMGS_WITH_PRIORITY_ATTR_COUNT > PRIORITY_COUNT_THRESHOLD) {
console.warn(formatRuntimeError(2966, `NgOptimizedImage: The "priority" attribute is set to true more than ${PRIORITY_COUNT_THRESHOLD} times (${IMGS_WITH_PRIORITY_ATTR_COUNT} times). Marking too many images as "high" priority can hurt your application's LCP (https://web.dev/lcp). "Priority" should only be set on the image expected to be the page's LCP element.`));
}
} else {
IMGS_WITH_PRIORITY_ATTR_COUNT++;
}
});
}
function assertPlaceholderDimensions(dir, imgElement) {
const computedStyle = window.getComputedStyle(imgElement);
let renderedWidth = parseFloat(computedStyle.getPropertyValue("width"));
let renderedHeight = parseFloat(computedStyle.getPropertyValue("height"));
if (renderedWidth > PLACEHOLDER_DIMENSION_LIMIT || renderedHeight > PLACEHOLDER_DIMENSION_LIMIT) {
console.warn(formatRuntimeError(2967, `${imgDirectiveDetails(dir.ngSrc)} it uses a placeholder image, but at least one of the dimensions attribute (height or width) exceeds the limit of ${PLACEHOLDER_DIMENSION_LIMIT}px. To fix this, use a smaller image as a placeholder.`));
}
}
function callOnLoadIfImageIsLoaded(img, callback) {
if (img.complete && img.naturalWidth) {
callback();
}
}
function round(input2) {
return Number.isInteger(input2) ? input2 : input2.toFixed(2);
}
function unwrapSafeUrl(value) {
if (typeof value === "string") {
return value;
}
return unwrapSafeValue(value);
}
function booleanOrUrlAttribute(value) {
if (typeof value === "string" && value !== "true" && value !== "false" && value !== "") {
return value;
}
return booleanAttribute(value);
}
// node_modules/@angular/platform-browser/fesm2022/dom_renderer-DGKzginR.mjs
var EVENT_MANAGER_PLUGINS = new InjectionToken(ngDevMode ? "EventManagerPlugins" : "");
var EventManager = class _EventManager {
_zone;
_plugins;
_eventNameToPlugin = /* @__PURE__ */ new Map();
/**
* Initializes an instance of the event-manager service.
*/
constructor(plugins, _zone) {
this._zone = _zone;
plugins.forEach((plugin) => {
plugin.manager = this;
});
this._plugins = plugins.slice().reverse();
}
/**
* Registers a handler for a specific element and event.
*
* @param element The HTML element to receive event notifications.
* @param eventName The name of the event to listen for.
* @param handler A function to call when the notification occurs. Receives the
* event object as an argument.
* @param options Options that configure how the event listener is bound.
* @returns A callback function that can be used to remove the handler.
*/
addEventListener(element, eventName, handler, options) {
const plugin = this._findPluginFor(eventName);
return plugin.addEventListener(element, eventName, handler, options);
}
/**
* Retrieves the compilation zone in which event listeners are registered.
*/
getZone() {
return this._zone;
}
/** @internal */
_findPluginFor(eventName) {
let plugin = this._eventNameToPlugin.get(eventName);
if (plugin) {
return plugin;
}
const plugins = this._plugins;
plugin = plugins.find((plugin2) => plugin2.supports(eventName));
if (!plugin) {
throw new RuntimeError(5101, (typeof ngDevMode === "undefined" || ngDevMode) && `No event manager plugin found for event ${eventName}`);
}
this._eventNameToPlugin.set(eventName, plugin);
return plugin;
}
static \u0275fac = function EventManager_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _EventManager)(\u0275\u0275inject(EVENT_MANAGER_PLUGINS), \u0275\u0275inject(NgZone));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _EventManager,
factory: _EventManager.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(EventManager, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [EVENT_MANAGER_PLUGINS]
}]
}, {
type: NgZone
}], null);
})();
var EventManagerPlugin = class {
_doc;
// TODO: remove (has some usage in G3)
constructor(_doc) {
this._doc = _doc;
}
// Using non-null assertion because it's set by EventManager's constructor
manager;
};
var APP_ID_ATTRIBUTE_NAME = "ng-app-id";
function removeElements(elements) {
for (const element of elements) {
element.remove();
}
}
function createStyleElement(style, doc) {
const styleElement = doc.createElement("style");
styleElement.textContent = style;
return styleElement;
}
function addServerStyles(doc, appId, inline, external) {
const elements = doc.head?.querySelectorAll(`style[${APP_ID_ATTRIBUTE_NAME}="${appId}"],link[${APP_ID_ATTRIBUTE_NAME}="${appId}"]`);
if (elements) {
for (const styleElement of elements) {
styleElement.removeAttribute(APP_ID_ATTRIBUTE_NAME);
if (styleElement instanceof HTMLLinkElement) {
external.set(styleElement.href.slice(styleElement.href.lastIndexOf("/") + 1), {
usage: 0,
elements: [styleElement]
});
} else if (styleElement.textContent) {
inline.set(styleElement.textContent, {
usage: 0,
elements: [styleElement]
});
}
}
}
}
function createLinkElement(url, doc) {
const linkElement = doc.createElement("link");
linkElement.setAttribute("rel", "stylesheet");
linkElement.setAttribute("href", url);
return linkElement;
}
var SharedStylesHost = class _SharedStylesHost {
doc;
appId;
nonce;
/**
* Provides usage information for active inline style content and associated HTML <style> elements.
* Embedded styles typically originate from the `styles` metadata of a rendered component.
*/
inline = /* @__PURE__ */ new Map();
/**
* Provides usage information for active external style URLs and the associated HTML <link> elements.
* External styles typically originate from the `ɵɵExternalStylesFeature` of a rendered component.
*/
external = /* @__PURE__ */ new Map();
/**
* Set of host DOM nodes that will have styles attached.
*/
hosts = /* @__PURE__ */ new Set();
/**
* Whether the application code is currently executing on a server.
*/
isServer;
constructor(doc, appId, nonce, platformId = {}) {
this.doc = doc;
this.appId = appId;
this.nonce = nonce;
this.isServer = isPlatformServer(platformId);
addServerStyles(doc, appId, this.inline, this.external);
this.hosts.add(doc.head);
}
/**
* Adds embedded styles to the DOM via HTML `style` elements.
* @param styles An array of style content strings.
*/
addStyles(styles, urls) {
for (const value of styles) {
this.addUsage(value, this.inline, createStyleElement);
}
urls?.forEach((value) => this.addUsage(value, this.external, createLinkElement));
}
/**
* Removes embedded styles from the DOM that were added as HTML `style` elements.
* @param styles An array of style content strings.
*/
removeStyles(styles, urls) {
for (const value of styles) {
this.removeUsage(value, this.inline);
}
urls?.forEach((value) => this.removeUsage(value, this.external));
}
addUsage(value, usages, creator) {
const record = usages.get(value);
if (record) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && record.usage === 0) {
record.elements.forEach((element) => element.setAttribute("ng-style-reused", ""));
}
record.usage++;
} else {
usages.set(value, {
usage: 1,
elements: [...this.hosts].map((host) => this.addElement(host, creator(value, this.doc)))
});
}
}
removeUsage(value, usages) {
const record = usages.get(value);
if (record) {
record.usage--;
if (record.usage <= 0) {
removeElements(record.elements);
usages.delete(value);
}
}
}
ngOnDestroy() {
for (const [, {
elements
}] of [...this.inline, ...this.external]) {
removeElements(elements);
}
this.hosts.clear();
}
/**
* Adds a host node to the set of style hosts and adds all existing style usage to
* the newly added host node.
*
* This is currently only used for Shadow DOM encapsulation mode.
*/
addHost(hostNode) {
this.hosts.add(hostNode);
for (const [style, {
elements
}] of this.inline) {
elements.push(this.addElement(hostNode, createStyleElement(style, this.doc)));
}
for (const [url, {
elements
}] of this.external) {
elements.push(this.addElement(hostNode, createLinkElement(url, this.doc)));
}
}
removeHost(hostNode) {
this.hosts.delete(hostNode);
}
addElement(host, element) {
if (this.nonce) {
element.setAttribute("nonce", this.nonce);
}
if (this.isServer) {
element.setAttribute(APP_ID_ATTRIBUTE_NAME, this.appId);
}
return host.appendChild(element);
}
static \u0275fac = function SharedStylesHost_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _SharedStylesHost)(\u0275\u0275inject(DOCUMENT), \u0275\u0275inject(APP_ID), \u0275\u0275inject(CSP_NONCE, 8), \u0275\u0275inject(PLATFORM_ID));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _SharedStylesHost,
factory: _SharedStylesHost.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SharedStylesHost, [{
type: Injectable
}], () => [{
type: Document,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [APP_ID]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [CSP_NONCE]
}, {
type: Optional
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [PLATFORM_ID]
}]
}], null);
})();
var NAMESPACE_URIS = {
"svg": "http://www.w3.org/2000/svg",
"xhtml": "http://www.w3.org/1999/xhtml",
"xlink": "http://www.w3.org/1999/xlink",
"xml": "http://www.w3.org/XML/1998/namespace",
"xmlns": "http://www.w3.org/2000/xmlns/",
"math": "http://www.w3.org/1998/Math/MathML"
};
var COMPONENT_REGEX = /%COMP%/g;
var SOURCEMAP_URL_REGEXP = /\/\*#\s*sourceMappingURL=(.+?)\s*\*\//;
var PROTOCOL_REGEXP = /^https?:/;
var COMPONENT_VARIABLE = "%COMP%";
var HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
var CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
var REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT = true;
var REMOVE_STYLES_ON_COMPONENT_DESTROY = new InjectionToken(ngDevMode ? "RemoveStylesOnCompDestroy" : "", {
providedIn: "root",
factory: () => REMOVE_STYLES_ON_COMPONENT_DESTROY_DEFAULT
});
function shimContentAttribute(componentShortId) {
return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId);
}
function shimHostAttribute(componentShortId) {
return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId);
}
function shimStylesContent(compId, styles) {
return styles.map((s) => s.replace(COMPONENT_REGEX, compId));
}
function addBaseHrefToCssSourceMap(baseHref, styles) {
if (!baseHref) {
return styles;
}
const absoluteBaseHrefUrl = new URL(baseHref, "http://localhost");
return styles.map((cssContent) => {
if (!cssContent.includes("sourceMappingURL=")) {
return cssContent;
}
return cssContent.replace(SOURCEMAP_URL_REGEXP, (_, sourceMapUrl) => {
if (sourceMapUrl[0] === "/" || sourceMapUrl.startsWith("data:") || PROTOCOL_REGEXP.test(sourceMapUrl)) {
return `/*# sourceMappingURL=${sourceMapUrl} */`;
}
const {
pathname: resolvedSourceMapUrl
} = new URL(sourceMapUrl, absoluteBaseHrefUrl);
return `/*# sourceMappingURL=${resolvedSourceMapUrl} */`;
});
});
}
var DomRendererFactory2 = class _DomRendererFactory2 {
eventManager;
sharedStylesHost;
appId;
removeStylesOnCompDestroy;
doc;
platformId;
ngZone;
nonce;
tracingService;
rendererByCompId = /* @__PURE__ */ new Map();
defaultRenderer;
platformIsServer;
constructor(eventManager, sharedStylesHost, appId, removeStylesOnCompDestroy, doc, platformId, ngZone, nonce = null, tracingService = null) {
this.eventManager = eventManager;
this.sharedStylesHost = sharedStylesHost;
this.appId = appId;
this.removeStylesOnCompDestroy = removeStylesOnCompDestroy;
this.doc = doc;
this.platformId = platformId;
this.ngZone = ngZone;
this.nonce = nonce;
this.tracingService = tracingService;
this.platformIsServer = isPlatformServer(platformId);
this.defaultRenderer = new DefaultDomRenderer2(eventManager, doc, ngZone, this.platformIsServer, this.tracingService);
}
createRenderer(element, type) {
if (!element || !type) {
return this.defaultRenderer;
}
if (this.platformIsServer && type.encapsulation === ViewEncapsulation.ShadowDom) {
type = __spreadProps(__spreadValues({}, type), {
encapsulation: ViewEncapsulation.Emulated
});
}
const renderer = this.getOrCreateRenderer(element, type);
if (renderer instanceof EmulatedEncapsulationDomRenderer2) {
renderer.applyToHost(element);
} else if (renderer instanceof NoneEncapsulationDomRenderer) {
renderer.applyStyles();
}
return renderer;
}
getOrCreateRenderer(element, type) {
const rendererByCompId = this.rendererByCompId;
let renderer = rendererByCompId.get(type.id);
if (!renderer) {
const doc = this.doc;
const ngZone = this.ngZone;
const eventManager = this.eventManager;
const sharedStylesHost = this.sharedStylesHost;
const removeStylesOnCompDestroy = this.removeStylesOnCompDestroy;
const platformIsServer = this.platformIsServer;
const tracingService = this.tracingService;
switch (type.encapsulation) {
case ViewEncapsulation.Emulated:
renderer = new EmulatedEncapsulationDomRenderer2(eventManager, sharedStylesHost, type, this.appId, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService);
break;
case ViewEncapsulation.ShadowDom:
return new ShadowDomRenderer(eventManager, sharedStylesHost, element, type, doc, ngZone, this.nonce, platformIsServer, tracingService);
default:
renderer = new NoneEncapsulationDomRenderer(eventManager, sharedStylesHost, type, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService);
break;
}
rendererByCompId.set(type.id, renderer);
}
return renderer;
}
ngOnDestroy() {
this.rendererByCompId.clear();
}
/**
* Used during HMR to clear any cached data about a component.
* @param componentId ID of the component that is being replaced.
*/
componentReplaced(componentId) {
this.rendererByCompId.delete(componentId);
}
static \u0275fac = function DomRendererFactory2_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DomRendererFactory2)(\u0275\u0275inject(EventManager), \u0275\u0275inject(SharedStylesHost), \u0275\u0275inject(APP_ID), \u0275\u0275inject(REMOVE_STYLES_ON_COMPONENT_DESTROY), \u0275\u0275inject(DOCUMENT), \u0275\u0275inject(PLATFORM_ID), \u0275\u0275inject(NgZone), \u0275\u0275inject(CSP_NONCE), \u0275\u0275inject(TracingService, 8));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DomRendererFactory2,
factory: _DomRendererFactory2.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DomRendererFactory2, [{
type: Injectable
}], () => [{
type: EventManager
}, {
type: SharedStylesHost
}, {
type: void 0,
decorators: [{
type: Inject,
args: [APP_ID]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [REMOVE_STYLES_ON_COMPONENT_DESTROY]
}]
}, {
type: Document,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}, {
type: Object,
decorators: [{
type: Inject,
args: [PLATFORM_ID]
}]
}, {
type: NgZone
}, {
type: void 0,
decorators: [{
type: Inject,
args: [CSP_NONCE]
}]
}, {
type: TracingService,
decorators: [{
type: Inject,
args: [TracingService]
}, {
type: Optional
}]
}], null);
})();
var DefaultDomRenderer2 = class {
eventManager;
doc;
ngZone;
platformIsServer;
tracingService;
data = /* @__PURE__ */ Object.create(null);
/**
* By default this renderer throws when encountering synthetic properties
* This can be disabled for example by the AsyncAnimationRendererFactory
*/
throwOnSyntheticProps = true;
constructor(eventManager, doc, ngZone, platformIsServer, tracingService) {
this.eventManager = eventManager;
this.doc = doc;
this.ngZone = ngZone;
this.platformIsServer = platformIsServer;
this.tracingService = tracingService;
}
destroy() {
}
destroyNode = null;
createElement(name, namespace) {
if (namespace) {
return this.doc.createElementNS(NAMESPACE_URIS[namespace] || namespace, name);
}
return this.doc.createElement(name);
}
createComment(value) {
return this.doc.createComment(value);
}
createText(value) {
return this.doc.createTextNode(value);
}
appendChild(parent, newChild) {
const targetParent = isTemplateNode(parent) ? parent.content : parent;
targetParent.appendChild(newChild);
}
insertBefore(parent, newChild, refChild) {
if (parent) {
const targetParent = isTemplateNode(parent) ? parent.content : parent;
targetParent.insertBefore(newChild, refChild);
}
}
removeChild(_parent, oldChild) {
oldChild.remove();
}
selectRootElement(selectorOrNode, preserveContent) {
let el = typeof selectorOrNode === "string" ? this.doc.querySelector(selectorOrNode) : selectorOrNode;
if (!el) {
throw new RuntimeError(-5104, (typeof ngDevMode === "undefined" || ngDevMode) && `The selector "${selectorOrNode}" did not match any elements`);
}
if (!preserveContent) {
el.textContent = "";
}
return el;
}
parentNode(node) {
return node.parentNode;
}
nextSibling(node) {
return node.nextSibling;
}
setAttribute(el, name, value, namespace) {
if (namespace) {
name = namespace + ":" + name;
const namespaceUri = NAMESPACE_URIS[namespace];
if (namespaceUri) {
el.setAttributeNS(namespaceUri, name, value);
} else {
el.setAttribute(name, value);
}
} else {
el.setAttribute(name, value);
}
}
removeAttribute(el, name, namespace) {
if (namespace) {
const namespaceUri = NAMESPACE_URIS[namespace];
if (namespaceUri) {
el.removeAttributeNS(namespaceUri, name);
} else {
el.removeAttribute(`${namespace}:${name}`);
}
} else {
el.removeAttribute(name);
}
}
addClass(el, name) {
el.classList.add(name);
}
removeClass(el, name) {
el.classList.remove(name);
}
setStyle(el, style, value, flags) {
if (flags & (RendererStyleFlags2.DashCase | RendererStyleFlags2.Important)) {
el.style.setProperty(style, value, flags & RendererStyleFlags2.Important ? "important" : "");
} else {
el.style[style] = value;
}
}
removeStyle(el, style, flags) {
if (flags & RendererStyleFlags2.DashCase) {
el.style.removeProperty(style);
} else {
el.style[style] = "";
}
}
setProperty(el, name, value) {
if (el == null) {
return;
}
(typeof ngDevMode === "undefined" || ngDevMode) && this.throwOnSyntheticProps && checkNoSyntheticProp(name, "property");
el[name] = value;
}
setValue(node, value) {
node.nodeValue = value;
}
listen(target, event, callback, options) {
(typeof ngDevMode === "undefined" || ngDevMode) && this.throwOnSyntheticProps && checkNoSyntheticProp(event, "listener");
if (typeof target === "string") {
target = getDOM().getGlobalEventTarget(this.doc, target);
if (!target) {
throw new RuntimeError(5102, (typeof ngDevMode === "undefined" || ngDevMode) && `Unsupported event target ${target} for event ${event}`);
}
}
let wrappedCallback = this.decoratePreventDefault(callback);
if (this.tracingService?.wrapEventListener) {
wrappedCallback = this.tracingService.wrapEventListener(target, event, wrappedCallback);
}
return this.eventManager.addEventListener(target, event, wrappedCallback, options);
}
decoratePreventDefault(eventHandler) {
return (event) => {
if (event === "__ngUnwrap__") {
return eventHandler;
}
const allowDefaultBehavior = this.platformIsServer ? this.ngZone.runGuarded(() => eventHandler(event)) : eventHandler(event);
if (allowDefaultBehavior === false) {
event.preventDefault();
}
return void 0;
};
}
};
var AT_CHARCODE = (() => "@".charCodeAt(0))();
function checkNoSyntheticProp(name, nameKind) {
if (name.charCodeAt(0) === AT_CHARCODE) {
throw new RuntimeError(5105, `Unexpected synthetic ${nameKind} ${name} found. Please make sure that:
- Make sure \`provideAnimationsAsync()\`, \`provideAnimations()\` or \`provideNoopAnimations()\` call was added to a list of providers used to bootstrap an application.
- There is a corresponding animation configuration named \`${name}\` defined in the \`animations\` field of the \`@Component\` decorator (see https://angular.dev/api/core/Component#animations).`);
}
}
function isTemplateNode(node) {
return node.tagName === "TEMPLATE" && node.content !== void 0;
}
var ShadowDomRenderer = class extends DefaultDomRenderer2 {
sharedStylesHost;
hostEl;
shadowRoot;
constructor(eventManager, sharedStylesHost, hostEl, component, doc, ngZone, nonce, platformIsServer, tracingService) {
super(eventManager, doc, ngZone, platformIsServer, tracingService);
this.sharedStylesHost = sharedStylesHost;
this.hostEl = hostEl;
this.shadowRoot = hostEl.attachShadow({
mode: "open"
});
this.sharedStylesHost.addHost(this.shadowRoot);
let styles = component.styles;
if (ngDevMode) {
const baseHref = getDOM().getBaseHref(doc) ?? "";
styles = addBaseHrefToCssSourceMap(baseHref, styles);
}
styles = shimStylesContent(component.id, styles);
for (const style of styles) {
const styleEl = document.createElement("style");
if (nonce) {
styleEl.setAttribute("nonce", nonce);
}
styleEl.textContent = style;
this.shadowRoot.appendChild(styleEl);
}
const styleUrls = component.getExternalStyles?.();
if (styleUrls) {
for (const styleUrl of styleUrls) {
const linkEl = createLinkElement(styleUrl, doc);
if (nonce) {
linkEl.setAttribute("nonce", nonce);
}
this.shadowRoot.appendChild(linkEl);
}
}
}
nodeOrShadowRoot(node) {
return node === this.hostEl ? this.shadowRoot : node;
}
appendChild(parent, newChild) {
return super.appendChild(this.nodeOrShadowRoot(parent), newChild);
}
insertBefore(parent, newChild, refChild) {
return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild);
}
removeChild(_parent, oldChild) {
return super.removeChild(null, oldChild);
}
parentNode(node) {
return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node)));
}
destroy() {
this.sharedStylesHost.removeHost(this.shadowRoot);
}
};
var NoneEncapsulationDomRenderer = class extends DefaultDomRenderer2 {
sharedStylesHost;
removeStylesOnCompDestroy;
styles;
styleUrls;
constructor(eventManager, sharedStylesHost, component, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService, compId) {
super(eventManager, doc, ngZone, platformIsServer, tracingService);
this.sharedStylesHost = sharedStylesHost;
this.removeStylesOnCompDestroy = removeStylesOnCompDestroy;
let styles = component.styles;
if (ngDevMode) {
const baseHref = getDOM().getBaseHref(doc) ?? "";
styles = addBaseHrefToCssSourceMap(baseHref, styles);
}
this.styles = compId ? shimStylesContent(compId, styles) : styles;
this.styleUrls = component.getExternalStyles?.(compId);
}
applyStyles() {
this.sharedStylesHost.addStyles(this.styles, this.styleUrls);
}
destroy() {
if (!this.removeStylesOnCompDestroy) {
return;
}
this.sharedStylesHost.removeStyles(this.styles, this.styleUrls);
}
};
var EmulatedEncapsulationDomRenderer2 = class extends NoneEncapsulationDomRenderer {
contentAttr;
hostAttr;
constructor(eventManager, sharedStylesHost, component, appId, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService) {
const compId = appId + "-" + component.id;
super(eventManager, sharedStylesHost, component, removeStylesOnCompDestroy, doc, ngZone, platformIsServer, tracingService, compId);
this.contentAttr = shimContentAttribute(compId);
this.hostAttr = shimHostAttribute(compId);
}
applyToHost(element) {
this.applyStyles();
this.setAttribute(element, this.hostAttr, "");
}
createElement(parent, name) {
const el = super.createElement(parent, name);
super.setAttribute(el, this.contentAttr, "");
return el;
}
};
// node_modules/@angular/platform-browser/fesm2022/browser-X3l5Bmdq.mjs
var BrowserDomAdapter = class _BrowserDomAdapter extends DomAdapter {
supportsDOMEvents = true;
static makeCurrent() {
setRootDomAdapter(new _BrowserDomAdapter());
}
onAndCancel(el, evt, listener, options) {
el.addEventListener(evt, listener, options);
return () => {
el.removeEventListener(evt, listener, options);
};
}
dispatchEvent(el, evt) {
el.dispatchEvent(evt);
}
remove(node) {
node.remove();
}
createElement(tagName, doc) {
doc = doc || this.getDefaultDocument();
return doc.createElement(tagName);
}
createHtmlDocument() {
return document.implementation.createHTMLDocument("fakeTitle");
}
getDefaultDocument() {
return document;
}
isElementNode(node) {
return node.nodeType === Node.ELEMENT_NODE;
}
isShadowRoot(node) {
return node instanceof DocumentFragment;
}
/** @deprecated No longer being used in Ivy code. To be removed in version 14. */
getGlobalEventTarget(doc, target) {
if (target === "window") {
return window;
}
if (target === "document") {
return doc;
}
if (target === "body") {
return doc.body;
}
return null;
}
getBaseHref(doc) {
const href = getBaseElementHref();
return href == null ? null : relativePath(href);
}
resetBaseElement() {
baseElement = null;
}
getUserAgent() {
return window.navigator.userAgent;
}
getCookie(name) {
return parseCookieValue(document.cookie, name);
}
};
var baseElement = null;
function getBaseElementHref() {
baseElement = baseElement || document.querySelector("base");
return baseElement ? baseElement.getAttribute("href") : null;
}
function relativePath(url) {
return new URL(url, document.baseURI).pathname;
}
var BrowserGetTestability = class {
addToWindow(registry) {
_global["getAngularTestability"] = (elem, findInAncestors = true) => {
const testability = registry.findTestabilityInTree(elem, findInAncestors);
if (testability == null) {
throw new RuntimeError(5103, (typeof ngDevMode === "undefined" || ngDevMode) && "Could not find testability for element.");
}
return testability;
};
_global["getAllAngularTestabilities"] = () => registry.getAllTestabilities();
_global["getAllAngularRootElements"] = () => registry.getAllRootElements();
const whenAllStable = (callback) => {
const testabilities = _global["getAllAngularTestabilities"]();
let count = testabilities.length;
const decrement = function() {
count--;
if (count == 0) {
callback();
}
};
testabilities.forEach((testability) => {
testability.whenStable(decrement);
});
};
if (!_global["frameworkStabilizers"]) {
_global["frameworkStabilizers"] = [];
}
_global["frameworkStabilizers"].push(whenAllStable);
}
findTestabilityInTree(registry, elem, findInAncestors) {
if (elem == null) {
return null;
}
const t = registry.getTestability(elem);
if (t != null) {
return t;
} else if (!findInAncestors) {
return null;
}
if (getDOM().isShadowRoot(elem)) {
return this.findTestabilityInTree(registry, elem.host, true);
}
return this.findTestabilityInTree(registry, elem.parentElement, true);
}
};
var BrowserXhr = class _BrowserXhr {
build() {
return new XMLHttpRequest();
}
static \u0275fac = function BrowserXhr_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BrowserXhr)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _BrowserXhr,
factory: _BrowserXhr.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BrowserXhr, [{
type: Injectable
}], null, null);
})();
var DomEventsPlugin = class _DomEventsPlugin extends EventManagerPlugin {
constructor(doc) {
super(doc);
}
// This plugin should come last in the list of plugins, because it accepts all
// events.
supports(eventName) {
return true;
}
addEventListener(element, eventName, handler, options) {
element.addEventListener(eventName, handler, options);
return () => this.removeEventListener(element, eventName, handler, options);
}
removeEventListener(target, eventName, callback, options) {
return target.removeEventListener(eventName, callback, options);
}
static \u0275fac = function DomEventsPlugin_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DomEventsPlugin)(\u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DomEventsPlugin,
factory: _DomEventsPlugin.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DomEventsPlugin, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
var MODIFIER_KEYS = ["alt", "control", "meta", "shift"];
var _keyMap = {
"\b": "Backspace",
" ": "Tab",
"\x7F": "Delete",
"\x1B": "Escape",
"Del": "Delete",
"Esc": "Escape",
"Left": "ArrowLeft",
"Right": "ArrowRight",
"Up": "ArrowUp",
"Down": "ArrowDown",
"Menu": "ContextMenu",
"Scroll": "ScrollLock",
"Win": "OS"
};
var MODIFIER_KEY_GETTERS = {
"alt": (event) => event.altKey,
"control": (event) => event.ctrlKey,
"meta": (event) => event.metaKey,
"shift": (event) => event.shiftKey
};
var KeyEventsPlugin = class _KeyEventsPlugin extends EventManagerPlugin {
/**
* Initializes an instance of the browser plug-in.
* @param doc The document in which key events will be detected.
*/
constructor(doc) {
super(doc);
}
/**
* Reports whether a named key event is supported.
* @param eventName The event name to query.
* @return True if the named key event is supported.
*/
supports(eventName) {
return _KeyEventsPlugin.parseEventName(eventName) != null;
}
/**
* Registers a handler for a specific element and key event.
* @param element The HTML element to receive event notifications.
* @param eventName The name of the key event to listen for.
* @param handler A function to call when the notification occurs. Receives the
* event object as an argument.
* @returns The key event that was registered.
*/
addEventListener(element, eventName, handler, options) {
const parsedEvent = _KeyEventsPlugin.parseEventName(eventName);
const outsideHandler = _KeyEventsPlugin.eventCallback(parsedEvent["fullKey"], handler, this.manager.getZone());
return this.manager.getZone().runOutsideAngular(() => {
return getDOM().onAndCancel(element, parsedEvent["domEventName"], outsideHandler, options);
});
}
/**
* Parses the user provided full keyboard event definition and normalizes it for
* later internal use. It ensures the string is all lowercase, converts special
* characters to a standard spelling, and orders all the values consistently.
*
* @param eventName The name of the key event to listen for.
* @returns an object with the full, normalized string, and the dom event name
* or null in the case when the event doesn't match a keyboard event.
*/
static parseEventName(eventName) {
const parts = eventName.toLowerCase().split(".");
const domEventName = parts.shift();
if (parts.length === 0 || !(domEventName === "keydown" || domEventName === "keyup")) {
return null;
}
const key = _KeyEventsPlugin._normalizeKey(parts.pop());
let fullKey = "";
let codeIX = parts.indexOf("code");
if (codeIX > -1) {
parts.splice(codeIX, 1);
fullKey = "code.";
}
MODIFIER_KEYS.forEach((modifierName) => {
const index = parts.indexOf(modifierName);
if (index > -1) {
parts.splice(index, 1);
fullKey += modifierName + ".";
}
});
fullKey += key;
if (parts.length != 0 || key.length === 0) {
return null;
}
const result = {};
result["domEventName"] = domEventName;
result["fullKey"] = fullKey;
return result;
}
/**
* Determines whether the actual keys pressed match the configured key code string.
* The `fullKeyCode` event is normalized in the `parseEventName` method when the
* event is attached to the DOM during the `addEventListener` call. This is unseen
* by the end user and is normalized for internal consistency and parsing.
*
* @param event The keyboard event.
* @param fullKeyCode The normalized user defined expected key event string
* @returns boolean.
*/
static matchEventFullKeyCode(event, fullKeyCode) {
let keycode = _keyMap[event.key] || event.key;
let key = "";
if (fullKeyCode.indexOf("code.") > -1) {
keycode = event.code;
key = "code.";
}
if (keycode == null || !keycode) return false;
keycode = keycode.toLowerCase();
if (keycode === " ") {
keycode = "space";
} else if (keycode === ".") {
keycode = "dot";
}
MODIFIER_KEYS.forEach((modifierName) => {
if (modifierName !== keycode) {
const modifierGetter = MODIFIER_KEY_GETTERS[modifierName];
if (modifierGetter(event)) {
key += modifierName + ".";
}
}
});
key += keycode;
return key === fullKeyCode;
}
/**
* Configures a handler callback for a key event.
* @param fullKey The event name that combines all simultaneous keystrokes.
* @param handler The function that responds to the key event.
* @param zone The zone in which the event occurred.
* @returns A callback function.
*/
static eventCallback(fullKey, handler, zone) {
return (event) => {
if (_KeyEventsPlugin.matchEventFullKeyCode(event, fullKey)) {
zone.runGuarded(() => handler(event));
}
};
}
/** @internal */
static _normalizeKey(keyName) {
return keyName === "esc" ? "escape" : keyName;
}
static \u0275fac = function KeyEventsPlugin_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _KeyEventsPlugin)(\u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _KeyEventsPlugin,
factory: _KeyEventsPlugin.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(KeyEventsPlugin, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
function initDomAdapter() {
BrowserDomAdapter.makeCurrent();
}
function errorHandler() {
return new ErrorHandler();
}
function _document() {
setDocument(document);
return document;
}
var INTERNAL_BROWSER_PLATFORM_PROVIDERS = [{
provide: PLATFORM_ID,
useValue: PLATFORM_BROWSER_ID
}, {
provide: PLATFORM_INITIALIZER,
useValue: initDomAdapter,
multi: true
}, {
provide: DOCUMENT,
useFactory: _document
}];
var platformBrowser = createPlatformFactory(platformCore, "browser", INTERNAL_BROWSER_PLATFORM_PROVIDERS);
var BROWSER_MODULE_PROVIDERS_MARKER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "BrowserModule Providers Marker" : "");
var TESTABILITY_PROVIDERS = [{
provide: TESTABILITY_GETTER,
useClass: BrowserGetTestability
}, {
provide: TESTABILITY,
useClass: Testability,
deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER]
}, {
provide: Testability,
// Also provide as `Testability` for backwards-compatibility.
useClass: Testability,
deps: [NgZone, TestabilityRegistry, TESTABILITY_GETTER]
}];
var BROWSER_MODULE_PROVIDERS = [{
provide: INJECTOR_SCOPE,
useValue: "root"
}, {
provide: ErrorHandler,
useFactory: errorHandler
}, {
provide: EVENT_MANAGER_PLUGINS,
useClass: DomEventsPlugin,
multi: true,
deps: [DOCUMENT]
}, {
provide: EVENT_MANAGER_PLUGINS,
useClass: KeyEventsPlugin,
multi: true,
deps: [DOCUMENT]
}, DomRendererFactory2, SharedStylesHost, EventManager, {
provide: RendererFactory2,
useExisting: DomRendererFactory2
}, {
provide: XhrFactory,
useClass: BrowserXhr
}, typeof ngDevMode === "undefined" || ngDevMode ? {
provide: BROWSER_MODULE_PROVIDERS_MARKER,
useValue: true
} : []];
var BrowserModule = class _BrowserModule {
constructor() {
if (typeof ngDevMode === "undefined" || ngDevMode) {
const providersAlreadyPresent = inject(BROWSER_MODULE_PROVIDERS_MARKER, {
optional: true,
skipSelf: true
});
if (providersAlreadyPresent) {
throw new RuntimeError(5100, `Providers from the \`BrowserModule\` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the \`CommonModule\` instead.`);
}
}
}
static \u0275fac = function BrowserModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BrowserModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _BrowserModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS],
imports: [CommonModule, ApplicationModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BrowserModule, [{
type: NgModule,
args: [{
providers: [...BROWSER_MODULE_PROVIDERS, ...TESTABILITY_PROVIDERS],
exports: [CommonModule, ApplicationModule]
}]
}], () => [], null);
})();
// node_modules/@angular/common/fesm2022/module-CYx9OwZ_.mjs
var HttpHandler = class {
};
var HttpBackend = class {
};
var HttpHeaders = class _HttpHeaders {
/**
* Internal map of lowercase header names to values.
*/
headers;
/**
* Internal map of lowercased header names to the normalized
* form of the name (the form seen first).
*/
normalizedNames = /* @__PURE__ */ new Map();
/**
* Complete the lazy initialization of this object (needed before reading).
*/
lazyInit;
/**
* Queued updates to be materialized the next initialization.
*/
lazyUpdate = null;
/** Constructs a new HTTP header object with the given values.*/
constructor(headers) {
if (!headers) {
this.headers = /* @__PURE__ */ new Map();
} else if (typeof headers === "string") {
this.lazyInit = () => {
this.headers = /* @__PURE__ */ new Map();
headers.split("\n").forEach((line) => {
const index = line.indexOf(":");
if (index > 0) {
const name = line.slice(0, index);
const value = line.slice(index + 1).trim();
this.addHeaderEntry(name, value);
}
});
};
} else if (typeof Headers !== "undefined" && headers instanceof Headers) {
this.headers = /* @__PURE__ */ new Map();
headers.forEach((value, name) => {
this.addHeaderEntry(name, value);
});
} else {
this.lazyInit = () => {
if (typeof ngDevMode === "undefined" || ngDevMode) {
assertValidHeaders(headers);
}
this.headers = /* @__PURE__ */ new Map();
Object.entries(headers).forEach(([name, values]) => {
this.setHeaderEntries(name, values);
});
};
}
}
/**
* Checks for existence of a given header.
*
* @param name The header name to check for existence.
*
* @returns True if the header exists, false otherwise.
*/
has(name) {
this.init();
return this.headers.has(name.toLowerCase());
}
/**
* Retrieves the first value of a given header.
*
* @param name The header name.
*
* @returns The value string if the header exists, null otherwise
*/
get(name) {
this.init();
const values = this.headers.get(name.toLowerCase());
return values && values.length > 0 ? values[0] : null;
}
/**
* Retrieves the names of the headers.
*
* @returns A list of header names.
*/
keys() {
this.init();
return Array.from(this.normalizedNames.values());
}
/**
* Retrieves a list of values for a given header.
*
* @param name The header name from which to retrieve values.
*
* @returns A string of values if the header exists, null otherwise.
*/
getAll(name) {
this.init();
return this.headers.get(name.toLowerCase()) || null;
}
/**
* Appends a new value to the existing set of values for a header
* and returns them in a clone of the original instance.
*
* @param name The header name for which to append the values.
* @param value The value to append.
*
* @returns A clone of the HTTP headers object with the value appended to the given header.
*/
append(name, value) {
return this.clone({
name,
value,
op: "a"
});
}
/**
* Sets or modifies a value for a given header in a clone of the original instance.
* If the header already exists, its value is replaced with the given value
* in the returned object.
*
* @param name The header name.
* @param value The value or values to set or override for the given header.
*
* @returns A clone of the HTTP headers object with the newly set header value.
*/
set(name, value) {
return this.clone({
name,
value,
op: "s"
});
}
/**
* Deletes values for a given header in a clone of the original instance.
*
* @param name The header name.
* @param value The value or values to delete for the given header.
*
* @returns A clone of the HTTP headers object with the given value deleted.
*/
delete(name, value) {
return this.clone({
name,
value,
op: "d"
});
}
maybeSetNormalizedName(name, lcName) {
if (!this.normalizedNames.has(lcName)) {
this.normalizedNames.set(lcName, name);
}
}
init() {
if (!!this.lazyInit) {
if (this.lazyInit instanceof _HttpHeaders) {
this.copyFrom(this.lazyInit);
} else {
this.lazyInit();
}
this.lazyInit = null;
if (!!this.lazyUpdate) {
this.lazyUpdate.forEach((update) => this.applyUpdate(update));
this.lazyUpdate = null;
}
}
}
copyFrom(other) {
other.init();
Array.from(other.headers.keys()).forEach((key) => {
this.headers.set(key, other.headers.get(key));
this.normalizedNames.set(key, other.normalizedNames.get(key));
});
}
clone(update) {
const clone = new _HttpHeaders();
clone.lazyInit = !!this.lazyInit && this.lazyInit instanceof _HttpHeaders ? this.lazyInit : this;
clone.lazyUpdate = (this.lazyUpdate || []).concat([update]);
return clone;
}
applyUpdate(update) {
const key = update.name.toLowerCase();
switch (update.op) {
case "a":
case "s":
let value = update.value;
if (typeof value === "string") {
value = [value];
}
if (value.length === 0) {
return;
}
this.maybeSetNormalizedName(update.name, key);
const base = (update.op === "a" ? this.headers.get(key) : void 0) || [];
base.push(...value);
this.headers.set(key, base);
break;
case "d":
const toDelete = update.value;
if (!toDelete) {
this.headers.delete(key);
this.normalizedNames.delete(key);
} else {
let existing = this.headers.get(key);
if (!existing) {
return;
}
existing = existing.filter((value2) => toDelete.indexOf(value2) === -1);
if (existing.length === 0) {
this.headers.delete(key);
this.normalizedNames.delete(key);
} else {
this.headers.set(key, existing);
}
}
break;
}
}
addHeaderEntry(name, value) {
const key = name.toLowerCase();
this.maybeSetNormalizedName(name, key);
if (this.headers.has(key)) {
this.headers.get(key).push(value);
} else {
this.headers.set(key, [value]);
}
}
setHeaderEntries(name, values) {
const headerValues = (Array.isArray(values) ? values : [values]).map((value) => value.toString());
const key = name.toLowerCase();
this.headers.set(key, headerValues);
this.maybeSetNormalizedName(name, key);
}
/**
* @internal
*/
forEach(fn) {
this.init();
Array.from(this.normalizedNames.keys()).forEach((key) => fn(this.normalizedNames.get(key), this.headers.get(key)));
}
};
function assertValidHeaders(headers) {
for (const [key, value] of Object.entries(headers)) {
if (!(typeof value === "string" || typeof value === "number") && !Array.isArray(value)) {
throw new Error(`Unexpected value of the \`${key}\` header provided. Expecting either a string, a number or an array, but got: \`${value}\`.`);
}
}
}
var HttpUrlEncodingCodec = class {
/**
* Encodes a key name for a URL parameter or query-string.
* @param key The key name.
* @returns The encoded key name.
*/
encodeKey(key) {
return standardEncoding(key);
}
/**
* Encodes the value of a URL parameter or query-string.
* @param value The value.
* @returns The encoded value.
*/
encodeValue(value) {
return standardEncoding(value);
}
/**
* Decodes an encoded URL parameter or query-string key.
* @param key The encoded key name.
* @returns The decoded key name.
*/
decodeKey(key) {
return decodeURIComponent(key);
}
/**
* Decodes an encoded URL parameter or query-string value.
* @param value The encoded value.
* @returns The decoded value.
*/
decodeValue(value) {
return decodeURIComponent(value);
}
};
function paramParser(rawParams, codec) {
const map2 = /* @__PURE__ */ new Map();
if (rawParams.length > 0) {
const params = rawParams.replace(/^\?/, "").split("&");
params.forEach((param) => {
const eqIdx = param.indexOf("=");
const [key, val] = eqIdx == -1 ? [codec.decodeKey(param), ""] : [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))];
const list = map2.get(key) || [];
list.push(val);
map2.set(key, list);
});
}
return map2;
}
var STANDARD_ENCODING_REGEX = /%(\d[a-f0-9])/gi;
var STANDARD_ENCODING_REPLACEMENTS = {
"40": "@",
"3A": ":",
"24": "$",
"2C": ",",
"3B": ";",
"3D": "=",
"3F": "?",
"2F": "/"
};
function standardEncoding(v) {
return encodeURIComponent(v).replace(STANDARD_ENCODING_REGEX, (s, t) => STANDARD_ENCODING_REPLACEMENTS[t] ?? s);
}
function valueToString(value) {
return `${value}`;
}
var HttpParams = class _HttpParams {
map;
encoder;
updates = null;
cloneFrom = null;
constructor(options = {}) {
this.encoder = options.encoder || new HttpUrlEncodingCodec();
if (options.fromString) {
if (options.fromObject) {
throw new RuntimeError(2805, ngDevMode && "Cannot specify both fromString and fromObject.");
}
this.map = paramParser(options.fromString, this.encoder);
} else if (!!options.fromObject) {
this.map = /* @__PURE__ */ new Map();
Object.keys(options.fromObject).forEach((key) => {
const value = options.fromObject[key];
const values = Array.isArray(value) ? value.map(valueToString) : [valueToString(value)];
this.map.set(key, values);
});
} else {
this.map = null;
}
}
/**
* Reports whether the body includes one or more values for a given parameter.
* @param param The parameter name.
* @returns True if the parameter has one or more values,
* false if it has no value or is not present.
*/
has(param) {
this.init();
return this.map.has(param);
}
/**
* Retrieves the first value for a parameter.
* @param param The parameter name.
* @returns The first value of the given parameter,
* or `null` if the parameter is not present.
*/
get(param) {
this.init();
const res = this.map.get(param);
return !!res ? res[0] : null;
}
/**
* Retrieves all values for a parameter.
* @param param The parameter name.
* @returns All values in a string array,
* or `null` if the parameter not present.
*/
getAll(param) {
this.init();
return this.map.get(param) || null;
}
/**
* Retrieves all the parameters for this body.
* @returns The parameter names in a string array.
*/
keys() {
this.init();
return Array.from(this.map.keys());
}
/**
* Appends a new value to existing values for a parameter.
* @param param The parameter name.
* @param value The new value to add.
* @return A new body with the appended value.
*/
append(param, value) {
return this.clone({
param,
value,
op: "a"
});
}
/**
* Constructs a new body with appended values for the given parameter name.
* @param params parameters and values
* @return A new body with the new value.
*/
appendAll(params) {
const updates = [];
Object.keys(params).forEach((param) => {
const value = params[param];
if (Array.isArray(value)) {
value.forEach((_value) => {
updates.push({
param,
value: _value,
op: "a"
});
});
} else {
updates.push({
param,
value,
op: "a"
});
}
});
return this.clone(updates);
}
/**
* Replaces the value for a parameter.
* @param param The parameter name.
* @param value The new value.
* @return A new body with the new value.
*/
set(param, value) {
return this.clone({
param,
value,
op: "s"
});
}
/**
* Removes a given value or all values from a parameter.
* @param param The parameter name.
* @param value The value to remove, if provided.
* @return A new body with the given value removed, or with all values
* removed if no value is specified.
*/
delete(param, value) {
return this.clone({
param,
value,
op: "d"
});
}
/**
* Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
* separated by `&`s.
*/
toString() {
this.init();
return this.keys().map((key) => {
const eKey = this.encoder.encodeKey(key);
return this.map.get(key).map((value) => eKey + "=" + this.encoder.encodeValue(value)).join("&");
}).filter((param) => param !== "").join("&");
}
clone(update) {
const clone = new _HttpParams({
encoder: this.encoder
});
clone.cloneFrom = this.cloneFrom || this;
clone.updates = (this.updates || []).concat(update);
return clone;
}
init() {
if (this.map === null) {
this.map = /* @__PURE__ */ new Map();
}
if (this.cloneFrom !== null) {
this.cloneFrom.init();
this.cloneFrom.keys().forEach((key) => this.map.set(key, this.cloneFrom.map.get(key)));
this.updates.forEach((update) => {
switch (update.op) {
case "a":
case "s":
const base = (update.op === "a" ? this.map.get(update.param) : void 0) || [];
base.push(valueToString(update.value));
this.map.set(update.param, base);
break;
case "d":
if (update.value !== void 0) {
let base2 = this.map.get(update.param) || [];
const idx = base2.indexOf(valueToString(update.value));
if (idx !== -1) {
base2.splice(idx, 1);
}
if (base2.length > 0) {
this.map.set(update.param, base2);
} else {
this.map.delete(update.param);
}
} else {
this.map.delete(update.param);
break;
}
}
});
this.cloneFrom = this.updates = null;
}
}
};
var HttpContext = class {
map = /* @__PURE__ */ new Map();
/**
* Store a value in the context. If a value is already present it will be overwritten.
*
* @param token The reference to an instance of `HttpContextToken`.
* @param value The value to store.
*
* @returns A reference to itself for easy chaining.
*/
set(token, value) {
this.map.set(token, value);
return this;
}
/**
* Retrieve the value associated with the given token.
*
* @param token The reference to an instance of `HttpContextToken`.
*
* @returns The stored value or default if one is defined.
*/
get(token) {
if (!this.map.has(token)) {
this.map.set(token, token.defaultValue());
}
return this.map.get(token);
}
/**
* Delete the value associated with the given token.
*
* @param token The reference to an instance of `HttpContextToken`.
*
* @returns A reference to itself for easy chaining.
*/
delete(token) {
this.map.delete(token);
return this;
}
/**
* Checks for existence of a given token.
*
* @param token The reference to an instance of `HttpContextToken`.
*
* @returns True if the token exists, false otherwise.
*/
has(token) {
return this.map.has(token);
}
/**
* @returns a list of tokens currently stored in the context.
*/
keys() {
return this.map.keys();
}
};
function mightHaveBody(method) {
switch (method) {
case "DELETE":
case "GET":
case "HEAD":
case "OPTIONS":
case "JSONP":
return false;
default:
return true;
}
}
function isArrayBuffer(value) {
return typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer;
}
function isBlob(value) {
return typeof Blob !== "undefined" && value instanceof Blob;
}
function isFormData(value) {
return typeof FormData !== "undefined" && value instanceof FormData;
}
function isUrlSearchParams(value) {
return typeof URLSearchParams !== "undefined" && value instanceof URLSearchParams;
}
var CONTENT_TYPE_HEADER = "Content-Type";
var ACCEPT_HEADER = "Accept";
var X_REQUEST_URL_HEADER = "X-Request-URL";
var TEXT_CONTENT_TYPE = "text/plain";
var JSON_CONTENT_TYPE = "application/json";
var ACCEPT_HEADER_VALUE = `${JSON_CONTENT_TYPE}, ${TEXT_CONTENT_TYPE}, */*`;
var HttpRequest = class _HttpRequest {
url;
/**
* The request body, or `null` if one isn't set.
*
* Bodies are not enforced to be immutable, as they can include a reference to any
* user-defined data type. However, interceptors should take care to preserve
* idempotence by treating them as such.
*/
body = null;
/**
* Outgoing headers for this request.
*/
headers;
/**
* Shared and mutable context that can be used by interceptors
*/
context;
/**
* Whether this request should be made in a way that exposes progress events.
*
* Progress events are expensive (change detection runs on each event) and so
* they should only be requested if the consumer intends to monitor them.
*
* Note: The `FetchBackend` doesn't support progress report on uploads.
*/
reportProgress = false;
/**
* Whether this request should be sent with outgoing credentials (cookies).
*/
withCredentials = false;
/**
* The expected response type of the server.
*
* This is used to parse the response appropriately before returning it to
* the requestee.
*/
responseType = "json";
/**
* The outgoing HTTP request method.
*/
method;
/**
* Outgoing URL parameters.
*
* To pass a string representation of HTTP parameters in the URL-query-string format,
* the `HttpParamsOptions`' `fromString` may be used. For example:
*
* ```ts
* new HttpParams({fromString: 'angular=awesome'})
* ```
*/
params;
/**
* The outgoing URL with all URL parameters set.
*/
urlWithParams;
/**
* The HttpTransferCache option for the request
*/
transferCache;
constructor(method, url, third, fourth) {
this.url = url;
this.method = method.toUpperCase();
let options;
if (mightHaveBody(this.method) || !!fourth) {
this.body = third !== void 0 ? third : null;
options = fourth;
} else {
options = third;
}
if (options) {
this.reportProgress = !!options.reportProgress;
this.withCredentials = !!options.withCredentials;
if (!!options.responseType) {
this.responseType = options.responseType;
}
if (!!options.headers) {
this.headers = options.headers;
}
if (!!options.context) {
this.context = options.context;
}
if (!!options.params) {
this.params = options.params;
}
this.transferCache = options.transferCache;
}
this.headers ??= new HttpHeaders();
this.context ??= new HttpContext();
if (!this.params) {
this.params = new HttpParams();
this.urlWithParams = url;
} else {
const params = this.params.toString();
if (params.length === 0) {
this.urlWithParams = url;
} else {
const qIdx = url.indexOf("?");
const sep = qIdx === -1 ? "?" : qIdx < url.length - 1 ? "&" : "";
this.urlWithParams = url + sep + params;
}
}
}
/**
* Transform the free-form body into a serialized format suitable for
* transmission to the server.
*/
serializeBody() {
if (this.body === null) {
return null;
}
if (typeof this.body === "string" || isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) || isUrlSearchParams(this.body)) {
return this.body;
}
if (this.body instanceof HttpParams) {
return this.body.toString();
}
if (typeof this.body === "object" || typeof this.body === "boolean" || Array.isArray(this.body)) {
return JSON.stringify(this.body);
}
return this.body.toString();
}
/**
* Examine the body and attempt to infer an appropriate MIME type
* for it.
*
* If no such type can be inferred, this method will return `null`.
*/
detectContentTypeHeader() {
if (this.body === null) {
return null;
}
if (isFormData(this.body)) {
return null;
}
if (isBlob(this.body)) {
return this.body.type || null;
}
if (isArrayBuffer(this.body)) {
return null;
}
if (typeof this.body === "string") {
return TEXT_CONTENT_TYPE;
}
if (this.body instanceof HttpParams) {
return "application/x-www-form-urlencoded;charset=UTF-8";
}
if (typeof this.body === "object" || typeof this.body === "number" || typeof this.body === "boolean") {
return JSON_CONTENT_TYPE;
}
return null;
}
clone(update = {}) {
const method = update.method || this.method;
const url = update.url || this.url;
const responseType = update.responseType || this.responseType;
const transferCache = update.transferCache ?? this.transferCache;
const body = update.body !== void 0 ? update.body : this.body;
const withCredentials = update.withCredentials ?? this.withCredentials;
const reportProgress = update.reportProgress ?? this.reportProgress;
let headers = update.headers || this.headers;
let params = update.params || this.params;
const context = update.context ?? this.context;
if (update.setHeaders !== void 0) {
headers = Object.keys(update.setHeaders).reduce((headers2, name) => headers2.set(name, update.setHeaders[name]), headers);
}
if (update.setParams) {
params = Object.keys(update.setParams).reduce((params2, param) => params2.set(param, update.setParams[param]), params);
}
return new _HttpRequest(method, url, body, {
params,
headers,
context,
reportProgress,
responseType,
withCredentials,
transferCache
});
}
};
var HttpEventType;
(function(HttpEventType2) {
HttpEventType2[HttpEventType2["Sent"] = 0] = "Sent";
HttpEventType2[HttpEventType2["UploadProgress"] = 1] = "UploadProgress";
HttpEventType2[HttpEventType2["ResponseHeader"] = 2] = "ResponseHeader";
HttpEventType2[HttpEventType2["DownloadProgress"] = 3] = "DownloadProgress";
HttpEventType2[HttpEventType2["Response"] = 4] = "Response";
HttpEventType2[HttpEventType2["User"] = 5] = "User";
})(HttpEventType || (HttpEventType = {}));
var HttpResponseBase = class {
/**
* All response headers.
*/
headers;
/**
* Response status code.
*/
status;
/**
* Textual description of response status code, defaults to OK.
*
* Do not depend on this.
*/
statusText;
/**
* URL of the resource retrieved, or null if not available.
*/
url;
/**
* Whether the status code falls in the 2xx range.
*/
ok;
/**
* Type of the response, narrowed to either the full response or the header.
*/
type;
/**
* Super-constructor for all responses.
*
* The single parameter accepted is an initialization hash. Any properties
* of the response passed there will override the default values.
*/
constructor(init, defaultStatus = 200, defaultStatusText = "OK") {
this.headers = init.headers || new HttpHeaders();
this.status = init.status !== void 0 ? init.status : defaultStatus;
this.statusText = init.statusText || defaultStatusText;
this.url = init.url || null;
this.ok = this.status >= 200 && this.status < 300;
}
};
var HttpHeaderResponse = class _HttpHeaderResponse extends HttpResponseBase {
/**
* Create a new `HttpHeaderResponse` with the given parameters.
*/
constructor(init = {}) {
super(init);
}
type = HttpEventType.ResponseHeader;
/**
* Copy this `HttpHeaderResponse`, overriding its contents with the
* given parameter hash.
*/
clone(update = {}) {
return new _HttpHeaderResponse({
headers: update.headers || this.headers,
status: update.status !== void 0 ? update.status : this.status,
statusText: update.statusText || this.statusText,
url: update.url || this.url || void 0
});
}
};
var HttpResponse = class _HttpResponse extends HttpResponseBase {
/**
* The response body, or `null` if one was not returned.
*/
body;
/**
* Construct a new `HttpResponse`.
*/
constructor(init = {}) {
super(init);
this.body = init.body !== void 0 ? init.body : null;
}
type = HttpEventType.Response;
clone(update = {}) {
return new _HttpResponse({
body: update.body !== void 0 ? update.body : this.body,
headers: update.headers || this.headers,
status: update.status !== void 0 ? update.status : this.status,
statusText: update.statusText || this.statusText,
url: update.url || this.url || void 0
});
}
};
var HttpErrorResponse = class extends HttpResponseBase {
name = "HttpErrorResponse";
message;
error;
/**
* Errors are never okay, even when the status code is in the 2xx success range.
*/
ok = false;
constructor(init) {
super(init, 0, "Unknown Error");
if (this.status >= 200 && this.status < 300) {
this.message = `Http failure during parsing for ${init.url || "(unknown url)"}`;
} else {
this.message = `Http failure response for ${init.url || "(unknown url)"}: ${init.status} ${init.statusText}`;
}
this.error = init.error || null;
}
};
var HTTP_STATUS_CODE_OK = 200;
var HTTP_STATUS_CODE_NO_CONTENT = 204;
var HttpStatusCode;
(function(HttpStatusCode2) {
HttpStatusCode2[HttpStatusCode2["Continue"] = 100] = "Continue";
HttpStatusCode2[HttpStatusCode2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
HttpStatusCode2[HttpStatusCode2["Processing"] = 102] = "Processing";
HttpStatusCode2[HttpStatusCode2["EarlyHints"] = 103] = "EarlyHints";
HttpStatusCode2[HttpStatusCode2["Ok"] = 200] = "Ok";
HttpStatusCode2[HttpStatusCode2["Created"] = 201] = "Created";
HttpStatusCode2[HttpStatusCode2["Accepted"] = 202] = "Accepted";
HttpStatusCode2[HttpStatusCode2["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
HttpStatusCode2[HttpStatusCode2["NoContent"] = 204] = "NoContent";
HttpStatusCode2[HttpStatusCode2["ResetContent"] = 205] = "ResetContent";
HttpStatusCode2[HttpStatusCode2["PartialContent"] = 206] = "PartialContent";
HttpStatusCode2[HttpStatusCode2["MultiStatus"] = 207] = "MultiStatus";
HttpStatusCode2[HttpStatusCode2["AlreadyReported"] = 208] = "AlreadyReported";
HttpStatusCode2[HttpStatusCode2["ImUsed"] = 226] = "ImUsed";
HttpStatusCode2[HttpStatusCode2["MultipleChoices"] = 300] = "MultipleChoices";
HttpStatusCode2[HttpStatusCode2["MovedPermanently"] = 301] = "MovedPermanently";
HttpStatusCode2[HttpStatusCode2["Found"] = 302] = "Found";
HttpStatusCode2[HttpStatusCode2["SeeOther"] = 303] = "SeeOther";
HttpStatusCode2[HttpStatusCode2["NotModified"] = 304] = "NotModified";
HttpStatusCode2[HttpStatusCode2["UseProxy"] = 305] = "UseProxy";
HttpStatusCode2[HttpStatusCode2["Unused"] = 306] = "Unused";
HttpStatusCode2[HttpStatusCode2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
HttpStatusCode2[HttpStatusCode2["PermanentRedirect"] = 308] = "PermanentRedirect";
HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest";
HttpStatusCode2[HttpStatusCode2["Unauthorized"] = 401] = "Unauthorized";
HttpStatusCode2[HttpStatusCode2["PaymentRequired"] = 402] = "PaymentRequired";
HttpStatusCode2[HttpStatusCode2["Forbidden"] = 403] = "Forbidden";
HttpStatusCode2[HttpStatusCode2["NotFound"] = 404] = "NotFound";
HttpStatusCode2[HttpStatusCode2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
HttpStatusCode2[HttpStatusCode2["NotAcceptable"] = 406] = "NotAcceptable";
HttpStatusCode2[HttpStatusCode2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
HttpStatusCode2[HttpStatusCode2["RequestTimeout"] = 408] = "RequestTimeout";
HttpStatusCode2[HttpStatusCode2["Conflict"] = 409] = "Conflict";
HttpStatusCode2[HttpStatusCode2["Gone"] = 410] = "Gone";
HttpStatusCode2[HttpStatusCode2["LengthRequired"] = 411] = "LengthRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionFailed"] = 412] = "PreconditionFailed";
HttpStatusCode2[HttpStatusCode2["PayloadTooLarge"] = 413] = "PayloadTooLarge";
HttpStatusCode2[HttpStatusCode2["UriTooLong"] = 414] = "UriTooLong";
HttpStatusCode2[HttpStatusCode2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
HttpStatusCode2[HttpStatusCode2["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
HttpStatusCode2[HttpStatusCode2["ExpectationFailed"] = 417] = "ExpectationFailed";
HttpStatusCode2[HttpStatusCode2["ImATeapot"] = 418] = "ImATeapot";
HttpStatusCode2[HttpStatusCode2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
HttpStatusCode2[HttpStatusCode2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
HttpStatusCode2[HttpStatusCode2["Locked"] = 423] = "Locked";
HttpStatusCode2[HttpStatusCode2["FailedDependency"] = 424] = "FailedDependency";
HttpStatusCode2[HttpStatusCode2["TooEarly"] = 425] = "TooEarly";
HttpStatusCode2[HttpStatusCode2["UpgradeRequired"] = 426] = "UpgradeRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionRequired"] = 428] = "PreconditionRequired";
HttpStatusCode2[HttpStatusCode2["TooManyRequests"] = 429] = "TooManyRequests";
HttpStatusCode2[HttpStatusCode2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
HttpStatusCode2[HttpStatusCode2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
HttpStatusCode2[HttpStatusCode2["InternalServerError"] = 500] = "InternalServerError";
HttpStatusCode2[HttpStatusCode2["NotImplemented"] = 501] = "NotImplemented";
HttpStatusCode2[HttpStatusCode2["BadGateway"] = 502] = "BadGateway";
HttpStatusCode2[HttpStatusCode2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
HttpStatusCode2[HttpStatusCode2["GatewayTimeout"] = 504] = "GatewayTimeout";
HttpStatusCode2[HttpStatusCode2["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
HttpStatusCode2[HttpStatusCode2["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
HttpStatusCode2[HttpStatusCode2["InsufficientStorage"] = 507] = "InsufficientStorage";
HttpStatusCode2[HttpStatusCode2["LoopDetected"] = 508] = "LoopDetected";
HttpStatusCode2[HttpStatusCode2["NotExtended"] = 510] = "NotExtended";
HttpStatusCode2[HttpStatusCode2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
})(HttpStatusCode || (HttpStatusCode = {}));
function addBody(options, body) {
return {
body,
headers: options.headers,
context: options.context,
observe: options.observe,
params: options.params,
reportProgress: options.reportProgress,
responseType: options.responseType,
withCredentials: options.withCredentials,
transferCache: options.transferCache
};
}
var HttpClient = class _HttpClient {
handler;
constructor(handler) {
this.handler = handler;
}
/**
* Constructs an observable for a generic HTTP request that, when subscribed,
* fires the request through the chain of registered interceptors and on to the
* server.
*
* You can pass an `HttpRequest` directly as the only parameter. In this case,
* the call returns an observable of the raw `HttpEvent` stream.
*
* Alternatively you can pass an HTTP method as the first parameter,
* a URL string as the second, and an options hash containing the request body as the third.
* See `addBody()`. In this case, the specified `responseType` and `observe` options determine the
* type of returned observable.
* * The `responseType` value determines how a successful response body is parsed.
* * If `responseType` is the default `json`, you can pass a type interface for the resulting
* object as a type parameter to the call.
*
* The `observe` value determines the return type, according to what you are interested in
* observing.
* * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including
* progress events by default.
* * An `observe` value of response returns an observable of `HttpResponse<T>`,
* where the `T` parameter depends on the `responseType` and any optionally provided type
* parameter.
* * An `observe` value of body returns an observable of `<T>` with the same `T` body type.
*
*/
request(first2, url, options = {}) {
let req;
if (first2 instanceof HttpRequest) {
req = first2;
} else {
let headers = void 0;
if (options.headers instanceof HttpHeaders) {
headers = options.headers;
} else {
headers = new HttpHeaders(options.headers);
}
let params = void 0;
if (!!options.params) {
if (options.params instanceof HttpParams) {
params = options.params;
} else {
params = new HttpParams({
fromObject: options.params
});
}
}
req = new HttpRequest(first2, url, options.body !== void 0 ? options.body : null, {
headers,
context: options.context,
params,
reportProgress: options.reportProgress,
// By default, JSON is assumed to be returned for all calls.
responseType: options.responseType || "json",
withCredentials: options.withCredentials,
transferCache: options.transferCache
});
}
const events$ = of(req).pipe(concatMap((req2) => this.handler.handle(req2)));
if (first2 instanceof HttpRequest || options.observe === "events") {
return events$;
}
const res$ = events$.pipe(filter((event) => event instanceof HttpResponse));
switch (options.observe || "body") {
case "body":
switch (req.responseType) {
case "arraybuffer":
return res$.pipe(map((res) => {
if (res.body !== null && !(res.body instanceof ArrayBuffer)) {
throw new RuntimeError(2806, ngDevMode && "Response is not an ArrayBuffer.");
}
return res.body;
}));
case "blob":
return res$.pipe(map((res) => {
if (res.body !== null && !(res.body instanceof Blob)) {
throw new RuntimeError(2807, ngDevMode && "Response is not a Blob.");
}
return res.body;
}));
case "text":
return res$.pipe(map((res) => {
if (res.body !== null && typeof res.body !== "string") {
throw new RuntimeError(2808, ngDevMode && "Response is not a string.");
}
return res.body;
}));
case "json":
default:
return res$.pipe(map((res) => res.body));
}
case "response":
return res$;
default:
throw new RuntimeError(2809, ngDevMode && `Unreachable: unhandled observe type ${options.observe}}`);
}
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `DELETE` request to execute on the server. See the individual overloads for
* details on the return type.
*
* @param url The endpoint URL.
* @param options The HTTP options to send with the request.
*
*/
delete(url, options = {}) {
return this.request("DELETE", url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `GET` request to execute on the server. See the individual overloads for
* details on the return type.
*/
get(url, options = {}) {
return this.request("GET", url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `HEAD` request to execute on the server. The `HEAD` method returns
* meta information about the resource without transferring the
* resource itself. See the individual overloads for
* details on the return type.
*/
head(url, options = {}) {
return this.request("HEAD", url, options);
}
/**
* Constructs an `Observable` that, when subscribed, causes a request with the special method
* `JSONP` to be dispatched via the interceptor pipeline.
* The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain
* API endpoints that don't support newer,
* and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol.
* JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the
* requests even if the API endpoint is not located on the same domain (origin) as the client-side
* application making the request.
* The endpoint API must support JSONP callback for JSONP requests to work.
* The resource API returns the JSON response wrapped in a callback function.
* You can pass the callback function name as one of the query parameters.
* Note that JSONP requests can only be used with `GET` requests.
*
* @param url The resource URL.
* @param callbackParam The callback function name.
*
*/
jsonp(url, callbackParam) {
return this.request("JSONP", url, {
params: new HttpParams().append(callbackParam, "JSONP_CALLBACK"),
observe: "body",
responseType: "json"
});
}
/**
* Constructs an `Observable` that, when subscribed, causes the configured
* `OPTIONS` request to execute on the server. This method allows the client
* to determine the supported HTTP methods and other capabilities of an endpoint,
* without implying a resource action. See the individual overloads for
* details on the return type.
*/
options(url, options = {}) {
return this.request("OPTIONS", url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `PATCH` request to execute on the server. See the individual overloads for
* details on the return type.
*/
patch(url, body, options = {}) {
return this.request("PATCH", url, addBody(options, body));
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `POST` request to execute on the server. The server responds with the location of
* the replaced resource. See the individual overloads for
* details on the return type.
*/
post(url, body, options = {}) {
return this.request("POST", url, addBody(options, body));
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `PUT` request to execute on the server. The `PUT` method replaces an existing resource
* with a new set of values.
* See the individual overloads for details on the return type.
*/
put(url, body, options = {}) {
return this.request("PUT", url, addBody(options, body));
}
static \u0275fac = function HttpClient_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpClient)(\u0275\u0275inject(HttpHandler));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HttpClient,
factory: _HttpClient.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClient, [{
type: Injectable
}], () => [{
type: HttpHandler
}], null);
})();
var XSSI_PREFIX$1 = /^\)\]\}',?\n/;
function getResponseUrl$1(response) {
if (response.url) {
return response.url;
}
const xRequestUrl = X_REQUEST_URL_HEADER.toLocaleLowerCase();
return response.headers.get(xRequestUrl);
}
var FETCH_BACKEND = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "FETCH_BACKEND" : "");
var FetchBackend = class _FetchBackend {
// We use an arrow function to always reference the current global implementation of `fetch`.
// This is helpful for cases when the global `fetch` implementation is modified by external code,
// see https://github.com/angular/angular/issues/57527.
fetchImpl = inject(FetchFactory, {
optional: true
})?.fetch ?? ((...args) => globalThis.fetch(...args));
ngZone = inject(NgZone);
handle(request) {
return new Observable((observer) => {
const aborter = new AbortController();
this.doRequest(request, aborter.signal, observer).then(noop, (error) => observer.error(new HttpErrorResponse({
error
})));
return () => aborter.abort();
});
}
doRequest(request, signal2, observer) {
return __async(this, null, function* () {
const init = this.createRequestInit(request);
let response;
try {
const fetchPromise = this.ngZone.runOutsideAngular(() => this.fetchImpl(request.urlWithParams, __spreadValues({
signal: signal2
}, init)));
silenceSuperfluousUnhandledPromiseRejection(fetchPromise);
observer.next({
type: HttpEventType.Sent
});
response = yield fetchPromise;
} catch (error) {
observer.error(new HttpErrorResponse({
error,
status: error.status ?? 0,
statusText: error.statusText,
url: request.urlWithParams,
headers: error.headers
}));
return;
}
const headers = new HttpHeaders(response.headers);
const statusText = response.statusText;
const url = getResponseUrl$1(response) ?? request.urlWithParams;
let status = response.status;
let body = null;
if (request.reportProgress) {
observer.next(new HttpHeaderResponse({
headers,
status,
statusText,
url
}));
}
if (response.body) {
const contentLength = response.headers.get("content-length");
const chunks = [];
const reader = response.body.getReader();
let receivedLength = 0;
let decoder;
let partialText;
const reqZone = typeof Zone !== "undefined" && Zone.current;
yield this.ngZone.runOutsideAngular(() => __async(this, null, function* () {
while (true) {
const {
done,
value
} = yield reader.read();
if (done) {
break;
}
chunks.push(value);
receivedLength += value.length;
if (request.reportProgress) {
partialText = request.responseType === "text" ? (partialText ?? "") + (decoder ??= new TextDecoder()).decode(value, {
stream: true
}) : void 0;
const reportProgress = () => observer.next({
type: HttpEventType.DownloadProgress,
total: contentLength ? +contentLength : void 0,
loaded: receivedLength,
partialText
});
reqZone ? reqZone.run(reportProgress) : reportProgress();
}
}
}));
const chunksAll = this.concatChunks(chunks, receivedLength);
try {
const contentType = response.headers.get(CONTENT_TYPE_HEADER) ?? "";
body = this.parseBody(request, chunksAll, contentType);
} catch (error) {
observer.error(new HttpErrorResponse({
error,
headers: new HttpHeaders(response.headers),
status: response.status,
statusText: response.statusText,
url: getResponseUrl$1(response) ?? request.urlWithParams
}));
return;
}
}
if (status === 0) {
status = body ? HTTP_STATUS_CODE_OK : 0;
}
const ok = status >= 200 && status < 300;
if (ok) {
observer.next(new HttpResponse({
body,
headers,
status,
statusText,
url
}));
observer.complete();
} else {
observer.error(new HttpErrorResponse({
error: body,
headers,
status,
statusText,
url
}));
}
});
}
parseBody(request, binContent, contentType) {
switch (request.responseType) {
case "json":
const text = new TextDecoder().decode(binContent).replace(XSSI_PREFIX$1, "");
return text === "" ? null : JSON.parse(text);
case "text":
return new TextDecoder().decode(binContent);
case "blob":
return new Blob([binContent], {
type: contentType
});
case "arraybuffer":
return binContent.buffer;
}
}
createRequestInit(req) {
const headers = {};
const credentials = req.withCredentials ? "include" : void 0;
req.headers.forEach((name, values) => headers[name] = values.join(","));
if (!req.headers.has(ACCEPT_HEADER)) {
headers[ACCEPT_HEADER] = ACCEPT_HEADER_VALUE;
}
if (!req.headers.has(CONTENT_TYPE_HEADER)) {
const detectedType = req.detectContentTypeHeader();
if (detectedType !== null) {
headers[CONTENT_TYPE_HEADER] = detectedType;
}
}
return {
body: req.serializeBody(),
method: req.method,
headers,
credentials
};
}
concatChunks(chunks, totalLength) {
const chunksAll = new Uint8Array(totalLength);
let position = 0;
for (const chunk of chunks) {
chunksAll.set(chunk, position);
position += chunk.length;
}
return chunksAll;
}
static \u0275fac = function FetchBackend_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FetchBackend)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FetchBackend,
factory: _FetchBackend.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FetchBackend, [{
type: Injectable
}], null, null);
})();
var FetchFactory = class {
};
function noop() {
}
function silenceSuperfluousUnhandledPromiseRejection(promise) {
promise.then(noop, noop);
}
function interceptorChainEndFn(req, finalHandlerFn) {
return finalHandlerFn(req);
}
function adaptLegacyInterceptorToChain(chainTailFn, interceptor) {
return (initialRequest, finalHandlerFn) => interceptor.intercept(initialRequest, {
handle: (downstreamRequest) => chainTailFn(downstreamRequest, finalHandlerFn)
});
}
function chainedInterceptorFn(chainTailFn, interceptorFn, injector) {
return (initialRequest, finalHandlerFn) => runInInjectionContext(injector, () => interceptorFn(initialRequest, (downstreamRequest) => chainTailFn(downstreamRequest, finalHandlerFn)));
}
var HTTP_INTERCEPTORS = new InjectionToken(ngDevMode ? "HTTP_INTERCEPTORS" : "");
var HTTP_INTERCEPTOR_FNS = new InjectionToken(ngDevMode ? "HTTP_INTERCEPTOR_FNS" : "");
var HTTP_ROOT_INTERCEPTOR_FNS = new InjectionToken(ngDevMode ? "HTTP_ROOT_INTERCEPTOR_FNS" : "");
var REQUESTS_CONTRIBUTE_TO_STABILITY = new InjectionToken(ngDevMode ? "REQUESTS_CONTRIBUTE_TO_STABILITY" : "", {
providedIn: "root",
factory: () => true
});
function legacyInterceptorFnFactory() {
let chain = null;
return (req, handler) => {
if (chain === null) {
const interceptors = inject(HTTP_INTERCEPTORS, {
optional: true
}) ?? [];
chain = interceptors.reduceRight(adaptLegacyInterceptorToChain, interceptorChainEndFn);
}
const pendingTasks = inject(PendingTasksInternal);
const contributeToStability = inject(REQUESTS_CONTRIBUTE_TO_STABILITY);
if (contributeToStability) {
const taskId = pendingTasks.add();
return chain(req, handler).pipe(finalize(() => pendingTasks.remove(taskId)));
} else {
return chain(req, handler);
}
};
}
var fetchBackendWarningDisplayed = false;
var HttpInterceptorHandler = class _HttpInterceptorHandler extends HttpHandler {
backend;
injector;
chain = null;
pendingTasks = inject(PendingTasksInternal);
contributeToStability = inject(REQUESTS_CONTRIBUTE_TO_STABILITY);
constructor(backend, injector) {
super();
this.backend = backend;
this.injector = injector;
if ((typeof ngDevMode === "undefined" || ngDevMode) && !fetchBackendWarningDisplayed) {
const isServer = isPlatformServer(injector.get(PLATFORM_ID));
const isTestingBackend = this.backend.isTestingBackend;
if (isServer && !(this.backend instanceof FetchBackend) && !isTestingBackend) {
fetchBackendWarningDisplayed = true;
injector.get(Console).warn(formatRuntimeError(2801, "Angular detected that `HttpClient` is not configured to use `fetch` APIs. It's strongly recommended to enable `fetch` for applications that use Server-Side Rendering for better performance and compatibility. To enable `fetch`, add the `withFetch()` to the `provideHttpClient()` call at the root of the application."));
}
}
}
handle(initialRequest) {
if (this.chain === null) {
const dedupedInterceptorFns = Array.from(/* @__PURE__ */ new Set([...this.injector.get(HTTP_INTERCEPTOR_FNS), ...this.injector.get(HTTP_ROOT_INTERCEPTOR_FNS, [])]));
this.chain = dedupedInterceptorFns.reduceRight((nextSequencedFn, interceptorFn) => chainedInterceptorFn(nextSequencedFn, interceptorFn, this.injector), interceptorChainEndFn);
}
if (this.contributeToStability) {
const taskId = this.pendingTasks.add();
return this.chain(initialRequest, (downstreamRequest) => this.backend.handle(downstreamRequest)).pipe(finalize(() => this.pendingTasks.remove(taskId)));
} else {
return this.chain(initialRequest, (downstreamRequest) => this.backend.handle(downstreamRequest));
}
}
static \u0275fac = function HttpInterceptorHandler_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpInterceptorHandler)(\u0275\u0275inject(HttpBackend), \u0275\u0275inject(EnvironmentInjector));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HttpInterceptorHandler,
factory: _HttpInterceptorHandler.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpInterceptorHandler, [{
type: Injectable
}], () => [{
type: HttpBackend
}, {
type: EnvironmentInjector
}], null);
})();
var nextRequestId = 0;
var foreignDocument;
var JSONP_ERR_NO_CALLBACK = "JSONP injected script did not invoke callback.";
var JSONP_ERR_WRONG_METHOD = "JSONP requests must use JSONP request method.";
var JSONP_ERR_WRONG_RESPONSE_TYPE = "JSONP requests must use Json response type.";
var JSONP_ERR_HEADERS_NOT_SUPPORTED = "JSONP requests do not support headers.";
var JsonpCallbackContext = class {
};
function jsonpCallbackContext() {
if (typeof window === "object") {
return window;
}
return {};
}
var JsonpClientBackend = class _JsonpClientBackend {
callbackMap;
document;
/**
* A resolved promise that can be used to schedule microtasks in the event handlers.
*/
resolvedPromise = Promise.resolve();
constructor(callbackMap, document2) {
this.callbackMap = callbackMap;
this.document = document2;
}
/**
* Get the name of the next callback method, by incrementing the global `nextRequestId`.
*/
nextCallback() {
return `ng_jsonp_callback_${nextRequestId++}`;
}
/**
* Processes a JSONP request and returns an event stream of the results.
* @param req The request object.
* @returns An observable of the response events.
*
*/
handle(req) {
if (req.method !== "JSONP") {
throw new Error(JSONP_ERR_WRONG_METHOD);
} else if (req.responseType !== "json") {
throw new Error(JSONP_ERR_WRONG_RESPONSE_TYPE);
}
if (req.headers.keys().length > 0) {
throw new Error(JSONP_ERR_HEADERS_NOT_SUPPORTED);
}
return new Observable((observer) => {
const callback = this.nextCallback();
const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`);
const node = this.document.createElement("script");
node.src = url;
let body = null;
let finished = false;
this.callbackMap[callback] = (data) => {
delete this.callbackMap[callback];
body = data;
finished = true;
};
const cleanup = () => {
node.removeEventListener("load", onLoad);
node.removeEventListener("error", onError);
node.remove();
delete this.callbackMap[callback];
};
const onLoad = (event) => {
this.resolvedPromise.then(() => {
cleanup();
if (!finished) {
observer.error(new HttpErrorResponse({
url,
status: 0,
statusText: "JSONP Error",
error: new Error(JSONP_ERR_NO_CALLBACK)
}));
return;
}
observer.next(new HttpResponse({
body,
status: HTTP_STATUS_CODE_OK,
statusText: "OK",
url
}));
observer.complete();
});
};
const onError = (error) => {
cleanup();
observer.error(new HttpErrorResponse({
error,
status: 0,
statusText: "JSONP Error",
url
}));
};
node.addEventListener("load", onLoad);
node.addEventListener("error", onError);
this.document.body.appendChild(node);
observer.next({
type: HttpEventType.Sent
});
return () => {
if (!finished) {
this.removeListeners(node);
}
cleanup();
};
});
}
removeListeners(script) {
foreignDocument ??= this.document.implementation.createHTMLDocument();
foreignDocument.adoptNode(script);
}
static \u0275fac = function JsonpClientBackend_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _JsonpClientBackend)(\u0275\u0275inject(JsonpCallbackContext), \u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _JsonpClientBackend,
factory: _JsonpClientBackend.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(JsonpClientBackend, [{
type: Injectable
}], () => [{
type: JsonpCallbackContext
}, {
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
function jsonpInterceptorFn(req, next) {
if (req.method === "JSONP") {
return inject(JsonpClientBackend).handle(req);
}
return next(req);
}
var JsonpInterceptor = class _JsonpInterceptor {
injector;
constructor(injector) {
this.injector = injector;
}
/**
* Identifies and handles a given JSONP request.
* @param initialRequest The outgoing request object to handle.
* @param next The next interceptor in the chain, or the backend
* if no interceptors remain in the chain.
* @returns An observable of the event stream.
*/
intercept(initialRequest, next) {
return runInInjectionContext(this.injector, () => jsonpInterceptorFn(initialRequest, (downstreamRequest) => next.handle(downstreamRequest)));
}
static \u0275fac = function JsonpInterceptor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _JsonpInterceptor)(\u0275\u0275inject(EnvironmentInjector));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _JsonpInterceptor,
factory: _JsonpInterceptor.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(JsonpInterceptor, [{
type: Injectable
}], () => [{
type: EnvironmentInjector
}], null);
})();
var XSSI_PREFIX = /^\)\]\}',?\n/;
var X_REQUEST_URL_REGEXP = RegExp(`^${X_REQUEST_URL_HEADER}:`, "m");
function getResponseUrl(xhr) {
if ("responseURL" in xhr && xhr.responseURL) {
return xhr.responseURL;
}
if (X_REQUEST_URL_REGEXP.test(xhr.getAllResponseHeaders())) {
return xhr.getResponseHeader(X_REQUEST_URL_HEADER);
}
return null;
}
var HttpXhrBackend = class _HttpXhrBackend {
xhrFactory;
constructor(xhrFactory) {
this.xhrFactory = xhrFactory;
}
/**
* Processes a request and returns a stream of response events.
* @param req The request object.
* @returns An observable of the response events.
*/
handle(req) {
if (req.method === "JSONP") {
throw new RuntimeError(-2800, (typeof ngDevMode === "undefined" || ngDevMode) && `Cannot make a JSONP request without JSONP support. To fix the problem, either add the \`withJsonpSupport()\` call (if \`provideHttpClient()\` is used) or import the \`HttpClientJsonpModule\` in the root NgModule.`);
}
const xhrFactory = this.xhrFactory;
const source = xhrFactory.\u0275loadImpl ? from(xhrFactory.\u0275loadImpl()) : of(null);
return source.pipe(switchMap(() => {
return new Observable((observer) => {
const xhr = xhrFactory.build();
xhr.open(req.method, req.urlWithParams);
if (req.withCredentials) {
xhr.withCredentials = true;
}
req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(",")));
if (!req.headers.has(ACCEPT_HEADER)) {
xhr.setRequestHeader(ACCEPT_HEADER, ACCEPT_HEADER_VALUE);
}
if (!req.headers.has(CONTENT_TYPE_HEADER)) {
const detectedType = req.detectContentTypeHeader();
if (detectedType !== null) {
xhr.setRequestHeader(CONTENT_TYPE_HEADER, detectedType);
}
}
if (req.responseType) {
const responseType = req.responseType.toLowerCase();
xhr.responseType = responseType !== "json" ? responseType : "text";
}
const reqBody = req.serializeBody();
let headerResponse = null;
const partialFromXhr = () => {
if (headerResponse !== null) {
return headerResponse;
}
const statusText = xhr.statusText || "OK";
const headers = new HttpHeaders(xhr.getAllResponseHeaders());
const url = getResponseUrl(xhr) || req.url;
headerResponse = new HttpHeaderResponse({
headers,
status: xhr.status,
statusText,
url
});
return headerResponse;
};
const onLoad = () => {
let {
headers,
status,
statusText,
url
} = partialFromXhr();
let body = null;
if (status !== HTTP_STATUS_CODE_NO_CONTENT) {
body = typeof xhr.response === "undefined" ? xhr.responseText : xhr.response;
}
if (status === 0) {
status = !!body ? HTTP_STATUS_CODE_OK : 0;
}
let ok = status >= 200 && status < 300;
if (req.responseType === "json" && typeof body === "string") {
const originalBody = body;
body = body.replace(XSSI_PREFIX, "");
try {
body = body !== "" ? JSON.parse(body) : null;
} catch (error) {
body = originalBody;
if (ok) {
ok = false;
body = {
error,
text: body
};
}
}
}
if (ok) {
observer.next(new HttpResponse({
body,
headers,
status,
statusText,
url: url || void 0
}));
observer.complete();
} else {
observer.error(new HttpErrorResponse({
// The error in this case is the response body (error from the server).
error: body,
headers,
status,
statusText,
url: url || void 0
}));
}
};
const onError = (error) => {
const {
url
} = partialFromXhr();
const res = new HttpErrorResponse({
error,
status: xhr.status || 0,
statusText: xhr.statusText || "Unknown Error",
url: url || void 0
});
observer.error(res);
};
let sentHeaders = false;
const onDownProgress = (event) => {
if (!sentHeaders) {
observer.next(partialFromXhr());
sentHeaders = true;
}
let progressEvent = {
type: HttpEventType.DownloadProgress,
loaded: event.loaded
};
if (event.lengthComputable) {
progressEvent.total = event.total;
}
if (req.responseType === "text" && !!xhr.responseText) {
progressEvent.partialText = xhr.responseText;
}
observer.next(progressEvent);
};
const onUpProgress = (event) => {
let progress = {
type: HttpEventType.UploadProgress,
loaded: event.loaded
};
if (event.lengthComputable) {
progress.total = event.total;
}
observer.next(progress);
};
xhr.addEventListener("load", onLoad);
xhr.addEventListener("error", onError);
xhr.addEventListener("timeout", onError);
xhr.addEventListener("abort", onError);
if (req.reportProgress) {
xhr.addEventListener("progress", onDownProgress);
if (reqBody !== null && xhr.upload) {
xhr.upload.addEventListener("progress", onUpProgress);
}
}
xhr.send(reqBody);
observer.next({
type: HttpEventType.Sent
});
return () => {
xhr.removeEventListener("error", onError);
xhr.removeEventListener("abort", onError);
xhr.removeEventListener("load", onLoad);
xhr.removeEventListener("timeout", onError);
if (req.reportProgress) {
xhr.removeEventListener("progress", onDownProgress);
if (reqBody !== null && xhr.upload) {
xhr.upload.removeEventListener("progress", onUpProgress);
}
}
if (xhr.readyState !== xhr.DONE) {
xhr.abort();
}
};
});
}));
}
static \u0275fac = function HttpXhrBackend_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpXhrBackend)(\u0275\u0275inject(XhrFactory));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HttpXhrBackend,
factory: _HttpXhrBackend.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXhrBackend, [{
type: Injectable
}], () => [{
type: XhrFactory
}], null);
})();
var XSRF_ENABLED = new InjectionToken(ngDevMode ? "XSRF_ENABLED" : "");
var XSRF_DEFAULT_COOKIE_NAME = "XSRF-TOKEN";
var XSRF_COOKIE_NAME = new InjectionToken(ngDevMode ? "XSRF_COOKIE_NAME" : "", {
providedIn: "root",
factory: () => XSRF_DEFAULT_COOKIE_NAME
});
var XSRF_DEFAULT_HEADER_NAME = "X-XSRF-TOKEN";
var XSRF_HEADER_NAME = new InjectionToken(ngDevMode ? "XSRF_HEADER_NAME" : "", {
providedIn: "root",
factory: () => XSRF_DEFAULT_HEADER_NAME
});
var HttpXsrfTokenExtractor = class {
};
var HttpXsrfCookieExtractor = class _HttpXsrfCookieExtractor {
doc;
cookieName;
lastCookieString = "";
lastToken = null;
/**
* @internal for testing
*/
parseCount = 0;
constructor(doc, cookieName) {
this.doc = doc;
this.cookieName = cookieName;
}
getToken() {
if (false) {
return null;
}
const cookieString = this.doc.cookie || "";
if (cookieString !== this.lastCookieString) {
this.parseCount++;
this.lastToken = parseCookieValue(cookieString, this.cookieName);
this.lastCookieString = cookieString;
}
return this.lastToken;
}
static \u0275fac = function HttpXsrfCookieExtractor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpXsrfCookieExtractor)(\u0275\u0275inject(DOCUMENT), \u0275\u0275inject(XSRF_COOKIE_NAME));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HttpXsrfCookieExtractor,
factory: _HttpXsrfCookieExtractor.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXsrfCookieExtractor, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}, {
type: void 0,
decorators: [{
type: Inject,
args: [XSRF_COOKIE_NAME]
}]
}], null);
})();
function xsrfInterceptorFn(req, next) {
const lcUrl = req.url.toLowerCase();
if (!inject(XSRF_ENABLED) || req.method === "GET" || req.method === "HEAD" || lcUrl.startsWith("http://") || lcUrl.startsWith("https://")) {
return next(req);
}
const token = inject(HttpXsrfTokenExtractor).getToken();
const headerName = inject(XSRF_HEADER_NAME);
if (token != null && !req.headers.has(headerName)) {
req = req.clone({
headers: req.headers.set(headerName, token)
});
}
return next(req);
}
var HttpXsrfInterceptor = class _HttpXsrfInterceptor {
injector;
constructor(injector) {
this.injector = injector;
}
intercept(initialRequest, next) {
return runInInjectionContext(this.injector, () => xsrfInterceptorFn(initialRequest, (downstreamRequest) => next.handle(downstreamRequest)));
}
static \u0275fac = function HttpXsrfInterceptor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpXsrfInterceptor)(\u0275\u0275inject(EnvironmentInjector));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HttpXsrfInterceptor,
factory: _HttpXsrfInterceptor.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpXsrfInterceptor, [{
type: Injectable
}], () => [{
type: EnvironmentInjector
}], null);
})();
var HttpFeatureKind;
(function(HttpFeatureKind2) {
HttpFeatureKind2[HttpFeatureKind2["Interceptors"] = 0] = "Interceptors";
HttpFeatureKind2[HttpFeatureKind2["LegacyInterceptors"] = 1] = "LegacyInterceptors";
HttpFeatureKind2[HttpFeatureKind2["CustomXsrfConfiguration"] = 2] = "CustomXsrfConfiguration";
HttpFeatureKind2[HttpFeatureKind2["NoXsrfProtection"] = 3] = "NoXsrfProtection";
HttpFeatureKind2[HttpFeatureKind2["JsonpSupport"] = 4] = "JsonpSupport";
HttpFeatureKind2[HttpFeatureKind2["RequestsMadeViaParent"] = 5] = "RequestsMadeViaParent";
HttpFeatureKind2[HttpFeatureKind2["Fetch"] = 6] = "Fetch";
})(HttpFeatureKind || (HttpFeatureKind = {}));
function makeHttpFeature(kind, providers) {
return {
\u0275kind: kind,
\u0275providers: providers
};
}
function provideHttpClient(...features) {
if (ngDevMode) {
const featureKinds = new Set(features.map((f) => f.\u0275kind));
if (featureKinds.has(HttpFeatureKind.NoXsrfProtection) && featureKinds.has(HttpFeatureKind.CustomXsrfConfiguration)) {
throw new Error(ngDevMode ? `Configuration error: found both withXsrfConfiguration() and withNoXsrfProtection() in the same call to provideHttpClient(), which is a contradiction.` : "");
}
}
const providers = [HttpClient, HttpXhrBackend, HttpInterceptorHandler, {
provide: HttpHandler,
useExisting: HttpInterceptorHandler
}, {
provide: HttpBackend,
useFactory: () => {
return inject(FETCH_BACKEND, {
optional: true
}) ?? inject(HttpXhrBackend);
}
}, {
provide: HTTP_INTERCEPTOR_FNS,
useValue: xsrfInterceptorFn,
multi: true
}, {
provide: XSRF_ENABLED,
useValue: true
}, {
provide: HttpXsrfTokenExtractor,
useClass: HttpXsrfCookieExtractor
}];
for (const feature of features) {
providers.push(...feature.\u0275providers);
}
return makeEnvironmentProviders(providers);
}
var LEGACY_INTERCEPTOR_FN = new InjectionToken(ngDevMode ? "LEGACY_INTERCEPTOR_FN" : "");
function withInterceptorsFromDi() {
return makeHttpFeature(HttpFeatureKind.LegacyInterceptors, [{
provide: LEGACY_INTERCEPTOR_FN,
useFactory: legacyInterceptorFnFactory
}, {
provide: HTTP_INTERCEPTOR_FNS,
useExisting: LEGACY_INTERCEPTOR_FN,
multi: true
}]);
}
function withXsrfConfiguration({
cookieName,
headerName
}) {
const providers = [];
if (cookieName !== void 0) {
providers.push({
provide: XSRF_COOKIE_NAME,
useValue: cookieName
});
}
if (headerName !== void 0) {
providers.push({
provide: XSRF_HEADER_NAME,
useValue: headerName
});
}
return makeHttpFeature(HttpFeatureKind.CustomXsrfConfiguration, providers);
}
function withNoXsrfProtection() {
return makeHttpFeature(HttpFeatureKind.NoXsrfProtection, [{
provide: XSRF_ENABLED,
useValue: false
}]);
}
function withJsonpSupport() {
return makeHttpFeature(HttpFeatureKind.JsonpSupport, [JsonpClientBackend, {
provide: JsonpCallbackContext,
useFactory: jsonpCallbackContext
}, {
provide: HTTP_INTERCEPTOR_FNS,
useValue: jsonpInterceptorFn,
multi: true
}]);
}
var HttpClientXsrfModule = class _HttpClientXsrfModule {
/**
* Disable the default XSRF protection.
*/
static disable() {
return {
ngModule: _HttpClientXsrfModule,
providers: [withNoXsrfProtection().\u0275providers]
};
}
/**
* Configure XSRF protection.
* @param options An object that can specify either or both
* cookie name or header name.
* - Cookie name default is `XSRF-TOKEN`.
* - Header name default is `X-XSRF-TOKEN`.
*
*/
static withOptions(options = {}) {
return {
ngModule: _HttpClientXsrfModule,
providers: withXsrfConfiguration(options).\u0275providers
};
}
static \u0275fac = function HttpClientXsrfModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpClientXsrfModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _HttpClientXsrfModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [HttpXsrfInterceptor, {
provide: HTTP_INTERCEPTORS,
useExisting: HttpXsrfInterceptor,
multi: true
}, {
provide: HttpXsrfTokenExtractor,
useClass: HttpXsrfCookieExtractor
}, withXsrfConfiguration({
cookieName: XSRF_DEFAULT_COOKIE_NAME,
headerName: XSRF_DEFAULT_HEADER_NAME
}).\u0275providers, {
provide: XSRF_ENABLED,
useValue: true
}]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientXsrfModule, [{
type: NgModule,
args: [{
providers: [HttpXsrfInterceptor, {
provide: HTTP_INTERCEPTORS,
useExisting: HttpXsrfInterceptor,
multi: true
}, {
provide: HttpXsrfTokenExtractor,
useClass: HttpXsrfCookieExtractor
}, withXsrfConfiguration({
cookieName: XSRF_DEFAULT_COOKIE_NAME,
headerName: XSRF_DEFAULT_HEADER_NAME
}).\u0275providers, {
provide: XSRF_ENABLED,
useValue: true
}]
}]
}], null, null);
})();
var HttpClientModule = class _HttpClientModule {
static \u0275fac = function HttpClientModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpClientModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _HttpClientModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [provideHttpClient(withInterceptorsFromDi())]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientModule, [{
type: NgModule,
args: [{
/**
* Configures the dependency injector where it is imported
* with supporting services for HTTP communications.
*/
providers: [provideHttpClient(withInterceptorsFromDi())]
}]
}], null, null);
})();
var HttpClientJsonpModule = class _HttpClientJsonpModule {
static \u0275fac = function HttpClientJsonpModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HttpClientJsonpModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _HttpClientJsonpModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [withJsonpSupport().\u0275providers]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HttpClientJsonpModule, [{
type: NgModule,
args: [{
providers: [withJsonpSupport().\u0275providers]
}]
}], null, null);
})();
// node_modules/@angular/common/fesm2022/http.mjs
var httpResource = (() => {
const jsonFn = makeHttpResourceFn("json");
jsonFn.arrayBuffer = makeHttpResourceFn("arraybuffer");
jsonFn.blob = makeHttpResourceFn("blob");
jsonFn.text = makeHttpResourceFn("text");
return jsonFn;
})();
function makeHttpResourceFn(responseType) {
return function httpResourceRef(request, options) {
options?.injector || assertInInjectionContext(httpResource);
const injector = options?.injector ?? inject(Injector);
return new HttpResourceImpl(injector, () => normalizeRequest(request, responseType), options?.defaultValue, options?.parse, options?.equal);
};
}
function normalizeRequest(request, responseType) {
let unwrappedRequest = typeof request === "function" ? request() : request;
if (unwrappedRequest === void 0) {
return void 0;
} else if (typeof unwrappedRequest === "string") {
unwrappedRequest = {
url: unwrappedRequest
};
}
const headers = unwrappedRequest.headers instanceof HttpHeaders ? unwrappedRequest.headers : new HttpHeaders(unwrappedRequest.headers);
const params = unwrappedRequest.params instanceof HttpParams ? unwrappedRequest.params : new HttpParams({
fromObject: unwrappedRequest.params
});
return new HttpRequest(unwrappedRequest.method ?? "GET", unwrappedRequest.url, unwrappedRequest.body ?? null, {
headers,
params,
reportProgress: unwrappedRequest.reportProgress,
withCredentials: unwrappedRequest.withCredentials,
responseType,
context: unwrappedRequest.context,
transferCache: unwrappedRequest.transferCache
});
}
var HttpResourceImpl = class extends ResourceImpl {
client;
_headers = linkedSignal({
source: this.extRequest,
computation: () => void 0
});
_progress = linkedSignal({
source: this.extRequest,
computation: () => void 0
});
_statusCode = linkedSignal({
source: this.extRequest,
computation: () => void 0
});
headers = computed(() => this.status() === ResourceStatus.Resolved || this.status() === ResourceStatus.Error ? this._headers() : void 0);
progress = this._progress.asReadonly();
statusCode = this._statusCode.asReadonly();
constructor(injector, request, defaultValue, parse, equal) {
super(request, ({
request: request2,
abortSignal
}) => {
let sub;
const onAbort = () => sub.unsubscribe();
abortSignal.addEventListener("abort", onAbort);
const stream = signal({
value: void 0
});
let resolve;
const promise = new Promise((r) => resolve = r);
const send = (value) => {
stream.set(value);
resolve?.(stream);
resolve = void 0;
};
sub = this.client.request(request2).subscribe({
next: (event) => {
switch (event.type) {
case HttpEventType.Response:
this._headers.set(event.headers);
this._statusCode.set(event.status);
try {
send({
value: parse ? parse(event.body) : event.body
});
} catch (error) {
send({
error
});
}
break;
case HttpEventType.DownloadProgress:
this._progress.set(event);
break;
}
},
error: (error) => {
if (error instanceof HttpErrorResponse) {
this._headers.set(error.headers);
this._statusCode.set(error.status);
}
send({
error
});
},
complete: () => {
if (resolve) {
send({
error: new Error("Resource completed before producing a value")
});
}
abortSignal.removeEventListener("abort", onAbort);
}
});
return promise;
}, defaultValue, equal, injector);
this.client = injector.get(HttpClient);
}
};
var HTTP_TRANSFER_CACHE_ORIGIN_MAP = new InjectionToken(ngDevMode ? "HTTP_TRANSFER_CACHE_ORIGIN_MAP" : "");
var CACHE_OPTIONS = new InjectionToken(ngDevMode ? "HTTP_TRANSFER_STATE_CACHE_OPTIONS" : "");
// node_modules/@angular/platform-browser/fesm2022/platform-browser.mjs
var Meta = class _Meta {
_doc;
_dom;
constructor(_doc) {
this._doc = _doc;
this._dom = getDOM();
}
/**
* Retrieves or creates a specific `<meta>` tag element in the current HTML document.
* In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
* values in the provided tag definition, and verifies that all other attribute values are equal.
* If an existing element is found, it is returned and is not modified in any way.
* @param tag The definition of a `<meta>` element to match or create.
* @param forceCreation True to create a new element without checking whether one already exists.
* @returns The existing element with the same attributes and values if found,
* the new element if no match is found, or `null` if the tag parameter is not defined.
*/
addTag(tag, forceCreation = false) {
if (!tag) return null;
return this._getOrCreateElement(tag, forceCreation);
}
/**
* Retrieves or creates a set of `<meta>` tag elements in the current HTML document.
* In searching for an existing tag, Angular attempts to match the `name` or `property` attribute
* values in the provided tag definition, and verifies that all other attribute values are equal.
* @param tags An array of tag definitions to match or create.
* @param forceCreation True to create new elements without checking whether they already exist.
* @returns The matching elements if found, or the new elements.
*/
addTags(tags, forceCreation = false) {
if (!tags) return [];
return tags.reduce((result, tag) => {
if (tag) {
result.push(this._getOrCreateElement(tag, forceCreation));
}
return result;
}, []);
}
/**
* Retrieves a `<meta>` tag element in the current HTML document.
* @param attrSelector The tag attribute and value to match against, in the format
* `"tag_attribute='value string'"`.
* @returns The matching element, if any.
*/
getTag(attrSelector) {
if (!attrSelector) return null;
return this._doc.querySelector(`meta[${attrSelector}]`) || null;
}
/**
* Retrieves a set of `<meta>` tag elements in the current HTML document.
* @param attrSelector The tag attribute and value to match against, in the format
* `"tag_attribute='value string'"`.
* @returns The matching elements, if any.
*/
getTags(attrSelector) {
if (!attrSelector) return [];
const list = this._doc.querySelectorAll(`meta[${attrSelector}]`);
return list ? [].slice.call(list) : [];
}
/**
* Modifies an existing `<meta>` tag element in the current HTML document.
* @param tag The tag description with which to replace the existing tag content.
* @param selector A tag attribute and value to match against, to identify
* an existing tag. A string in the format `"tag_attribute=`value string`"`.
* If not supplied, matches a tag with the same `name` or `property` attribute value as the
* replacement tag.
* @return The modified element.
*/
updateTag(tag, selector) {
if (!tag) return null;
selector = selector || this._parseSelector(tag);
const meta = this.getTag(selector);
if (meta) {
return this._setMetaElementAttributes(tag, meta);
}
return this._getOrCreateElement(tag, true);
}
/**
* Removes an existing `<meta>` tag element from the current HTML document.
* @param attrSelector A tag attribute and value to match against, to identify
* an existing tag. A string in the format `"tag_attribute=`value string`"`.
*/
removeTag(attrSelector) {
this.removeTagElement(this.getTag(attrSelector));
}
/**
* Removes an existing `<meta>` tag element from the current HTML document.
* @param meta The tag definition to match against to identify an existing tag.
*/
removeTagElement(meta) {
if (meta) {
this._dom.remove(meta);
}
}
_getOrCreateElement(meta, forceCreation = false) {
if (!forceCreation) {
const selector = this._parseSelector(meta);
const elem = this.getTags(selector).filter((elem2) => this._containsAttributes(meta, elem2))[0];
if (elem !== void 0) return elem;
}
const element = this._dom.createElement("meta");
this._setMetaElementAttributes(meta, element);
const head = this._doc.getElementsByTagName("head")[0];
head.appendChild(element);
return element;
}
_setMetaElementAttributes(tag, el) {
Object.keys(tag).forEach((prop) => el.setAttribute(this._getMetaKeyMap(prop), tag[prop]));
return el;
}
_parseSelector(tag) {
const attr = tag.name ? "name" : "property";
return `${attr}="${tag[attr]}"`;
}
_containsAttributes(tag, elem) {
return Object.keys(tag).every((key) => elem.getAttribute(this._getMetaKeyMap(key)) === tag[key]);
}
_getMetaKeyMap(prop) {
return META_KEYS_MAP[prop] || prop;
}
static \u0275fac = function Meta_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Meta)(\u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Meta,
factory: _Meta.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Meta, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
var META_KEYS_MAP = {
httpEquiv: "http-equiv"
};
var Title = class _Title {
_doc;
constructor(_doc) {
this._doc = _doc;
}
/**
* Get the title of the current HTML document.
*/
getTitle() {
return this._doc.title;
}
/**
* Set the title of the current HTML document.
* @param newTitle
*/
setTitle(newTitle) {
this._doc.title = newTitle || "";
}
static \u0275fac = function Title_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Title)(\u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Title,
factory: _Title.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Title, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
var EVENT_NAMES = {
// pan
"pan": true,
"panstart": true,
"panmove": true,
"panend": true,
"pancancel": true,
"panleft": true,
"panright": true,
"panup": true,
"pandown": true,
// pinch
"pinch": true,
"pinchstart": true,
"pinchmove": true,
"pinchend": true,
"pinchcancel": true,
"pinchin": true,
"pinchout": true,
// press
"press": true,
"pressup": true,
// rotate
"rotate": true,
"rotatestart": true,
"rotatemove": true,
"rotateend": true,
"rotatecancel": true,
// swipe
"swipe": true,
"swipeleft": true,
"swiperight": true,
"swipeup": true,
"swipedown": true,
// tap
"tap": true,
"doubletap": true
};
var HAMMER_GESTURE_CONFIG = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "HammerGestureConfig" : "");
var HAMMER_LOADER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "HammerLoader" : "");
var HammerGestureConfig = class _HammerGestureConfig {
/**
* A set of supported event names for gestures to be used in Angular.
* Angular supports all built-in recognizers, as listed in
* [HammerJS documentation](https://hammerjs.github.io/).
*/
events = [];
/**
* Maps gesture event names to a set of configuration options
* that specify overrides to the default values for specific properties.
*
* The key is a supported event name to be configured,
* and the options object contains a set of properties, with override values
* to be applied to the named recognizer event.
* For example, to disable recognition of the rotate event, specify
* `{"rotate": {"enable": false}}`.
*
* Properties that are not present take the HammerJS default values.
* For information about which properties are supported for which events,
* and their allowed and default values, see
* [HammerJS documentation](https://hammerjs.github.io/).
*
*/
overrides = {};
/**
* Properties whose default values can be overridden for a given event.
* Different sets of properties apply to different events.
* For information about which properties are supported for which events,
* and their allowed and default values, see
* [HammerJS documentation](https://hammerjs.github.io/).
*/
options;
/**
* Creates a [HammerJS Manager](https://hammerjs.github.io/api/#hammermanager)
* and attaches it to a given HTML element.
* @param element The element that will recognize gestures.
* @returns A HammerJS event-manager object.
*/
buildHammer(element) {
const mc = new Hammer(element, this.options);
mc.get("pinch").set({
enable: true
});
mc.get("rotate").set({
enable: true
});
for (const eventName in this.overrides) {
mc.get(eventName).set(this.overrides[eventName]);
}
return mc;
}
static \u0275fac = function HammerGestureConfig_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HammerGestureConfig)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HammerGestureConfig,
factory: _HammerGestureConfig.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HammerGestureConfig, [{
type: Injectable
}], null, null);
})();
var HammerGesturesPlugin = class _HammerGesturesPlugin extends EventManagerPlugin {
_config;
_injector;
loader;
_loaderPromise = null;
constructor(doc, _config, _injector, loader) {
super(doc);
this._config = _config;
this._injector = _injector;
this.loader = loader;
}
supports(eventName) {
if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) {
return false;
}
if (!window.Hammer && !this.loader) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
const _console = this._injector.get(Console);
_console.warn(`The "${eventName}" event cannot be bound because Hammer.JS is not loaded and no custom loader has been specified.`);
}
return false;
}
return true;
}
addEventListener(element, eventName, handler) {
const zone = this.manager.getZone();
eventName = eventName.toLowerCase();
if (!window.Hammer && this.loader) {
this._loaderPromise = this._loaderPromise || zone.runOutsideAngular(() => this.loader());
let cancelRegistration = false;
let deregister = () => {
cancelRegistration = true;
};
zone.runOutsideAngular(() => this._loaderPromise.then(() => {
if (!window.Hammer) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
const _console = this._injector.get(Console);
_console.warn(`The custom HAMMER_LOADER completed, but Hammer.JS is not present.`);
}
deregister = () => {
};
return;
}
if (!cancelRegistration) {
deregister = this.addEventListener(element, eventName, handler);
}
}).catch(() => {
if (typeof ngDevMode === "undefined" || ngDevMode) {
const _console = this._injector.get(Console);
_console.warn(`The "${eventName}" event cannot be bound because the custom Hammer.JS loader failed.`);
}
deregister = () => {
};
}));
return () => {
deregister();
};
}
return zone.runOutsideAngular(() => {
const mc = this._config.buildHammer(element);
const callback = function(eventObj) {
zone.runGuarded(function() {
handler(eventObj);
});
};
mc.on(eventName, callback);
return () => {
mc.off(eventName, callback);
if (typeof mc.destroy === "function") {
mc.destroy();
}
};
});
}
isCustomEvent(eventName) {
return this._config.events.indexOf(eventName) > -1;
}
static \u0275fac = function HammerGesturesPlugin_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HammerGesturesPlugin)(\u0275\u0275inject(DOCUMENT), \u0275\u0275inject(HAMMER_GESTURE_CONFIG), \u0275\u0275inject(Injector), \u0275\u0275inject(HAMMER_LOADER, 8));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HammerGesturesPlugin,
factory: _HammerGesturesPlugin.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HammerGesturesPlugin, [{
type: Injectable
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}, {
type: HammerGestureConfig,
decorators: [{
type: Inject,
args: [HAMMER_GESTURE_CONFIG]
}]
}, {
type: Injector
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [HAMMER_LOADER]
}]
}], null);
})();
var HammerModule = class _HammerModule {
static \u0275fac = function HammerModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HammerModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _HammerModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [{
provide: EVENT_MANAGER_PLUGINS,
useClass: HammerGesturesPlugin,
multi: true,
deps: [DOCUMENT, HAMMER_GESTURE_CONFIG, Injector, [new Optional(), HAMMER_LOADER]]
}, {
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerGestureConfig
}]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HammerModule, [{
type: NgModule,
args: [{
providers: [{
provide: EVENT_MANAGER_PLUGINS,
useClass: HammerGesturesPlugin,
multi: true,
deps: [DOCUMENT, HAMMER_GESTURE_CONFIG, Injector, [new Optional(), HAMMER_LOADER]]
}, {
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerGestureConfig
}]
}]
}], null, null);
})();
var DomSanitizer = class _DomSanitizer {
static \u0275fac = function DomSanitizer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DomSanitizer)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DomSanitizer,
factory: function DomSanitizer_Factory(__ngFactoryType__) {
let __ngConditionalFactory__ = null;
if (__ngFactoryType__) {
__ngConditionalFactory__ = new (__ngFactoryType__ || _DomSanitizer)();
} else {
__ngConditionalFactory__ = \u0275\u0275inject(DomSanitizerImpl);
}
return __ngConditionalFactory__;
},
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DomSanitizer, [{
type: Injectable,
args: [{
providedIn: "root",
useExisting: forwardRef(() => DomSanitizerImpl)
}]
}], null, null);
})();
var DomSanitizerImpl = class _DomSanitizerImpl extends DomSanitizer {
_doc;
constructor(_doc) {
super();
this._doc = _doc;
}
sanitize(ctx, value) {
if (value == null) return null;
switch (ctx) {
case SecurityContext.NONE:
return value;
case SecurityContext.HTML:
if (allowSanitizationBypassAndThrow(
value,
"HTML"
/* BypassType.Html */
)) {
return unwrapSafeValue(value);
}
return _sanitizeHtml(this._doc, String(value)).toString();
case SecurityContext.STYLE:
if (allowSanitizationBypassAndThrow(
value,
"Style"
/* BypassType.Style */
)) {
return unwrapSafeValue(value);
}
return value;
case SecurityContext.SCRIPT:
if (allowSanitizationBypassAndThrow(
value,
"Script"
/* BypassType.Script */
)) {
return unwrapSafeValue(value);
}
throw new RuntimeError(5200, (typeof ngDevMode === "undefined" || ngDevMode) && "unsafe value used in a script context");
case SecurityContext.URL:
if (allowSanitizationBypassAndThrow(
value,
"URL"
/* BypassType.Url */
)) {
return unwrapSafeValue(value);
}
return _sanitizeUrl(String(value));
case SecurityContext.RESOURCE_URL:
if (allowSanitizationBypassAndThrow(
value,
"ResourceURL"
/* BypassType.ResourceUrl */
)) {
return unwrapSafeValue(value);
}
throw new RuntimeError(5201, (typeof ngDevMode === "undefined" || ngDevMode) && `unsafe value used in a resource URL context (see ${XSS_SECURITY_URL})`);
default:
throw new RuntimeError(5202, (typeof ngDevMode === "undefined" || ngDevMode) && `Unexpected SecurityContext ${ctx} (see ${XSS_SECURITY_URL})`);
}
}
bypassSecurityTrustHtml(value) {
return bypassSanitizationTrustHtml(value);
}
bypassSecurityTrustStyle(value) {
return bypassSanitizationTrustStyle(value);
}
bypassSecurityTrustScript(value) {
return bypassSanitizationTrustScript(value);
}
bypassSecurityTrustUrl(value) {
return bypassSanitizationTrustUrl(value);
}
bypassSecurityTrustResourceUrl(value) {
return bypassSanitizationTrustResourceUrl(value);
}
static \u0275fac = function DomSanitizerImpl_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DomSanitizerImpl)(\u0275\u0275inject(DOCUMENT));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DomSanitizerImpl,
factory: _DomSanitizerImpl.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DomSanitizerImpl, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: void 0,
decorators: [{
type: Inject,
args: [DOCUMENT]
}]
}], null);
})();
var HydrationFeatureKind;
(function(HydrationFeatureKind2) {
HydrationFeatureKind2[HydrationFeatureKind2["NoHttpTransferCache"] = 0] = "NoHttpTransferCache";
HydrationFeatureKind2[HydrationFeatureKind2["HttpTransferCacheOptions"] = 1] = "HttpTransferCacheOptions";
HydrationFeatureKind2[HydrationFeatureKind2["I18nSupport"] = 2] = "I18nSupport";
HydrationFeatureKind2[HydrationFeatureKind2["EventReplay"] = 3] = "EventReplay";
HydrationFeatureKind2[HydrationFeatureKind2["IncrementalHydration"] = 4] = "IncrementalHydration";
})(HydrationFeatureKind || (HydrationFeatureKind = {}));
var VERSION3 = new Version("19.2.11");
// node_modules/@angular/router/fesm2022/router-Dwfin5Au.mjs
var PRIMARY_OUTLET = "primary";
var RouteTitleKey = /* @__PURE__ */ 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 \u0275fac = function UrlSerializer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _UrlSerializer)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
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 = void 0;
if (path.indexOf(":") > -1) {
outletName = path.slice(0, path.indexOf(":"));
this.capture(outletName);
this.capture(":");
} else if (allowPrimary) {
outletName = PRIMARY_OUTLET;
}
const children = this.parseChildren();
segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children);
this.consumeOptional("//");
}
return segments;
}
peekStartsWith(str) {
return this.remaining.startsWith(str);
}
// Consumes the prefix when it is present and returns whether it has been consumed
consumeOptional(str) {
if (this.peekStartsWith(str)) {
this.remaining = this.remaining.substring(str.length);
return true;
}
return false;
}
capture(str) {
if (!this.consumeOptional(str)) {
throw new RuntimeError(4011, (typeof ngDevMode === "undefined" || ngDevMode) && `Expected "${str}".`);
}
}
};
function createRoot(rootCandidate) {
return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], {
[PRIMARY_OUTLET]: rootCandidate
}) : rootCandidate;
}
function squashSegmentGroup(segmentGroup) {
const newChildren = {};
for (const [childOutlet, 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, stringify2(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, stringify2(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 stringify2(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";
})(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 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.redirectTo && (route.component || route.loadComponent)) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
}
if (route.component && route.loadComponent) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
}
if (route.redirectTo && route.canActivate) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and canActivate cannot be used together. Redirects happen before activation so canActivate will never be executed.`);
}
if (route.path && route.matcher) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
}
if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
}
if (route.path === void 0 && route.matcher === void 0) {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`);
}
if (typeof route.path === "string" && route.path.charAt(0) === "/") {
throw new RuntimeError(4014, `Invalid configuration of route '${fullPath}': path cannot start with a slash`);
}
if (route.path === "" && route.redirectTo !== void 0 && route.pathMatch === void 0) {
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
throw new RuntimeError(4014, `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
}
if (requireStandaloneComponents) {
assertStandalone(fullPath, route.component);
}
}
if (route.children) {
validateConfig(route.children, fullPath, requireStandaloneComponents);
}
}
function getFullPath(parentPath, currentRoute) {
if (!currentRoute) {
return parentPath;
}
if (!parentPath && !currentRoute.path) {
return "";
} else if (parentPath && !currentRoute.path) {
return `${parentPath}/`;
} else if (!parentPath && currentRoute.path) {
return currentRoute.path;
} else {
return `${parentPath}/${currentRoute.path}`;
}
}
function getOutlet(route) {
return route.outlet || PRIMARY_OUTLET;
}
function sortByMatchingOutlets(routes2, outletName) {
const sortedConfig = routes2.filter((r) => getOutlet(r) === outletName);
sortedConfig.push(...routes2.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 \u0275fac = function ChildrenOutletContexts_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ChildrenOutletContexts)(\u0275\u0275inject(EnvironmentInjector));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ChildrenOutletContexts,
factory: _ChildrenOutletContexts.\u0275fac,
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(void 0);
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 \u0275fac = function RouterOutlet_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterOutlet)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RouterOutlet,
selectors: [["router-outlet"]],
inputs: {
name: "name",
routerOutletData: [1, "routerOutletData"]
},
outputs: {
activateEvents: "activate",
deactivateEvents: "deactivate",
attachEvents: "attach",
detachEvents: "detach"
},
exportAs: ["outlet"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(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"]
}]
});
})();
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 \u0275fac = function RoutedComponentInputBinder_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RoutedComponentInputBinder)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _RoutedComponentInputBinder,
factory: _RoutedComponentInputBinder.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RoutedComponentInputBinder, [{
type: Injectable
}], null, null);
})();
var \u0275EmptyOutletComponent = class _\u0275EmptyOutletComponent {
static \u0275fac = function \u0275EmptyOutletComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _\u0275EmptyOutletComponent)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _\u0275EmptyOutletComponent,
selectors: [["ng-component"]],
exportAs: ["emptyRouterOutlet"],
decls: 1,
vars: 0,
template: function _EmptyOutletComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "router-outlet");
}
},
dependencies: [RouterOutlet],
encapsulation: 2
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(\u0275EmptyOutletComponent, [{
type: Component,
args: [{
template: `<router-outlet/>`,
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 = \u0275EmptyOutletComponent;
}
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 = /* @__PURE__ */ 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) {
if (typeof redirectTo !== "string") {
const redirectToFn = redirectTo;
const {
queryParams,
fragment,
routeConfig,
url,
outlet,
params,
data,
title
} = currentSnapshot;
const newRedirect = runInInjectionContext(injector, () => redirectToFn({
params,
data,
queryParams,
fragment,
routeConfig,
url,
outlet,
title
}));
if (newRedirect instanceof UrlTree) {
throw new AbsoluteRedirect(newRedirect);
}
redirectTo = newRedirect;
}
const newTree = this.applyRedirectCreateUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams);
if (redirectTo[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;
}
};
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, routes2, children) {
const res = {};
for (const r of routes2) {
if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return __spreadValues(__spreadValues({}, children), res);
}
function createChildrenForEmptyPaths(routes2, primarySegment) {
const res = {};
res[PRIMARY_OUTLET] = primarySegment;
for (const r of routes2) {
if (r.path === "" && getOutlet(r) !== PRIMARY_OUTLET) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return res;
}
function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes2) {
return routes2.some((r) => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
}
function containsEmptyPathMatches(segmentGroup, slicedSegments, routes2) {
return routes2.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, routes2, segmentGroup, segments, outlet, allowRedirects, parentRoute) {
return from(routes2).pipe(concatMap((r) => {
return this.processSegmentAgainstRoute(r._injector ?? injector, routes2, 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, routes2, 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, routes2, route, segments, outlet, parentRoute);
}
return noMatch$1(rawSegment);
}
expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes2, 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 this.applyRedirects.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => {
return this.processSegment(injector, routes2, 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 resolveNode(resolve, futureARS, futureRSS, injector).pipe(map((resolvedData) => {
futureARS._resolvedData = resolvedData;
futureARS.data = getInherited(futureARS, futureARS.parent, paramsInheritanceStrategy).resolve;
return null;
}));
}
function resolveNode(resolve, futureARS, futureRSS, injector) {
const keys = getDataKeys(resolve);
if (keys.length === 0) {
return of({});
}
const data = {};
return from(keys).pipe(mergeMap((key) => getResolver(resolve[key], futureARS, futureRSS, injector).pipe(first(), tap((value) => {
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 \u0275fac = function TitleStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TitleStrategy)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
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 \u0275fac = function DefaultTitleStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DefaultTitleStrategy)(\u0275\u0275inject(Title));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DefaultTitleStrategy,
factory: _DefaultTitleStrategy.\u0275fac,
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(route) {
if (this.componentLoaders.get(route)) {
return this.componentLoaders.get(route);
} else if (route._loadedComponent) {
return of(route._loadedComponent);
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const loadRunner = wrapIntoObservable(route.loadComponent()).pipe(map(maybeUnwrapDefaultExport), tap((component) => {
if (this.onLoadEndListener) {
this.onLoadEndListener(route);
}
(typeof ngDevMode === "undefined" || ngDevMode) && assertStandalone(route.path ?? "", component);
route._loadedComponent = component;
}), finalize(() => {
this.componentLoaders.delete(route);
}));
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
this.componentLoaders.set(route, loader);
return loader;
}
loadChildren(parentInjector, route) {
if (this.childrenLoaders.get(route)) {
return this.childrenLoaders.get(route);
} else if (route._loadedRoutes) {
return of({
routes: route._loadedRoutes,
injector: route._loadedInjector
});
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const moduleFactoryOrRoutes$ = loadChildren(route, this.compiler, parentInjector, this.onLoadEndListener);
const loadRunner = moduleFactoryOrRoutes$.pipe(finalize(() => {
this.childrenLoaders.delete(route);
}));
const loader = new ConnectableObservable(loadRunner, () => new Subject()).pipe(refCount());
this.childrenLoaders.set(route, loader);
return loader;
}
static \u0275fac = function RouterConfigLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterConfigLoader)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _RouterConfigLoader,
factory: _RouterConfigLoader.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterConfigLoader, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
function loadChildren(route, compiler, parentInjector, onLoadEndListener) {
return wrapIntoObservable(route.loadChildren()).pipe(map(maybeUnwrapDefaultExport), mergeMap((t) => {
if (t instanceof NgModuleFactory$1 || Array.isArray(t)) {
return of(t);
} else {
return from(compiler.compileModuleAsync(t));
}
}), map((factoryOrRoutes) => {
if (onLoadEndListener) {
onLoadEndListener(route);
}
let injector;
let rawRoutes;
let requireStandaloneComponents = false;
if (Array.isArray(factoryOrRoutes)) {
rawRoutes = factoryOrRoutes;
requireStandaloneComponents = true;
} else {
injector = factoryOrRoutes.create(parentInjector).injector;
rawRoutes = injector.get(ROUTES, [], {
optional: true,
self: true
}).flat();
}
const routes2 = rawRoutes.map(standardizeConfig);
(typeof ngDevMode === "undefined" || ngDevMode) && validateConfig(routes2, route.path, requireStandaloneComponents);
return {
routes: routes2,
injector
};
}));
}
function isWrappedDefaultExport(value) {
return value && typeof value === "object" && "default" in value;
}
function maybeUnwrapDefaultExport(input2) {
return isWrappedDefaultExport(input2) ? input2["default"] : input2;
}
var UrlHandlingStrategy = class _UrlHandlingStrategy {
static \u0275fac = function UrlHandlingStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _UrlHandlingStrategy)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
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 \u0275fac = function DefaultUrlHandlingStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DefaultUrlHandlingStrategy)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DefaultUrlHandlingStrategy,
factory: _DefaultUrlHandlingStrategy.\u0275fac,
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 document2 = injector.get(DOCUMENT);
return injector.get(NgZone).runOutsideAngular(() => {
if (!document2.startViewTransition || transitionOptions.skipNextTransition) {
transitionOptions.skipNextTransition = false;
return new Promise((resolve) => setTimeout(resolve));
}
let resolveViewTransitionStarted;
const viewTransitionStarted = new Promise((resolve) => {
resolveViewTransitionStarted = resolve;
});
const transition = document2.startViewTransition(() => {
resolveViewTransitionStarted();
return createRenderPromise(injector);
});
const {
onViewTransitionCreated
} = transitionOptions;
if (onViewTransitionCreated) {
runInInjectionContext(injector, () => onViewTransitionCreated({
transition,
from: from2,
to
}));
}
return viewTransitionStarted;
});
}
function createRenderPromise(injector) {
return new Promise((resolve) => {
afterNextRender({
read: () => setTimeout(resolve)
}, {
injector
});
});
}
var NAVIGATION_ERROR_HANDLER = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "navigation error handler" : "");
var NavigationTransitions = class _NavigationTransitions {
currentNavigation = null;
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.
*/
transitionAbortSubject = 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;
this.transitions?.next(__spreadProps(__spreadValues({}, request), {
extractedUrl: this.urlHandlingStrategy.extract(request.rawUrl),
targetSnapshot: null,
targetRouterState: null,
guards: {
canActivateChecks: [],
canDeactivateChecks: []
},
guardsResult: null,
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 completed = false;
let errored = 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 = {
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
})
};
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 = __spreadProps(__spreadValues({}, this.currentNavigation), {
finalUrl: t2.urlAfterRedirects
});
const routesRecognized = new RoutesRecognized(t2.id, this.urlSerializer.serialize(t2.extractedUrl), this.urlSerializer.serialize(t2.urlAfterRedirects), t2.targetSnapshot);
this.events.next(routesRecognized);
})
);
} else if (urlTransition && this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
const {
id,
extractedUrl,
source,
restoredState,
extras
} = t;
const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
this.events.next(navStart);
const targetSnapshot = createEmptyState(this.rootComponentType).snapshot;
this.currentTransition = overallTransitionState = __spreadProps(__spreadValues({}, t), {
targetSnapshot,
urlAfterRedirects: extractedUrl,
extras: __spreadProps(__spreadValues({}, extras), {
skipLocationChange: false,
replaceUrl: false
})
});
this.currentNavigation.finalUrl = extractedUrl;
return of(overallTransitionState);
} else {
const reason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation was ignored because the UrlHandlingStrategy indicated neither the current URL ${t.currentRawUrl} nor target URL ${t.rawUrl} should be processed.` : "";
this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, 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 && !route.routeConfig._loadedComponent) {
loaders.push(this.configLoader.loadComponent(route.routeConfig).pipe(tap((loadedComponent) => {
route.component = loadedComponent;
}), map(() => void 0)));
}
for (const child of route.children) {
loaders.push(...loadComponents(child));
}
return loaders;
};
return combineLatest(loadComponents(t.targetSnapshot.root)).pipe(defaultIfEmpty(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.targetRouterState = targetRouterState;
return overallTransitionState;
}),
tap(() => {
this.events.next(new BeforeActivateRoutes());
}),
activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt), this.inputBindingEnabled),
// Ensure that if some observable used to drive the transition doesn't
// complete, the navigation still finalizes This should never happen, but
// this is done as a safety measure to avoid surfacing this error (#49567).
take(1),
tap({
next: (t) => {
completed = true;
this.lastSuccessfulNavigation = this.currentNavigation;
this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
this.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
t.resolve(true);
},
complete: () => {
completed = true;
}
}),
// There used to be a lot more logic happening directly within the
// transition Observable. Some of this logic has been refactored out to
// other places but there may still be errors that happen there. This gives
// us a way to cancel the transition from the outside. This may also be
// required in the future to support something like the abort signal of the
// Navigation API where the navigation gets aborted from outside the
// transition.
takeUntil(this.transitionAbortSubject.pipe(tap((err) => {
throw err;
}))),
finalize(() => {
if (!completed && !errored) {
const cancelationReason = typeof ngDevMode === "undefined" || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : "";
this.cancelNavigationTransition(overallTransitionState, cancelationReason, NavigationCancellationCode.SupersededByNewNavigation);
}
if (this.currentTransition?.id === overallTransitionState.id) {
this.currentNavigation = null;
this.currentTransition = null;
}
}),
catchError((e) => {
if (this.destroyed) {
overallTransitionState.resolve(false);
return EMPTY;
}
errored = 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 targetBrowserUrl = this.currentNavigation?.targetBrowserUrl ?? this.currentNavigation?.extractedUrl;
return currentBrowserUrl.toString() !== targetBrowserUrl?.toString() && !this.currentNavigation?.extras.skipLocationChange;
}
static \u0275fac = function NavigationTransitions_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NavigationTransitions)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _NavigationTransitions,
factory: _NavigationTransitions.\u0275fac,
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 \u0275fac = function RouteReuseStrategy_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouteReuseStrategy)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
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 \u0275fac = /* @__PURE__ */ (() => {
let \u0275DefaultRouteReuseStrategy_BaseFactory;
return function DefaultRouteReuseStrategy_Factory(__ngFactoryType__) {
return (\u0275DefaultRouteReuseStrategy_BaseFactory || (\u0275DefaultRouteReuseStrategy_BaseFactory = \u0275\u0275getInheritedFactory(_DefaultRouteReuseStrategy)))(__ngFactoryType__ || _DefaultRouteReuseStrategy);
};
})();
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _DefaultRouteReuseStrategy,
factory: _DefaultRouteReuseStrategy.\u0275fac,
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 \u0275fac = function StateManager_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _StateManager)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
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()?.\u0275routerPageId ?? 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.GuardRejected || e.code === NavigationCancellationCode.NoDataFromResolver)) {
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,
\u0275routerPageId: routerPageId
};
}
return {
navigationId
};
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275HistoryStateManager_BaseFactory;
return function HistoryStateManager_Factory(__ngFactoryType__) {
return (\u0275HistoryStateManager_BaseFactory || (\u0275HistoryStateManager_BaseFactory = \u0275\u0275getInheritedFactory(_HistoryStateManager)))(__ngFactoryType__ || _HistoryStateManager);
};
})();
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HistoryStateManager,
factory: _HistoryStateManager.\u0275fac,
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);
/**
* 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
});
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 = 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.transitionAbortSubject.next(e2);
}
});
this.eventsSubscription.add(subscription);
}
/** @internal */
resetRootComponentType(rootComponentType) {
this.routerState.root.component = rootComponentType;
this.navigationTransitions.rootComponentType = rootComponentType;
}
/**
* Sets up the location change listener and performs the initial navigation.
*/
initialNavigation() {
this.setUpLocationChangeListener();
if (!this.navigationTransitions.hasRequestedNavigation) {
this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, this.stateManager.restoredState());
}
}
/**
* Sets up the location change listener. This listener detects navigations triggered from outside
* the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
* navigation so that the correct events, guards, etc. are triggered.
*/
setUpLocationChangeListener() {
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.\u0275routerPageId;
if (Object.keys(stateCopy).length !== 0) {
extras.state = stateCopy;
}
}
const urlTree = this.parseUrl(url);
this.scheduleNavigation(urlTree, source, restoredState, extras);
}
/** The current URL. */
get url() {
return this.serializeUrl(this.currentUrlTree);
}
/**
* Returns the current `Navigation` object when the router is navigating,
* and `null` when idle.
*/
getCurrentNavigation() {
return this.navigationTransitions.currentNavigation;
}
/**
* The `Navigation` object of the most recent navigation to succeed and `null` if there
* has not been a successful navigation yet.
*/
get lastSuccessfulNavigation() {
return this.navigationTransitions.lastSuccessfulNavigation;
}
/**
* Resets the route configuration used for navigation and generating links.
*
* @param config The route array for the new configuration.
*
* @usageNotes
*
* ```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 {
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 \u0275fac = function Router_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Router)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Router,
factory: _Router.\u0275fac,
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}`);
}
}
}
function isPublicRouterEvent(e) {
return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest);
}
// node_modules/@angular/router/fesm2022/router_module-DTJgGWLd.mjs
var RouterLink = class _RouterLink {
router;
route;
tabIndexAttribute;
renderer;
el;
locationStrategy;
/**
* Represents an `href` attribute value applied to a host element,
* when a host element is `<a>`. For other tags, the value is `null`.
*/
href = null;
/**
* Represents the `target` attribute on a host element.
* This is only used when the host element is an `<a>` tag.
*/
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 `<a>` tag. */
isAnchorElement;
subscription;
/** @internal */
onChanges = new Subject();
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;
const tagName = el.nativeElement.tagName?.toLowerCase();
this.isAnchorElement = tagName === "a" || tagName === "area";
if (this.isAnchorElement) {
this.subscription = router.events.subscribe((s) => {
if (s instanceof NavigationEnd) {
this.updateHref();
}
});
} else {
this.setTabIndexIfNotOnNativeEl("0");
}
}
/**
* 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(4016, "Cannot configure queryParams or fragment when using a UrlTree as the routerLink input value.");
}
if (this.isAnchorElement) {
this.updateHref();
}
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);
return !this.isAnchorElement;
}
/** @docs-private */
ngOnDestroy() {
this.subscription?.unsubscribe();
}
updateHref() {
const urlTree = this.urlTree;
this.href = urlTree !== null && this.locationStrategy ? this.locationStrategy?.prepareExternalUrl(this.router.serializeUrl(urlTree)) : null;
const sanitizedValue = this.href === null ? null : (
// This class represents a directive that can be added to both `<a>` elements,
// as well as other elements. As a result, we can't define security context at
// compile time. So the security context is deferred to runtime.
// The `ɵɵsanitizeUrlOrResourceUrl` selects the necessary sanitizer function
// based on the tag and property names. The logic mimics the one from
// `packages/compiler/src/schema/dom_security_schema.ts`, which is used at compile time.
//
// Note: we should investigate whether we can switch to using `@HostBinding('attr.href')`
// instead of applying a value via a renderer, after a final merge of the
// `RouterLinkWithHref` directive.
\u0275\u0275sanitizeUrlOrResourceUrl(this.href, this.el.nativeElement.tagName.toLowerCase(), "href")
);
this.applyAttributeValue("href", sanitizedValue);
}
applyAttributeValue(attrName, attrValue) {
const renderer = this.renderer;
const nativeElement = this.el.nativeElement;
if (attrValue !== null) {
renderer.setAttribute(nativeElement, attrName, attrValue);
} else {
renderer.removeAttribute(nativeElement, attrName);
}
}
get urlTree() {
if (this.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 \u0275fac = function RouterLink_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterLink)(\u0275\u0275directiveInject(Router), \u0275\u0275directiveInject(ActivatedRoute), \u0275\u0275injectAttribute("tabindex"), \u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(LocationStrategy));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RouterLink,
selectors: [["", "routerLink", ""]],
hostVars: 1,
hostBindings: function RouterLink_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("click", function RouterLink_click_HostBindingHandler($event) {
return ctx.onClick($event.button, $event.ctrlKey, $event.shiftKey, $event.altKey, $event.metaKey);
});
}
if (rf & 2) {
\u0275\u0275attribute("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: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterLink, [{
type: Directive,
args: [{
selector: "[routerLink]"
}]
}], () => [{
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
* <a
* routerLink="/user/bob"
* routerLinkActive="active-link"
* (isActiveChange)="this.onRouterLinkActive($event)">Bob</a>
* ```
*/
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 \u0275fac = function RouterLinkActive_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterLinkActive)(\u0275\u0275directiveInject(Router), \u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(ChangeDetectorRef), \u0275\u0275directiveInject(RouterLink, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RouterLinkActive,
selectors: [["", "routerLinkActive", ""]],
contentQueries: function RouterLinkActive_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
\u0275\u0275contentQuery(dirIndex, RouterLink, 5);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx.links = _t);
}
},
inputs: {
routerLinkActiveOptions: "routerLinkActiveOptions",
ariaCurrentWhenActive: "ariaCurrentWhenActive",
routerLinkActive: "routerLinkActive"
},
outputs: {
isActiveChange: "isActiveChange"
},
exportAs: ["routerLinkActive"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(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 \u0275fac = function PreloadAllModules_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PreloadAllModules)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _PreloadAllModules,
factory: _PreloadAllModules.\u0275fac,
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 \u0275fac = function NoPreloading_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NoPreloading)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _NoPreloading,
factory: _NoPreloading.\u0275fac,
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, routes2) {
const res = [];
for (const route of routes2) {
if (route.providers && !route._injector) {
route._injector = createEnvironmentInjector(route.providers, injector, `Route: ${route.path}`);
}
const injectorForCurrentRoute = route._injector ?? injector;
const injectorForChildren = route._loadedInjector ?? injectorForCurrentRoute;
if (route.loadChildren && !route._loadedRoutes && route.canLoad === void 0 || route.loadComponent && !route._loadedComponent) {
res.push(this.preloadConfig(injectorForCurrentRoute, route));
}
if (route.children || route._loadedRoutes) {
res.push(this.processRoutes(injectorForChildren, route.children ?? route._loadedRoutes));
}
}
return from(res).pipe(mergeAll());
}
preloadConfig(injector, route) {
return this.preloadingStrategy.preload(route, () => {
let loadedChildren$;
if (route.loadChildren && route.canLoad === void 0) {
loadedChildren$ = this.loader.loadChildren(injector, route);
} else {
loadedChildren$ = of(null);
}
const recursiveLoadChildren$ = loadedChildren$.pipe(mergeMap((config) => {
if (config === null) {
return of(void 0);
}
route._loadedRoutes = config.routes;
route._loadedInjector = config.injector;
return this.processRoutes(config.injector ?? injector, config.routes);
}));
if (route.loadComponent && !route._loadedComponent) {
const loadComponent$ = this.loader.loadComponent(route);
return from([recursiveLoadChildren$, loadComponent$]).pipe(mergeAll());
} else {
return recursiveLoadChildren$;
}
});
}
static \u0275fac = function RouterPreloader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterPreloader)(\u0275\u0275inject(Router), \u0275\u0275inject(EnvironmentInjector), \u0275\u0275inject(PreloadingStrategy), \u0275\u0275inject(RouterConfigLoader));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _RouterPreloader,
factory: _RouterPreloader.\u0275fac,
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";
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;
if (e.position) {
if (this.options.scrollPositionRestoration === "top") {
this.viewportScroller.scrollToPosition([0, 0]);
} else if (this.options.scrollPositionRestoration === "enabled") {
this.viewportScroller.scrollToPosition(e.position);
}
} else {
if (e.anchor && this.options.anchorScrolling === "enabled") {
this.viewportScroller.scrollToAnchor(e.anchor);
} else if (this.options.scrollPositionRestoration !== "disabled") {
this.viewportScroller.scrollToPosition([0, 0]);
}
}
});
}
scheduleScrollEvent(routerEvent, anchor) {
this.zone.runOutsideAngular(() => {
setTimeout(() => {
this.zone.run(() => {
this.transitions.events.next(new Scroll(routerEvent, this.lastSource === "popstate" ? this.store[this.restoredId] : null, anchor));
});
}, 0);
});
}
/** @docs-private */
ngOnDestroy() {
this.routerEventsSubscription?.unsubscribe();
this.scrollEventsSubscription?.unsubscribe();
}
static \u0275fac = function RouterScroller_Factory(__ngFactoryType__) {
\u0275\u0275invalidFactory();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _RouterScroller,
factory: _RouterScroller.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RouterScroller, [{
type: Injectable
}], () => [{
type: UrlSerializer
}, {
type: NavigationTransitions
}, {
type: ViewportScroller
}, {
type: NgZone
}, {
type: void 0
}], null);
})();
function rootRoute(router) {
return router.routerState.root;
}
function routerFeature(kind, providers) {
return {
\u0275kind: kind,
\u0275providers: providers
};
}
var ROUTER_IS_PROVIDED = new InjectionToken("", {
providedIn: "root",
factory: () => false
});
function getBootstrapListener() {
const injector = inject(Injector);
return (bootstrappedComponentRef) => {
const ref = injector.get(ApplicationRef);
if (bootstrappedComponentRef !== ref.components[0]) {
return;
}
const router = injector.get(Router);
const bootstrapDone = injector.get(BOOTSTRAP_DONE);
if (injector.get(INITIAL_NAVIGATION) === 1) {
router.initialNavigation();
}
injector.get(ROUTER_PRELOADER, null, InjectFlags.Optional)?.setUpPreloading();
injector.get(ROUTER_SCROLLER, null, InjectFlags.Optional)?.init();
router.resetRootComponentType(ref.componentTypes[0]);
if (!bootstrapDone.closed) {
bootstrapDone.next();
bootstrapDone.complete();
bootstrapDone.unsubscribe();
}
};
}
var BOOTSTRAP_DONE = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "bootstrap done indicator" : "", {
factory: () => {
return new Subject();
}
});
var INITIAL_NAVIGATION = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "initial navigation" : "", {
providedIn: "root",
factory: () => 1
/* InitialNavigation.EnabledNonBlocking */
});
function withEnabledBlockingInitialNavigation() {
const providers = [{
provide: INITIAL_NAVIGATION,
useValue: 0
/* InitialNavigation.EnabledBlocking */
}, 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 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, \u0275EmptyOutletComponent];
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(routes2, config) {
return {
ngModule: _RouterModule,
providers: [ROUTER_PROVIDERS, typeof ngDevMode === "undefined" || ngDevMode ? config?.enableTracing ? withDebugTracing().\u0275providers : [] : [], {
provide: ROUTES,
multi: true,
useValue: routes2
}, 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).\u0275providers : [], config?.initialNavigation ? provideInitialNavigation(config) : [], config?.bindToComponentInputs ? withComponentInputBinding().\u0275providers : [], config?.enableViewTransitions ? withViewTransitions().\u0275providers : [], 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(routes2) {
return {
ngModule: _RouterModule,
providers: [{
provide: ROUTES,
multi: true,
useValue: routes2
}]
};
}
static \u0275fac = function RouterModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RouterModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _RouterModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(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().\u0275providers : [], config.initialNavigation === "enabledBlocking" ? withEnabledBlockingInitialNavigation().\u0275providers : []];
}
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
var VERSION4 = new Version("19.2.11");
// src/app/services/tutorial.service.ts
var baseUrl = "http://localhost:8080/api/tutorials";
var TutorialService = class _TutorialService {
http;
constructor(http) {
this.http = http;
}
getAll() {
return this.http.get(baseUrl);
}
get(id) {
return this.http.get(`${baseUrl}/${id}`);
}
create(data) {
return this.http.post(baseUrl, data);
}
update(id, data) {
return this.http.put(`${baseUrl}/${id}`, data);
}
delete(id) {
return this.http.delete(`${baseUrl}/${id}`);
}
deleteAll() {
return this.http.delete(baseUrl);
}
findByTitle(title) {
return this.http.get(`${baseUrl}?title=${title}`);
}
static \u0275fac = function TutorialService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TutorialService)(\u0275\u0275inject(HttpClient));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _TutorialService, factory: _TutorialService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TutorialService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{ type: HttpClient }], null);
})();
// node_modules/@angular/forms/fesm2022/forms.mjs
var BaseControlValueAccessor = class _BaseControlValueAccessor {
_renderer;
_elementRef;
/**
* The registered callback function called when a change or input event occurs on the input
* element.
* @docs-private
*/
onChange = (_) => {
};
/**
* The registered callback function called when a blur event occurs on the input element.
* @docs-private
*/
onTouched = () => {
};
constructor(_renderer, _elementRef) {
this._renderer = _renderer;
this._elementRef = _elementRef;
}
/**
* Helper method that sets a property on a target element using the current Renderer
* implementation.
* @docs-private
*/
setProperty(key, value) {
this._renderer.setProperty(this._elementRef.nativeElement, key, value);
}
/**
* Registers a function called when the control is touched.
* @docs-private
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Registers a function called when the control value changes.
* @docs-private
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* Sets the "disabled" property on the range input element.
* @docs-private
*/
setDisabledState(isDisabled) {
this.setProperty("disabled", isDisabled);
}
static \u0275fac = function BaseControlValueAccessor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BaseControlValueAccessor)(\u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(ElementRef));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _BaseControlValueAccessor
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BaseControlValueAccessor, [{
type: Directive
}], () => [{
type: Renderer2
}, {
type: ElementRef
}], null);
})();
var BuiltInControlValueAccessor = class _BuiltInControlValueAccessor extends BaseControlValueAccessor {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275BuiltInControlValueAccessor_BaseFactory;
return function BuiltInControlValueAccessor_Factory(__ngFactoryType__) {
return (\u0275BuiltInControlValueAccessor_BaseFactory || (\u0275BuiltInControlValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_BuiltInControlValueAccessor)))(__ngFactoryType__ || _BuiltInControlValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _BuiltInControlValueAccessor,
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BuiltInControlValueAccessor, [{
type: Directive
}], null, null);
})();
var NG_VALUE_ACCESSOR = new InjectionToken(ngDevMode ? "NgValueAccessor" : "");
var CHECKBOX_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckboxControlValueAccessor),
multi: true
};
var CheckboxControlValueAccessor = class _CheckboxControlValueAccessor extends BuiltInControlValueAccessor {
/**
* Sets the "checked" property on the input element.
* @docs-private
*/
writeValue(value) {
this.setProperty("checked", value);
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275CheckboxControlValueAccessor_BaseFactory;
return function CheckboxControlValueAccessor_Factory(__ngFactoryType__) {
return (\u0275CheckboxControlValueAccessor_BaseFactory || (\u0275CheckboxControlValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_CheckboxControlValueAccessor)))(__ngFactoryType__ || _CheckboxControlValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CheckboxControlValueAccessor,
selectors: [["input", "type", "checkbox", "formControlName", ""], ["input", "type", "checkbox", "formControl", ""], ["input", "type", "checkbox", "ngModel", ""]],
hostBindings: function CheckboxControlValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("change", function CheckboxControlValueAccessor_change_HostBindingHandler($event) {
return ctx.onChange($event.target.checked);
})("blur", function CheckboxControlValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([CHECKBOX_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CheckboxControlValueAccessor, [{
type: Directive,
args: [{
selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]",
host: {
"(change)": "onChange($event.target.checked)",
"(blur)": "onTouched()"
},
providers: [CHECKBOX_VALUE_ACCESSOR],
standalone: false
}]
}], null, null);
})();
var DEFAULT_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DefaultValueAccessor),
multi: true
};
function _isAndroid() {
const userAgent = getDOM() ? getDOM().getUserAgent() : "";
return /android (\d+)/.test(userAgent.toLowerCase());
}
var COMPOSITION_BUFFER_MODE = new InjectionToken(ngDevMode ? "CompositionEventMode" : "");
var DefaultValueAccessor = class _DefaultValueAccessor extends BaseControlValueAccessor {
_compositionMode;
/** Whether the user is creating a composition string (IME events). */
_composing = false;
constructor(renderer, elementRef, _compositionMode) {
super(renderer, elementRef);
this._compositionMode = _compositionMode;
if (this._compositionMode == null) {
this._compositionMode = !_isAndroid();
}
}
/**
* Sets the "value" property on the input element.
* @docs-private
*/
writeValue(value) {
const normalizedValue = value == null ? "" : value;
this.setProperty("value", normalizedValue);
}
/** @internal */
_handleInput(value) {
if (!this._compositionMode || this._compositionMode && !this._composing) {
this.onChange(value);
}
}
/** @internal */
_compositionStart() {
this._composing = true;
}
/** @internal */
_compositionEnd(value) {
this._composing = false;
this._compositionMode && this.onChange(value);
}
static \u0275fac = function DefaultValueAccessor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DefaultValueAccessor)(\u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(COMPOSITION_BUFFER_MODE, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _DefaultValueAccessor,
selectors: [["input", "formControlName", "", 3, "type", "checkbox"], ["textarea", "formControlName", ""], ["input", "formControl", "", 3, "type", "checkbox"], ["textarea", "formControl", ""], ["input", "ngModel", "", 3, "type", "checkbox"], ["textarea", "ngModel", ""], ["", "ngDefaultControl", ""]],
hostBindings: function DefaultValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("input", function DefaultValueAccessor_input_HostBindingHandler($event) {
return ctx._handleInput($event.target.value);
})("blur", function DefaultValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
})("compositionstart", function DefaultValueAccessor_compositionstart_HostBindingHandler() {
return ctx._compositionStart();
})("compositionend", function DefaultValueAccessor_compositionend_HostBindingHandler($event) {
return ctx._compositionEnd($event.target.value);
});
}
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([DEFAULT_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DefaultValueAccessor, [{
type: Directive,
args: [{
selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]",
// TODO: vsavkin replace the above selector with the one below it once
// https://github.com/angular/angular/issues/3011 is implemented
// selector: '[ngModel],[formControl],[formControlName]',
host: {
"(input)": "$any(this)._handleInput($event.target.value)",
"(blur)": "onTouched()",
"(compositionstart)": "$any(this)._compositionStart()",
"(compositionend)": "$any(this)._compositionEnd($event.target.value)"
},
providers: [DEFAULT_VALUE_ACCESSOR],
standalone: false
}]
}], () => [{
type: Renderer2
}, {
type: ElementRef
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [COMPOSITION_BUFFER_MODE]
}]
}], null);
})();
function isEmptyInputValue(value) {
return value == null || lengthOrSize(value) === 0;
}
function lengthOrSize(value) {
if (value == null) {
return null;
} else if (Array.isArray(value) || typeof value === "string") {
return value.length;
} else if (value instanceof Set) {
return value.size;
}
return null;
}
var NG_VALIDATORS = new InjectionToken(ngDevMode ? "NgValidators" : "");
var NG_ASYNC_VALIDATORS = new InjectionToken(ngDevMode ? "NgAsyncValidators" : "");
var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
var Validators = class {
/**
* @description
* Validator that requires the control's value to be greater than or equal to the provided number.
*
* @usageNotes
*
* ### Validate against a minimum of 3
*
* ```ts
* const control = new FormControl(2, Validators.min(3));
*
* console.log(control.errors); // {min: {min: 3, actual: 2}}
* ```
*
* @returns A validator function that returns an error map with the
* `min` property if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static min(min) {
return minValidator(min);
}
/**
* @description
* Validator that requires the control's value to be less than or equal to the provided number.
*
* @usageNotes
*
* ### Validate against a maximum of 15
*
* ```ts
* const control = new FormControl(16, Validators.max(15));
*
* console.log(control.errors); // {max: {max: 15, actual: 16}}
* ```
*
* @returns A validator function that returns an error map with the
* `max` property if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static max(max) {
return maxValidator(max);
}
/**
* @description
* Validator that requires the control have a non-empty value.
*
* @usageNotes
*
* ### Validate that the field is non-empty
*
* ```ts
* const control = new FormControl('', Validators.required);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map with the `required` property
* if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static required(control) {
return requiredValidator(control);
}
/**
* @description
* Validator that requires the control's value be true. This validator is commonly
* used for required checkboxes.
*
* @usageNotes
*
* ### Validate that the field value is true
*
* ```ts
* const control = new FormControl('some value', Validators.requiredTrue);
*
* console.log(control.errors); // {required: true}
* ```
*
* @returns An error map that contains the `required` property
* set to `true` if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static requiredTrue(control) {
return requiredTrueValidator(control);
}
/**
* @description
* Validator that requires the control's value pass an email validation test.
*
* Tests the value using a [regular
* expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
* pattern suitable for common use cases. The pattern is based on the definition of a valid email
* address in the [WHATWG HTML
* specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) with
* some enhancements to incorporate more RFC rules (such as rules related to domain names and the
* lengths of different parts of the address).
*
* The differences from the WHATWG version include:
* - Disallow `local-part` (the part before the `@` symbol) to begin or end with a period (`.`).
* - Disallow `local-part` to be longer than 64 characters.
* - Disallow the whole address to be longer than 254 characters.
*
* If this pattern does not satisfy your business needs, you can use `Validators.pattern()` to
* validate the value against a different pattern.
*
* @usageNotes
*
* ### Validate that the field matches a valid email pattern
*
* ```ts
* const control = new FormControl('bad@', Validators.email);
*
* console.log(control.errors); // {email: true}
* ```
*
* @returns An error map with the `email` property
* if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static email(control) {
return emailValidator(control);
}
/**
* @description
* Validator that requires the number of items in the control's value to be greater than or equal
* to the provided minimum length. This validator is also provided by default if you use
* the HTML5 `minlength` attribute. Note that the `minLength` validator is intended to be used
* only for types that have a numeric `length` or `size` property, such as strings, arrays or
* sets. The `minLength` validator logic is also not invoked for values when their `length` or
* `size` property is 0 (for example in case of an empty string or an empty array), to support
* optional controls. You can use the standard `required` validator if empty values should not be
* considered valid.
*
* @usageNotes
*
* ### Validate that the field has a minimum of 3 characters
*
* ```ts
* const control = new FormControl('ng', Validators.minLength(3));
*
* console.log(control.errors); // {minlength: {requiredLength: 3, actualLength: 2}}
* ```
*
* ```html
* <input minlength="5">
* ```
*
* @returns A validator function that returns an error map with the
* `minlength` property if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static minLength(minLength) {
return minLengthValidator(minLength);
}
/**
* @description
* Validator that requires the number of items in the control's value to be less than or equal
* to the provided maximum length. This validator is also provided by default if you use
* the HTML5 `maxlength` attribute. Note that the `maxLength` validator is intended to be used
* only for types that have a numeric `length` or `size` property, such as strings, arrays or
* sets.
*
* @usageNotes
*
* ### Validate that the field has maximum of 5 characters
*
* ```ts
* const control = new FormControl('Angular', Validators.maxLength(5));
*
* console.log(control.errors); // {maxlength: {requiredLength: 5, actualLength: 7}}
* ```
*
* ```html
* <input maxlength="5">
* ```
*
* @returns A validator function that returns an error map with the
* `maxlength` property if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static maxLength(maxLength) {
return maxLengthValidator(maxLength);
}
/**
* @description
* Validator that requires the control's value to match a regex pattern. This validator is also
* provided by default if you use the HTML5 `pattern` attribute.
*
* @usageNotes
*
* ### Validate that the field only contains letters or spaces
*
* ```ts
* const control = new FormControl('1', Validators.pattern('[a-zA-Z ]*'));
*
* console.log(control.errors); // {pattern: {requiredPattern: '^[a-zA-Z ]*$', actualValue: '1'}}
* ```
*
* ```html
* <input pattern="[a-zA-Z ]*">
* ```
*
* ### Pattern matching with the global or sticky flag
*
* `RegExp` objects created with the `g` or `y` flags that are passed into `Validators.pattern`
* can produce different results on the same input when validations are run consecutively. This is
* due to how the behavior of `RegExp.prototype.test` is
* specified in [ECMA-262](https://tc39.es/ecma262/#sec-regexpbuiltinexec)
* (`RegExp` preserves the index of the last match when the global or sticky flag is used).
* Due to this behavior, it is recommended that when using
* `Validators.pattern` you **do not** pass in a `RegExp` object with either the global or sticky
* flag enabled.
*
* ```ts
* // Not recommended (since the `g` flag is used)
* const controlOne = new FormControl('1', Validators.pattern(/foo/g));
*
* // Good
* const controlTwo = new FormControl('1', Validators.pattern(/foo/));
* ```
*
* @param pattern A regular expression to be used as is to test the values, or a string.
* If a string is passed, the `^` character is prepended and the `$` character is
* appended to the provided string (if not already present), and the resulting regular
* expression is used to test the values.
*
* @returns A validator function that returns an error map with the
* `pattern` property if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static pattern(pattern) {
return patternValidator(pattern);
}
/**
* @description
* Validator that performs no operation.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static nullValidator(control) {
return nullValidator();
}
static compose(validators) {
return compose(validators);
}
/**
* @description
* Compose multiple async validators into a single function that returns the union
* of the individual error objects for the provided control.
*
* @returns A validator function that returns an error map with the
* merged error objects of the async validators if the validation check fails, otherwise `null`.
*
* @see {@link /api/forms/AbstractControl#updateValueAndValidity updateValueAndValidity}
*
*/
static composeAsync(validators) {
return composeAsync(validators);
}
};
function minValidator(min) {
return (control) => {
if (control.value == null || min == null) {
return null;
}
const value = parseFloat(control.value);
return !isNaN(value) && value < min ? {
"min": {
"min": min,
"actual": control.value
}
} : null;
};
}
function maxValidator(max) {
return (control) => {
if (control.value == null || max == null) {
return null;
}
const value = parseFloat(control.value);
return !isNaN(value) && value > max ? {
"max": {
"max": max,
"actual": control.value
}
} : null;
};
}
function requiredValidator(control) {
return isEmptyInputValue(control.value) ? {
"required": true
} : null;
}
function requiredTrueValidator(control) {
return control.value === true ? null : {
"required": true
};
}
function emailValidator(control) {
if (isEmptyInputValue(control.value)) {
return null;
}
return EMAIL_REGEXP.test(control.value) ? null : {
"email": true
};
}
function minLengthValidator(minLength) {
return (control) => {
const length = control.value?.length ?? lengthOrSize(control.value);
if (length === null || length === 0) {
return null;
}
return length < minLength ? {
"minlength": {
"requiredLength": minLength,
"actualLength": length
}
} : null;
};
}
function maxLengthValidator(maxLength) {
return (control) => {
const length = control.value?.length ?? lengthOrSize(control.value);
if (length !== null && length > maxLength) {
return {
"maxlength": {
"requiredLength": maxLength,
"actualLength": length
}
};
}
return null;
};
}
function patternValidator(pattern) {
if (!pattern) return nullValidator;
let regex;
let regexStr;
if (typeof pattern === "string") {
regexStr = "";
if (pattern.charAt(0) !== "^") regexStr += "^";
regexStr += pattern;
if (pattern.charAt(pattern.length - 1) !== "$") regexStr += "$";
regex = new RegExp(regexStr);
} else {
regexStr = pattern.toString();
regex = pattern;
}
return (control) => {
if (isEmptyInputValue(control.value)) {
return null;
}
const value = control.value;
return regex.test(value) ? null : {
"pattern": {
"requiredPattern": regexStr,
"actualValue": value
}
};
};
}
function nullValidator(control) {
return null;
}
function isPresent(o) {
return o != null;
}
function toObservable(value) {
const obs = isPromise(value) ? from(value) : value;
if ((typeof ngDevMode === "undefined" || ngDevMode) && !isSubscribable(obs)) {
let errorMessage = `Expected async validator to return Promise or Observable.`;
if (typeof value === "object") {
errorMessage += " Are you using a synchronous validator where an async validator is expected?";
}
throw new RuntimeError(-1101, errorMessage);
}
return obs;
}
function mergeErrors(arrayOfErrors) {
let res = {};
arrayOfErrors.forEach((errors) => {
res = errors != null ? __spreadValues(__spreadValues({}, res), errors) : res;
});
return Object.keys(res).length === 0 ? null : res;
}
function executeValidators(control, validators) {
return validators.map((validator) => validator(control));
}
function isValidatorFn(validator) {
return !validator.validate;
}
function normalizeValidators(validators) {
return validators.map((validator) => {
return isValidatorFn(validator) ? validator : (c) => validator.validate(c);
});
}
function compose(validators) {
if (!validators) return null;
const presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0) return null;
return function(control) {
return mergeErrors(executeValidators(control, presentValidators));
};
}
function composeValidators(validators) {
return validators != null ? compose(normalizeValidators(validators)) : null;
}
function composeAsync(validators) {
if (!validators) return null;
const presentValidators = validators.filter(isPresent);
if (presentValidators.length == 0) return null;
return function(control) {
const observables = executeValidators(control, presentValidators).map(toObservable);
return forkJoin(observables).pipe(map(mergeErrors));
};
}
function composeAsyncValidators(validators) {
return validators != null ? composeAsync(normalizeValidators(validators)) : null;
}
function mergeValidators(controlValidators, dirValidator) {
if (controlValidators === null) return [dirValidator];
return Array.isArray(controlValidators) ? [...controlValidators, dirValidator] : [controlValidators, dirValidator];
}
function getControlValidators(control) {
return control._rawValidators;
}
function getControlAsyncValidators(control) {
return control._rawAsyncValidators;
}
function makeValidatorsArray(validators) {
if (!validators) return [];
return Array.isArray(validators) ? validators : [validators];
}
function hasValidator(validators, validator) {
return Array.isArray(validators) ? validators.includes(validator) : validators === validator;
}
function addValidators(validators, currentValidators) {
const current = makeValidatorsArray(currentValidators);
const validatorsToAdd = makeValidatorsArray(validators);
validatorsToAdd.forEach((v) => {
if (!hasValidator(current, v)) {
current.push(v);
}
});
return current;
}
function removeValidators(validators, currentValidators) {
return makeValidatorsArray(currentValidators).filter((v) => !hasValidator(validators, v));
}
var AbstractControlDirective = class {
/**
* @description
* Reports the value of the control if it is present, otherwise null.
*/
get value() {
return this.control ? this.control.value : null;
}
/**
* @description
* Reports whether the control is valid. A control is considered valid if no
* validation errors exist with the current value.
* If the control is not present, null is returned.
*/
get valid() {
return this.control ? this.control.valid : null;
}
/**
* @description
* Reports whether the control is invalid, meaning that an error exists in the input value.
* If the control is not present, null is returned.
*/
get invalid() {
return this.control ? this.control.invalid : null;
}
/**
* @description
* Reports whether a control is pending, meaning that async validation is occurring and
* errors are not yet available for the input value. If the control is not present, null is
* returned.
*/
get pending() {
return this.control ? this.control.pending : null;
}
/**
* @description
* Reports whether the control is disabled, meaning that the control is disabled
* in the UI and is exempt from validation checks and excluded from aggregate
* values of ancestor controls. If the control is not present, null is returned.
*/
get disabled() {
return this.control ? this.control.disabled : null;
}
/**
* @description
* Reports whether the control is enabled, meaning that the control is included in ancestor
* calculations of validity or value. If the control is not present, null is returned.
*/
get enabled() {
return this.control ? this.control.enabled : null;
}
/**
* @description
* Reports the control's validation errors. If the control is not present, null is returned.
*/
get errors() {
return this.control ? this.control.errors : null;
}
/**
* @description
* Reports whether the control is pristine, meaning that the user has not yet changed
* the value in the UI. If the control is not present, null is returned.
*/
get pristine() {
return this.control ? this.control.pristine : null;
}
/**
* @description
* Reports whether the control is dirty, meaning that the user has changed
* the value in the UI. If the control is not present, null is returned.
*/
get dirty() {
return this.control ? this.control.dirty : null;
}
/**
* @description
* Reports whether the control is touched, meaning that the user has triggered
* a `blur` event on it. If the control is not present, null is returned.
*/
get touched() {
return this.control ? this.control.touched : null;
}
/**
* @description
* Reports the validation status of the control. Possible values include:
* 'VALID', 'INVALID', 'DISABLED', and 'PENDING'.
* If the control is not present, null is returned.
*/
get status() {
return this.control ? this.control.status : null;
}
/**
* @description
* Reports whether the control is untouched, meaning that the user has not yet triggered
* a `blur` event on it. If the control is not present, null is returned.
*/
get untouched() {
return this.control ? this.control.untouched : null;
}
/**
* @description
* Returns a multicasting observable that emits a validation status whenever it is
* calculated for the control. If the control is not present, null is returned.
*/
get statusChanges() {
return this.control ? this.control.statusChanges : null;
}
/**
* @description
* Returns a multicasting observable of value changes for the control that emits every time the
* value of the control changes in the UI or programmatically.
* If the control is not present, null is returned.
*/
get valueChanges() {
return this.control ? this.control.valueChanges : null;
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return null;
}
/**
* Contains the result of merging synchronous validators into a single validator function
* (combined using `Validators.compose`).
*/
_composedValidatorFn;
/**
* Contains the result of merging asynchronous validators into a single validator function
* (combined using `Validators.composeAsync`).
*/
_composedAsyncValidatorFn;
/**
* Set of synchronous validators as they were provided while calling `setValidators` function.
* @internal
*/
_rawValidators = [];
/**
* Set of asynchronous validators as they were provided while calling `setAsyncValidators`
* function.
* @internal
*/
_rawAsyncValidators = [];
/**
* Sets synchronous validators for this directive.
* @internal
*/
_setValidators(validators) {
this._rawValidators = validators || [];
this._composedValidatorFn = composeValidators(this._rawValidators);
}
/**
* Sets asynchronous validators for this directive.
* @internal
*/
_setAsyncValidators(validators) {
this._rawAsyncValidators = validators || [];
this._composedAsyncValidatorFn = composeAsyncValidators(this._rawAsyncValidators);
}
/**
* @description
* Synchronous validator function composed of all the synchronous validators registered with this
* directive.
*/
get validator() {
return this._composedValidatorFn || null;
}
/**
* @description
* Asynchronous validator function composed of all the asynchronous validators registered with
* this directive.
*/
get asyncValidator() {
return this._composedAsyncValidatorFn || null;
}
/*
* The set of callbacks to be invoked when directive instance is being destroyed.
*/
_onDestroyCallbacks = [];
/**
* Internal function to register callbacks that should be invoked
* when directive instance is being destroyed.
* @internal
*/
_registerOnDestroy(fn) {
this._onDestroyCallbacks.push(fn);
}
/**
* Internal function to invoke all registered "on destroy" callbacks.
* Note: calling this function also clears the list of callbacks.
* @internal
*/
_invokeOnDestroyCallbacks() {
this._onDestroyCallbacks.forEach((fn) => fn());
this._onDestroyCallbacks = [];
}
/**
* @description
* Resets the control with the provided value if the control is present.
*/
reset(value = void 0) {
if (this.control) this.control.reset(value);
}
/**
* @description
* Reports whether the control with the given path has the error specified.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```ts
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* If no path is given, this method checks for the error on the current control.
*
* @returns whether the given error is present in the control at the given path.
*
* If the control is not present, false is returned.
*/
hasError(errorCode, path) {
return this.control ? this.control.hasError(errorCode, path) : false;
}
/**
* @description
* Reports error data for the control with the given path.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```ts
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* @returns error data for that particular error. If the control or error is not present,
* null is returned.
*/
getError(errorCode, path) {
return this.control ? this.control.getError(errorCode, path) : null;
}
};
var ControlContainer = class extends AbstractControlDirective {
/**
* @description
* The name for the control
*/
name;
/**
* @description
* The top-level form directive for the control.
*/
get formDirective() {
return null;
}
/**
* @description
* The path to this group.
*/
get path() {
return null;
}
};
var NgControl = class extends AbstractControlDirective {
/**
* @description
* The parent form for the control.
*
* @internal
*/
_parent = null;
/**
* @description
* The name for the control
*/
name = null;
/**
* @description
* The value accessor for the control
*/
valueAccessor = null;
};
var AbstractControlStatus = class {
_cd;
constructor(cd) {
this._cd = cd;
}
get isTouched() {
this._cd?.control?._touched?.();
return !!this._cd?.control?.touched;
}
get isUntouched() {
return !!this._cd?.control?.untouched;
}
get isPristine() {
this._cd?.control?._pristine?.();
return !!this._cd?.control?.pristine;
}
get isDirty() {
return !!this._cd?.control?.dirty;
}
get isValid() {
this._cd?.control?._status?.();
return !!this._cd?.control?.valid;
}
get isInvalid() {
return !!this._cd?.control?.invalid;
}
get isPending() {
return !!this._cd?.control?.pending;
}
get isSubmitted() {
this._cd?._submitted?.();
return !!this._cd?.submitted;
}
};
var ngControlStatusHost = {
"[class.ng-untouched]": "isUntouched",
"[class.ng-touched]": "isTouched",
"[class.ng-pristine]": "isPristine",
"[class.ng-dirty]": "isDirty",
"[class.ng-valid]": "isValid",
"[class.ng-invalid]": "isInvalid",
"[class.ng-pending]": "isPending"
};
var ngGroupStatusHost = __spreadProps(__spreadValues({}, ngControlStatusHost), {
"[class.ng-submitted]": "isSubmitted"
});
var NgControlStatus = class _NgControlStatus extends AbstractControlStatus {
constructor(cd) {
super(cd);
}
static \u0275fac = function NgControlStatus_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgControlStatus)(\u0275\u0275directiveInject(NgControl, 2));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgControlStatus,
selectors: [["", "formControlName", ""], ["", "ngModel", ""], ["", "formControl", ""]],
hostVars: 14,
hostBindings: function NgControlStatus_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending);
}
},
standalone: false,
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgControlStatus, [{
type: Directive,
args: [{
selector: "[formControlName],[ngModel],[formControl]",
host: ngControlStatusHost,
standalone: false
}]
}], () => [{
type: NgControl,
decorators: [{
type: Self
}]
}], null);
})();
var NgControlStatusGroup = class _NgControlStatusGroup extends AbstractControlStatus {
constructor(cd) {
super(cd);
}
static \u0275fac = function NgControlStatusGroup_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgControlStatusGroup)(\u0275\u0275directiveInject(ControlContainer, 10));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgControlStatusGroup,
selectors: [["", "formGroupName", ""], ["", "formArrayName", ""], ["", "ngModelGroup", ""], ["", "formGroup", ""], ["form", 3, "ngNoForm", ""], ["", "ngForm", ""]],
hostVars: 16,
hostBindings: function NgControlStatusGroup_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("ng-untouched", ctx.isUntouched)("ng-touched", ctx.isTouched)("ng-pristine", ctx.isPristine)("ng-dirty", ctx.isDirty)("ng-valid", ctx.isValid)("ng-invalid", ctx.isInvalid)("ng-pending", ctx.isPending)("ng-submitted", ctx.isSubmitted);
}
},
standalone: false,
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgControlStatusGroup, [{
type: Directive,
args: [{
selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]",
host: ngGroupStatusHost,
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Optional
}, {
type: Self
}]
}], null);
})();
var formControlNameExample = `
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});`;
var formGroupNameExample = `
<div [formGroup]="myGroup">
<div formGroupName="person">
<input formControlName="firstName">
</div>
</div>
In your class:
this.myGroup = new FormGroup({
person: new FormGroup({ firstName: new FormControl() })
});`;
var formArrayNameExample = `
<div [formGroup]="myGroup">
<div formArrayName="cities">
<div *ngFor="let city of cityArray.controls; index as i">
<input [formControlName]="i">
</div>
</div>
</div>
In your class:
this.cityArray = new FormArray([new FormControl('SF')]);
this.myGroup = new FormGroup({
cities: this.cityArray
});`;
var ngModelGroupExample = `
<form>
<div ngModelGroup="person">
<input [(ngModel)]="person.name" name="firstName">
</div>
</form>`;
var ngModelWithFormGroupExample = `
<div [formGroup]="myGroup">
<input formControlName="firstName">
<input [(ngModel)]="showMoreControls" [ngModelOptions]="{standalone: true}">
</div>
`;
function controlParentException(nameOrIndex) {
return new RuntimeError(1050, `formControlName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
${describeFormControl(nameOrIndex)}
Example:
${formControlNameExample}`);
}
function describeFormControl(nameOrIndex) {
if (nameOrIndex == null || nameOrIndex === "") {
return "";
}
const valueType = typeof nameOrIndex === "string" ? "name" : "index";
return `Affected Form Control ${valueType}: "${nameOrIndex}"`;
}
function ngModelGroupException() {
return new RuntimeError(1051, `formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents
that also have a "form" prefix: formGroupName, formArrayName, or formGroup.
Option 1: Update the parent to be formGroupName (reactive form strategy)
${formGroupNameExample}
Option 2: Use ngModel instead of formControlName (template-driven strategy)
${ngModelGroupExample}`);
}
function missingFormException() {
return new RuntimeError(1052, `formGroup expects a FormGroup instance. Please pass one in.
Example:
${formControlNameExample}`);
}
function groupParentException() {
return new RuntimeError(1053, `formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
Example:
${formGroupNameExample}`);
}
function arrayParentException() {
return new RuntimeError(1054, `formArrayName must be used with a parent formGroup directive. You'll want to add a formGroup
directive and pass it an existing FormGroup instance (you can create one in your class).
Example:
${formArrayNameExample}`);
}
var disabledAttrWarning = `
It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true
when you set up this control in your component class, the disabled attribute will actually be set in the DOM for
you. We recommend using this approach to avoid 'changed after checked' errors.
Example:
// Specify the \`disabled\` property at control creation time:
form = new FormGroup({
first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
last: new FormControl('Drew', Validators.required)
});
// Controls can also be enabled/disabled after creation:
form.get('first')?.enable();
form.get('last')?.disable();
`;
var asyncValidatorsDroppedWithOptsWarning = `
It looks like you're constructing using a FormControl with both an options argument and an
async validators argument. Mixing these arguments will cause your async validators to be dropped.
You should either put all your validators in the options object, or in separate validators
arguments. For example:
// Using validators arguments
fc = new FormControl(42, Validators.required, myAsyncValidator);
// Using AbstractControlOptions
fc = new FormControl(42, {validators: Validators.required, asyncValidators: myAV});
// Do NOT mix them: async validators will be dropped!
fc = new FormControl(42, {validators: Validators.required}, /* Oops! */ myAsyncValidator);
`;
function ngModelWarning(directiveName) {
return `
It looks like you're using ngModel on the same form field as ${directiveName}.
Support for using the ngModel input property and ngModelChange event with
reactive form directives has been deprecated in Angular v6 and will be removed
in a future version of Angular.
For more information on this, see our API docs here:
https://angular.io/api/forms/${directiveName === "formControl" ? "FormControlDirective" : "FormControlName"}#use-with-ngmodel
`;
}
function describeKey(isFormGroup, key) {
return isFormGroup ? `with name: '${key}'` : `at index: ${key}`;
}
function noControlsError(isFormGroup) {
return `
There are no form controls registered with this ${isFormGroup ? "group" : "array"} yet. If you're using ngModel,
you may want to check next tick (e.g. use setTimeout).
`;
}
function missingControlError(isFormGroup, key) {
return `Cannot find form control ${describeKey(isFormGroup, key)}`;
}
function missingControlValueError(isFormGroup, key) {
return `Must supply a value for form control ${describeKey(isFormGroup, key)}`;
}
var VALID = "VALID";
var INVALID = "INVALID";
var PENDING = "PENDING";
var DISABLED = "DISABLED";
var ControlEvent = class {
};
var ValueChangeEvent = class extends ControlEvent {
value;
source;
constructor(value, source) {
super();
this.value = value;
this.source = source;
}
};
var PristineChangeEvent = class extends ControlEvent {
pristine;
source;
constructor(pristine, source) {
super();
this.pristine = pristine;
this.source = source;
}
};
var TouchedChangeEvent = class extends ControlEvent {
touched;
source;
constructor(touched, source) {
super();
this.touched = touched;
this.source = source;
}
};
var StatusChangeEvent = class extends ControlEvent {
status;
source;
constructor(status, source) {
super();
this.status = status;
this.source = source;
}
};
var FormSubmittedEvent = class extends ControlEvent {
source;
constructor(source) {
super();
this.source = source;
}
};
var FormResetEvent = class extends ControlEvent {
source;
constructor(source) {
super();
this.source = source;
}
};
function pickValidators(validatorOrOpts) {
return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.validators : validatorOrOpts) || null;
}
function coerceToValidator(validator) {
return Array.isArray(validator) ? composeValidators(validator) : validator || null;
}
function pickAsyncValidators(asyncValidator, validatorOrOpts) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (isOptionsObj(validatorOrOpts) && asyncValidator) {
console.warn(asyncValidatorsDroppedWithOptsWarning);
}
}
return (isOptionsObj(validatorOrOpts) ? validatorOrOpts.asyncValidators : asyncValidator) || null;
}
function coerceToAsyncValidator(asyncValidator) {
return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) : asyncValidator || null;
}
function isOptionsObj(validatorOrOpts) {
return validatorOrOpts != null && !Array.isArray(validatorOrOpts) && typeof validatorOrOpts === "object";
}
function assertControlPresent(parent, isGroup, key) {
const controls = parent.controls;
const collection = isGroup ? Object.keys(controls) : controls;
if (!collection.length) {
throw new RuntimeError(1e3, typeof ngDevMode === "undefined" || ngDevMode ? noControlsError(isGroup) : "");
}
if (!controls[key]) {
throw new RuntimeError(1001, typeof ngDevMode === "undefined" || ngDevMode ? missingControlError(isGroup, key) : "");
}
}
function assertAllValuesPresent(control, isGroup, value) {
control._forEachChild((_, key) => {
if (value[key] === void 0) {
throw new RuntimeError(1002, typeof ngDevMode === "undefined" || ngDevMode ? missingControlValueError(isGroup, key) : "");
}
});
}
var AbstractControl = class {
/** @internal */
_pendingDirty = false;
/**
* Indicates that a control has its own pending asynchronous validation in progress.
* It also stores if the control should emit events when the validation status changes.
*
* @internal
*/
_hasOwnPendingAsyncValidator = null;
/** @internal */
_pendingTouched = false;
/** @internal */
_onCollectionChange = () => {
};
/** @internal */
_updateOn;
_parent = null;
_asyncValidationSubscription;
/**
* Contains the result of merging synchronous validators into a single validator function
* (combined using `Validators.compose`).
*
* @internal
*/
_composedValidatorFn;
/**
* Contains the result of merging asynchronous validators into a single validator function
* (combined using `Validators.composeAsync`).
*
* @internal
*/
_composedAsyncValidatorFn;
/**
* Synchronous validators as they were provided:
* - in `AbstractControl` constructor
* - as an argument while calling `setValidators` function
* - while calling the setter on the `validator` field (e.g. `control.validator = validatorFn`)
*
* @internal
*/
_rawValidators;
/**
* Asynchronous validators as they were provided:
* - in `AbstractControl` constructor
* - as an argument while calling `setAsyncValidators` function
* - while calling the setter on the `asyncValidator` field (e.g. `control.asyncValidator =
* asyncValidatorFn`)
*
* @internal
*/
_rawAsyncValidators;
/**
* The current value of the control.
*
* * For a `FormControl`, the current value.
* * For an enabled `FormGroup`, the values of enabled controls as an object
* with a key-value pair for each member of the group.
* * For a disabled `FormGroup`, the values of all controls as an object
* with a key-value pair for each member of the group.
* * For a `FormArray`, the values of enabled controls as an array.
*
*/
value;
/**
* Initialize the AbstractControl instance.
*
* @param validators The function or array of functions that is used to determine the validity of
* this control synchronously.
* @param asyncValidators The function or array of functions that is used to determine validity of
* this control asynchronously.
*/
constructor(validators, asyncValidators) {
this._assignValidators(validators);
this._assignAsyncValidators(asyncValidators);
}
/**
* Returns the function that is used to determine the validity of this control synchronously.
* If multiple validators have been added, this will be a single composed function.
* See `Validators.compose()` for additional information.
*/
get validator() {
return this._composedValidatorFn;
}
set validator(validatorFn) {
this._rawValidators = this._composedValidatorFn = validatorFn;
}
/**
* Returns the function that is used to determine the validity of this control asynchronously.
* If multiple validators have been added, this will be a single composed function.
* See `Validators.compose()` for additional information.
*/
get asyncValidator() {
return this._composedAsyncValidatorFn;
}
set asyncValidator(asyncValidatorFn) {
this._rawAsyncValidators = this._composedAsyncValidatorFn = asyncValidatorFn;
}
/**
* The parent control.
*/
get parent() {
return this._parent;
}
/**
* The validation status of the control.
*
* @see {@link FormControlStatus}
*
* These status values are mutually exclusive, so a control cannot be
* both valid AND invalid or invalid AND disabled.
*/
get status() {
return untracked(this.statusReactive);
}
set status(v) {
untracked(() => this.statusReactive.set(v));
}
/** @internal */
_status = computed(() => this.statusReactive());
statusReactive = signal(void 0);
/**
* A control is `valid` when its `status` is `VALID`.
*
* @see {@link AbstractControl.status}
*
* @returns True if the control has passed all of its validation tests,
* false otherwise.
*/
get valid() {
return this.status === VALID;
}
/**
* A control is `invalid` when its `status` is `INVALID`.
*
* @see {@link AbstractControl.status}
*
* @returns True if this control has failed one or more of its validation checks,
* false otherwise.
*/
get invalid() {
return this.status === INVALID;
}
/**
* A control is `pending` when its `status` is `PENDING`.
*
* @see {@link AbstractControl.status}
*
* @returns True if this control is in the process of conducting a validation check,
* false otherwise.
*/
get pending() {
return this.status == PENDING;
}
/**
* A control is `disabled` when its `status` is `DISABLED`.
*
* Disabled controls are exempt from validation checks and
* are not included in the aggregate value of their ancestor
* controls.
*
* @see {@link AbstractControl.status}
*
* @returns True if the control is disabled, false otherwise.
*/
get disabled() {
return this.status === DISABLED;
}
/**
* A control is `enabled` as long as its `status` is not `DISABLED`.
*
* @returns True if the control has any status other than 'DISABLED',
* false if the status is 'DISABLED'.
*
* @see {@link AbstractControl.status}
*
*/
get enabled() {
return this.status !== DISABLED;
}
/**
* An object containing any errors generated by failing validation,
* or null if there are no errors.
*/
errors;
/**
* A control is `pristine` if the user has not yet changed
* the value in the UI.
*
* @returns True if the user has not yet changed the value in the UI; compare `dirty`.
* Programmatic changes to a control's value do not mark it dirty.
*/
get pristine() {
return untracked(this.pristineReactive);
}
set pristine(v) {
untracked(() => this.pristineReactive.set(v));
}
/** @internal */
_pristine = computed(() => this.pristineReactive());
pristineReactive = signal(true);
/**
* A control is `dirty` if the user has changed the value
* in the UI.
*
* @returns True if the user has changed the value of this control in the UI; compare `pristine`.
* Programmatic changes to a control's value do not mark it dirty.
*/
get dirty() {
return !this.pristine;
}
/**
* True if the control is marked as `touched`.
*
* A control is marked `touched` once the user has triggered
* a `blur` event on it.
*/
get touched() {
return untracked(this.touchedReactive);
}
set touched(v) {
untracked(() => this.touchedReactive.set(v));
}
/** @internal */
_touched = computed(() => this.touchedReactive());
touchedReactive = signal(false);
/**
* True if the control has not been marked as touched
*
* A control is `untouched` if the user has not yet triggered
* a `blur` event on it.
*/
get untouched() {
return !this.touched;
}
/**
* Exposed as observable, see below.
*
* @internal
*/
_events = new Subject();
/**
* A multicasting observable that emits an event every time the state of the control changes.
* It emits for value, status, pristine or touched changes.
*
* **Note**: On value change, the emit happens right after a value of this control is updated. The
* value of a parent control (for example if this FormControl is a part of a FormGroup) is updated
* later, so accessing a value of a parent control (using the `value` property) from the callback
* of this event might result in getting a value that has not been updated yet. Subscribe to the
* `events` of the parent control instead.
* For other event types, the events are emitted after the parent control has been updated.
*
*/
events = this._events.asObservable();
/**
* A multicasting observable that emits an event every time the value of the control changes, in
* the UI or programmatically. It also emits an event each time you call enable() or disable()
* without passing along {emitEvent: false} as a function argument.
*
* **Note**: the emit happens right after a value of this control is updated. The value of a
* parent control (for example if this FormControl is a part of a FormGroup) is updated later, so
* accessing a value of a parent control (using the `value` property) from the callback of this
* event might result in getting a value that has not been updated yet. Subscribe to the
* `valueChanges` event of the parent control instead.
*/
valueChanges;
/**
* A multicasting observable that emits an event every time the validation `status` of the control
* recalculates.
*
* @see {@link FormControlStatus}
* @see {@link AbstractControl.status}
*/
statusChanges;
/**
* Reports the update strategy of the `AbstractControl` (meaning
* the event on which the control updates itself).
* Possible values: `'change'` | `'blur'` | `'submit'`
* Default value: `'change'`
*/
get updateOn() {
return this._updateOn ? this._updateOn : this.parent ? this.parent.updateOn : "change";
}
/**
* Sets the synchronous validators that are active on this control. Calling
* this overwrites any existing synchronous validators.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* If you want to add a new validator without affecting existing ones, consider
* using `addValidators()` method instead.
*/
setValidators(validators) {
this._assignValidators(validators);
}
/**
* Sets the asynchronous validators that are active on this control. Calling this
* overwrites any existing asynchronous validators.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* If you want to add a new validator without affecting existing ones, consider
* using `addAsyncValidators()` method instead.
*/
setAsyncValidators(validators) {
this._assignAsyncValidators(validators);
}
/**
* Add a synchronous validator or validators to this control, without affecting other validators.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* Adding a validator that already exists will have no effect. If duplicate validator functions
* are present in the `validators` array, only the first instance would be added to a form
* control.
*
* @param validators The new validator function or functions to add to this control.
*/
addValidators(validators) {
this.setValidators(addValidators(validators, this._rawValidators));
}
/**
* Add an asynchronous validator or validators to this control, without affecting other
* validators.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* Adding a validator that already exists will have no effect.
*
* @param validators The new asynchronous validator function or functions to add to this control.
*/
addAsyncValidators(validators) {
this.setAsyncValidators(addValidators(validators, this._rawAsyncValidators));
}
/**
* Remove a synchronous validator from this control, without affecting other validators.
* Validators are compared by function reference; you must pass a reference to the exact same
* validator function as the one that was originally set. If a provided validator is not found,
* it is ignored.
*
* @usageNotes
*
* ### Reference to a ValidatorFn
*
* ```
* // Reference to the RequiredValidator
* const ctrl = new FormControl<string | null>('', Validators.required);
* ctrl.removeValidators(Validators.required);
*
* // Reference to anonymous function inside MinValidator
* const minValidator = Validators.min(3);
* const ctrl = new FormControl<string | null>('', minValidator);
* expect(ctrl.hasValidator(minValidator)).toEqual(true)
* expect(ctrl.hasValidator(Validators.min(3))).toEqual(false)
*
* ctrl.removeValidators(minValidator);
* ```
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* @param validators The validator or validators to remove.
*/
removeValidators(validators) {
this.setValidators(removeValidators(validators, this._rawValidators));
}
/**
* Remove an asynchronous validator from this control, without affecting other validators.
* Validators are compared by function reference; you must pass a reference to the exact same
* validator function as the one that was originally set. If a provided validator is not found, it
* is ignored.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
* @param validators The asynchronous validator or validators to remove.
*/
removeAsyncValidators(validators) {
this.setAsyncValidators(removeValidators(validators, this._rawAsyncValidators));
}
/**
* Check whether a synchronous validator function is present on this control. The provided
* validator must be a reference to the exact same function that was provided.
*
* @usageNotes
*
* ### Reference to a ValidatorFn
*
* ```
* // Reference to the RequiredValidator
* const ctrl = new FormControl<number | null>(0, Validators.required);
* expect(ctrl.hasValidator(Validators.required)).toEqual(true)
*
* // Reference to anonymous function inside MinValidator
* const minValidator = Validators.min(3);
* const ctrl = new FormControl<number | null>(0, minValidator);
* expect(ctrl.hasValidator(minValidator)).toEqual(true)
* expect(ctrl.hasValidator(Validators.min(3))).toEqual(false)
* ```
*
* @param validator The validator to check for presence. Compared by function reference.
* @returns Whether the provided validator was found on this control.
*/
hasValidator(validator) {
return hasValidator(this._rawValidators, validator);
}
/**
* Check whether an asynchronous validator function is present on this control. The provided
* validator must be a reference to the exact same function that was provided.
*
* @param validator The asynchronous validator to check for presence. Compared by function
* reference.
* @returns Whether the provided asynchronous validator was found on this control.
*/
hasAsyncValidator(validator) {
return hasValidator(this._rawAsyncValidators, validator);
}
/**
* Empties out the synchronous validator list.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
*/
clearValidators() {
this.validator = null;
}
/**
* Empties out the async validator list.
*
* When you add or remove a validator at run time, you must call
* `updateValueAndValidity()` for the new validation to take effect.
*
*/
clearAsyncValidators() {
this.asyncValidator = null;
}
markAsTouched(opts = {}) {
const changed = this.touched === false;
this.touched = true;
const sourceControl = opts.sourceControl ?? this;
if (this._parent && !opts.onlySelf) {
this._parent.markAsTouched(__spreadProps(__spreadValues({}, opts), {
sourceControl
}));
}
if (changed && opts.emitEvent !== false) {
this._events.next(new TouchedChangeEvent(true, sourceControl));
}
}
/**
* Marks the control and all its descendant controls as `touched`.
* @see {@link markAsTouched()}
*
* @param opts Configuration options that determine how the control propagates changes
* and emits events after marking is applied.
* * `emitEvent`: When true or not supplied (the default), the `events`
* observable emits a `TouchedChangeEvent` with the `touched` property being `true`.
* When false, no events are emitted.
*/
markAllAsTouched(opts = {}) {
this.markAsTouched({
onlySelf: true,
emitEvent: opts.emitEvent,
sourceControl: this
});
this._forEachChild((control) => control.markAllAsTouched(opts));
}
markAsUntouched(opts = {}) {
const changed = this.touched === true;
this.touched = false;
this._pendingTouched = false;
const sourceControl = opts.sourceControl ?? this;
this._forEachChild((control) => {
control.markAsUntouched({
onlySelf: true,
emitEvent: opts.emitEvent,
sourceControl
});
});
if (this._parent && !opts.onlySelf) {
this._parent._updateTouched(opts, sourceControl);
}
if (changed && opts.emitEvent !== false) {
this._events.next(new TouchedChangeEvent(false, sourceControl));
}
}
markAsDirty(opts = {}) {
const changed = this.pristine === true;
this.pristine = false;
const sourceControl = opts.sourceControl ?? this;
if (this._parent && !opts.onlySelf) {
this._parent.markAsDirty(__spreadProps(__spreadValues({}, opts), {
sourceControl
}));
}
if (changed && opts.emitEvent !== false) {
this._events.next(new PristineChangeEvent(false, sourceControl));
}
}
markAsPristine(opts = {}) {
const changed = this.pristine === false;
this.pristine = true;
this._pendingDirty = false;
const sourceControl = opts.sourceControl ?? this;
this._forEachChild((control) => {
control.markAsPristine({
onlySelf: true,
emitEvent: opts.emitEvent
});
});
if (this._parent && !opts.onlySelf) {
this._parent._updatePristine(opts, sourceControl);
}
if (changed && opts.emitEvent !== false) {
this._events.next(new PristineChangeEvent(true, sourceControl));
}
}
markAsPending(opts = {}) {
this.status = PENDING;
const sourceControl = opts.sourceControl ?? this;
if (opts.emitEvent !== false) {
this._events.next(new StatusChangeEvent(this.status, sourceControl));
this.statusChanges.emit(this.status);
}
if (this._parent && !opts.onlySelf) {
this._parent.markAsPending(__spreadProps(__spreadValues({}, opts), {
sourceControl
}));
}
}
disable(opts = {}) {
const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);
this.status = DISABLED;
this.errors = null;
this._forEachChild((control) => {
control.disable(__spreadProps(__spreadValues({}, opts), {
onlySelf: true
}));
});
this._updateValue();
const sourceControl = opts.sourceControl ?? this;
if (opts.emitEvent !== false) {
this._events.next(new ValueChangeEvent(this.value, sourceControl));
this._events.next(new StatusChangeEvent(this.status, sourceControl));
this.valueChanges.emit(this.value);
this.statusChanges.emit(this.status);
}
this._updateAncestors(__spreadProps(__spreadValues({}, opts), {
skipPristineCheck
}), this);
this._onDisabledChange.forEach((changeFn) => changeFn(true));
}
/**
* Enables the control. This means the control is included in validation checks and
* the aggregate value of its parent. Its status recalculates based on its value and
* its validators.
*
* By default, if the control has children, all children are enabled.
*
* @see {@link AbstractControl.status}
*
* @param opts Configure options that control how the control propagates changes and
* emits events when marked as untouched
* * `onlySelf`: When true, mark only this control. When false or not supplied,
* marks all direct ancestors. Default is false.
* * `emitEvent`: When true or not supplied (the default), the `statusChanges`,
* `valueChanges` and `events`
* observables emit events with the latest status and value when the control is enabled.
* When false, no events are emitted.
*/
enable(opts = {}) {
const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);
this.status = VALID;
this._forEachChild((control) => {
control.enable(__spreadProps(__spreadValues({}, opts), {
onlySelf: true
}));
});
this.updateValueAndValidity({
onlySelf: true,
emitEvent: opts.emitEvent
});
this._updateAncestors(__spreadProps(__spreadValues({}, opts), {
skipPristineCheck
}), this);
this._onDisabledChange.forEach((changeFn) => changeFn(false));
}
_updateAncestors(opts, sourceControl) {
if (this._parent && !opts.onlySelf) {
this._parent.updateValueAndValidity(opts);
if (!opts.skipPristineCheck) {
this._parent._updatePristine({}, sourceControl);
}
this._parent._updateTouched({}, sourceControl);
}
}
/**
* Sets the parent of the control
*
* @param parent The new parent.
*/
setParent(parent) {
this._parent = parent;
}
/**
* The raw value of this control. For most control implementations, the raw value will include
* disabled children.
*/
getRawValue() {
return this.value;
}
updateValueAndValidity(opts = {}) {
this._setInitialStatus();
this._updateValue();
if (this.enabled) {
const shouldHaveEmitted = this._cancelExistingSubscription();
this.errors = this._runValidator();
this.status = this._calculateStatus();
if (this.status === VALID || this.status === PENDING) {
this._runAsyncValidator(shouldHaveEmitted, opts.emitEvent);
}
}
const sourceControl = opts.sourceControl ?? this;
if (opts.emitEvent !== false) {
this._events.next(new ValueChangeEvent(this.value, sourceControl));
this._events.next(new StatusChangeEvent(this.status, sourceControl));
this.valueChanges.emit(this.value);
this.statusChanges.emit(this.status);
}
if (this._parent && !opts.onlySelf) {
this._parent.updateValueAndValidity(__spreadProps(__spreadValues({}, opts), {
sourceControl
}));
}
}
/** @internal */
_updateTreeValidity(opts = {
emitEvent: true
}) {
this._forEachChild((ctrl) => ctrl._updateTreeValidity(opts));
this.updateValueAndValidity({
onlySelf: true,
emitEvent: opts.emitEvent
});
}
_setInitialStatus() {
this.status = this._allControlsDisabled() ? DISABLED : VALID;
}
_runValidator() {
return this.validator ? this.validator(this) : null;
}
_runAsyncValidator(shouldHaveEmitted, emitEvent) {
if (this.asyncValidator) {
this.status = PENDING;
this._hasOwnPendingAsyncValidator = {
emitEvent: emitEvent !== false
};
const obs = toObservable(this.asyncValidator(this));
this._asyncValidationSubscription = obs.subscribe((errors) => {
this._hasOwnPendingAsyncValidator = null;
this.setErrors(errors, {
emitEvent,
shouldHaveEmitted
});
});
}
}
_cancelExistingSubscription() {
if (this._asyncValidationSubscription) {
this._asyncValidationSubscription.unsubscribe();
const shouldHaveEmitted = this._hasOwnPendingAsyncValidator?.emitEvent ?? false;
this._hasOwnPendingAsyncValidator = null;
return shouldHaveEmitted;
}
return false;
}
setErrors(errors, opts = {}) {
this.errors = errors;
this._updateControlsErrors(opts.emitEvent !== false, this, opts.shouldHaveEmitted);
}
/**
* Retrieves a child control given the control's name or path.
*
* @param path A dot-delimited string or array of string/number values that define the path to the
* control. If a string is provided, passing it as a string literal will result in improved type
* information. Likewise, if an array is provided, passing it `as const` will cause improved type
* information to be available.
*
* @usageNotes
* ### Retrieve a nested control
*
* For example, to get a `name` control nested within a `person` sub-group:
*
* * `this.form.get('person.name');`
*
* -OR-
*
* * `this.form.get(['person', 'name'] as const);` // `as const` gives improved typings
*
* ### Retrieve a control in a FormArray
*
* When accessing an element inside a FormArray, you can use an element index.
* For example, to get a `price` control from the first element in an `items` array you can use:
*
* * `this.form.get('items.0.price');`
*
* -OR-
*
* * `this.form.get(['items', 0, 'price']);`
*/
get(path) {
let currPath = path;
if (currPath == null) return null;
if (!Array.isArray(currPath)) currPath = currPath.split(".");
if (currPath.length === 0) return null;
return currPath.reduce((control, name) => control && control._find(name), this);
}
/**
* @description
* Reports error data for the control with the given path.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```ts
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* @returns error data for that particular error. If the control or error is not present,
* null is returned.
*/
getError(errorCode, path) {
const control = path ? this.get(path) : this;
return control && control.errors ? control.errors[errorCode] : null;
}
/**
* @description
* Reports whether the control with the given path has the error specified.
*
* @param errorCode The code of the error to check
* @param path A list of control names that designates how to move from the current control
* to the control that should be queried for errors.
*
* @usageNotes
* For example, for the following `FormGroup`:
*
* ```ts
* form = new FormGroup({
* address: new FormGroup({ street: new FormControl() })
* });
* ```
*
* The path to the 'street' control from the root form would be 'address' -> 'street'.
*
* It can be provided to this method in one of two formats:
*
* 1. An array of string control names, e.g. `['address', 'street']`
* 1. A period-delimited list of control names in one string, e.g. `'address.street'`
*
* If no path is given, this method checks for the error on the current control.
*
* @returns whether the given error is present in the control at the given path.
*
* If the control is not present, false is returned.
*/
hasError(errorCode, path) {
return !!this.getError(errorCode, path);
}
/**
* Retrieves the top-level ancestor of this control.
*/
get root() {
let x = this;
while (x._parent) {
x = x._parent;
}
return x;
}
/** @internal */
_updateControlsErrors(emitEvent, changedControl, shouldHaveEmitted) {
this.status = this._calculateStatus();
if (emitEvent) {
this.statusChanges.emit(this.status);
}
if (emitEvent || shouldHaveEmitted) {
this._events.next(new StatusChangeEvent(this.status, changedControl));
}
if (this._parent) {
this._parent._updateControlsErrors(emitEvent, changedControl, shouldHaveEmitted);
}
}
/** @internal */
_initObservables() {
this.valueChanges = new EventEmitter();
this.statusChanges = new EventEmitter();
}
_calculateStatus() {
if (this._allControlsDisabled()) return DISABLED;
if (this.errors) return INVALID;
if (this._hasOwnPendingAsyncValidator || this._anyControlsHaveStatus(PENDING)) return PENDING;
if (this._anyControlsHaveStatus(INVALID)) return INVALID;
return VALID;
}
/** @internal */
_anyControlsHaveStatus(status) {
return this._anyControls((control) => control.status === status);
}
/** @internal */
_anyControlsDirty() {
return this._anyControls((control) => control.dirty);
}
/** @internal */
_anyControlsTouched() {
return this._anyControls((control) => control.touched);
}
/** @internal */
_updatePristine(opts, changedControl) {
const newPristine = !this._anyControlsDirty();
const changed = this.pristine !== newPristine;
this.pristine = newPristine;
if (this._parent && !opts.onlySelf) {
this._parent._updatePristine(opts, changedControl);
}
if (changed) {
this._events.next(new PristineChangeEvent(this.pristine, changedControl));
}
}
/** @internal */
_updateTouched(opts = {}, changedControl) {
this.touched = this._anyControlsTouched();
this._events.next(new TouchedChangeEvent(this.touched, changedControl));
if (this._parent && !opts.onlySelf) {
this._parent._updateTouched(opts, changedControl);
}
}
/** @internal */
_onDisabledChange = [];
/** @internal */
_registerOnCollectionChange(fn) {
this._onCollectionChange = fn;
}
/** @internal */
_setUpdateStrategy(opts) {
if (isOptionsObj(opts) && opts.updateOn != null) {
this._updateOn = opts.updateOn;
}
}
/**
* Check to see if parent has been marked artificially dirty.
*
* @internal
*/
_parentMarkedDirty(onlySelf) {
const parentDirty = this._parent && this._parent.dirty;
return !onlySelf && !!parentDirty && !this._parent._anyControlsDirty();
}
/** @internal */
_find(name) {
return null;
}
/**
* Internal implementation of the `setValidators` method. Needs to be separated out into a
* different method, because it is called in the constructor and it can break cases where
* a control is extended.
*/
_assignValidators(validators) {
this._rawValidators = Array.isArray(validators) ? validators.slice() : validators;
this._composedValidatorFn = coerceToValidator(this._rawValidators);
}
/**
* Internal implementation of the `setAsyncValidators` method. Needs to be separated out into a
* different method, because it is called in the constructor and it can break cases where
* a control is extended.
*/
_assignAsyncValidators(validators) {
this._rawAsyncValidators = Array.isArray(validators) ? validators.slice() : validators;
this._composedAsyncValidatorFn = coerceToAsyncValidator(this._rawAsyncValidators);
}
};
var FormGroup = class extends AbstractControl {
/**
* Creates a new `FormGroup` instance.
*
* @param controls A collection of child controls. The key for each child is the name
* under which it is registered.
*
* @param validatorOrOpts A synchronous validator function, or an array of
* such functions, or an `AbstractControlOptions` object that contains validation functions
* and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator functions
*
*/
constructor(controls, validatorOrOpts, asyncValidator) {
super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
(typeof ngDevMode === "undefined" || ngDevMode) && validateFormGroupControls(controls);
this.controls = controls;
this._initObservables();
this._setUpdateStrategy(validatorOrOpts);
this._setUpControls();
this.updateValueAndValidity({
onlySelf: true,
// If `asyncValidator` is present, it will trigger control status change from `PENDING` to
// `VALID` or `INVALID`. The status should be broadcasted via the `statusChanges` observable,
// so we set `emitEvent` to `true` to allow that during the control creation process.
emitEvent: !!this.asyncValidator
});
}
controls;
registerControl(name, control) {
if (this.controls[name]) return this.controls[name];
this.controls[name] = control;
control.setParent(this);
control._registerOnCollectionChange(this._onCollectionChange);
return control;
}
addControl(name, control, options = {}) {
this.registerControl(name, control);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
this._onCollectionChange();
}
/**
* Remove a control from this group. In a strongly-typed group, required controls cannot be
* removed.
*
* This method also updates the value and validity of the control.
*
* @param name The control name to remove from the collection
* @param options Specifies whether this FormGroup instance should emit events after a
* control is removed.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control is
* removed. When false, no events are emitted.
*/
removeControl(name, options = {}) {
if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {
});
delete this.controls[name];
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
this._onCollectionChange();
}
setControl(name, control, options = {}) {
if (this.controls[name]) this.controls[name]._registerOnCollectionChange(() => {
});
delete this.controls[name];
if (control) this.registerControl(name, control);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
this._onCollectionChange();
}
contains(controlName) {
return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled;
}
/**
* Sets the value of the `FormGroup`. It accepts an object that matches
* the structure of the group, with control names as keys.
*
* @usageNotes
* ### Set the complete value for the form group
*
* ```ts
* const form = new FormGroup({
* first: new FormControl(),
* last: new FormControl()
* });
*
* console.log(form.value); // {first: null, last: null}
*
* form.setValue({first: 'Nancy', last: 'Drew'});
* console.log(form.value); // {first: 'Nancy', last: 'Drew'}
* ```
*
* @throws When strict checks fail, such as setting the value of a control
* that doesn't exist or if you exclude a value of a control that does exist.
*
* @param value The new value for the control that matches the structure of the group.
* @param options Configuration options that determine how the control propagates changes
* and emits events after the value changes.
* The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
* updateValueAndValidity} method.
*
* * `onlySelf`: When true, each change only affects this control, and not its parent. Default is
* false.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges`
* observables emit events with the latest status and value when the control value is updated.
* When false, no events are emitted.
*/
setValue(value, options = {}) {
assertAllValuesPresent(this, true, value);
Object.keys(value).forEach((name) => {
assertControlPresent(this, true, name);
this.controls[name].setValue(value[name], {
onlySelf: true,
emitEvent: options.emitEvent
});
});
this.updateValueAndValidity(options);
}
/**
* Patches the value of the `FormGroup`. It accepts an object with control
* names as keys, and does its best to match the values to the correct controls
* in the group.
*
* It accepts both super-sets and sub-sets of the group without throwing an error.
*
* @usageNotes
* ### Patch the value for a form group
*
* ```ts
* const form = new FormGroup({
* first: new FormControl(),
* last: new FormControl()
* });
* console.log(form.value); // {first: null, last: null}
*
* form.patchValue({first: 'Nancy'});
* console.log(form.value); // {first: 'Nancy', last: null}
* ```
*
* @param value The object that matches the structure of the group.
* @param options Configuration options that determine how the control propagates changes and
* emits events after the value is patched.
* * `onlySelf`: When true, each change only affects this control and not its parent. Default is
* true.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control value
* is updated. When false, no events are emitted. The configuration options are passed to
* the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method.
*/
patchValue(value, options = {}) {
if (value == null) return;
Object.keys(value).forEach((name) => {
const control = this.controls[name];
if (control) {
control.patchValue(
/* Guaranteed to be present, due to the outer forEach. */
value[name],
{
onlySelf: true,
emitEvent: options.emitEvent
}
);
}
});
this.updateValueAndValidity(options);
}
/**
* Resets the `FormGroup`, marks all descendants `pristine` and `untouched` and sets
* the value of all descendants to their default values, or null if no defaults were provided.
*
* You reset to a specific form state by passing in a map of states
* that matches the structure of your form, with control names as keys. The state
* is a standalone value or a form state object with both a value and a disabled
* status.
*
* @param value Resets the control with an initial value,
* or an object that defines the initial value and disabled state.
*
* @param options Configuration options that determine how the control propagates changes
* and emits events when the group is reset.
* * `onlySelf`: When true, each change only affects this control, and not its parent. Default is
* false.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges`
* observables emit events with the latest status and value when the control is reset.
* When false, no events are emitted.
* The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
* updateValueAndValidity} method.
*
* @usageNotes
*
* ### Reset the form group values
*
* ```ts
* const form = new FormGroup({
* first: new FormControl('first name'),
* last: new FormControl('last name')
* });
*
* console.log(form.value); // {first: 'first name', last: 'last name'}
*
* form.reset({ first: 'name', last: 'last name' });
*
* console.log(form.value); // {first: 'name', last: 'last name'}
* ```
*
* ### Reset the form group values and disabled status
*
* ```ts
* const form = new FormGroup({
* first: new FormControl('first name'),
* last: new FormControl('last name')
* });
*
* form.reset({
* first: {value: 'name', disabled: true},
* last: 'last'
* });
*
* console.log(form.value); // {last: 'last'}
* console.log(form.get('first').status); // 'DISABLED'
* ```
*/
reset(value = {}, options = {}) {
this._forEachChild((control, name) => {
control.reset(value ? value[name] : null, {
onlySelf: true,
emitEvent: options.emitEvent
});
});
this._updatePristine(options, this);
this._updateTouched(options, this);
this.updateValueAndValidity(options);
}
/**
* The aggregate value of the `FormGroup`, including any disabled controls.
*
* Retrieves all values regardless of disabled status.
*/
getRawValue() {
return this._reduceChildren({}, (acc, control, name) => {
acc[name] = control.getRawValue();
return acc;
});
}
/** @internal */
_syncPendingControls() {
let subtreeUpdated = this._reduceChildren(false, (updated, child) => {
return child._syncPendingControls() ? true : updated;
});
if (subtreeUpdated) this.updateValueAndValidity({
onlySelf: true
});
return subtreeUpdated;
}
/** @internal */
_forEachChild(cb) {
Object.keys(this.controls).forEach((key) => {
const control = this.controls[key];
control && cb(control, key);
});
}
/** @internal */
_setUpControls() {
this._forEachChild((control) => {
control.setParent(this);
control._registerOnCollectionChange(this._onCollectionChange);
});
}
/** @internal */
_updateValue() {
this.value = this._reduceValue();
}
/** @internal */
_anyControls(condition) {
for (const [controlName, control] of Object.entries(this.controls)) {
if (this.contains(controlName) && condition(control)) {
return true;
}
}
return false;
}
/** @internal */
_reduceValue() {
let acc = {};
return this._reduceChildren(acc, (acc2, control, name) => {
if (control.enabled || this.disabled) {
acc2[name] = control.value;
}
return acc2;
});
}
/** @internal */
_reduceChildren(initValue, fn) {
let res = initValue;
this._forEachChild((control, name) => {
res = fn(res, control, name);
});
return res;
}
/** @internal */
_allControlsDisabled() {
for (const controlName of Object.keys(this.controls)) {
if (this.controls[controlName].enabled) {
return false;
}
}
return Object.keys(this.controls).length > 0 || this.disabled;
}
/** @internal */
_find(name) {
return this.controls.hasOwnProperty(name) ? this.controls[name] : null;
}
};
function validateFormGroupControls(controls) {
const invalidKeys = Object.keys(controls).filter((key) => key.includes("."));
if (invalidKeys.length > 0) {
console.warn(`FormGroup keys cannot include \`.\`, please replace the keys for: ${invalidKeys.join(",")}.`);
}
}
var FormRecord = class extends FormGroup {
};
var CALL_SET_DISABLED_STATE = new InjectionToken(typeof ngDevMode === "undefined" || ngDevMode ? "CallSetDisabledState" : "", {
providedIn: "root",
factory: () => setDisabledStateDefault
});
var setDisabledStateDefault = "always";
function controlPath(name, parent) {
return [...parent.path, name];
}
function setUpControl(control, dir, callSetDisabledState = setDisabledStateDefault) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (!control) _throwError(dir, "Cannot find control with");
if (!dir.valueAccessor) _throwMissingValueAccessorError(dir);
}
setUpValidators(control, dir);
dir.valueAccessor.writeValue(control.value);
if (control.disabled || callSetDisabledState === "always") {
dir.valueAccessor.setDisabledState?.(control.disabled);
}
setUpViewChangePipeline(control, dir);
setUpModelChangePipeline(control, dir);
setUpBlurPipeline(control, dir);
setUpDisabledChangeHandler(control, dir);
}
function cleanUpControl(control, dir, validateControlPresenceOnChange = true) {
const noop2 = () => {
if (validateControlPresenceOnChange && (typeof ngDevMode === "undefined" || ngDevMode)) {
_noControlError(dir);
}
};
if (dir.valueAccessor) {
dir.valueAccessor.registerOnChange(noop2);
dir.valueAccessor.registerOnTouched(noop2);
}
cleanUpValidators(control, dir);
if (control) {
dir._invokeOnDestroyCallbacks();
control._registerOnCollectionChange(() => {
});
}
}
function registerOnValidatorChange(validators, onChange) {
validators.forEach((validator) => {
if (validator.registerOnValidatorChange) validator.registerOnValidatorChange(onChange);
});
}
function setUpDisabledChangeHandler(control, dir) {
if (dir.valueAccessor.setDisabledState) {
const onDisabledChange = (isDisabled) => {
dir.valueAccessor.setDisabledState(isDisabled);
};
control.registerOnDisabledChange(onDisabledChange);
dir._registerOnDestroy(() => {
control._unregisterOnDisabledChange(onDisabledChange);
});
}
}
function setUpValidators(control, dir) {
const validators = getControlValidators(control);
if (dir.validator !== null) {
control.setValidators(mergeValidators(validators, dir.validator));
} else if (typeof validators === "function") {
control.setValidators([validators]);
}
const asyncValidators = getControlAsyncValidators(control);
if (dir.asyncValidator !== null) {
control.setAsyncValidators(mergeValidators(asyncValidators, dir.asyncValidator));
} else if (typeof asyncValidators === "function") {
control.setAsyncValidators([asyncValidators]);
}
const onValidatorChange = () => control.updateValueAndValidity();
registerOnValidatorChange(dir._rawValidators, onValidatorChange);
registerOnValidatorChange(dir._rawAsyncValidators, onValidatorChange);
}
function cleanUpValidators(control, dir) {
let isControlUpdated = false;
if (control !== null) {
if (dir.validator !== null) {
const validators = getControlValidators(control);
if (Array.isArray(validators) && validators.length > 0) {
const updatedValidators = validators.filter((validator) => validator !== dir.validator);
if (updatedValidators.length !== validators.length) {
isControlUpdated = true;
control.setValidators(updatedValidators);
}
}
}
if (dir.asyncValidator !== null) {
const asyncValidators = getControlAsyncValidators(control);
if (Array.isArray(asyncValidators) && asyncValidators.length > 0) {
const updatedAsyncValidators = asyncValidators.filter((asyncValidator) => asyncValidator !== dir.asyncValidator);
if (updatedAsyncValidators.length !== asyncValidators.length) {
isControlUpdated = true;
control.setAsyncValidators(updatedAsyncValidators);
}
}
}
}
const noop2 = () => {
};
registerOnValidatorChange(dir._rawValidators, noop2);
registerOnValidatorChange(dir._rawAsyncValidators, noop2);
return isControlUpdated;
}
function setUpViewChangePipeline(control, dir) {
dir.valueAccessor.registerOnChange((newValue) => {
control._pendingValue = newValue;
control._pendingChange = true;
control._pendingDirty = true;
if (control.updateOn === "change") updateControl(control, dir);
});
}
function setUpBlurPipeline(control, dir) {
dir.valueAccessor.registerOnTouched(() => {
control._pendingTouched = true;
if (control.updateOn === "blur" && control._pendingChange) updateControl(control, dir);
if (control.updateOn !== "submit") control.markAsTouched();
});
}
function updateControl(control, dir) {
if (control._pendingDirty) control.markAsDirty();
control.setValue(control._pendingValue, {
emitModelToViewChange: false
});
dir.viewToModelUpdate(control._pendingValue);
control._pendingChange = false;
}
function setUpModelChangePipeline(control, dir) {
const onChange = (newValue, emitModelEvent) => {
dir.valueAccessor.writeValue(newValue);
if (emitModelEvent) dir.viewToModelUpdate(newValue);
};
control.registerOnChange(onChange);
dir._registerOnDestroy(() => {
control._unregisterOnChange(onChange);
});
}
function setUpFormContainer(control, dir) {
if (control == null && (typeof ngDevMode === "undefined" || ngDevMode)) _throwError(dir, "Cannot find control with");
setUpValidators(control, dir);
}
function cleanUpFormContainer(control, dir) {
return cleanUpValidators(control, dir);
}
function _noControlError(dir) {
return _throwError(dir, "There is no FormControl instance attached to form control element with");
}
function _throwError(dir, message) {
const messageEnd = _describeControlLocation(dir);
throw new Error(`${message} ${messageEnd}`);
}
function _describeControlLocation(dir) {
const path = dir.path;
if (path && path.length > 1) return `path: '${path.join(" -> ")}'`;
if (path?.[0]) return `name: '${path}'`;
return "unspecified name attribute";
}
function _throwMissingValueAccessorError(dir) {
const loc = _describeControlLocation(dir);
throw new RuntimeError(-1203, `No value accessor for form control ${loc}.`);
}
function _throwInvalidValueAccessorError(dir) {
const loc = _describeControlLocation(dir);
throw new RuntimeError(1200, `Value accessor was not provided as an array for form control with ${loc}. Check that the \`NG_VALUE_ACCESSOR\` token is configured as a \`multi: true\` provider.`);
}
function isPropertyUpdated(changes, viewModel) {
if (!changes.hasOwnProperty("model")) return false;
const change = changes["model"];
if (change.isFirstChange()) return true;
return !Object.is(viewModel, change.currentValue);
}
function isBuiltInAccessor(valueAccessor) {
return Object.getPrototypeOf(valueAccessor.constructor) === BuiltInControlValueAccessor;
}
function syncPendingControls(form, directives) {
form._syncPendingControls();
directives.forEach((dir) => {
const control = dir.control;
if (control.updateOn === "submit" && control._pendingChange) {
dir.viewToModelUpdate(control._pendingValue);
control._pendingChange = false;
}
});
}
function selectValueAccessor(dir, valueAccessors) {
if (!valueAccessors) return null;
if (!Array.isArray(valueAccessors) && (typeof ngDevMode === "undefined" || ngDevMode)) _throwInvalidValueAccessorError(dir);
let defaultAccessor = void 0;
let builtinAccessor = void 0;
let customAccessor = void 0;
valueAccessors.forEach((v) => {
if (v.constructor === DefaultValueAccessor) {
defaultAccessor = v;
} else if (isBuiltInAccessor(v)) {
if (builtinAccessor && (typeof ngDevMode === "undefined" || ngDevMode)) _throwError(dir, "More than one built-in value accessor matches form control with");
builtinAccessor = v;
} else {
if (customAccessor && (typeof ngDevMode === "undefined" || ngDevMode)) _throwError(dir, "More than one custom value accessor matches form control with");
customAccessor = v;
}
});
if (customAccessor) return customAccessor;
if (builtinAccessor) return builtinAccessor;
if (defaultAccessor) return defaultAccessor;
if (typeof ngDevMode === "undefined" || ngDevMode) {
_throwError(dir, "No valid value accessor for form control with");
}
return null;
}
function removeListItem$1(list, el) {
const index = list.indexOf(el);
if (index > -1) list.splice(index, 1);
}
function _ngModelWarning(name, type, instance, warningConfig) {
if (warningConfig === "never") return;
if ((warningConfig === null || warningConfig === "once") && !type._ngModelWarningSentOnce || warningConfig === "always" && !instance._ngModelWarningSent) {
console.warn(ngModelWarning(name));
type._ngModelWarningSentOnce = true;
instance._ngModelWarningSent = true;
}
}
var formDirectiveProvider$1 = {
provide: ControlContainer,
useExisting: forwardRef(() => NgForm)
};
var resolvedPromise$1 = (() => Promise.resolve())();
var NgForm = class _NgForm extends ControlContainer {
callSetDisabledState;
/**
* @description
* Returns whether the form submission has been triggered.
*/
get submitted() {
return untracked(this.submittedReactive);
}
/** @internal */
_submitted = computed(() => this.submittedReactive());
submittedReactive = signal(false);
_directives = /* @__PURE__ */ new Set();
/**
* @description
* The `FormGroup` instance created for this form.
*/
form;
/**
* @description
* Event emitter for the "ngSubmit" event
*/
ngSubmit = new EventEmitter();
/**
* @description
* Tracks options for the `NgForm` instance.
*
* **updateOn**: Sets the default `updateOn` value for all child `NgModels` below it
* unless explicitly set by a child `NgModel` using `ngModelOptions`). Defaults to 'change'.
* Possible values: `'change'` | `'blur'` | `'submit'`.
*
*/
options;
constructor(validators, asyncValidators, callSetDisabledState) {
super();
this.callSetDisabledState = callSetDisabledState;
this.form = new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));
}
/** @docs-private */
ngAfterViewInit() {
this._setUpdateStrategy();
}
/**
* @description
* The directive instance.
*/
get formDirective() {
return this;
}
/**
* @description
* The internal `FormGroup` instance.
*/
get control() {
return this.form;
}
/**
* @description
* Returns an array representing the path to this group. Because this directive
* always lives at the top level of a form, it is always an empty array.
*/
get path() {
return [];
}
/**
* @description
* Returns a map of the controls in this group.
*/
get controls() {
return this.form.controls;
}
/**
* @description
* Method that sets up the control directive in this group, re-calculates its value
* and validity, and adds the instance to the internal list of directives.
*
* @param dir The `NgModel` directive instance.
*/
addControl(dir) {
resolvedPromise$1.then(() => {
const container = this._findContainer(dir.path);
dir.control = container.registerControl(dir.name, dir.control);
setUpControl(dir.control, dir, this.callSetDisabledState);
dir.control.updateValueAndValidity({
emitEvent: false
});
this._directives.add(dir);
});
}
/**
* @description
* Retrieves the `FormControl` instance from the provided `NgModel` directive.
*
* @param dir The `NgModel` directive instance.
*/
getControl(dir) {
return this.form.get(dir.path);
}
/**
* @description
* Removes the `NgModel` instance from the internal list of directives
*
* @param dir The `NgModel` directive instance.
*/
removeControl(dir) {
resolvedPromise$1.then(() => {
const container = this._findContainer(dir.path);
if (container) {
container.removeControl(dir.name);
}
this._directives.delete(dir);
});
}
/**
* @description
* Adds a new `NgModelGroup` directive instance to the form.
*
* @param dir The `NgModelGroup` directive instance.
*/
addFormGroup(dir) {
resolvedPromise$1.then(() => {
const container = this._findContainer(dir.path);
const group = new FormGroup({});
setUpFormContainer(group, dir);
container.registerControl(dir.name, group);
group.updateValueAndValidity({
emitEvent: false
});
});
}
/**
* @description
* Removes the `NgModelGroup` directive instance from the form.
*
* @param dir The `NgModelGroup` directive instance.
*/
removeFormGroup(dir) {
resolvedPromise$1.then(() => {
const container = this._findContainer(dir.path);
if (container) {
container.removeControl(dir.name);
}
});
}
/**
* @description
* Retrieves the `FormGroup` for a provided `NgModelGroup` directive instance
*
* @param dir The `NgModelGroup` directive instance.
*/
getFormGroup(dir) {
return this.form.get(dir.path);
}
/**
* Sets the new value for the provided `NgControl` directive.
*
* @param dir The `NgControl` directive instance.
* @param value The new value for the directive's control.
*/
updateModel(dir, value) {
resolvedPromise$1.then(() => {
const ctrl = this.form.get(dir.path);
ctrl.setValue(value);
});
}
/**
* @description
* Sets the value for this `FormGroup`.
*
* @param value The new value
*/
setValue(value) {
this.control.setValue(value);
}
/**
* @description
* Method called when the "submit" event is triggered on the form.
* Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
*
* @param $event The "submit" event object
*/
onSubmit($event) {
this.submittedReactive.set(true);
syncPendingControls(this.form, this._directives);
this.ngSubmit.emit($event);
this.form._events.next(new FormSubmittedEvent(this.control));
return $event?.target?.method === "dialog";
}
/**
* @description
* Method called when the "reset" event is triggered on the form.
*/
onReset() {
this.resetForm();
}
/**
* @description
* Resets the form to an initial value and resets its submitted status.
*
* @param value The new value for the form.
*/
resetForm(value = void 0) {
this.form.reset(value);
this.submittedReactive.set(false);
this.form._events.next(new FormResetEvent(this.form));
}
_setUpdateStrategy() {
if (this.options && this.options.updateOn != null) {
this.form._updateOn = this.options.updateOn;
}
}
_findContainer(path) {
path.pop();
return path.length ? this.form.get(path) : this.form;
}
static \u0275fac = function NgForm_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgForm)(\u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10), \u0275\u0275directiveInject(CALL_SET_DISABLED_STATE, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgForm,
selectors: [["form", 3, "ngNoForm", "", 3, "formGroup", ""], ["ng-form"], ["", "ngForm", ""]],
hostBindings: function NgForm_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("submit", function NgForm_submit_HostBindingHandler($event) {
return ctx.onSubmit($event);
})("reset", function NgForm_reset_HostBindingHandler() {
return ctx.onReset();
});
}
},
inputs: {
options: [0, "ngFormOptions", "options"]
},
outputs: {
ngSubmit: "ngSubmit"
},
exportAs: ["ngForm"],
standalone: false,
features: [\u0275\u0275ProvidersFeature([formDirectiveProvider$1]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgForm, [{
type: Directive,
args: [{
selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]",
providers: [formDirectiveProvider$1],
host: {
"(submit)": "onSubmit($event)",
"(reset)": "onReset()"
},
outputs: ["ngSubmit"],
exportAs: "ngForm",
standalone: false
}]
}], () => [{
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}]
}], {
options: [{
type: Input,
args: ["ngFormOptions"]
}]
});
})();
function removeListItem(list, el) {
const index = list.indexOf(el);
if (index > -1) list.splice(index, 1);
}
function isFormControlState(formState) {
return typeof formState === "object" && formState !== null && Object.keys(formState).length === 2 && "value" in formState && "disabled" in formState;
}
var FormControl = class FormControl2 extends AbstractControl {
/** @publicApi */
defaultValue = null;
/** @internal */
_onChange = [];
/** @internal */
_pendingValue;
/** @internal */
_pendingChange = false;
constructor(formState = null, validatorOrOpts, asyncValidator) {
super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
this._applyFormState(formState);
this._setUpdateStrategy(validatorOrOpts);
this._initObservables();
this.updateValueAndValidity({
onlySelf: true,
// If `asyncValidator` is present, it will trigger control status change from `PENDING` to
// `VALID` or `INVALID`.
// The status should be broadcasted via the `statusChanges` observable, so we set
// `emitEvent` to `true` to allow that during the control creation process.
emitEvent: !!this.asyncValidator
});
if (isOptionsObj(validatorOrOpts) && (validatorOrOpts.nonNullable || validatorOrOpts.initialValueIsDefault)) {
if (isFormControlState(formState)) {
this.defaultValue = formState.value;
} else {
this.defaultValue = formState;
}
}
}
setValue(value, options = {}) {
this.value = this._pendingValue = value;
if (this._onChange.length && options.emitModelToViewChange !== false) {
this._onChange.forEach((changeFn) => changeFn(this.value, options.emitViewToModelChange !== false));
}
this.updateValueAndValidity(options);
}
patchValue(value, options = {}) {
this.setValue(value, options);
}
reset(formState = this.defaultValue, options = {}) {
this._applyFormState(formState);
this.markAsPristine(options);
this.markAsUntouched(options);
this.setValue(this.value, options);
this._pendingChange = false;
}
/** @internal */
_updateValue() {
}
/** @internal */
_anyControls(condition) {
return false;
}
/** @internal */
_allControlsDisabled() {
return this.disabled;
}
registerOnChange(fn) {
this._onChange.push(fn);
}
/** @internal */
_unregisterOnChange(fn) {
removeListItem(this._onChange, fn);
}
registerOnDisabledChange(fn) {
this._onDisabledChange.push(fn);
}
/** @internal */
_unregisterOnDisabledChange(fn) {
removeListItem(this._onDisabledChange, fn);
}
/** @internal */
_forEachChild(cb) {
}
/** @internal */
_syncPendingControls() {
if (this.updateOn === "submit") {
if (this._pendingDirty) this.markAsDirty();
if (this._pendingTouched) this.markAsTouched();
if (this._pendingChange) {
this.setValue(this._pendingValue, {
onlySelf: true,
emitModelToViewChange: false
});
return true;
}
}
return false;
}
_applyFormState(formState) {
if (isFormControlState(formState)) {
this.value = this._pendingValue = formState.value;
formState.disabled ? this.disable({
onlySelf: true,
emitEvent: false
}) : this.enable({
onlySelf: true,
emitEvent: false
});
} else {
this.value = this._pendingValue = formState;
}
}
};
var isFormControl = (control) => control instanceof FormControl;
var AbstractFormGroupDirective = class _AbstractFormGroupDirective extends ControlContainer {
/**
* @description
* The parent control for the group
*
* @internal
*/
_parent;
/** @docs-private */
ngOnInit() {
this._checkParentType();
this.formDirective.addFormGroup(this);
}
/** @docs-private */
ngOnDestroy() {
if (this.formDirective) {
this.formDirective.removeFormGroup(this);
}
}
/**
* @description
* The `FormGroup` bound to this directive.
*/
get control() {
return this.formDirective.getFormGroup(this);
}
/**
* @description
* The path to this group from the top-level directive.
*/
get path() {
return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
}
/**
* @description
* The top-level directive for this group if present, otherwise null.
*/
get formDirective() {
return this._parent ? this._parent.formDirective : null;
}
/** @internal */
_checkParentType() {
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275AbstractFormGroupDirective_BaseFactory;
return function AbstractFormGroupDirective_Factory(__ngFactoryType__) {
return (\u0275AbstractFormGroupDirective_BaseFactory || (\u0275AbstractFormGroupDirective_BaseFactory = \u0275\u0275getInheritedFactory(_AbstractFormGroupDirective)))(__ngFactoryType__ || _AbstractFormGroupDirective);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _AbstractFormGroupDirective,
standalone: false,
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AbstractFormGroupDirective, [{
type: Directive,
args: [{
standalone: false
}]
}], null, null);
})();
function modelParentException() {
return new RuntimeError(1350, `
ngModel cannot be used to register form controls with a parent formGroup directive. Try using
formGroup's partner directive "formControlName" instead. Example:
${formControlNameExample}
Or, if you'd like to avoid registering this form control, indicate that it's standalone in ngModelOptions:
Example:
${ngModelWithFormGroupExample}`);
}
function formGroupNameException() {
return new RuntimeError(1351, `
ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.
Option 1: Use formControlName instead of ngModel (reactive strategy):
${formGroupNameExample}
Option 2: Update ngModel's parent be ngModelGroup (template-driven strategy):
${ngModelGroupExample}`);
}
function missingNameException() {
return new RuntimeError(1352, `If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Example 1: <input [(ngModel)]="person.firstName" name="first">
Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">`);
}
function modelGroupParentException() {
return new RuntimeError(1353, `
ngModelGroup cannot be used with a parent formGroup directive.
Option 1: Use formGroupName instead of ngModelGroup (reactive strategy):
${formGroupNameExample}
Option 2: Use a regular form tag instead of the formGroup directive (template-driven strategy):
${ngModelGroupExample}`);
}
var modelGroupProvider = {
provide: ControlContainer,
useExisting: forwardRef(() => NgModelGroup)
};
var NgModelGroup = class _NgModelGroup extends AbstractFormGroupDirective {
/**
* @description
* Tracks the name of the `NgModelGroup` bound to the directive. The name corresponds
* to a key in the parent `NgForm`.
*/
name = "";
constructor(parent, validators, asyncValidators) {
super();
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
}
/** @internal */
_checkParentType() {
if (!(this._parent instanceof _NgModelGroup) && !(this._parent instanceof NgForm) && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw modelGroupParentException();
}
}
static \u0275fac = function NgModelGroup_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgModelGroup)(\u0275\u0275directiveInject(ControlContainer, 5), \u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgModelGroup,
selectors: [["", "ngModelGroup", ""]],
inputs: {
name: [0, "ngModelGroup", "name"]
},
exportAs: ["ngModelGroup"],
standalone: false,
features: [\u0275\u0275ProvidersFeature([modelGroupProvider]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgModelGroup, [{
type: Directive,
args: [{
selector: "[ngModelGroup]",
providers: [modelGroupProvider],
exportAs: "ngModelGroup",
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Host
}, {
type: SkipSelf
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}], {
name: [{
type: Input,
args: ["ngModelGroup"]
}]
});
})();
var formControlBinding$1 = {
provide: NgControl,
useExisting: forwardRef(() => NgModel)
};
var resolvedPromise = (() => Promise.resolve())();
var NgModel = class _NgModel extends NgControl {
_changeDetectorRef;
callSetDisabledState;
control = new FormControl();
// At runtime we coerce arbitrary values assigned to the "disabled" input to a "boolean".
// This is not reflected in the type of the property because outside of templates, consumers
// should only deal with booleans. In templates, a string is allowed for convenience and to
// match the native "disabled attribute" semantics which can be observed on input elements.
// This static member tells the compiler that values of type "string" can also be assigned
// to the input in a template.
/** @docs-private */
static ngAcceptInputType_isDisabled;
/** @internal */
_registered = false;
/**
* Internal reference to the view model value.
* @docs-private
*/
viewModel;
/**
* @description
* Tracks the name bound to the directive. If a parent form exists, it
* uses this name as a key to retrieve this control's value.
*/
name = "";
/**
* @description
* Tracks whether the control is disabled.
*/
isDisabled;
/**
* @description
* Tracks the value bound to this directive.
*/
model;
/**
* @description
* Tracks the configuration options for this `ngModel` instance.
*
* **name**: An alternative to setting the name attribute on the form control element. See
* the [example](api/forms/NgModel#using-ngmodel-on-a-standalone-control) for using `NgModel`
* as a standalone control.
*
* **standalone**: When set to true, the `ngModel` will not register itself with its parent form,
* and acts as if it's not in the form. Defaults to false. If no parent form exists, this option
* has no effect.
*
* **updateOn**: Defines the event upon which the form control value and validity update.
* Defaults to 'change'. Possible values: `'change'` | `'blur'` | `'submit'`.
*
*/
options;
/**
* @description
* Event emitter for producing the `ngModelChange` event after
* the view model updates.
*/
update = new EventEmitter();
constructor(parent, validators, asyncValidators, valueAccessors, _changeDetectorRef, callSetDisabledState) {
super();
this._changeDetectorRef = _changeDetectorRef;
this.callSetDisabledState = callSetDisabledState;
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
/** @docs-private */
ngOnChanges(changes) {
this._checkForErrors();
if (!this._registered || "name" in changes) {
if (this._registered) {
this._checkName();
if (this.formDirective) {
const oldName = changes["name"].previousValue;
this.formDirective.removeControl({
name: oldName,
path: this._getPath(oldName)
});
}
}
this._setUpControl();
}
if ("isDisabled" in changes) {
this._updateDisabled(changes);
}
if (isPropertyUpdated(changes, this.viewModel)) {
this._updateValue(this.model);
this.viewModel = this.model;
}
}
/** @docs-private */
ngOnDestroy() {
this.formDirective && this.formDirective.removeControl(this);
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return this._getPath(this.name);
}
/**
* @description
* The top-level directive for this control if present, otherwise null.
*/
get formDirective() {
return this._parent ? this._parent.formDirective : null;
}
/**
* @description
* Sets the new value for the view model and emits an `ngModelChange` event.
*
* @param newValue The new value emitted by `ngModelChange`.
*/
viewToModelUpdate(newValue) {
this.viewModel = newValue;
this.update.emit(newValue);
}
_setUpControl() {
this._setUpdateStrategy();
this._isStandalone() ? this._setUpStandalone() : this.formDirective.addControl(this);
this._registered = true;
}
_setUpdateStrategy() {
if (this.options && this.options.updateOn != null) {
this.control._updateOn = this.options.updateOn;
}
}
_isStandalone() {
return !this._parent || !!(this.options && this.options.standalone);
}
_setUpStandalone() {
setUpControl(this.control, this, this.callSetDisabledState);
this.control.updateValueAndValidity({
emitEvent: false
});
}
_checkForErrors() {
if ((typeof ngDevMode === "undefined" || ngDevMode) && !this._isStandalone()) {
checkParentType$1(this._parent);
}
this._checkName();
}
_checkName() {
if (this.options && this.options.name) this.name = this.options.name;
if (!this._isStandalone() && !this.name && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw missingNameException();
}
}
_updateValue(value) {
resolvedPromise.then(() => {
this.control.setValue(value, {
emitViewToModelChange: false
});
this._changeDetectorRef?.markForCheck();
});
}
_updateDisabled(changes) {
const disabledValue = changes["isDisabled"].currentValue;
const isDisabled = disabledValue !== 0 && booleanAttribute(disabledValue);
resolvedPromise.then(() => {
if (isDisabled && !this.control.disabled) {
this.control.disable();
} else if (!isDisabled && this.control.disabled) {
this.control.enable();
}
this._changeDetectorRef?.markForCheck();
});
}
_getPath(controlName) {
return this._parent ? controlPath(controlName, this._parent) : [controlName];
}
static \u0275fac = function NgModel_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgModel)(\u0275\u0275directiveInject(ControlContainer, 9), \u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10), \u0275\u0275directiveInject(NG_VALUE_ACCESSOR, 10), \u0275\u0275directiveInject(ChangeDetectorRef, 8), \u0275\u0275directiveInject(CALL_SET_DISABLED_STATE, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgModel,
selectors: [["", "ngModel", "", 3, "formControlName", "", 3, "formControl", ""]],
inputs: {
name: "name",
isDisabled: [0, "disabled", "isDisabled"],
model: [0, "ngModel", "model"],
options: [0, "ngModelOptions", "options"]
},
outputs: {
update: "ngModelChange"
},
exportAs: ["ngModel"],
standalone: false,
features: [\u0275\u0275ProvidersFeature([formControlBinding$1]), \u0275\u0275InheritDefinitionFeature, \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgModel, [{
type: Directive,
args: [{
selector: "[ngModel]:not([formControlName]):not([formControl])",
providers: [formControlBinding$1],
exportAs: "ngModel",
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Optional
}, {
type: Host
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALUE_ACCESSOR]
}]
}, {
type: ChangeDetectorRef,
decorators: [{
type: Optional
}, {
type: Inject,
args: [ChangeDetectorRef]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}]
}], {
name: [{
type: Input
}],
isDisabled: [{
type: Input,
args: ["disabled"]
}],
model: [{
type: Input,
args: ["ngModel"]
}],
options: [{
type: Input,
args: ["ngModelOptions"]
}],
update: [{
type: Output,
args: ["ngModelChange"]
}]
});
})();
function checkParentType$1(parent) {
if (!(parent instanceof NgModelGroup) && parent instanceof AbstractFormGroupDirective) {
throw formGroupNameException();
} else if (!(parent instanceof NgModelGroup) && !(parent instanceof NgForm)) {
throw modelParentException();
}
}
var \u0275NgNoValidate = class _\u0275NgNoValidate {
static \u0275fac = function \u0275NgNoValidate_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _\u0275NgNoValidate)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _\u0275NgNoValidate,
selectors: [["form", 3, "ngNoForm", "", 3, "ngNativeValidate", ""]],
hostAttrs: ["novalidate", ""],
standalone: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(\u0275NgNoValidate, [{
type: Directive,
args: [{
selector: "form:not([ngNoForm]):not([ngNativeValidate])",
host: {
"novalidate": ""
},
standalone: false
}]
}], null, null);
})();
var NUMBER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NumberValueAccessor),
multi: true
};
var NumberValueAccessor = class _NumberValueAccessor extends BuiltInControlValueAccessor {
/**
* Sets the "value" property on the input element.
* @docs-private
*/
writeValue(value) {
const normalizedValue = value == null ? "" : value;
this.setProperty("value", normalizedValue);
}
/**
* Registers a function called when the control value changes.
* @docs-private
*/
registerOnChange(fn) {
this.onChange = (value) => {
fn(value == "" ? null : parseFloat(value));
};
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275NumberValueAccessor_BaseFactory;
return function NumberValueAccessor_Factory(__ngFactoryType__) {
return (\u0275NumberValueAccessor_BaseFactory || (\u0275NumberValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_NumberValueAccessor)))(__ngFactoryType__ || _NumberValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NumberValueAccessor,
selectors: [["input", "type", "number", "formControlName", ""], ["input", "type", "number", "formControl", ""], ["input", "type", "number", "ngModel", ""]],
hostBindings: function NumberValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("input", function NumberValueAccessor_input_HostBindingHandler($event) {
return ctx.onChange($event.target.value);
})("blur", function NumberValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([NUMBER_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NumberValueAccessor, [{
type: Directive,
args: [{
selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]",
host: {
"(input)": "onChange($event.target.value)",
"(blur)": "onTouched()"
},
providers: [NUMBER_VALUE_ACCESSOR],
standalone: false
}]
}], null, null);
})();
var RADIO_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioControlValueAccessor),
multi: true
};
function throwNameError() {
throw new RuntimeError(1202, `
If you define both a name and a formControlName attribute on your radio button, their values
must match. Ex: <input type="radio" formControlName="food" name="food">
`);
}
var RadioControlRegistry = class _RadioControlRegistry {
_accessors = [];
/**
* @description
* Adds a control to the internal registry. For internal use only.
*/
add(control, accessor) {
this._accessors.push([control, accessor]);
}
/**
* @description
* Removes a control from the internal registry. For internal use only.
*/
remove(accessor) {
for (let i = this._accessors.length - 1; i >= 0; --i) {
if (this._accessors[i][1] === accessor) {
this._accessors.splice(i, 1);
return;
}
}
}
/**
* @description
* Selects a radio button. For internal use only.
*/
select(accessor) {
this._accessors.forEach((c) => {
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
c[1].fireUncheck(accessor.value);
}
});
}
_isSameGroup(controlPair, accessor) {
if (!controlPair[0].control) return false;
return controlPair[0]._parent === accessor._control._parent && controlPair[1].name === accessor.name;
}
static \u0275fac = function RadioControlRegistry_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RadioControlRegistry)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _RadioControlRegistry,
factory: _RadioControlRegistry.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RadioControlRegistry, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var RadioControlValueAccessor = class _RadioControlValueAccessor extends BuiltInControlValueAccessor {
_registry;
_injector;
/** @internal */
_state;
/** @internal */
_control;
/** @internal */
_fn;
setDisabledStateFired = false;
/**
* The registered callback function called when a change event occurs on the input element.
* Note: we declare `onChange` here (also used as host listener) as a function with no arguments
* to override the `onChange` function (which expects 1 argument) in the parent
* `BaseControlValueAccessor` class.
* @docs-private
*/
onChange = () => {
};
/**
* @description
* Tracks the name of the radio input element.
*/
name;
/**
* @description
* Tracks the name of the `FormControl` bound to the directive. The name corresponds
* to a key in the parent `FormGroup` or `FormArray`.
*/
formControlName;
/**
* @description
* Tracks the value of the radio input element
*/
value;
callSetDisabledState = inject(CALL_SET_DISABLED_STATE, {
optional: true
}) ?? setDisabledStateDefault;
constructor(renderer, elementRef, _registry, _injector) {
super(renderer, elementRef);
this._registry = _registry;
this._injector = _injector;
}
/** @docs-private */
ngOnInit() {
this._control = this._injector.get(NgControl);
this._checkName();
this._registry.add(this._control, this);
}
/** @docs-private */
ngOnDestroy() {
this._registry.remove(this);
}
/**
* Sets the "checked" property value on the radio input element.
* @docs-private
*/
writeValue(value) {
this._state = value === this.value;
this.setProperty("checked", this._state);
}
/**
* Registers a function called when the control value changes.
* @docs-private
*/
registerOnChange(fn) {
this._fn = fn;
this.onChange = () => {
fn(this.value);
this._registry.select(this);
};
}
/** @docs-private */
setDisabledState(isDisabled) {
if (this.setDisabledStateFired || isDisabled || this.callSetDisabledState === "whenDisabledForLegacyCode") {
this.setProperty("disabled", isDisabled);
}
this.setDisabledStateFired = true;
}
/**
* Sets the "value" on the radio input element and unchecks it.
*
* @param value
*/
fireUncheck(value) {
this.writeValue(value);
}
_checkName() {
if (this.name && this.formControlName && this.name !== this.formControlName && (typeof ngDevMode === "undefined" || ngDevMode)) {
throwNameError();
}
if (!this.name && this.formControlName) this.name = this.formControlName;
}
static \u0275fac = function RadioControlValueAccessor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RadioControlValueAccessor)(\u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(RadioControlRegistry), \u0275\u0275directiveInject(Injector));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RadioControlValueAccessor,
selectors: [["input", "type", "radio", "formControlName", ""], ["input", "type", "radio", "formControl", ""], ["input", "type", "radio", "ngModel", ""]],
hostBindings: function RadioControlValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("change", function RadioControlValueAccessor_change_HostBindingHandler() {
return ctx.onChange();
})("blur", function RadioControlValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
inputs: {
name: "name",
formControlName: "formControlName",
value: "value"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([RADIO_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RadioControlValueAccessor, [{
type: Directive,
args: [{
selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]",
host: {
"(change)": "onChange()",
"(blur)": "onTouched()"
},
providers: [RADIO_VALUE_ACCESSOR],
standalone: false
}]
}], () => [{
type: Renderer2
}, {
type: ElementRef
}, {
type: RadioControlRegistry
}, {
type: Injector
}], {
name: [{
type: Input
}],
formControlName: [{
type: Input
}],
value: [{
type: Input
}]
});
})();
var RANGE_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RangeValueAccessor),
multi: true
};
var RangeValueAccessor = class _RangeValueAccessor extends BuiltInControlValueAccessor {
/**
* Sets the "value" property on the input element.
* @docs-private
*/
writeValue(value) {
this.setProperty("value", parseFloat(value));
}
/**
* Registers a function called when the control value changes.
* @docs-private
*/
registerOnChange(fn) {
this.onChange = (value) => {
fn(value == "" ? null : parseFloat(value));
};
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275RangeValueAccessor_BaseFactory;
return function RangeValueAccessor_Factory(__ngFactoryType__) {
return (\u0275RangeValueAccessor_BaseFactory || (\u0275RangeValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_RangeValueAccessor)))(__ngFactoryType__ || _RangeValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RangeValueAccessor,
selectors: [["input", "type", "range", "formControlName", ""], ["input", "type", "range", "formControl", ""], ["input", "type", "range", "ngModel", ""]],
hostBindings: function RangeValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("change", function RangeValueAccessor_change_HostBindingHandler($event) {
return ctx.onChange($event.target.value);
})("input", function RangeValueAccessor_input_HostBindingHandler($event) {
return ctx.onChange($event.target.value);
})("blur", function RangeValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([RANGE_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RangeValueAccessor, [{
type: Directive,
args: [{
selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]",
host: {
"(change)": "onChange($event.target.value)",
"(input)": "onChange($event.target.value)",
"(blur)": "onTouched()"
},
providers: [RANGE_VALUE_ACCESSOR],
standalone: false
}]
}], null, null);
})();
var NG_MODEL_WITH_FORM_CONTROL_WARNING = new InjectionToken(ngDevMode ? "NgModelWithFormControlWarning" : "");
var formControlBinding = {
provide: NgControl,
useExisting: forwardRef(() => FormControlDirective)
};
var FormControlDirective = class _FormControlDirective extends NgControl {
_ngModelWarningConfig;
callSetDisabledState;
/**
* Internal reference to the view model value.
* @docs-private
*/
viewModel;
/**
* @description
* Tracks the `FormControl` instance bound to the directive.
*/
form;
/**
* @description
* Triggers a warning in dev mode that this input should not be used with reactive forms.
*/
set isDisabled(isDisabled) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
console.warn(disabledAttrWarning);
}
}
// TODO(kara): remove next 4 properties once deprecation period is over
/** @deprecated as of v6 */
model;
/** @deprecated as of v6 */
update = new EventEmitter();
/**
* @description
* Static property used to track whether any ngModel warnings have been sent across
* all instances of FormControlDirective. Used to support warning config of "once".
*
* @internal
*/
static _ngModelWarningSentOnce = false;
/**
* @description
* Instance property used to track whether an ngModel warning has been sent out for this
* particular `FormControlDirective` instance. Used to support warning config of "always".
*
* @internal
*/
_ngModelWarningSent = false;
constructor(validators, asyncValidators, valueAccessors, _ngModelWarningConfig, callSetDisabledState) {
super();
this._ngModelWarningConfig = _ngModelWarningConfig;
this.callSetDisabledState = callSetDisabledState;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
/** @docs-private */
ngOnChanges(changes) {
if (this._isControlChanged(changes)) {
const previousForm = changes["form"].previousValue;
if (previousForm) {
cleanUpControl(
previousForm,
this,
/* validateControlPresenceOnChange */
false
);
}
setUpControl(this.form, this, this.callSetDisabledState);
this.form.updateValueAndValidity({
emitEvent: false
});
}
if (isPropertyUpdated(changes, this.viewModel)) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
_ngModelWarning("formControl", _FormControlDirective, this, this._ngModelWarningConfig);
}
this.form.setValue(this.model);
this.viewModel = this.model;
}
}
/** @docs-private */
ngOnDestroy() {
if (this.form) {
cleanUpControl(
this.form,
this,
/* validateControlPresenceOnChange */
false
);
}
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return [];
}
/**
* @description
* The `FormControl` bound to this directive.
*/
get control() {
return this.form;
}
/**
* @description
* Sets the new value for the view model and emits an `ngModelChange` event.
*
* @param newValue The new value for the view model.
*/
viewToModelUpdate(newValue) {
this.viewModel = newValue;
this.update.emit(newValue);
}
_isControlChanged(changes) {
return changes.hasOwnProperty("form");
}
static \u0275fac = function FormControlDirective_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormControlDirective)(\u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10), \u0275\u0275directiveInject(NG_VALUE_ACCESSOR, 10), \u0275\u0275directiveInject(NG_MODEL_WITH_FORM_CONTROL_WARNING, 8), \u0275\u0275directiveInject(CALL_SET_DISABLED_STATE, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _FormControlDirective,
selectors: [["", "formControl", ""]],
inputs: {
form: [0, "formControl", "form"],
isDisabled: [0, "disabled", "isDisabled"],
model: [0, "ngModel", "model"]
},
outputs: {
update: "ngModelChange"
},
exportAs: ["ngForm"],
standalone: false,
features: [\u0275\u0275ProvidersFeature([formControlBinding]), \u0275\u0275InheritDefinitionFeature, \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormControlDirective, [{
type: Directive,
args: [{
selector: "[formControl]",
providers: [formControlBinding],
exportAs: "ngForm",
standalone: false
}]
}], () => [{
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALUE_ACCESSOR]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [NG_MODEL_WITH_FORM_CONTROL_WARNING]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}]
}], {
form: [{
type: Input,
args: ["formControl"]
}],
isDisabled: [{
type: Input,
args: ["disabled"]
}],
model: [{
type: Input,
args: ["ngModel"]
}],
update: [{
type: Output,
args: ["ngModelChange"]
}]
});
})();
var formDirectiveProvider = {
provide: ControlContainer,
useExisting: forwardRef(() => FormGroupDirective)
};
var FormGroupDirective = class _FormGroupDirective extends ControlContainer {
callSetDisabledState;
/**
* @description
* Reports whether the form submission has been triggered.
*/
get submitted() {
return untracked(this._submittedReactive);
}
// TODO(atscott): Remove once invalid API usage is cleaned up internally
set submitted(value) {
this._submittedReactive.set(value);
}
/** @internal */
_submitted = computed(() => this._submittedReactive());
_submittedReactive = signal(false);
/**
* Reference to an old form group input value, which is needed to cleanup
* old instance in case it was replaced with a new one.
*/
_oldForm;
/**
* Callback that should be invoked when controls in FormGroup or FormArray collection change
* (added or removed). This callback triggers corresponding DOM updates.
*/
_onCollectionChange = () => this._updateDomValue();
/**
* @description
* Tracks the list of added `FormControlName` instances
*/
directives = [];
/**
* @description
* Tracks the `FormGroup` bound to this directive.
*/
form = null;
/**
* @description
* Emits an event when the form submission has been triggered.
*/
ngSubmit = new EventEmitter();
constructor(validators, asyncValidators, callSetDisabledState) {
super();
this.callSetDisabledState = callSetDisabledState;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
}
/** @docs-private */
ngOnChanges(changes) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && !this.form) {
throw missingFormException();
}
if (changes.hasOwnProperty("form")) {
this._updateValidators();
this._updateDomValue();
this._updateRegistrations();
this._oldForm = this.form;
}
}
/** @docs-private */
ngOnDestroy() {
if (this.form) {
cleanUpValidators(this.form, this);
if (this.form._onCollectionChange === this._onCollectionChange) {
this.form._registerOnCollectionChange(() => {
});
}
}
}
/**
* @description
* Returns this directive's instance.
*/
get formDirective() {
return this;
}
/**
* @description
* Returns the `FormGroup` bound to this directive.
*/
get control() {
return this.form;
}
/**
* @description
* Returns an array representing the path to this group. Because this directive
* always lives at the top level of a form, it always an empty array.
*/
get path() {
return [];
}
/**
* @description
* Method that sets up the control directive in this group, re-calculates its value
* and validity, and adds the instance to the internal list of directives.
*
* @param dir The `FormControlName` directive instance.
*/
addControl(dir) {
const ctrl = this.form.get(dir.path);
setUpControl(ctrl, dir, this.callSetDisabledState);
ctrl.updateValueAndValidity({
emitEvent: false
});
this.directives.push(dir);
return ctrl;
}
/**
* @description
* Retrieves the `FormControl` instance from the provided `FormControlName` directive
*
* @param dir The `FormControlName` directive instance.
*/
getControl(dir) {
return this.form.get(dir.path);
}
/**
* @description
* Removes the `FormControlName` instance from the internal list of directives
*
* @param dir The `FormControlName` directive instance.
*/
removeControl(dir) {
cleanUpControl(
dir.control || null,
dir,
/* validateControlPresenceOnChange */
false
);
removeListItem$1(this.directives, dir);
}
/**
* Adds a new `FormGroupName` directive instance to the form.
*
* @param dir The `FormGroupName` directive instance.
*/
addFormGroup(dir) {
this._setUpFormContainer(dir);
}
/**
* Performs the necessary cleanup when a `FormGroupName` directive instance is removed from the
* view.
*
* @param dir The `FormGroupName` directive instance.
*/
removeFormGroup(dir) {
this._cleanUpFormContainer(dir);
}
/**
* @description
* Retrieves the `FormGroup` for a provided `FormGroupName` directive instance
*
* @param dir The `FormGroupName` directive instance.
*/
getFormGroup(dir) {
return this.form.get(dir.path);
}
/**
* Performs the necessary setup when a `FormArrayName` directive instance is added to the view.
*
* @param dir The `FormArrayName` directive instance.
*/
addFormArray(dir) {
this._setUpFormContainer(dir);
}
/**
* Performs the necessary cleanup when a `FormArrayName` directive instance is removed from the
* view.
*
* @param dir The `FormArrayName` directive instance.
*/
removeFormArray(dir) {
this._cleanUpFormContainer(dir);
}
/**
* @description
* Retrieves the `FormArray` for a provided `FormArrayName` directive instance.
*
* @param dir The `FormArrayName` directive instance.
*/
getFormArray(dir) {
return this.form.get(dir.path);
}
/**
* Sets the new value for the provided `FormControlName` directive.
*
* @param dir The `FormControlName` directive instance.
* @param value The new value for the directive's control.
*/
updateModel(dir, value) {
const ctrl = this.form.get(dir.path);
ctrl.setValue(value);
}
/**
* @description
* Method called with the "submit" event is triggered on the form.
* Triggers the `ngSubmit` emitter to emit the "submit" event as its payload.
*
* @param $event The "submit" event object
*/
onSubmit($event) {
this._submittedReactive.set(true);
syncPendingControls(this.form, this.directives);
this.ngSubmit.emit($event);
this.form._events.next(new FormSubmittedEvent(this.control));
return $event?.target?.method === "dialog";
}
/**
* @description
* Method called when the "reset" event is triggered on the form.
*/
onReset() {
this.resetForm();
}
/**
* @description
* Resets the form to an initial value and resets its submitted status.
*
* @param value The new value for the form.
*/
resetForm(value = void 0) {
this.form.reset(value);
this._submittedReactive.set(false);
this.form._events.next(new FormResetEvent(this.form));
}
/** @internal */
_updateDomValue() {
this.directives.forEach((dir) => {
const oldCtrl = dir.control;
const newCtrl = this.form.get(dir.path);
if (oldCtrl !== newCtrl) {
cleanUpControl(oldCtrl || null, dir);
if (isFormControl(newCtrl)) {
setUpControl(newCtrl, dir, this.callSetDisabledState);
dir.control = newCtrl;
}
}
});
this.form._updateTreeValidity({
emitEvent: false
});
}
_setUpFormContainer(dir) {
const ctrl = this.form.get(dir.path);
setUpFormContainer(ctrl, dir);
ctrl.updateValueAndValidity({
emitEvent: false
});
}
_cleanUpFormContainer(dir) {
if (this.form) {
const ctrl = this.form.get(dir.path);
if (ctrl) {
const isControlUpdated = cleanUpFormContainer(ctrl, dir);
if (isControlUpdated) {
ctrl.updateValueAndValidity({
emitEvent: false
});
}
}
}
}
_updateRegistrations() {
this.form._registerOnCollectionChange(this._onCollectionChange);
if (this._oldForm) {
this._oldForm._registerOnCollectionChange(() => {
});
}
}
_updateValidators() {
setUpValidators(this.form, this);
if (this._oldForm) {
cleanUpValidators(this._oldForm, this);
}
}
static \u0275fac = function FormGroupDirective_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormGroupDirective)(\u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10), \u0275\u0275directiveInject(CALL_SET_DISABLED_STATE, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _FormGroupDirective,
selectors: [["", "formGroup", ""]],
hostBindings: function FormGroupDirective_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("submit", function FormGroupDirective_submit_HostBindingHandler($event) {
return ctx.onSubmit($event);
})("reset", function FormGroupDirective_reset_HostBindingHandler() {
return ctx.onReset();
});
}
},
inputs: {
form: [0, "formGroup", "form"]
},
outputs: {
ngSubmit: "ngSubmit"
},
exportAs: ["ngForm"],
standalone: false,
features: [\u0275\u0275ProvidersFeature([formDirectiveProvider]), \u0275\u0275InheritDefinitionFeature, \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormGroupDirective, [{
type: Directive,
args: [{
selector: "[formGroup]",
providers: [formDirectiveProvider],
host: {
"(submit)": "onSubmit($event)",
"(reset)": "onReset()"
},
exportAs: "ngForm",
standalone: false
}]
}], () => [{
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [CALL_SET_DISABLED_STATE]
}]
}], {
form: [{
type: Input,
args: ["formGroup"]
}],
ngSubmit: [{
type: Output
}]
});
})();
var formGroupNameProvider = {
provide: ControlContainer,
useExisting: forwardRef(() => FormGroupName)
};
var FormGroupName = class _FormGroupName extends AbstractFormGroupDirective {
/**
* @description
* Tracks the name of the `FormGroup` bound to the directive. The name corresponds
* to a key in the parent `FormGroup` or `FormArray`.
* Accepts a name as a string or a number.
* The name in the form of a string is useful for individual forms,
* while the numerical form allows for form groups to be bound
* to indices when iterating over groups in a `FormArray`.
*/
name = null;
constructor(parent, validators, asyncValidators) {
super();
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
}
/** @internal */
_checkParentType() {
if (hasInvalidParent(this._parent) && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw groupParentException();
}
}
static \u0275fac = function FormGroupName_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormGroupName)(\u0275\u0275directiveInject(ControlContainer, 13), \u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _FormGroupName,
selectors: [["", "formGroupName", ""]],
inputs: {
name: [0, "formGroupName", "name"]
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([formGroupNameProvider]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormGroupName, [{
type: Directive,
args: [{
selector: "[formGroupName]",
providers: [formGroupNameProvider],
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Optional
}, {
type: Host
}, {
type: SkipSelf
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}], {
name: [{
type: Input,
args: ["formGroupName"]
}]
});
})();
var formArrayNameProvider = {
provide: ControlContainer,
useExisting: forwardRef(() => FormArrayName)
};
var FormArrayName = class _FormArrayName extends ControlContainer {
/** @internal */
_parent;
/**
* @description
* Tracks the name of the `FormArray` bound to the directive. The name corresponds
* to a key in the parent `FormGroup` or `FormArray`.
* Accepts a name as a string or a number.
* The name in the form of a string is useful for individual forms,
* while the numerical form allows for form arrays to be bound
* to indices when iterating over arrays in a `FormArray`.
*/
name = null;
constructor(parent, validators, asyncValidators) {
super();
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
}
/**
* A lifecycle method called when the directive's inputs are initialized. For internal use only.
* @throws If the directive does not have a valid parent.
* @docs-private
*/
ngOnInit() {
if (hasInvalidParent(this._parent) && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw arrayParentException();
}
this.formDirective.addFormArray(this);
}
/**
* A lifecycle method called before the directive's instance is destroyed. For internal use only.
* @docs-private
*/
ngOnDestroy() {
this.formDirective?.removeFormArray(this);
}
/**
* @description
* The `FormArray` bound to this directive.
*/
get control() {
return this.formDirective.getFormArray(this);
}
/**
* @description
* The top-level directive for this group if present, otherwise null.
*/
get formDirective() {
return this._parent ? this._parent.formDirective : null;
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
}
static \u0275fac = function FormArrayName_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormArrayName)(\u0275\u0275directiveInject(ControlContainer, 13), \u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _FormArrayName,
selectors: [["", "formArrayName", ""]],
inputs: {
name: [0, "formArrayName", "name"]
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([formArrayNameProvider]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormArrayName, [{
type: Directive,
args: [{
selector: "[formArrayName]",
providers: [formArrayNameProvider],
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Optional
}, {
type: Host
}, {
type: SkipSelf
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}], {
name: [{
type: Input,
args: ["formArrayName"]
}]
});
})();
function hasInvalidParent(parent) {
return !(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) && !(parent instanceof FormArrayName);
}
var controlNameBinding = {
provide: NgControl,
useExisting: forwardRef(() => FormControlName)
};
var FormControlName = class _FormControlName extends NgControl {
_ngModelWarningConfig;
_added = false;
/**
* Internal reference to the view model value.
* @internal
*/
viewModel;
/**
* @description
* Tracks the `FormControl` instance bound to the directive.
*/
control;
/**
* @description
* Tracks the name of the `FormControl` bound to the directive. The name corresponds
* to a key in the parent `FormGroup` or `FormArray`.
* Accepts a name as a string or a number.
* The name in the form of a string is useful for individual forms,
* while the numerical form allows for form controls to be bound
* to indices when iterating over controls in a `FormArray`.
*/
name = null;
/**
* @description
* Triggers a warning in dev mode that this input should not be used with reactive forms.
*/
set isDisabled(isDisabled) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
console.warn(disabledAttrWarning);
}
}
// TODO(kara): remove next 4 properties once deprecation period is over
/** @deprecated as of v6 */
model;
/** @deprecated as of v6 */
update = new EventEmitter();
/**
* @description
* Static property used to track whether any ngModel warnings have been sent across
* all instances of FormControlName. Used to support warning config of "once".
*
* @internal
*/
static _ngModelWarningSentOnce = false;
/**
* @description
* Instance property used to track whether an ngModel warning has been sent out for this
* particular FormControlName instance. Used to support warning config of "always".
*
* @internal
*/
_ngModelWarningSent = false;
constructor(parent, validators, asyncValidators, valueAccessors, _ngModelWarningConfig) {
super();
this._ngModelWarningConfig = _ngModelWarningConfig;
this._parent = parent;
this._setValidators(validators);
this._setAsyncValidators(asyncValidators);
this.valueAccessor = selectValueAccessor(this, valueAccessors);
}
/** @docs-private */
ngOnChanges(changes) {
if (!this._added) this._setUpControl();
if (isPropertyUpdated(changes, this.viewModel)) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
_ngModelWarning("formControlName", _FormControlName, this, this._ngModelWarningConfig);
}
this.viewModel = this.model;
this.formDirective.updateModel(this, this.model);
}
}
/** @docs-private */
ngOnDestroy() {
if (this.formDirective) {
this.formDirective.removeControl(this);
}
}
/**
* @description
* Sets the new value for the view model and emits an `ngModelChange` event.
*
* @param newValue The new value for the view model.
*/
viewToModelUpdate(newValue) {
this.viewModel = newValue;
this.update.emit(newValue);
}
/**
* @description
* Returns an array that represents the path from the top-level form to this control.
* Each index is the string name of the control on that level.
*/
get path() {
return controlPath(this.name == null ? this.name : this.name.toString(), this._parent);
}
/**
* @description
* The top-level directive for this group if present, otherwise null.
*/
get formDirective() {
return this._parent ? this._parent.formDirective : null;
}
_setUpControl() {
if (typeof ngDevMode === "undefined" || ngDevMode) {
checkParentType(this._parent, this.name);
}
this.control = this.formDirective.addControl(this);
this._added = true;
}
static \u0275fac = function FormControlName_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormControlName)(\u0275\u0275directiveInject(ControlContainer, 13), \u0275\u0275directiveInject(NG_VALIDATORS, 10), \u0275\u0275directiveInject(NG_ASYNC_VALIDATORS, 10), \u0275\u0275directiveInject(NG_VALUE_ACCESSOR, 10), \u0275\u0275directiveInject(NG_MODEL_WITH_FORM_CONTROL_WARNING, 8));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _FormControlName,
selectors: [["", "formControlName", ""]],
inputs: {
name: [0, "formControlName", "name"],
isDisabled: [0, "disabled", "isDisabled"],
model: [0, "ngModel", "model"]
},
outputs: {
update: "ngModelChange"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([controlNameBinding]), \u0275\u0275InheritDefinitionFeature, \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormControlName, [{
type: Directive,
args: [{
selector: "[formControlName]",
providers: [controlNameBinding],
standalone: false
}]
}], () => [{
type: ControlContainer,
decorators: [{
type: Optional
}, {
type: Host
}, {
type: SkipSelf
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_ASYNC_VALIDATORS]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Self
}, {
type: Inject,
args: [NG_VALUE_ACCESSOR]
}]
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [NG_MODEL_WITH_FORM_CONTROL_WARNING]
}]
}], {
name: [{
type: Input,
args: ["formControlName"]
}],
isDisabled: [{
type: Input,
args: ["disabled"]
}],
model: [{
type: Input,
args: ["ngModel"]
}],
update: [{
type: Output,
args: ["ngModelChange"]
}]
});
})();
function checkParentType(parent, name) {
if (!(parent instanceof FormGroupName) && parent instanceof AbstractFormGroupDirective) {
throw ngModelGroupException();
} else if (!(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) && !(parent instanceof FormArrayName)) {
throw controlParentException(name);
}
}
var SELECT_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SelectControlValueAccessor),
multi: true
};
function _buildValueString$1(id, value) {
if (id == null) return `${value}`;
if (value && typeof value === "object") value = "Object";
return `${id}: ${value}`.slice(0, 50);
}
function _extractId$1(valueString) {
return valueString.split(":")[0];
}
var SelectControlValueAccessor = class _SelectControlValueAccessor extends BuiltInControlValueAccessor {
/** @docs-private */
value;
/** @internal */
_optionMap = /* @__PURE__ */ new Map();
/** @internal */
_idCounter = 0;
/**
* @description
* Tracks the option comparison algorithm for tracking identities when
* checking for changes.
*/
set compareWith(fn) {
if (typeof fn !== "function" && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw new RuntimeError(1201, `compareWith must be a function, but received ${JSON.stringify(fn)}`);
}
this._compareWith = fn;
}
_compareWith = Object.is;
/**
* Sets the "value" property on the select element.
* @docs-private
*/
writeValue(value) {
this.value = value;
const id = this._getOptionId(value);
const valueString = _buildValueString$1(id, value);
this.setProperty("value", valueString);
}
/**
* Registers a function called when the control value changes.
* @docs-private
*/
registerOnChange(fn) {
this.onChange = (valueString) => {
this.value = this._getOptionValue(valueString);
fn(this.value);
};
}
/** @internal */
_registerOption() {
return (this._idCounter++).toString();
}
/** @internal */
_getOptionId(value) {
for (const id of this._optionMap.keys()) {
if (this._compareWith(this._optionMap.get(id), value)) return id;
}
return null;
}
/** @internal */
_getOptionValue(valueString) {
const id = _extractId$1(valueString);
return this._optionMap.has(id) ? this._optionMap.get(id) : valueString;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275SelectControlValueAccessor_BaseFactory;
return function SelectControlValueAccessor_Factory(__ngFactoryType__) {
return (\u0275SelectControlValueAccessor_BaseFactory || (\u0275SelectControlValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_SelectControlValueAccessor)))(__ngFactoryType__ || _SelectControlValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _SelectControlValueAccessor,
selectors: [["select", "formControlName", "", 3, "multiple", ""], ["select", "formControl", "", 3, "multiple", ""], ["select", "ngModel", "", 3, "multiple", ""]],
hostBindings: function SelectControlValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("change", function SelectControlValueAccessor_change_HostBindingHandler($event) {
return ctx.onChange($event.target.value);
})("blur", function SelectControlValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
inputs: {
compareWith: "compareWith"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([SELECT_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SelectControlValueAccessor, [{
type: Directive,
args: [{
selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]",
host: {
"(change)": "onChange($event.target.value)",
"(blur)": "onTouched()"
},
providers: [SELECT_VALUE_ACCESSOR],
standalone: false
}]
}], null, {
compareWith: [{
type: Input
}]
});
})();
var NgSelectOption = class _NgSelectOption {
_element;
_renderer;
_select;
/**
* @description
* ID of the option element
*/
id;
constructor(_element, _renderer, _select) {
this._element = _element;
this._renderer = _renderer;
this._select = _select;
if (this._select) this.id = this._select._registerOption();
}
/**
* @description
* Tracks the value bound to the option element. Unlike the value binding,
* ngValue supports binding to objects.
*/
set ngValue(value) {
if (this._select == null) return;
this._select._optionMap.set(this.id, value);
this._setElementValue(_buildValueString$1(this.id, value));
this._select.writeValue(this._select.value);
}
/**
* @description
* Tracks simple string values bound to the option element.
* For objects, use the `ngValue` input binding.
*/
set value(value) {
this._setElementValue(value);
if (this._select) this._select.writeValue(this._select.value);
}
/** @internal */
_setElementValue(value) {
this._renderer.setProperty(this._element.nativeElement, "value", value);
}
/** @docs-private */
ngOnDestroy() {
if (this._select) {
this._select._optionMap.delete(this.id);
this._select.writeValue(this._select.value);
}
}
static \u0275fac = function NgSelectOption_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NgSelectOption)(\u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(SelectControlValueAccessor, 9));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _NgSelectOption,
selectors: [["option"]],
inputs: {
ngValue: "ngValue",
value: "value"
},
standalone: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgSelectOption, [{
type: Directive,
args: [{
selector: "option",
standalone: false
}]
}], () => [{
type: ElementRef
}, {
type: Renderer2
}, {
type: SelectControlValueAccessor,
decorators: [{
type: Optional
}, {
type: Host
}]
}], {
ngValue: [{
type: Input,
args: ["ngValue"]
}],
value: [{
type: Input,
args: ["value"]
}]
});
})();
var SELECT_MULTIPLE_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SelectMultipleControlValueAccessor),
multi: true
};
function _buildValueString(id, value) {
if (id == null) return `${value}`;
if (typeof value === "string") value = `'${value}'`;
if (value && typeof value === "object") value = "Object";
return `${id}: ${value}`.slice(0, 50);
}
function _extractId(valueString) {
return valueString.split(":")[0];
}
var SelectMultipleControlValueAccessor = class _SelectMultipleControlValueAccessor extends BuiltInControlValueAccessor {
/**
* The current value.
* @docs-private
*/
value;
/** @internal */
_optionMap = /* @__PURE__ */ new Map();
/** @internal */
_idCounter = 0;
/**
* @description
* Tracks the option comparison algorithm for tracking identities when
* checking for changes.
*/
set compareWith(fn) {
if (typeof fn !== "function" && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw new RuntimeError(1201, `compareWith must be a function, but received ${JSON.stringify(fn)}`);
}
this._compareWith = fn;
}
_compareWith = Object.is;
/**
* Sets the "value" property on one or of more of the select's options.
* @docs-private
*/
writeValue(value) {
this.value = value;
let optionSelectedStateSetter;
if (Array.isArray(value)) {
const ids = value.map((v) => this._getOptionId(v));
optionSelectedStateSetter = (opt, o) => {
opt._setSelected(ids.indexOf(o.toString()) > -1);
};
} else {
optionSelectedStateSetter = (opt, o) => {
opt._setSelected(false);
};
}
this._optionMap.forEach(optionSelectedStateSetter);
}
/**
* Registers a function called when the control value changes
* and writes an array of the selected options.
* @docs-private
*/
registerOnChange(fn) {
this.onChange = (element) => {
const selected = [];
const selectedOptions = element.selectedOptions;
if (selectedOptions !== void 0) {
const options = selectedOptions;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
const val = this._getOptionValue(opt.value);
selected.push(val);
}
} else {
const options = element.options;
for (let i = 0; i < options.length; i++) {
const opt = options[i];
if (opt.selected) {
const val = this._getOptionValue(opt.value);
selected.push(val);
}
}
}
this.value = selected;
fn(selected);
};
}
/** @internal */
_registerOption(value) {
const id = (this._idCounter++).toString();
this._optionMap.set(id, value);
return id;
}
/** @internal */
_getOptionId(value) {
for (const id of this._optionMap.keys()) {
if (this._compareWith(this._optionMap.get(id)._value, value)) return id;
}
return null;
}
/** @internal */
_getOptionValue(valueString) {
const id = _extractId(valueString);
return this._optionMap.has(id) ? this._optionMap.get(id)._value : valueString;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275SelectMultipleControlValueAccessor_BaseFactory;
return function SelectMultipleControlValueAccessor_Factory(__ngFactoryType__) {
return (\u0275SelectMultipleControlValueAccessor_BaseFactory || (\u0275SelectMultipleControlValueAccessor_BaseFactory = \u0275\u0275getInheritedFactory(_SelectMultipleControlValueAccessor)))(__ngFactoryType__ || _SelectMultipleControlValueAccessor);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _SelectMultipleControlValueAccessor,
selectors: [["select", "multiple", "", "formControlName", ""], ["select", "multiple", "", "formControl", ""], ["select", "multiple", "", "ngModel", ""]],
hostBindings: function SelectMultipleControlValueAccessor_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("change", function SelectMultipleControlValueAccessor_change_HostBindingHandler($event) {
return ctx.onChange($event.target);
})("blur", function SelectMultipleControlValueAccessor_blur_HostBindingHandler() {
return ctx.onTouched();
});
}
},
inputs: {
compareWith: "compareWith"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([SELECT_MULTIPLE_VALUE_ACCESSOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SelectMultipleControlValueAccessor, [{
type: Directive,
args: [{
selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]",
host: {
"(change)": "onChange($event.target)",
"(blur)": "onTouched()"
},
providers: [SELECT_MULTIPLE_VALUE_ACCESSOR],
standalone: false
}]
}], null, {
compareWith: [{
type: Input
}]
});
})();
var \u0275NgSelectMultipleOption = class _\u0275NgSelectMultipleOption {
_element;
_renderer;
_select;
id;
/** @internal */
_value;
constructor(_element, _renderer, _select) {
this._element = _element;
this._renderer = _renderer;
this._select = _select;
if (this._select) {
this.id = this._select._registerOption(this);
}
}
/**
* @description
* Tracks the value bound to the option element. Unlike the value binding,
* ngValue supports binding to objects.
*/
set ngValue(value) {
if (this._select == null) return;
this._value = value;
this._setElementValue(_buildValueString(this.id, value));
this._select.writeValue(this._select.value);
}
/**
* @description
* Tracks simple string values bound to the option element.
* For objects, use the `ngValue` input binding.
*/
set value(value) {
if (this._select) {
this._value = value;
this._setElementValue(_buildValueString(this.id, value));
this._select.writeValue(this._select.value);
} else {
this._setElementValue(value);
}
}
/** @internal */
_setElementValue(value) {
this._renderer.setProperty(this._element.nativeElement, "value", value);
}
/** @internal */
_setSelected(selected) {
this._renderer.setProperty(this._element.nativeElement, "selected", selected);
}
/** @docs-private */
ngOnDestroy() {
if (this._select) {
this._select._optionMap.delete(this.id);
this._select.writeValue(this._select.value);
}
}
static \u0275fac = function \u0275NgSelectMultipleOption_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _\u0275NgSelectMultipleOption)(\u0275\u0275directiveInject(ElementRef), \u0275\u0275directiveInject(Renderer2), \u0275\u0275directiveInject(SelectMultipleControlValueAccessor, 9));
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _\u0275NgSelectMultipleOption,
selectors: [["option"]],
inputs: {
ngValue: "ngValue",
value: "value"
},
standalone: false
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(\u0275NgSelectMultipleOption, [{
type: Directive,
args: [{
selector: "option",
standalone: false
}]
}], () => [{
type: ElementRef
}, {
type: Renderer2
}, {
type: SelectMultipleControlValueAccessor,
decorators: [{
type: Optional
}, {
type: Host
}]
}], {
ngValue: [{
type: Input,
args: ["ngValue"]
}],
value: [{
type: Input,
args: ["value"]
}]
});
})();
function toInteger(value) {
return typeof value === "number" ? value : parseInt(value, 10);
}
function toFloat(value) {
return typeof value === "number" ? value : parseFloat(value);
}
var AbstractValidatorDirective = class _AbstractValidatorDirective {
_validator = nullValidator;
_onChange;
/**
* A flag that tracks whether this validator is enabled.
*
* Marking it `internal` (vs `protected`), so that this flag can be used in host bindings of
* directive classes that extend this base class.
* @internal
*/
_enabled;
/** @docs-private */
ngOnChanges(changes) {
if (this.inputName in changes) {
const input2 = this.normalizeInput(changes[this.inputName].currentValue);
this._enabled = this.enabled(input2);
this._validator = this._enabled ? this.createValidator(input2) : nullValidator;
if (this._onChange) {
this._onChange();
}
}
}
/** @docs-private */
validate(control) {
return this._validator(control);
}
/** @docs-private */
registerOnValidatorChange(fn) {
this._onChange = fn;
}
/**
* @description
* Determines whether this validator should be active or not based on an input.
* Base class implementation checks whether an input is defined (if the value is different from
* `null` and `undefined`). Validator classes that extend this base class can override this
* function with the logic specific to a particular validator directive.
*/
enabled(input2) {
return input2 != null;
}
static \u0275fac = function AbstractValidatorDirective_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AbstractValidatorDirective)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _AbstractValidatorDirective,
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AbstractValidatorDirective, [{
type: Directive
}], null, null);
})();
var MAX_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MaxValidator),
multi: true
};
var MaxValidator = class _MaxValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the max bound to this directive.
*/
max;
/** @internal */
inputName = "max";
/** @internal */
normalizeInput = (input2) => toFloat(input2);
/** @internal */
createValidator = (max) => maxValidator(max);
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MaxValidator_BaseFactory;
return function MaxValidator_Factory(__ngFactoryType__) {
return (\u0275MaxValidator_BaseFactory || (\u0275MaxValidator_BaseFactory = \u0275\u0275getInheritedFactory(_MaxValidator)))(__ngFactoryType__ || _MaxValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MaxValidator,
selectors: [["input", "type", "number", "max", "", "formControlName", ""], ["input", "type", "number", "max", "", "formControl", ""], ["input", "type", "number", "max", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function MaxValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("max", ctx._enabled ? ctx.max : null);
}
},
inputs: {
max: "max"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([MAX_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MaxValidator, [{
type: Directive,
args: [{
selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",
providers: [MAX_VALIDATOR],
host: {
"[attr.max]": "_enabled ? max : null"
},
standalone: false
}]
}], null, {
max: [{
type: Input
}]
});
})();
var MIN_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MinValidator),
multi: true
};
var MinValidator = class _MinValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the min bound to this directive.
*/
min;
/** @internal */
inputName = "min";
/** @internal */
normalizeInput = (input2) => toFloat(input2);
/** @internal */
createValidator = (min) => minValidator(min);
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MinValidator_BaseFactory;
return function MinValidator_Factory(__ngFactoryType__) {
return (\u0275MinValidator_BaseFactory || (\u0275MinValidator_BaseFactory = \u0275\u0275getInheritedFactory(_MinValidator)))(__ngFactoryType__ || _MinValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MinValidator,
selectors: [["input", "type", "number", "min", "", "formControlName", ""], ["input", "type", "number", "min", "", "formControl", ""], ["input", "type", "number", "min", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function MinValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("min", ctx._enabled ? ctx.min : null);
}
},
inputs: {
min: "min"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([MIN_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MinValidator, [{
type: Directive,
args: [{
selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",
providers: [MIN_VALIDATOR],
host: {
"[attr.min]": "_enabled ? min : null"
},
standalone: false
}]
}], null, {
min: [{
type: Input
}]
});
})();
var REQUIRED_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => RequiredValidator),
multi: true
};
var CHECKBOX_REQUIRED_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => CheckboxRequiredValidator),
multi: true
};
var RequiredValidator = class _RequiredValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the required attribute bound to this directive.
*/
required;
/** @internal */
inputName = "required";
/** @internal */
normalizeInput = booleanAttribute;
/** @internal */
createValidator = (input2) => requiredValidator;
/** @docs-private */
enabled(input2) {
return input2;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275RequiredValidator_BaseFactory;
return function RequiredValidator_Factory(__ngFactoryType__) {
return (\u0275RequiredValidator_BaseFactory || (\u0275RequiredValidator_BaseFactory = \u0275\u0275getInheritedFactory(_RequiredValidator)))(__ngFactoryType__ || _RequiredValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _RequiredValidator,
selectors: [["", "required", "", "formControlName", "", 3, "type", "checkbox"], ["", "required", "", "formControl", "", 3, "type", "checkbox"], ["", "required", "", "ngModel", "", 3, "type", "checkbox"]],
hostVars: 1,
hostBindings: function RequiredValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("required", ctx._enabled ? "" : null);
}
},
inputs: {
required: "required"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([REQUIRED_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RequiredValidator, [{
type: Directive,
args: [{
selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",
providers: [REQUIRED_VALIDATOR],
host: {
"[attr.required]": '_enabled ? "" : null'
},
standalone: false
}]
}], null, {
required: [{
type: Input
}]
});
})();
var CheckboxRequiredValidator = class _CheckboxRequiredValidator extends RequiredValidator {
/** @internal */
createValidator = (input2) => requiredTrueValidator;
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275CheckboxRequiredValidator_BaseFactory;
return function CheckboxRequiredValidator_Factory(__ngFactoryType__) {
return (\u0275CheckboxRequiredValidator_BaseFactory || (\u0275CheckboxRequiredValidator_BaseFactory = \u0275\u0275getInheritedFactory(_CheckboxRequiredValidator)))(__ngFactoryType__ || _CheckboxRequiredValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CheckboxRequiredValidator,
selectors: [["input", "type", "checkbox", "required", "", "formControlName", ""], ["input", "type", "checkbox", "required", "", "formControl", ""], ["input", "type", "checkbox", "required", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function CheckboxRequiredValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("required", ctx._enabled ? "" : null);
}
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([CHECKBOX_REQUIRED_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CheckboxRequiredValidator, [{
type: Directive,
args: [{
selector: "input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]",
providers: [CHECKBOX_REQUIRED_VALIDATOR],
host: {
"[attr.required]": '_enabled ? "" : null'
},
standalone: false
}]
}], null, null);
})();
var EMAIL_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => EmailValidator),
multi: true
};
var EmailValidator = class _EmailValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the email attribute bound to this directive.
*/
email;
/** @internal */
inputName = "email";
/** @internal */
normalizeInput = booleanAttribute;
/** @internal */
createValidator = (input2) => emailValidator;
/** @docs-private */
enabled(input2) {
return input2;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275EmailValidator_BaseFactory;
return function EmailValidator_Factory(__ngFactoryType__) {
return (\u0275EmailValidator_BaseFactory || (\u0275EmailValidator_BaseFactory = \u0275\u0275getInheritedFactory(_EmailValidator)))(__ngFactoryType__ || _EmailValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _EmailValidator,
selectors: [["", "email", "", "formControlName", ""], ["", "email", "", "formControl", ""], ["", "email", "", "ngModel", ""]],
inputs: {
email: "email"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([EMAIL_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(EmailValidator, [{
type: Directive,
args: [{
selector: "[email][formControlName],[email][formControl],[email][ngModel]",
providers: [EMAIL_VALIDATOR],
standalone: false
}]
}], null, {
email: [{
type: Input
}]
});
})();
var MIN_LENGTH_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MinLengthValidator),
multi: true
};
var MinLengthValidator = class _MinLengthValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the minimum length bound to this directive.
*/
minlength;
/** @internal */
inputName = "minlength";
/** @internal */
normalizeInput = (input2) => toInteger(input2);
/** @internal */
createValidator = (minlength) => minLengthValidator(minlength);
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MinLengthValidator_BaseFactory;
return function MinLengthValidator_Factory(__ngFactoryType__) {
return (\u0275MinLengthValidator_BaseFactory || (\u0275MinLengthValidator_BaseFactory = \u0275\u0275getInheritedFactory(_MinLengthValidator)))(__ngFactoryType__ || _MinLengthValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MinLengthValidator,
selectors: [["", "minlength", "", "formControlName", ""], ["", "minlength", "", "formControl", ""], ["", "minlength", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function MinLengthValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("minlength", ctx._enabled ? ctx.minlength : null);
}
},
inputs: {
minlength: "minlength"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([MIN_LENGTH_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MinLengthValidator, [{
type: Directive,
args: [{
selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]",
providers: [MIN_LENGTH_VALIDATOR],
host: {
"[attr.minlength]": "_enabled ? minlength : null"
},
standalone: false
}]
}], null, {
minlength: [{
type: Input
}]
});
})();
var MAX_LENGTH_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MaxLengthValidator),
multi: true
};
var MaxLengthValidator = class _MaxLengthValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the maximum length bound to this directive.
*/
maxlength;
/** @internal */
inputName = "maxlength";
/** @internal */
normalizeInput = (input2) => toInteger(input2);
/** @internal */
createValidator = (maxlength) => maxLengthValidator(maxlength);
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MaxLengthValidator_BaseFactory;
return function MaxLengthValidator_Factory(__ngFactoryType__) {
return (\u0275MaxLengthValidator_BaseFactory || (\u0275MaxLengthValidator_BaseFactory = \u0275\u0275getInheritedFactory(_MaxLengthValidator)))(__ngFactoryType__ || _MaxLengthValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MaxLengthValidator,
selectors: [["", "maxlength", "", "formControlName", ""], ["", "maxlength", "", "formControl", ""], ["", "maxlength", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function MaxLengthValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("maxlength", ctx._enabled ? ctx.maxlength : null);
}
},
inputs: {
maxlength: "maxlength"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([MAX_LENGTH_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MaxLengthValidator, [{
type: Directive,
args: [{
selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",
providers: [MAX_LENGTH_VALIDATOR],
host: {
"[attr.maxlength]": "_enabled ? maxlength : null"
},
standalone: false
}]
}], null, {
maxlength: [{
type: Input
}]
});
})();
var PATTERN_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => PatternValidator),
multi: true
};
var PatternValidator = class _PatternValidator extends AbstractValidatorDirective {
/**
* @description
* Tracks changes to the pattern bound to this directive.
*/
pattern;
// This input is always defined, since the name matches selector.
/** @internal */
inputName = "pattern";
/** @internal */
normalizeInput = (input2) => input2;
/** @internal */
createValidator = (input2) => patternValidator(input2);
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275PatternValidator_BaseFactory;
return function PatternValidator_Factory(__ngFactoryType__) {
return (\u0275PatternValidator_BaseFactory || (\u0275PatternValidator_BaseFactory = \u0275\u0275getInheritedFactory(_PatternValidator)))(__ngFactoryType__ || _PatternValidator);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _PatternValidator,
selectors: [["", "pattern", "", "formControlName", ""], ["", "pattern", "", "formControl", ""], ["", "pattern", "", "ngModel", ""]],
hostVars: 1,
hostBindings: function PatternValidator_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("pattern", ctx._enabled ? ctx.pattern : null);
}
},
inputs: {
pattern: "pattern"
},
standalone: false,
features: [\u0275\u0275ProvidersFeature([PATTERN_VALIDATOR]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PatternValidator, [{
type: Directive,
args: [{
selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]",
providers: [PATTERN_VALIDATOR],
host: {
"[attr.pattern]": "_enabled ? pattern : null"
},
standalone: false
}]
}], null, {
pattern: [{
type: Input
}]
});
})();
var SHARED_FORM_DIRECTIVES = [\u0275NgNoValidate, NgSelectOption, \u0275NgSelectMultipleOption, DefaultValueAccessor, NumberValueAccessor, RangeValueAccessor, CheckboxControlValueAccessor, SelectControlValueAccessor, SelectMultipleControlValueAccessor, RadioControlValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, PatternValidator, CheckboxRequiredValidator, EmailValidator, MinValidator, MaxValidator];
var TEMPLATE_DRIVEN_DIRECTIVES = [NgModel, NgModelGroup, NgForm];
var REACTIVE_DRIVEN_DIRECTIVES = [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName];
var \u0275InternalFormsSharedModule = class _\u0275InternalFormsSharedModule {
static \u0275fac = function \u0275InternalFormsSharedModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _\u0275InternalFormsSharedModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _\u0275InternalFormsSharedModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(\u0275InternalFormsSharedModule, [{
type: NgModule,
args: [{
declarations: SHARED_FORM_DIRECTIVES,
exports: SHARED_FORM_DIRECTIVES
}]
}], null, null);
})();
var FormArray = class extends AbstractControl {
/**
* Creates a new `FormArray` instance.
*
* @param controls An array of child controls. Each child control is given an index
* where it is registered.
*
* @param validatorOrOpts A synchronous validator function, or an array of
* such functions, or an `AbstractControlOptions` object that contains validation functions
* and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator functions
*
*/
constructor(controls, validatorOrOpts, asyncValidator) {
super(pickValidators(validatorOrOpts), pickAsyncValidators(asyncValidator, validatorOrOpts));
this.controls = controls;
this._initObservables();
this._setUpdateStrategy(validatorOrOpts);
this._setUpControls();
this.updateValueAndValidity({
onlySelf: true,
// If `asyncValidator` is present, it will trigger control status change from `PENDING` to
// `VALID` or `INVALID`.
// The status should be broadcasted via the `statusChanges` observable, so we set `emitEvent`
// to `true` to allow that during the control creation process.
emitEvent: !!this.asyncValidator
});
}
controls;
/**
* Get the `AbstractControl` at the given `index` in the array.
*
* @param index Index in the array to retrieve the control. If `index` is negative, it will wrap
* around from the back, and if index is greatly negative (less than `-length`), the result is
* undefined. This behavior is the same as `Array.at(index)`.
*/
at(index) {
return this.controls[this._adjustIndex(index)];
}
/**
* Insert a new `AbstractControl` at the end of the array.
*
* @param control Form control to be inserted
* @param options Specifies whether this FormArray instance should emit events after a new
* control is added.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control is
* inserted. When false, no events are emitted.
*/
push(control, options = {}) {
this.controls.push(control);
this._registerControl(control);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
this._onCollectionChange();
}
/**
* Insert a new `AbstractControl` at the given `index` in the array.
*
* @param index Index in the array to insert the control. If `index` is negative, wraps around
* from the back. If `index` is greatly negative (less than `-length`), prepends to the array.
* This behavior is the same as `Array.splice(index, 0, control)`.
* @param control Form control to be inserted
* @param options Specifies whether this FormArray instance should emit events after a new
* control is inserted.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control is
* inserted. When false, no events are emitted.
*/
insert(index, control, options = {}) {
this.controls.splice(index, 0, control);
this._registerControl(control);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
}
/**
* Remove the control at the given `index` in the array.
*
* @param index Index in the array to remove the control. If `index` is negative, wraps around
* from the back. If `index` is greatly negative (less than `-length`), removes the first
* element. This behavior is the same as `Array.splice(index, 1)`.
* @param options Specifies whether this FormArray instance should emit events after a
* control is removed.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control is
* removed. When false, no events are emitted.
*/
removeAt(index, options = {}) {
let adjustedIndex = this._adjustIndex(index);
if (adjustedIndex < 0) adjustedIndex = 0;
if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {
});
this.controls.splice(adjustedIndex, 1);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
}
/**
* Replace an existing control.
*
* @param index Index in the array to replace the control. If `index` is negative, wraps around
* from the back. If `index` is greatly negative (less than `-length`), replaces the first
* element. This behavior is the same as `Array.splice(index, 1, control)`.
* @param control The `AbstractControl` control to replace the existing control
* @param options Specifies whether this FormArray instance should emit events after an
* existing control is replaced with a new one.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control is
* replaced with a new one. When false, no events are emitted.
*/
setControl(index, control, options = {}) {
let adjustedIndex = this._adjustIndex(index);
if (adjustedIndex < 0) adjustedIndex = 0;
if (this.controls[adjustedIndex]) this.controls[adjustedIndex]._registerOnCollectionChange(() => {
});
this.controls.splice(adjustedIndex, 1);
if (control) {
this.controls.splice(adjustedIndex, 0, control);
this._registerControl(control);
}
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
this._onCollectionChange();
}
/**
* Length of the control array.
*/
get length() {
return this.controls.length;
}
/**
* Sets the value of the `FormArray`. It accepts an array that matches
* the structure of the control.
*
* This method performs strict checks, and throws an error if you try
* to set the value of a control that doesn't exist or if you exclude the
* value of a control.
*
* @usageNotes
* ### Set the values for the controls in the form array
*
* ```ts
* const arr = new FormArray([
* new FormControl(),
* new FormControl()
* ]);
* console.log(arr.value); // [null, null]
*
* arr.setValue(['Nancy', 'Drew']);
* console.log(arr.value); // ['Nancy', 'Drew']
* ```
*
* @param value Array of values for the controls
* @param options Configure options that determine how the control propagates changes and
* emits events after the value changes
*
* * `onlySelf`: When true, each change only affects this control, and not its parent. Default
* is false.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges`
* observables emit events with the latest status and value when the control value is updated.
* When false, no events are emitted.
* The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
* updateValueAndValidity} method.
*/
setValue(value, options = {}) {
assertAllValuesPresent(this, false, value);
value.forEach((newValue, index) => {
assertControlPresent(this, false, index);
this.at(index).setValue(newValue, {
onlySelf: true,
emitEvent: options.emitEvent
});
});
this.updateValueAndValidity(options);
}
/**
* Patches the value of the `FormArray`. It accepts an array that matches the
* structure of the control, and does its best to match the values to the correct
* controls in the group.
*
* It accepts both super-sets and sub-sets of the array without throwing an error.
*
* @usageNotes
* ### Patch the values for controls in a form array
*
* ```ts
* const arr = new FormArray([
* new FormControl(),
* new FormControl()
* ]);
* console.log(arr.value); // [null, null]
*
* arr.patchValue(['Nancy']);
* console.log(arr.value); // ['Nancy', null]
* ```
*
* @param value Array of latest values for the controls
* @param options Configure options that determine how the control propagates changes and
* emits events after the value changes
*
* * `onlySelf`: When true, each change only affects this control, and not its parent. Default
* is false.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when the control
* value is updated. When false, no events are emitted. The configuration options are passed to
* the {@link AbstractControl#updateValueAndValidity updateValueAndValidity} method.
*/
patchValue(value, options = {}) {
if (value == null) return;
value.forEach((newValue, index) => {
if (this.at(index)) {
this.at(index).patchValue(newValue, {
onlySelf: true,
emitEvent: options.emitEvent
});
}
});
this.updateValueAndValidity(options);
}
/**
* Resets the `FormArray` and all descendants are marked `pristine` and `untouched`, and the
* value of all descendants to null or null maps.
*
* You reset to a specific form state by passing in an array of states
* that matches the structure of the control. The state is a standalone value
* or a form state object with both a value and a disabled status.
*
* @usageNotes
* ### Reset the values in a form array
*
* ```ts
* const arr = new FormArray([
* new FormControl(),
* new FormControl()
* ]);
* arr.reset(['name', 'last name']);
*
* console.log(arr.value); // ['name', 'last name']
* ```
*
* ### Reset the values in a form array and the disabled status for the first control
*
* ```ts
* arr.reset([
* {value: 'name', disabled: true},
* 'last'
* ]);
*
* console.log(arr.value); // ['last']
* console.log(arr.at(0).status); // 'DISABLED'
* ```
*
* @param value Array of values for the controls
* @param options Configure options that determine how the control propagates changes and
* emits events after the value changes
*
* * `onlySelf`: When true, each change only affects this control, and not its parent. Default
* is false.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges`
* observables emit events with the latest status and value when the control is reset.
* When false, no events are emitted.
* The configuration options are passed to the {@link AbstractControl#updateValueAndValidity
* updateValueAndValidity} method.
*/
reset(value = [], options = {}) {
this._forEachChild((control, index) => {
control.reset(value[index], {
onlySelf: true,
emitEvent: options.emitEvent
});
});
this._updatePristine(options, this);
this._updateTouched(options, this);
this.updateValueAndValidity(options);
}
/**
* The aggregate value of the array, including any disabled controls.
*
* Reports all values regardless of disabled status.
*/
getRawValue() {
return this.controls.map((control) => control.getRawValue());
}
/**
* Remove all controls in the `FormArray`.
*
* @param options Specifies whether this FormArray instance should emit events after all
* controls are removed.
* * `emitEvent`: When true or not supplied (the default), both the `statusChanges` and
* `valueChanges` observables emit events with the latest status and value when all controls
* in this FormArray instance are removed. When false, no events are emitted.
*
* @usageNotes
* ### Remove all elements from a FormArray
*
* ```ts
* const arr = new FormArray([
* new FormControl(),
* new FormControl()
* ]);
* console.log(arr.length); // 2
*
* arr.clear();
* console.log(arr.length); // 0
* ```
*
* It's a simpler and more efficient alternative to removing all elements one by one:
*
* ```ts
* const arr = new FormArray([
* new FormControl(),
* new FormControl()
* ]);
*
* while (arr.length) {
* arr.removeAt(0);
* }
* ```
*/
clear(options = {}) {
if (this.controls.length < 1) return;
this._forEachChild((control) => control._registerOnCollectionChange(() => {
}));
this.controls.splice(0);
this.updateValueAndValidity({
emitEvent: options.emitEvent
});
}
/**
* Adjusts a negative index by summing it with the length of the array. For very negative
* indices, the result may remain negative.
* @internal
*/
_adjustIndex(index) {
return index < 0 ? index + this.length : index;
}
/** @internal */
_syncPendingControls() {
let subtreeUpdated = this.controls.reduce((updated, child) => {
return child._syncPendingControls() ? true : updated;
}, false);
if (subtreeUpdated) this.updateValueAndValidity({
onlySelf: true
});
return subtreeUpdated;
}
/** @internal */
_forEachChild(cb) {
this.controls.forEach((control, index) => {
cb(control, index);
});
}
/** @internal */
_updateValue() {
this.value = this.controls.filter((control) => control.enabled || this.disabled).map((control) => control.value);
}
/** @internal */
_anyControls(condition) {
return this.controls.some((control) => control.enabled && condition(control));
}
/** @internal */
_setUpControls() {
this._forEachChild((control) => this._registerControl(control));
}
/** @internal */
_allControlsDisabled() {
for (const control of this.controls) {
if (control.enabled) return false;
}
return this.controls.length > 0 || this.disabled;
}
_registerControl(control) {
control.setParent(this);
control._registerOnCollectionChange(this._onCollectionChange);
}
/** @internal */
_find(name) {
return this.at(name) ?? null;
}
};
function isAbstractControlOptions(options) {
return !!options && (options.asyncValidators !== void 0 || options.validators !== void 0 || options.updateOn !== void 0);
}
var FormBuilder = class _FormBuilder {
useNonNullable = false;
/**
* @description
* Returns a FormBuilder in which automatically constructed `FormControl` elements
* have `{nonNullable: true}` and are non-nullable.
*
* **Constructing non-nullable controls**
*
* When constructing a control, it will be non-nullable, and will reset to its initial value.
*
* ```ts
* let nnfb = new FormBuilder().nonNullable;
* let name = nnfb.control('Alex'); // FormControl<string>
* name.reset();
* console.log(name); // 'Alex'
* ```
*
* **Constructing non-nullable groups or arrays**
*
* When constructing a group or array, all automatically created inner controls will be
* non-nullable, and will reset to their initial values.
*
* ```ts
* let nnfb = new FormBuilder().nonNullable;
* let name = nnfb.group({who: 'Alex'}); // FormGroup<{who: FormControl<string>}>
* name.reset();
* console.log(name); // {who: 'Alex'}
* ```
* **Constructing *nullable* fields on groups or arrays**
*
* It is still possible to have a nullable field. In particular, any `FormControl` which is
* *already* constructed will not be altered. For example:
*
* ```ts
* let nnfb = new FormBuilder().nonNullable;
* // FormGroup<{who: FormControl<string|null>}>
* let name = nnfb.group({who: new FormControl('Alex')});
* name.reset(); console.log(name); // {who: null}
* ```
*
* Because the inner control is constructed explicitly by the caller, the builder has
* no control over how it is created, and cannot exclude the `null`.
*/
get nonNullable() {
const nnfb = new _FormBuilder();
nnfb.useNonNullable = true;
return nnfb;
}
group(controls, options = null) {
const reducedControls = this._reduceControls(controls);
let newOptions = {};
if (isAbstractControlOptions(options)) {
newOptions = options;
} else if (options !== null) {
newOptions.validators = options.validator;
newOptions.asyncValidators = options.asyncValidator;
}
return new FormGroup(reducedControls, newOptions);
}
/**
* @description
* Constructs a new `FormRecord` instance. Accepts a single generic argument, which is an object
* containing all the keys and corresponding inner control types.
*
* @param controls A collection of child controls. The key for each child is the name
* under which it is registered.
*
* @param options Configuration options object for the `FormRecord`. The object should have the
* `AbstractControlOptions` type and might contain the following fields:
* * `validators`: A synchronous validator function, or an array of validator functions.
* * `asyncValidators`: A single async validator or array of async validator functions.
* * `updateOn`: The event upon which the control should be updated (options: 'change' | 'blur'
* | submit').
*/
record(controls, options = null) {
const reducedControls = this._reduceControls(controls);
return new FormRecord(reducedControls, options);
}
/**
* @description
* Constructs a new `FormControl` with the given state, validators and options. Sets
* `{nonNullable: true}` in the options to get a non-nullable control. Otherwise, the
* control will be nullable. Accepts a single generic argument, which is the type of the
* control's value.
*
* @param formState Initializes the control with an initial state value, or
* with an object that contains both a value and a disabled status.
*
* @param validatorOrOpts A synchronous validator function, or an array of
* such functions, or a `FormControlOptions` object that contains
* validation functions and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator
* functions.
*
* @usageNotes
*
* ### Initialize a control as disabled
*
* The following example returns a control with an initial value in a disabled state.
*
* {@example forms/ts/formBuilder/form_builder_example.ts region='disabled-control'}
*/
control(formState, validatorOrOpts, asyncValidator) {
let newOptions = {};
if (!this.useNonNullable) {
return new FormControl(formState, validatorOrOpts, asyncValidator);
}
if (isAbstractControlOptions(validatorOrOpts)) {
newOptions = validatorOrOpts;
} else {
newOptions.validators = validatorOrOpts;
newOptions.asyncValidators = asyncValidator;
}
return new FormControl(formState, __spreadProps(__spreadValues({}, newOptions), {
nonNullable: true
}));
}
/**
* Constructs a new `FormArray` from the given array of configurations,
* validators and options. Accepts a single generic argument, which is the type of each control
* inside the array.
*
* @param controls An array of child controls or control configs. Each child control is given an
* index when it is registered.
*
* @param validatorOrOpts A synchronous validator function, or an array of such functions, or an
* `AbstractControlOptions` object that contains
* validation functions and a validation trigger.
*
* @param asyncValidator A single async validator or array of async validator functions.
*/
array(controls, validatorOrOpts, asyncValidator) {
const createdControls = controls.map((c) => this._createControl(c));
return new FormArray(createdControls, validatorOrOpts, asyncValidator);
}
/** @internal */
_reduceControls(controls) {
const createdControls = {};
Object.keys(controls).forEach((controlName) => {
createdControls[controlName] = this._createControl(controls[controlName]);
});
return createdControls;
}
/** @internal */
_createControl(controls) {
if (controls instanceof FormControl) {
return controls;
} else if (controls instanceof AbstractControl) {
return controls;
} else if (Array.isArray(controls)) {
const value = controls[0];
const validator = controls.length > 1 ? controls[1] : null;
const asyncValidator = controls.length > 2 ? controls[2] : null;
return this.control(value, validator, asyncValidator);
} else {
return this.control(controls);
}
}
static \u0275fac = function FormBuilder_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormBuilder)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FormBuilder,
factory: _FormBuilder.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormBuilder, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var NonNullableFormBuilder = class _NonNullableFormBuilder {
static \u0275fac = function NonNullableFormBuilder_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _NonNullableFormBuilder)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _NonNullableFormBuilder,
factory: () => (() => inject(FormBuilder).nonNullable)(),
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NonNullableFormBuilder, [{
type: Injectable,
args: [{
providedIn: "root",
useFactory: () => inject(FormBuilder).nonNullable
}]
}], null, null);
})();
var UntypedFormBuilder = class _UntypedFormBuilder extends FormBuilder {
group(controlsConfig, options = null) {
return super.group(controlsConfig, options);
}
/**
* Like `FormBuilder#control`, except the resulting control is untyped.
*/
control(formState, validatorOrOpts, asyncValidator) {
return super.control(formState, validatorOrOpts, asyncValidator);
}
/**
* Like `FormBuilder#array`, except the resulting array is untyped.
*/
array(controlsConfig, validatorOrOpts, asyncValidator) {
return super.array(controlsConfig, validatorOrOpts, asyncValidator);
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275UntypedFormBuilder_BaseFactory;
return function UntypedFormBuilder_Factory(__ngFactoryType__) {
return (\u0275UntypedFormBuilder_BaseFactory || (\u0275UntypedFormBuilder_BaseFactory = \u0275\u0275getInheritedFactory(_UntypedFormBuilder)))(__ngFactoryType__ || _UntypedFormBuilder);
};
})();
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _UntypedFormBuilder,
factory: _UntypedFormBuilder.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(UntypedFormBuilder, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var VERSION5 = new Version("19.2.11");
var FormsModule = class _FormsModule {
/**
* @description
* Provides options for configuring the forms module.
*
* @param opts An object of configuration options
* * `callSetDisabledState` Configures whether to `always` call `setDisabledState`, which is more
* correct, or to only call it `whenDisabled`, which is the legacy behavior.
*/
static withConfig(opts) {
return {
ngModule: _FormsModule,
providers: [{
provide: CALL_SET_DISABLED_STATE,
useValue: opts.callSetDisabledState ?? setDisabledStateDefault
}]
};
}
static \u0275fac = function FormsModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FormsModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _FormsModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [\u0275InternalFormsSharedModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FormsModule, [{
type: NgModule,
args: [{
declarations: TEMPLATE_DRIVEN_DIRECTIVES,
exports: [\u0275InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
}]
}], null, null);
})();
var ReactiveFormsModule = class _ReactiveFormsModule {
/**
* @description
* Provides options for configuring the reactive forms module.
*
* @param opts An object of configuration options
* * `warnOnNgModelWithFormControl` Configures when to emit a warning when an `ngModel`
* binding is used with reactive form directives.
* * `callSetDisabledState` Configures whether to `always` call `setDisabledState`, which is more
* correct, or to only call it `whenDisabled`, which is the legacy behavior.
*/
static withConfig(opts) {
return {
ngModule: _ReactiveFormsModule,
providers: [{
provide: NG_MODEL_WITH_FORM_CONTROL_WARNING,
useValue: opts.warnOnNgModelWithFormControl ?? "always"
}, {
provide: CALL_SET_DISABLED_STATE,
useValue: opts.callSetDisabledState ?? setDisabledStateDefault
}]
};
}
static \u0275fac = function ReactiveFormsModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ReactiveFormsModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _ReactiveFormsModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [\u0275InternalFormsSharedModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ReactiveFormsModule, [{
type: NgModule,
args: [{
declarations: [REACTIVE_DRIVEN_DIRECTIVES],
exports: [\u0275InternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES]
}]
}], null, null);
})();
// src/app/components/tutorials-list/tutorials-list.component.ts
function TutorialsListComponent_li_11_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "li", 11);
\u0275\u0275listener("click", function TutorialsListComponent_li_11_Template_li_click_0_listener() {
const ctx_r1 = \u0275\u0275restoreView(_r1);
const tutorial_r3 = ctx_r1.$implicit;
const i_r4 = ctx_r1.index;
const ctx_r4 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r4.setActiveTutorial(tutorial_r3, i_r4));
});
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const tutorial_r3 = ctx.$implicit;
const i_r4 = ctx.index;
const ctx_r4 = \u0275\u0275nextContext();
\u0275\u0275classProp("active", i_r4 == ctx_r4.currentIndex);
\u0275\u0275advance();
\u0275\u0275textInterpolate1(" ", tutorial_r3.title, " ");
}
}
function TutorialsListComponent_div_15_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div")(1, "h4");
\u0275\u0275text(2, "Tutorial");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(3, "div")(4, "label")(5, "strong");
\u0275\u0275text(6, "Title:");
\u0275\u0275elementEnd()();
\u0275\u0275text(7);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(8, "div")(9, "label")(10, "strong");
\u0275\u0275text(11, "Description:");
\u0275\u0275elementEnd()();
\u0275\u0275text(12);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(13, "div")(14, "label")(15, "strong");
\u0275\u0275text(16, "Status:");
\u0275\u0275elementEnd()();
\u0275\u0275text(17);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(18, "a", 12);
\u0275\u0275text(19, " Edit ");
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const ctx_r4 = \u0275\u0275nextContext();
\u0275\u0275advance(7);
\u0275\u0275textInterpolate1(" ", ctx_r4.currentTutorial.title, " ");
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1(" ", ctx_r4.currentTutorial.description, " ");
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1(" ", ctx_r4.currentTutorial.published ? "Published" : "Pending", " ");
\u0275\u0275advance();
\u0275\u0275propertyInterpolate1("routerLink", "/tutorials/", ctx_r4.currentTutorial.id, "");
}
}
function TutorialsListComponent_div_16_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275element(1, "br");
\u0275\u0275elementStart(2, "p");
\u0275\u0275text(3, "Please click on a Tutorial...");
\u0275\u0275elementEnd()();
}
}
var TutorialsListComponent = class _TutorialsListComponent {
tutorialService;
tutorials;
currentTutorial = {};
currentIndex = -1;
title = "";
constructor(tutorialService) {
this.tutorialService = tutorialService;
}
ngOnInit() {
this.retrieveTutorials();
}
retrieveTutorials() {
this.tutorialService.getAll().subscribe((data) => {
this.tutorials = data;
console.log(data);
}, (error) => {
console.log(error);
});
}
refreshList() {
this.retrieveTutorials();
this.currentTutorial = {};
this.currentIndex = -1;
}
setActiveTutorial(tutorial, index) {
this.currentTutorial = tutorial;
this.currentIndex = index;
}
removeAllTutorials() {
this.tutorialService.deleteAll().subscribe((response) => {
console.log(response);
this.refreshList();
}, (error) => {
console.log(error);
});
}
searchTitle() {
this.currentTutorial = {};
this.currentIndex = -1;
this.tutorialService.findByTitle(this.title).subscribe((data) => {
this.tutorials = data;
console.log(data);
}, (error) => {
console.log(error);
});
}
static \u0275fac = function TutorialsListComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TutorialsListComponent)(\u0275\u0275directiveInject(TutorialService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _TutorialsListComponent, selectors: [["app-tutorials-list"]], standalone: false, decls: 17, vars: 4, consts: [[1, "list", "row"], [1, "col-md-8"], [1, "input-group", "mb-3"], ["type", "text", "placeholder", "Search by title", 1, "form-control", 3, "ngModelChange", "ngModel"], [1, "input-group-append"], ["type", "button", 1, "btn", "btn-outline-secondary", 3, "click"], [1, "col-md-6"], [1, "list-group"], ["class", "list-group-item", 3, "active", "click", 4, "ngFor", "ngForOf"], [1, "m-3", "btn", "btn-sm", "btn-danger", 3, "click"], [4, "ngIf"], [1, "list-group-item", 3, "click"], [1, "badge", "badge-warning", 3, "routerLink"]], template: function TutorialsListComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "input", 3);
\u0275\u0275twoWayListener("ngModelChange", function TutorialsListComponent_Template_input_ngModelChange_3_listener($event) {
\u0275\u0275twoWayBindingSet(ctx.title, $event) || (ctx.title = $event);
return $event;
});
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "div", 4)(5, "button", 5);
\u0275\u0275listener("click", function TutorialsListComponent_Template_button_click_5_listener() {
return ctx.searchTitle();
});
\u0275\u0275text(6, " Search ");
\u0275\u0275elementEnd()()()();
\u0275\u0275elementStart(7, "div", 6)(8, "h4");
\u0275\u0275text(9, "Tutorials List");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(10, "ul", 7);
\u0275\u0275template(11, TutorialsListComponent_li_11_Template, 2, 3, "li", 8);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(12, "button", 9);
\u0275\u0275listener("click", function TutorialsListComponent_Template_button_click_12_listener() {
return ctx.removeAllTutorials();
});
\u0275\u0275text(13, " Remove All ");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(14, "div", 6);
\u0275\u0275template(15, TutorialsListComponent_div_15_Template, 20, 5, "div", 10)(16, TutorialsListComponent_div_16_Template, 4, 0, "div", 10);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(3);
\u0275\u0275twoWayProperty("ngModel", ctx.title);
\u0275\u0275advance(8);
\u0275\u0275property("ngForOf", ctx.tutorials);
\u0275\u0275advance(4);
\u0275\u0275property("ngIf", ctx.currentTutorial.id);
\u0275\u0275advance();
\u0275\u0275property("ngIf", !ctx.currentTutorial);
}
}, dependencies: [NgForOf, NgIf, RouterLink, DefaultValueAccessor, NgControlStatus, NgModel], styles: ["\n\n.list[_ngcontent-%COMP%] {\n text-align: left;\n max-width: 750px;\n margin: auto;\n}\n/*# sourceMappingURL=tutorials-list.component.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TutorialsListComponent, [{
type: Component,
args: [{ selector: "app-tutorials-list", standalone: false, template: '<div class="list row">\r\n <div class="col-md-8">\r\n <div class="input-group mb-3">\r\n <input\r\n type="text"\r\n class="form-control"\r\n placeholder="Search by title"\r\n [(ngModel)]="title"\r\n />\r\n <div class="input-group-append">\r\n <button\r\n class="btn btn-outline-secondary"\r\n type="button"\r\n (click)="searchTitle()"\r\n >\r\n Search\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div class="col-md-6">\r\n <h4>Tutorials List</h4>\r\n <ul class="list-group">\r\n <li\r\n class="list-group-item"\r\n *ngFor="let tutorial of tutorials; let i = index"\r\n [class.active]="i == currentIndex"\r\n (click)="setActiveTutorial(tutorial, i)"\r\n >\r\n {{ tutorial.title }}\r\n </li>\r\n </ul>\r\n\r\n <button class="m-3 btn btn-sm btn-danger" (click)="removeAllTutorials()">\r\n Remove All\r\n </button>\r\n </div>\r\n <div class="col-md-6">\r\n <div *ngIf="currentTutorial.id">\r\n <h4>Tutorial</h4>\r\n <div>\r\n <label><strong>Title:</strong></label> {{ currentTutorial.title }}\r\n </div>\r\n <div>\r\n <label><strong>Description:</strong></label>\r\n {{ currentTutorial.description }}\r\n </div>\r\n <div>\r\n <label><strong>Status:</strong></label>\r\n {{ currentTutorial.published ? "Published" : "Pending" }}\r\n </div>\r\n\r\n <a class="badge badge-warning" routerLink="/tutorials/{{ currentTutorial.id }}">\r\n Edit\r\n </a>\r\n </div>\r\n\r\n <div *ngIf="!currentTutorial">\r\n <br />\r\n <p>Please click on a Tutorial...</p>\r\n </div>\r\n </div>\r\n</div>', styles: ["/* src/app/components/tutorials-list/tutorials-list.component.scss */\n.list {\n text-align: left;\n max-width: 750px;\n margin: auto;\n}\n/*# sourceMappingURL=tutorials-list.component.css.map */\n"] }]
}], () => [{ type: TutorialService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(TutorialsListComponent, { className: "TutorialsListComponent", filePath: "src/app/components/tutorials-list/tutorials-list.component.ts", lineNumber: 11 });
})();
// src/app/components/tutorial-details/tutorial-details.component.ts
function TutorialDetailsComponent_div_1_button_17_Template(rf, ctx) {
if (rf & 1) {
const _r3 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 11);
\u0275\u0275listener("click", function TutorialDetailsComponent_div_1_button_17_Template_button_click_0_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.updatePublished(false));
});
\u0275\u0275text(1, " UnPublish ");
\u0275\u0275elementEnd();
}
}
function TutorialDetailsComponent_div_1_button_18_Template(rf, ctx) {
if (rf & 1) {
const _r4 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 11);
\u0275\u0275listener("click", function TutorialDetailsComponent_div_1_button_18_Template_button_click_0_listener() {
\u0275\u0275restoreView(_r4);
const ctx_r1 = \u0275\u0275nextContext(2);
return \u0275\u0275resetView(ctx_r1.updatePublished(true));
});
\u0275\u0275text(1, " Publish ");
\u0275\u0275elementEnd();
}
}
function TutorialDetailsComponent_div_1_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div", 2)(1, "h4");
\u0275\u0275text(2, "Tutorial");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(3, "form")(4, "div", 3)(5, "label", 4);
\u0275\u0275text(6, "Title");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(7, "input", 5);
\u0275\u0275twoWayListener("ngModelChange", function TutorialDetailsComponent_div_1_Template_input_ngModelChange_7_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r1.currentTutorial.title, $event) || (ctx_r1.currentTutorial.title = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(8, "div", 3)(9, "label", 6);
\u0275\u0275text(10, "Description");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(11, "input", 7);
\u0275\u0275twoWayListener("ngModelChange", function TutorialDetailsComponent_div_1_Template_input_ngModelChange_11_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r1.currentTutorial.description, $event) || (ctx_r1.currentTutorial.description = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(12, "div", 3)(13, "label")(14, "strong");
\u0275\u0275text(15, "Status:");
\u0275\u0275elementEnd()();
\u0275\u0275text(16);
\u0275\u0275elementEnd()();
\u0275\u0275template(17, TutorialDetailsComponent_div_1_button_17_Template, 2, 0, "button", 8)(18, TutorialDetailsComponent_div_1_button_18_Template, 2, 0, "button", 8);
\u0275\u0275elementStart(19, "button", 9);
\u0275\u0275listener("click", function TutorialDetailsComponent_div_1_Template_button_click_19_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.deleteTutorial());
});
\u0275\u0275text(20, " Delete ");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(21, "button", 10);
\u0275\u0275listener("click", function TutorialDetailsComponent_div_1_Template_button_click_21_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.updateTutorial());
});
\u0275\u0275text(22, " Update ");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(23, "p");
\u0275\u0275text(24);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275advance(7);
\u0275\u0275twoWayProperty("ngModel", ctx_r1.currentTutorial.title);
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r1.currentTutorial.description);
\u0275\u0275advance(5);
\u0275\u0275textInterpolate1(" ", ctx_r1.currentTutorial.published ? "Published" : "Pending", " ");
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx_r1.currentTutorial.published);
\u0275\u0275advance();
\u0275\u0275property("ngIf", !ctx_r1.currentTutorial.published);
\u0275\u0275advance(6);
\u0275\u0275textInterpolate(ctx_r1.message);
}
}
function TutorialDetailsComponent_div_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275element(1, "br");
\u0275\u0275elementStart(2, "p");
\u0275\u0275text(3, "Cannot access this Tutorial...");
\u0275\u0275elementEnd()();
}
}
var TutorialDetailsComponent = class _TutorialDetailsComponent {
tutorialService;
route;
router;
currentTutorial = {
title: "",
description: "",
published: false
};
message = "";
constructor(tutorialService, route, router) {
this.tutorialService = tutorialService;
this.route = route;
this.router = router;
}
ngOnInit() {
this.message = "";
this.getTutorial(this.route.snapshot.params.id);
}
getTutorial(id) {
this.tutorialService.get(id).subscribe((data) => {
this.currentTutorial = data;
console.log(data);
}, (error) => {
console.log(error);
});
}
updatePublished(status) {
const data = {
title: this.currentTutorial.title,
description: this.currentTutorial.description,
published: status
};
this.message = "";
this.tutorialService.update(this.currentTutorial.id, data).subscribe((response) => {
this.currentTutorial.published = status;
console.log(response);
this.message = response.message ? response.message : "The status was updated successfully!";
}, (error) => {
console.log(error);
});
}
updateTutorial() {
this.message = "";
this.tutorialService.update(this.currentTutorial.id, this.currentTutorial).subscribe((response) => {
console.log(response);
this.message = response.message ? response.message : "This tutorial was updated successfully!";
}, (error) => {
console.log(error);
});
}
deleteTutorial() {
this.tutorialService.delete(this.currentTutorial.id).subscribe((response) => {
console.log(response);
this.router.navigate(["/tutorials"]);
}, (error) => {
console.log(error);
});
}
static \u0275fac = function TutorialDetailsComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TutorialDetailsComponent)(\u0275\u0275directiveInject(TutorialService), \u0275\u0275directiveInject(ActivatedRoute), \u0275\u0275directiveInject(Router));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _TutorialDetailsComponent, selectors: [["app-tutorial-details"]], standalone: false, decls: 3, vars: 2, consts: [["class", "edit-form", 4, "ngIf"], [4, "ngIf"], [1, "edit-form"], [1, "form-group"], ["for", "title"], ["type", "text", "id", "title", "name", "title", 1, "form-control", 3, "ngModelChange", "ngModel"], ["for", "description"], ["type", "text", "id", "description", "name", "description", 1, "form-control", 3, "ngModelChange", "ngModel"], ["class", "badge badge-primary mr-2", 3, "click", 4, "ngIf"], [1, "badge", "badge-danger", "mr-2", 3, "click"], ["type", "submit", 1, "badge", "badge-success", "mb-2", 3, "click"], [1, "badge", "badge-primary", "mr-2", 3, "click"]], template: function TutorialDetailsComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275template(1, TutorialDetailsComponent_div_1_Template, 25, 6, "div", 0)(2, TutorialDetailsComponent_div_2_Template, 4, 0, "div", 1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.currentTutorial.id);
\u0275\u0275advance();
\u0275\u0275property("ngIf", !ctx.currentTutorial.id);
}
}, dependencies: [NgIf, \u0275NgNoValidate, DefaultValueAccessor, NgControlStatus, NgControlStatusGroup, NgModel, NgForm], styles: ["\n\n.edit-form[_ngcontent-%COMP%] {\n max-width: 400px;\n margin: auto;\n}\n/*# sourceMappingURL=tutorial-details.component.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TutorialDetailsComponent, [{
type: Component,
args: [{ selector: "app-tutorial-details", standalone: false, template: '<div>\r\n <div *ngIf="currentTutorial.id" class="edit-form">\r\n <h4>Tutorial</h4>\r\n <form>\r\n <div class="form-group">\r\n <label for="title">Title</label>\r\n <input\r\n type="text"\r\n class="form-control"\r\n id="title"\r\n [(ngModel)]="currentTutorial.title"\r\n name="title"\r\n />\r\n </div>\r\n <div class="form-group">\r\n <label for="description">Description</label>\r\n <input\r\n type="text"\r\n class="form-control"\r\n id="description"\r\n [(ngModel)]="currentTutorial.description"\r\n name="description"\r\n />\r\n </div>\r\n\r\n <div class="form-group">\r\n <label><strong>Status:</strong></label>\r\n {{ currentTutorial.published ? "Published" : "Pending" }}\r\n </div>\r\n </form>\r\n\r\n <button\r\n class="badge badge-primary mr-2"\r\n *ngIf="currentTutorial.published"\r\n (click)="updatePublished(false)"\r\n >\r\n UnPublish\r\n </button>\r\n <button\r\n *ngIf="!currentTutorial.published"\r\n class="badge badge-primary mr-2"\r\n (click)="updatePublished(true)"\r\n >\r\n Publish\r\n </button>\r\n\r\n <button class="badge badge-danger mr-2" (click)="deleteTutorial()">\r\n Delete\r\n </button>\r\n\r\n <button\r\n type="submit"\r\n class="badge badge-success mb-2"\r\n (click)="updateTutorial()"\r\n >\r\n Update\r\n </button>\r\n <p>{{ message }}</p>\r\n </div>\r\n\r\n <div *ngIf="!currentTutorial.id">\r\n <br />\r\n <p>Cannot access this Tutorial...</p>\r\n </div>\r\n</div>', styles: ["/* src/app/components/tutorial-details/tutorial-details.component.scss */\n.edit-form {\n max-width: 400px;\n margin: auto;\n}\n/*# sourceMappingURL=tutorial-details.component.css.map */\n"] }]
}], () => [{ type: TutorialService }, { type: ActivatedRoute }, { type: Router }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(TutorialDetailsComponent, { className: "TutorialDetailsComponent", filePath: "src/app/components/tutorial-details/tutorial-details.component.ts", lineNumber: 12 });
})();
// src/app/components/add-tutorial/add-tutorial.component.ts
function AddTutorialComponent_div_2_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div")(1, "div", 2)(2, "label", 3);
\u0275\u0275text(3, "Title");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "input", 4);
\u0275\u0275twoWayListener("ngModelChange", function AddTutorialComponent_div_2_Template_input_ngModelChange_4_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r1.tutorial.title, $event) || (ctx_r1.tutorial.title = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(5, "div", 2)(6, "label", 5);
\u0275\u0275text(7, "Description");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(8, "input", 6);
\u0275\u0275twoWayListener("ngModelChange", function AddTutorialComponent_div_2_Template_input_ngModelChange_8_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r1.tutorial.description, $event) || (ctx_r1.tutorial.description = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(9, "button", 7);
\u0275\u0275listener("click", function AddTutorialComponent_div_2_Template_button_click_9_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.saveTutorial());
});
\u0275\u0275text(10, "Submit");
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r1.tutorial.title);
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r1.tutorial.description);
}
}
function AddTutorialComponent_div_3_Template(rf, ctx) {
if (rf & 1) {
const _r3 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "div")(1, "h4");
\u0275\u0275text(2, "Tutorial was submitted successfully!");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(3, "button", 7);
\u0275\u0275listener("click", function AddTutorialComponent_div_3_Template_button_click_3_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.newTutorial());
});
\u0275\u0275text(4, "Add");
\u0275\u0275elementEnd()();
}
}
var AddTutorialComponent = class _AddTutorialComponent {
tutorialService;
tutorial = {
title: "",
description: "",
published: false
};
submitted = false;
constructor(tutorialService) {
this.tutorialService = tutorialService;
}
ngOnInit() {
}
saveTutorial() {
const data = {
title: this.tutorial.title,
description: this.tutorial.description
};
this.tutorialService.create(data).subscribe((response) => {
console.log(response);
this.submitted = true;
}, (error) => {
console.log(error);
});
}
newTutorial() {
this.submitted = false;
this.tutorial = {
title: "",
description: "",
published: false
};
}
static \u0275fac = function AddTutorialComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AddTutorialComponent)(\u0275\u0275directiveInject(TutorialService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _AddTutorialComponent, selectors: [["app-add-tutorial"]], standalone: false, decls: 4, vars: 2, consts: [[1, "submit-form"], [4, "ngIf"], [1, "form-group"], ["for", "title"], ["type", "text", "id", "title", "required", "", "name", "title", 1, "form-control", 3, "ngModelChange", "ngModel"], ["for", "description"], ["id", "description", "required", "", "name", "description", 1, "form-control", 3, "ngModelChange", "ngModel"], [1, "btn", "btn-success", 3, "click"]], template: function AddTutorialComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div")(1, "div", 0);
\u0275\u0275template(2, AddTutorialComponent_div_2_Template, 11, 2, "div", 1)(3, AddTutorialComponent_div_3_Template, 5, 0, "div", 1);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", !ctx.submitted);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.submitted);
}
}, dependencies: [NgIf, DefaultValueAccessor, NgControlStatus, RequiredValidator, NgModel], styles: ["\n\n.submit-form[_ngcontent-%COMP%] {\n max-width: 400px;\n margin: auto;\n}\n/*# sourceMappingURL=add-tutorial.component.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AddTutorialComponent, [{
type: Component,
args: [{ selector: "app-add-tutorial", standalone: false, template: '<div>\r\n <div class="submit-form">\r\n <div *ngIf="!submitted">\r\n <div class="form-group">\r\n <label for="title">Title</label>\r\n <input\r\n type="text"\r\n class="form-control"\r\n id="title"\r\n required\r\n [(ngModel)]="tutorial.title"\r\n name="title"\r\n />\r\n </div>\r\n\r\n <div class="form-group">\r\n <label for="description">Description</label>\r\n <input\r\n class="form-control"\r\n id="description"\r\n required\r\n [(ngModel)]="tutorial.description"\r\n name="description"\r\n />\r\n </div>\r\n\r\n <button (click)="saveTutorial()" class="btn btn-success">Submit</button>\r\n </div>\r\n\r\n <div *ngIf="submitted">\r\n <h4>Tutorial was submitted successfully!</h4>\r\n <button class="btn btn-success" (click)="newTutorial()">Add</button>\r\n </div>\r\n </div>\r\n</div>', styles: ["/* src/app/components/add-tutorial/add-tutorial.component.scss */\n.submit-form {\n max-width: 400px;\n margin: auto;\n}\n/*# sourceMappingURL=add-tutorial.component.css.map */\n"] }]
}], () => [{ type: TutorialService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(AddTutorialComponent, { className: "AddTutorialComponent", filePath: "src/app/components/add-tutorial/add-tutorial.component.ts", lineNumber: 11 });
})();
// src/app/services/user.service.ts
var API_URL = "http://localhost:8080/api/users/";
var UserService = class _UserService {
http;
constructor(http) {
this.http = http;
}
getPublicContent() {
return this.http.get(API_URL + "all", { responseType: "text" });
}
getUserBoard() {
return this.http.get(API_URL + "user", { responseType: "text" });
}
getModeratorBoard() {
return this.http.get(API_URL + "mod", { responseType: "text" });
}
getAdminBoard() {
return this.http.get(API_URL);
}
static \u0275fac = function UserService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _UserService)(\u0275\u0275inject(HttpClient));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _UserService, factory: _UserService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(UserService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{ type: HttpClient }], null);
})();
// src/app/services/roles.service.ts
var API_URL2 = "http://localhost:8080/api/roles/";
var RolesService = class _RolesService {
http;
constructor(http) {
this.http = http;
}
getAllRoles() {
return this.http.get(API_URL2);
}
static \u0275fac = function RolesService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RolesService)(\u0275\u0275inject(HttpClient));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _RolesService, factory: _RolesService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RolesService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{ type: HttpClient }], null);
})();
// src/app/components/board-admin/board-admin.component.ts
var BoardAdminComponent = class _BoardAdminComponent {
userService;
roleService;
gridApi;
rowData;
allRoles;
roles;
columnDefs;
constructor(userService, roleService) {
this.userService = userService;
this.roleService = roleService;
this.allRoles = this.getAllRoles();
}
ngOnInit() {
this.userService.getAdminBoard().subscribe((data) => {
this.rowData = data;
}, (err) => {
this.rowData = JSON.parse(err.error).message;
});
this.columnDefs = [
{ headerName: "User name", field: "username" },
{ headerName: "Email", field: "email" },
{
headerName: "Roles",
field: "roles",
editable: true,
cellEditorParams: {
allRoles: this.allRoles
}
// cellRendererParams: {
// values: this.allRoles
// }
}
];
}
getAllRoles() {
let returnValue;
returnValue = [];
this.roleService.getAllRoles().subscribe((data) => {
returnValue = data;
}, (err) => {
returnValue = JSON.parse(err.error).message;
});
return returnValue;
}
ngOnGridReady(params) {
this.gridApi = params.api;
}
static \u0275fac = function BoardAdminComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BoardAdminComponent)(\u0275\u0275directiveInject(UserService), \u0275\u0275directiveInject(RolesService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _BoardAdminComponent, selectors: [["app-board-admin"]], standalone: false, decls: 0, vars: 0, template: function BoardAdminComponent_Template(rf, ctx) {
}, encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BoardAdminComponent, [{
type: Component,
args: [{ selector: "app-board-admin", standalone: false, template: "\r\n\r\n" }]
}], () => [{ type: UserService }, { type: RolesService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(BoardAdminComponent, { className: "BoardAdminComponent", filePath: "src/app/components/board-admin/board-admin.component.ts", lineNumber: 15 });
})();
// src/app/components/board-moderator/board-moderator.component.ts
var BoardModeratorComponent = class _BoardModeratorComponent {
constructor() {
}
ngOnInit() {
}
static \u0275fac = function BoardModeratorComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BoardModeratorComponent)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _BoardModeratorComponent, selectors: [["app-board-moderator"]], standalone: false, decls: 2, vars: 0, template: function BoardModeratorComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "p");
\u0275\u0275text(1, "board-moderator works!");
\u0275\u0275elementEnd();
}
}, encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BoardModeratorComponent, [{
type: Component,
args: [{ selector: "app-board-moderator", standalone: false, template: "<p>board-moderator works!</p>\r\n" }]
}], () => [], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(BoardModeratorComponent, { className: "BoardModeratorComponent", filePath: "src/app/components/board-moderator/board-moderator.component.ts", lineNumber: 9 });
})();
// src/app/components/board-user/board-user.component.ts
var BoardUserComponent = class _BoardUserComponent {
constructor() {
}
ngOnInit() {
}
static \u0275fac = function BoardUserComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BoardUserComponent)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _BoardUserComponent, selectors: [["app-board-user"]], standalone: false, decls: 2, vars: 0, template: function BoardUserComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "p");
\u0275\u0275text(1, "board-user works!");
\u0275\u0275elementEnd();
}
}, encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BoardUserComponent, [{
type: Component,
args: [{ selector: "app-board-user", standalone: false, template: "<p>board-user works!</p>\r\n" }]
}], () => [], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(BoardUserComponent, { className: "BoardUserComponent", filePath: "src/app/components/board-user/board-user.component.ts", lineNumber: 9 });
})();
// src/app/services/token-storage.service.ts
var TOKEN_KEY = "auth-token";
var USER_KEY = "auth-user";
var TokenStorageService = class _TokenStorageService {
constructor() {
}
signOut() {
window.sessionStorage.clear();
}
saveToken(token) {
window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY, token);
}
getToken() {
return window.sessionStorage.getItem(TOKEN_KEY);
}
saveUser(user) {
window.sessionStorage.removeItem(USER_KEY);
window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
}
getUser() {
const user = window.sessionStorage.getItem(USER_KEY);
if (user) {
return JSON.parse(user);
}
return {};
}
clean() {
window.sessionStorage.clear();
}
isLoggedIn() {
const user = window.sessionStorage.getItem(USER_KEY);
if (user) {
return true;
}
return false;
}
static \u0275fac = function TokenStorageService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TokenStorageService)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _TokenStorageService, factory: _TokenStorageService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TokenStorageService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// src/app/components/profile/profile.component.ts
function ProfileComponent_div_0_li_17_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "li");
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const role_r1 = ctx.$implicit;
\u0275\u0275advance();
\u0275\u0275textInterpolate1(" ", role_r1, " ");
}
}
function ProfileComponent_div_0_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 2)(1, "header", 3)(2, "h3")(3, "strong");
\u0275\u0275text(4);
\u0275\u0275elementEnd();
\u0275\u0275text(5, " Profile ");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(6, "p")(7, "strong");
\u0275\u0275text(8, "Token:");
\u0275\u0275elementEnd();
\u0275\u0275text(9);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(10, "p")(11, "strong");
\u0275\u0275text(12, "Email:");
\u0275\u0275elementEnd();
\u0275\u0275text(13);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "strong");
\u0275\u0275text(15, "Roles:");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(16, "ul");
\u0275\u0275template(17, ProfileComponent_div_0_li_17_Template, 2, 1, "li", 4);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275advance(4);
\u0275\u0275textInterpolate(ctx_r1.currentUser.username);
\u0275\u0275advance(5);
\u0275\u0275textInterpolate2(" ", ctx_r1.currentUser.accessToken.substring(0, 20), " ... ", ctx_r1.currentUser.accessToken.substr(ctx_r1.currentUser.accessToken.length - 20), " ");
\u0275\u0275advance(4);
\u0275\u0275textInterpolate1(" ", ctx_r1.currentUser.email, " ");
\u0275\u0275advance(4);
\u0275\u0275property("ngForOf", ctx_r1.currentUser.roles);
}
}
function ProfileComponent_ng_template_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275text(0, " Please login. ");
}
}
var ProfileComponent = class _ProfileComponent {
token;
currentUser;
constructor(token) {
this.token = token;
}
ngOnInit() {
this.currentUser = this.token.getUser();
}
static \u0275fac = function ProfileComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ProfileComponent)(\u0275\u0275directiveInject(TokenStorageService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _ProfileComponent, selectors: [["app-profile"]], standalone: false, decls: 3, vars: 2, consts: [["loggedOut", ""], ["class", "container", 4, "ngIf", "ngIfElse"], [1, "container"], [1, "jumbotron"], [4, "ngFor", "ngForOf"]], template: function ProfileComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, ProfileComponent_div_0_Template, 18, 5, "div", 1)(1, ProfileComponent_ng_template_1_Template, 1, 0, "ng-template", null, 0, \u0275\u0275templateRefExtractor);
}
if (rf & 2) {
const loggedOut_r3 = \u0275\u0275reference(2);
\u0275\u0275property("ngIf", ctx.currentUser)("ngIfElse", loggedOut_r3);
}
}, dependencies: [NgForOf, NgIf], encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ProfileComponent, [{
type: Component,
args: [{ selector: "app-profile", standalone: false, template: '<div class="container" *ngIf="currentUser; else loggedOut">\r\n <header class="jumbotron">\r\n <h3>\r\n <strong>{{ currentUser.username }}</strong> Profile\r\n </h3>\r\n </header>\r\n <p>\r\n <strong>Token:</strong>\r\n {{ currentUser.accessToken.substring(0, 20) }} ...\r\n {{ currentUser.accessToken.substr(currentUser.accessToken.length - 20) }}\r\n </p>\r\n <p>\r\n <strong>Email:</strong>\r\n {{ currentUser.email }}\r\n </p>\r\n <strong>Roles:</strong>\r\n <ul>\r\n <li *ngFor="let role of currentUser.roles">\r\n {{ role }}\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n <ng-template #loggedOut>\r\n Please login.\r\n </ng-template>' }]
}], () => [{ type: TokenStorageService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(ProfileComponent, { className: "ProfileComponent", filePath: "src/app/components/profile/profile.component.ts", lineNumber: 10 });
})();
// src/app/services/auth.service.ts
var AUTH_API = "http://localhost:8080/api/auth/";
var httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" })
};
var AuthService = class _AuthService {
http;
constructor(http) {
this.http = http;
}
login(username, password) {
return this.http.post(AUTH_API + "signin", {
username,
password
}, httpOptions);
}
register(username, email, password) {
return this.http.post(AUTH_API + "signup", {
username,
email,
password
}, httpOptions);
}
logout() {
return this.http.post(AUTH_API + "signout", {}, httpOptions);
}
static \u0275fac = function AuthService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AuthService)(\u0275\u0275inject(HttpClient));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _AuthService, factory: _AuthService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AuthService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{ type: HttpClient }], null);
})();
// src/app/components/register/register.component.ts
var _c0 = () => ({ standalone: true });
function RegisterComponent_form_3_div_7_div_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, "Username is required");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_7_div_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, " Username must be at least 3 characters ");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_7_div_3_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, " Username must be at most 20 characters ");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_7_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 20);
\u0275\u0275template(1, RegisterComponent_form_3_div_7_div_1_Template, 2, 0, "div", 21)(2, RegisterComponent_form_3_div_7_div_2_Template, 2, 0, "div", 21)(3, RegisterComponent_form_3_div_7_div_3_Template, 2, 0, "div", 21);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275nextContext();
const username_r4 = \u0275\u0275reference(6);
\u0275\u0275advance();
\u0275\u0275property("ngIf", username_r4.errors.required);
\u0275\u0275advance();
\u0275\u0275property("ngIf", username_r4.errors.minlength);
\u0275\u0275advance();
\u0275\u0275property("ngIf", username_r4.errors.maxlength);
}
}
function RegisterComponent_form_3_div_13_div_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, "Email is required");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_13_div_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, " Email must be a valid email address ");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_13_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 20);
\u0275\u0275template(1, RegisterComponent_form_3_div_13_div_1_Template, 2, 0, "div", 21)(2, RegisterComponent_form_3_div_13_div_2_Template, 2, 0, "div", 21);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275nextContext();
const email_r5 = \u0275\u0275reference(12);
\u0275\u0275advance();
\u0275\u0275property("ngIf", email_r5.errors.required);
\u0275\u0275advance();
\u0275\u0275property("ngIf", email_r5.errors.email);
}
}
function RegisterComponent_form_3_div_19_div_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, "Password is required");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_19_div_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, " Password must be at least 6 characters ");
\u0275\u0275elementEnd();
}
}
function RegisterComponent_form_3_div_19_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 20);
\u0275\u0275template(1, RegisterComponent_form_3_div_19_div_1_Template, 2, 0, "div", 21)(2, RegisterComponent_form_3_div_19_div_2_Template, 2, 0, "div", 21);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275nextContext();
const password_r6 = \u0275\u0275reference(18);
\u0275\u0275advance();
\u0275\u0275property("ngIf", password_r6.errors.required);
\u0275\u0275advance();
\u0275\u0275property("ngIf", password_r6.errors.minlength);
}
}
function RegisterComponent_form_3_div_23_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 22);
\u0275\u0275text(1, " Signup failed!");
\u0275\u0275element(2, "br");
\u0275\u0275text(3);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r2 = \u0275\u0275nextContext(2);
\u0275\u0275advance(3);
\u0275\u0275textInterpolate1("", ctx_r2.errorMessage, " ");
}
}
function RegisterComponent_form_3_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "form", 9, 0);
\u0275\u0275listener("ngSubmit", function RegisterComponent_form_3_Template_form_ngSubmit_0_listener() {
\u0275\u0275restoreView(_r1);
const f_r2 = \u0275\u0275reference(1);
const ctx_r2 = \u0275\u0275nextContext();
return \u0275\u0275resetView(f_r2.form.valid && ctx_r2.onSubmit());
});
\u0275\u0275elementStart(2, "div", 10)(3, "label", 11);
\u0275\u0275text(4, "Username");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(5, "input", 12, 1);
\u0275\u0275twoWayListener("ngModelChange", function RegisterComponent_form_3_Template_input_ngModelChange_5_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r2.form.username, $event) || (ctx_r2.form.username = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd();
\u0275\u0275template(7, RegisterComponent_form_3_div_7_Template, 4, 3, "div", 13);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(8, "div", 10)(9, "label", 14);
\u0275\u0275text(10, "Email");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(11, "input", 15, 2);
\u0275\u0275twoWayListener("ngModelChange", function RegisterComponent_form_3_Template_input_ngModelChange_11_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r2.form.email, $event) || (ctx_r2.form.email = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd();
\u0275\u0275template(13, RegisterComponent_form_3_div_13_Template, 3, 2, "div", 13);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "div", 10)(15, "label", 16);
\u0275\u0275text(16, "Password");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(17, "input", 17, 3);
\u0275\u0275twoWayListener("ngModelChange", function RegisterComponent_form_3_Template_input_ngModelChange_17_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r2.form.password, $event) || (ctx_r2.form.password = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd();
\u0275\u0275template(19, RegisterComponent_form_3_div_19_Template, 3, 2, "div", 13);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(20, "div", 10)(21, "button", 18);
\u0275\u0275text(22, "Sign Up");
\u0275\u0275elementEnd()();
\u0275\u0275template(23, RegisterComponent_form_3_div_23_Template, 4, 1, "div", 19);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const f_r2 = \u0275\u0275reference(1);
const username_r4 = \u0275\u0275reference(6);
const email_r5 = \u0275\u0275reference(12);
const password_r6 = \u0275\u0275reference(18);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275advance(5);
\u0275\u0275twoWayProperty("ngModel", ctx_r2.form.username);
\u0275\u0275property("ngModelOptions", \u0275\u0275pureFunction0(10, _c0));
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", username_r4.errors && f_r2.submitted);
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r2.form.email);
\u0275\u0275property("ngModelOptions", \u0275\u0275pureFunction0(11, _c0));
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", email_r5.errors && f_r2.submitted);
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r2.form.password);
\u0275\u0275property("ngModelOptions", \u0275\u0275pureFunction0(12, _c0));
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", password_r6.errors && f_r2.submitted);
\u0275\u0275advance(4);
\u0275\u0275property("ngIf", f_r2.submitted && ctx_r2.isSignUpFailed);
}
}
function RegisterComponent_div_4_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 23);
\u0275\u0275text(1, " Your registration is successful! ");
\u0275\u0275elementEnd();
}
}
var RegisterComponent = class _RegisterComponent {
authService;
form = {
username: null,
email: null,
password: null
};
isSuccessful = false;
isSignUpFailed = false;
errorMessage = "";
constructor(authService) {
this.authService = authService;
}
ngOnInit() {
}
onSubmit() {
const { username, email, password } = this.form;
this.authService.register(username, email, password).subscribe((data) => {
console.log(data);
this.isSuccessful = true;
this.isSignUpFailed = false;
}, (err) => {
this.errorMessage = err.error.message;
this.isSignUpFailed = true;
});
}
static \u0275fac = function RegisterComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _RegisterComponent)(\u0275\u0275directiveInject(AuthService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _RegisterComponent, selectors: [["app-register"]], standalone: false, decls: 5, vars: 2, consts: [["f", "ngForm"], ["username", "ngModel"], ["email", "ngModel"], ["password", "ngModel"], [1, "col-md-12"], ["id", "register"], ["id", "foto", "id", "profile-img", "src", "//ssl.gstatic.com/accounts/ui/avatar_2x.png", 1, "profile-img-card"], ["name", "form", "novalidate", "", 3, "ngSubmit", 4, "ngIf"], ["class", "alert alert-success", 4, "ngIf"], ["name", "form", "novalidate", "", 3, "ngSubmit"], [1, "form-group"], ["for", "username"], ["type", "text", "id", "username", "required", "", "minlength", "3", "maxlength", "20", 1, "form-control", 3, "ngModelChange", "ngModel", "ngModelOptions"], ["class", "alert-danger", 4, "ngIf"], ["for", "email"], ["type", "email", "id", "email", "required", "", "email", "", 1, "form-control", 3, "ngModelChange", "ngModel", "ngModelOptions"], ["for", "password"], ["type", "password", "id", "password", "required", "", "minlength", "6", 1, "form-control", 3, "ngModelChange", "ngModel", "ngModelOptions"], [1, "btn", "btn-primary", "btn-block"], ["class", "alert alert-warning", 4, "ngIf"], [1, "alert-danger"], [4, "ngIf"], [1, "alert", "alert-warning"], [1, "alert", "alert-success"]], template: function RegisterComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 4)(1, "div", 5);
\u0275\u0275element(2, "img", 6);
\u0275\u0275template(3, RegisterComponent_form_3_Template, 24, 13, "form", 7)(4, RegisterComponent_div_4_Template, 2, 0, "div", 8);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(3);
\u0275\u0275property("ngIf", !ctx.isSuccessful);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.isSuccessful);
}
}, dependencies: [NgIf, \u0275NgNoValidate, DefaultValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, MaxLengthValidator, EmailValidator, NgModel, NgForm], encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(RegisterComponent, [{
type: Component,
args: [{ selector: "app-register", standalone: false, template: '<div class="col-md-12">\r\n <div id="register">\r\n <img id="foto"\r\n id="profile-img"\r\n src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"\r\n class="profile-img-card"\r\n />\r\n <form\r\n *ngIf="!isSuccessful"\r\n name="form"\r\n (ngSubmit)="f.form.valid && onSubmit()"\r\n #f="ngForm"\r\n novalidate\r\n >\r\n <div class="form-group">\r\n <label for="username">Username</label>\r\n <input\r\n type="text"\r\n class="form-control"\r\n id="username"\r\n [(ngModel)]="form.username"\r\n [ngModelOptions]="{standalone: true}"\r\n required\r\n minlength="3"\r\n maxlength="20"\r\n #username="ngModel"\r\n />\r\n <div class="alert-danger" *ngIf="username.errors && f.submitted">\r\n <div *ngIf="username.errors.required">Username is required</div>\r\n <div *ngIf="username.errors.minlength">\r\n Username must be at least 3 characters\r\n </div>\r\n <div *ngIf="username.errors.maxlength">\r\n Username must be at most 20 characters\r\n </div>\r\n </div>\r\n </div>\r\n <div class="form-group">\r\n <label for="email">Email</label>\r\n <input\r\n type="email"\r\n class="form-control"\r\n id="email"\r\n [(ngModel)]="form.email"\r\n [ngModelOptions]="{standalone: true}"\r\n required\r\n email\r\n #email="ngModel"\r\n />\r\n <div class="alert-danger" *ngIf="email.errors && f.submitted">\r\n <div *ngIf="email.errors.required">Email is required</div>\r\n <div *ngIf="email.errors.email">\r\n Email must be a valid email address\r\n </div>\r\n </div>\r\n </div>\r\n <div class="form-group">\r\n <label for="password">Password</label>\r\n <input\r\n type="password"\r\n class="form-control"\r\n id="password"\r\n [(ngModel)]="form.password"\r\n [ngModelOptions]="{standalone: true}"\r\n required\r\n minlength="6"\r\n #password="ngModel"\r\n />\r\n <div class="alert-danger" *ngIf="password.errors && f.submitted">\r\n <div *ngIf="password.errors.required">Password is required</div>\r\n <div *ngIf="password.errors.minlength">\r\n Password must be at least 6 characters\r\n </div>\r\n </div>\r\n </div>\r\n <div class="form-group">\r\n <button class="btn btn-primary btn-block">Sign Up</button>\r\n </div>\r\n\r\n <div class="alert alert-warning" *ngIf="f.submitted && isSignUpFailed">\r\n Signup failed!<br />{{ errorMessage }}\r\n </div>\r\n </form>\r\n\r\n <div class="alert alert-success" *ngIf="isSuccessful">\r\n Your registration is successful!\r\n </div>\r\n </div>\r\n </div>\r\n' }]
}], () => [{ type: AuthService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(RegisterComponent, { className: "RegisterComponent", filePath: "src/app/components/register/register.component.ts", lineNumber: 10 });
})();
// src/app/components/login/login.component.ts
function LoginComponent_form_3_div_7_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 16);
\u0275\u0275text(1, " Username is required! ");
\u0275\u0275elementEnd();
}
}
function LoginComponent_form_3_div_13_div_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, "Password is required");
\u0275\u0275elementEnd();
}
}
function LoginComponent_form_3_div_13_div_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div");
\u0275\u0275text(1, " Password must be at least 6 characters ");
\u0275\u0275elementEnd();
}
}
function LoginComponent_form_3_div_13_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 16);
\u0275\u0275template(1, LoginComponent_form_3_div_13_div_1_Template, 2, 0, "div", 17)(2, LoginComponent_form_3_div_13_div_2_Template, 2, 0, "div", 17);
\u0275\u0275elementEnd();
}
if (rf & 2) {
\u0275\u0275nextContext();
const password_r4 = \u0275\u0275reference(12);
\u0275\u0275advance();
\u0275\u0275property("ngIf", password_r4.errors.required);
\u0275\u0275advance();
\u0275\u0275property("ngIf", password_r4.errors.minlength);
}
}
function LoginComponent_form_3_div_18_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 16);
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r2 = \u0275\u0275nextContext(2);
\u0275\u0275advance();
\u0275\u0275textInterpolate1(" Login failed: ", ctx_r2.errorMessage, " ");
}
}
function LoginComponent_form_3_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "form", 8, 0);
\u0275\u0275listener("ngSubmit", function LoginComponent_form_3_Template_form_ngSubmit_0_listener() {
\u0275\u0275restoreView(_r1);
const f_r2 = \u0275\u0275reference(1);
const ctx_r2 = \u0275\u0275nextContext();
return \u0275\u0275resetView(f_r2.form.valid && ctx_r2.onSubmit());
});
\u0275\u0275elementStart(2, "div", 9)(3, "label", 10);
\u0275\u0275text(4, "Username");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(5, "input", 11, 1);
\u0275\u0275twoWayListener("ngModelChange", function LoginComponent_form_3_Template_input_ngModelChange_5_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r2.form.username, $event) || (ctx_r2.form.username = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd();
\u0275\u0275template(7, LoginComponent_form_3_div_7_Template, 2, 0, "div", 12);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(8, "div", 9)(9, "label", 13);
\u0275\u0275text(10, "Password");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(11, "input", 14, 2);
\u0275\u0275twoWayListener("ngModelChange", function LoginComponent_form_3_Template_input_ngModelChange_11_listener($event) {
\u0275\u0275restoreView(_r1);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275twoWayBindingSet(ctx_r2.form.password, $event) || (ctx_r2.form.password = $event);
return \u0275\u0275resetView($event);
});
\u0275\u0275elementEnd();
\u0275\u0275template(13, LoginComponent_form_3_div_13_Template, 3, 2, "div", 12);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(14, "div", 9)(15, "button", 15);
\u0275\u0275text(16, " Login ");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(17, "div", 9);
\u0275\u0275template(18, LoginComponent_form_3_div_18_Template, 2, 1, "div", 12);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
const f_r2 = \u0275\u0275reference(1);
const username_r5 = \u0275\u0275reference(6);
const password_r4 = \u0275\u0275reference(12);
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275advance(5);
\u0275\u0275twoWayProperty("ngModel", ctx_r2.form.username);
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", username_r5.errors && f_r2.submitted);
\u0275\u0275advance(4);
\u0275\u0275twoWayProperty("ngModel", ctx_r2.form.password);
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", password_r4.errors && f_r2.submitted);
\u0275\u0275advance(5);
\u0275\u0275property("ngIf", f_r2.submitted && ctx_r2.isLoginFailed);
}
}
function LoginComponent_div_4_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 18);
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r2 = \u0275\u0275nextContext();
\u0275\u0275advance();
\u0275\u0275textInterpolate1(" Logged in as ", ctx_r2.roles, ". ");
}
}
var LoginComponent = class _LoginComponent {
authService;
tokenStorage;
form = {
username: null,
password: null
};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = "";
roles = [];
constructor(authService, tokenStorage) {
this.authService = authService;
this.tokenStorage = tokenStorage;
}
ngOnInit() {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
}
}
onSubmit() {
const { username, password } = this.form;
this.authService.login(username, password).subscribe((data) => {
this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
this.reloadPage();
}, (err) => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
});
}
reloadPage() {
window.location.reload();
}
static \u0275fac = function LoginComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _LoginComponent)(\u0275\u0275directiveInject(AuthService), \u0275\u0275directiveInject(TokenStorageService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _LoginComponent, selectors: [["app-login"]], decls: 5, vars: 2, consts: [["f", "ngForm"], ["username", "ngModel"], ["password", "ngModel"], [1, "col-md-12"], [1, "card", "card-container"], ["id", "profile-img", "src", "//ssl.gstatic.com/accounts/ui/avatar_2x.png", 1, "profile-img-card"], ["name", "form", "novalidate", "", 3, "ngSubmit", 4, "ngIf"], ["class", "alert alert-success", 4, "ngIf"], ["name", "form", "novalidate", "", 3, "ngSubmit"], [1, "form-group"], ["for", "username"], ["type", "text", "id", "username", "required", "", 1, "form-control", 3, "ngModelChange", "ngModel"], ["class", "alert alert-danger", "role", "alert", 4, "ngIf"], ["for", "password"], ["type", "password", "id", "password", "required", "", "minlength", "6", 1, "form-control", 3, "ngModelChange", "ngModel"], [1, "btn", "btn-primary", "btn-block"], ["role", "alert", 1, "alert", "alert-danger"], [4, "ngIf"], [1, "alert", "alert-success"]], template: function LoginComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 3)(1, "div", 4);
\u0275\u0275element(2, "img", 5);
\u0275\u0275template(3, LoginComponent_form_3_Template, 19, 5, "form", 6)(4, LoginComponent_div_4_Template, 2, 1, "div", 7);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(3);
\u0275\u0275property("ngIf", !ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.isLoggedIn);
}
}, dependencies: [FormsModule, \u0275NgNoValidate, DefaultValueAccessor, NgControlStatus, NgControlStatusGroup, RequiredValidator, MinLengthValidator, NgModel, NgForm, NgIf], encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(LoginComponent, [{
type: Component,
args: [{ selector: "app-login", imports: [
FormsModule,
NgIf
], template: '<div class="col-md-12">\r\n <div class="card card-container">\r\n <img\r\n id="profile-img"\r\n src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"\r\n class="profile-img-card"\r\n />\r\n <form\r\n *ngIf="!isLoggedIn"\r\n name="form"\r\n (ngSubmit)="f.form.valid && onSubmit()"\r\n #f="ngForm"\r\n novalidate\r\n >\r\n <div class="form-group">\r\n <label for="username">Username</label>\r\n <input\r\n type="text"\r\n class="form-control"\r\n id="username"\r\n [(ngModel)]="form.username"\r\n required\r\n #username="ngModel"\r\n />\r\n <div\r\n class="alert alert-danger"\r\n role="alert"\r\n *ngIf="username.errors && f.submitted"\r\n >\r\n Username is required!\r\n </div>\r\n </div>\r\n <div class="form-group">\r\n <label for="password">Password</label>\r\n <input\r\n type="password"\r\n class="form-control"\r\n id="password"\r\n [(ngModel)]="form.password"\r\n required\r\n minlength="6"\r\n #password="ngModel"\r\n />\r\n <div\r\n class="alert alert-danger"\r\n role="alert"\r\n *ngIf="password.errors && f.submitted"\r\n >\r\n <div *ngIf="password.errors.required">Password is required</div>\r\n <div *ngIf="password.errors.minlength">\r\n Password must be at least 6 characters\r\n </div>\r\n </div>\r\n </div>\r\n <div class="form-group">\r\n <button class="btn btn-primary btn-block">\r\n Login\r\n </button>\r\n </div>\r\n <div class="form-group">\r\n <div\r\n class="alert alert-danger"\r\n role="alert"\r\n *ngIf="f.submitted && isLoginFailed"\r\n >\r\n Login failed: {{ errorMessage }}\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class="alert alert-success" *ngIf="isLoggedIn">\r\n Logged in as {{ roles }}.\r\n </div>\r\n </div>\r\n </div>\r\n' }]
}], () => [{ type: AuthService }, { type: TokenStorageService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(LoginComponent, { className: "LoginComponent", filePath: "src/app/components/login/login.component.ts", lineNumber: 16 });
})();
// src/app/components/home/home.component.ts
var HomeComponent = class _HomeComponent {
userService;
content;
constructor(userService) {
this.userService = userService;
}
ngOnInit() {
}
static \u0275fac = function HomeComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HomeComponent)(\u0275\u0275directiveInject(UserService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _HomeComponent, selectors: [["app-home"]], standalone: false, decls: 4, vars: 1, consts: [[1, "container"], [1, "jumbotron"]], template: function HomeComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0)(1, "header", 1)(2, "p");
\u0275\u0275text(3);
\u0275\u0275elementEnd()()();
}
if (rf & 2) {
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(ctx.content);
}
}, encapsulation: 2 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HomeComponent, [{
type: Component,
args: [{ selector: "app-home", standalone: false, template: '<div class="container">\r\n <header class="jumbotron">\r\n <p>{{ content }}</p>\r\n </header>\r\n </div>' }]
}], () => [{ type: UserService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(HomeComponent, { className: "HomeComponent", filePath: "src/app/components/home/home.component.ts", lineNumber: 10 });
})();
// src/app/app-routing.module.ts
var routes = [
{ path: "home", component: HomeComponent },
{ path: "login", component: LoginComponent },
{ path: "register", component: RegisterComponent },
{ path: "profile", component: ProfileComponent },
{ path: "user", component: BoardUserComponent },
{ path: "mod", component: BoardModeratorComponent },
{ path: "admin", component: BoardAdminComponent },
{ path: "", redirectTo: "home", pathMatch: "full" },
{ path: "tutorials", component: TutorialsListComponent },
{ path: "tutorials/:id", component: TutorialDetailsComponent },
{ path: "add", component: AddTutorialComponent }
];
var AppRoutingModule = class _AppRoutingModule {
static \u0275fac = function AppRoutingModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AppRoutingModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({ type: _AppRoutingModule });
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({ imports: [RouterModule.forRoot(routes, { useHash: true }), RouterModule] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AppRoutingModule, [{
type: NgModule,
args: [{
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/portal-directives-Bw5woq8I.mjs
function throwNullPortalError() {
throw Error("Must provide a portal to attach");
}
function throwPortalAlreadyAttachedError() {
throw Error("Host already has a portal attached");
}
function throwPortalOutletAlreadyDisposedError() {
throw Error("This PortalOutlet has already been disposed");
}
function throwUnknownPortalTypeError() {
throw Error("Attempting to attach an unknown Portal type. BasePortalOutlet accepts either a ComponentPortal or a TemplatePortal.");
}
function throwNullPortalOutletError() {
throw Error("Attempting to attach a portal to a null PortalOutlet");
}
function throwNoPortalAttachedError() {
throw Error("Attempting to detach a portal that is not attached to a host");
}
var Portal = class {
_attachedHost;
/** Attach this portal to a host. */
attach(host) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (host == null) {
throwNullPortalOutletError();
}
if (host.hasAttached()) {
throwPortalAlreadyAttachedError();
}
}
this._attachedHost = host;
return host.attach(this);
}
/** Detach this portal from its host */
detach() {
let host = this._attachedHost;
if (host != null) {
this._attachedHost = null;
host.detach();
} else if (typeof ngDevMode === "undefined" || ngDevMode) {
throwNoPortalAttachedError();
}
}
/** Whether this portal is attached to a host. */
get isAttached() {
return this._attachedHost != null;
}
/**
* Sets the PortalOutlet reference without performing `attach()`. This is used directly by
* the PortalOutlet when it is performing an `attach()` or `detach()`.
*/
setAttachedHost(host) {
this._attachedHost = host;
}
};
var ComponentPortal = class extends Portal {
/** The type of the component that will be instantiated for attachment. */
component;
/**
* Where the attached component should live in Angular's *logical* component tree.
* This is different from where the component *renders*, which is determined by the PortalOutlet.
* The origin is necessary when the host is outside of the Angular application context.
*/
viewContainerRef;
/** Injector used for the instantiation of the component. */
injector;
/**
* @deprecated No longer in use. To be removed.
* @breaking-change 18.0.0
*/
componentFactoryResolver;
/**
* List of DOM nodes that should be projected through `<ng-content>` of the attached component.
*/
projectableNodes;
constructor(component, viewContainerRef, injector, _componentFactoryResolver, projectableNodes) {
super();
this.component = component;
this.viewContainerRef = viewContainerRef;
this.injector = injector;
this.projectableNodes = projectableNodes;
}
};
var TemplatePortal = class extends Portal {
templateRef;
viewContainerRef;
context;
injector;
constructor(templateRef, viewContainerRef, context, injector) {
super();
this.templateRef = templateRef;
this.viewContainerRef = viewContainerRef;
this.context = context;
this.injector = injector;
}
get origin() {
return this.templateRef.elementRef;
}
/**
* Attach the portal to the provided `PortalOutlet`.
* When a context is provided it will override the `context` property of the `TemplatePortal`
* instance.
*/
attach(host, context = this.context) {
this.context = context;
return super.attach(host);
}
detach() {
this.context = void 0;
return super.detach();
}
};
var DomPortal = class extends Portal {
/** DOM node hosting the portal's content. */
element;
constructor(element) {
super();
this.element = element instanceof ElementRef ? element.nativeElement : element;
}
};
var BasePortalOutlet = class {
/** The portal currently attached to the host. */
_attachedPortal;
/** A function that will permanently dispose this host. */
_disposeFn;
/** Whether this host has already been permanently disposed. */
_isDisposed = false;
/** Whether this host has an attached portal. */
hasAttached() {
return !!this._attachedPortal;
}
/** Attaches a portal. */
attach(portal) {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (!portal) {
throwNullPortalError();
}
if (this.hasAttached()) {
throwPortalAlreadyAttachedError();
}
if (this._isDisposed) {
throwPortalOutletAlreadyDisposedError();
}
}
if (portal instanceof ComponentPortal) {
this._attachedPortal = portal;
return this.attachComponentPortal(portal);
} else if (portal instanceof TemplatePortal) {
this._attachedPortal = portal;
return this.attachTemplatePortal(portal);
} else if (this.attachDomPortal && portal instanceof DomPortal) {
this._attachedPortal = portal;
return this.attachDomPortal(portal);
}
if (typeof ngDevMode === "undefined" || ngDevMode) {
throwUnknownPortalTypeError();
}
}
// @breaking-change 10.0.0 `attachDomPortal` to become a required abstract method.
attachDomPortal = null;
/** Detaches a previously attached portal. */
detach() {
if (this._attachedPortal) {
this._attachedPortal.setAttachedHost(null);
this._attachedPortal = null;
}
this._invokeDisposeFn();
}
/** Permanently dispose of this portal host. */
dispose() {
if (this.hasAttached()) {
this.detach();
}
this._invokeDisposeFn();
this._isDisposed = true;
}
/** @docs-private */
setDisposeFn(fn) {
this._disposeFn = fn;
}
_invokeDisposeFn() {
if (this._disposeFn) {
this._disposeFn();
this._disposeFn = null;
}
}
};
var DomPortalOutlet = class extends BasePortalOutlet {
outletElement;
_appRef;
_defaultInjector;
_document;
/**
* @param outletElement Element into which the content is projected.
* @param _unusedComponentFactoryResolver Used to resolve the component factory.
* Only required when attaching component portals.
* @param _appRef Reference to the application. Only used in component portals when there
* is no `ViewContainerRef` available.
* @param _defaultInjector Injector to use as a fallback when the portal being attached doesn't
* have one. Only used for component portals.
* @param _document Reference to the document. Used when attaching a DOM portal. Will eventually
* become a required parameter.
*/
constructor(outletElement, _unusedComponentFactoryResolver, _appRef, _defaultInjector, _document2) {
super();
this.outletElement = outletElement;
this._appRef = _appRef;
this._defaultInjector = _defaultInjector;
this._document = _document2;
}
/**
* Attach the given ComponentPortal to DOM element.
* @param portal Portal to be attached
* @returns Reference to the created component.
*/
attachComponentPortal(portal) {
let componentRef;
if (portal.viewContainerRef) {
const injector = portal.injector || portal.viewContainerRef.injector;
const ngModuleRef = injector.get(NgModuleRef$1, null, {
optional: true
}) || void 0;
componentRef = portal.viewContainerRef.createComponent(portal.component, {
index: portal.viewContainerRef.length,
injector,
ngModuleRef,
projectableNodes: portal.projectableNodes || void 0
});
this.setDisposeFn(() => componentRef.destroy());
} else {
if ((typeof ngDevMode === "undefined" || ngDevMode) && !this._appRef) {
throw Error("Cannot attach component portal to outlet without an ApplicationRef.");
}
const appRef = this._appRef;
const elementInjector = portal.injector || this._defaultInjector || Injector.NULL;
const environmentInjector = elementInjector.get(EnvironmentInjector, appRef.injector);
componentRef = createComponent(portal.component, {
elementInjector,
environmentInjector,
projectableNodes: portal.projectableNodes || void 0
});
appRef.attachView(componentRef.hostView);
this.setDisposeFn(() => {
if (appRef.viewCount > 0) {
appRef.detachView(componentRef.hostView);
}
componentRef.destroy();
});
}
this.outletElement.appendChild(this._getComponentRootNode(componentRef));
this._attachedPortal = portal;
return componentRef;
}
/**
* Attaches a template portal to the DOM as an embedded view.
* @param portal Portal to be attached.
* @returns Reference to the created embedded view.
*/
attachTemplatePortal(portal) {
let viewContainer = portal.viewContainerRef;
let viewRef = viewContainer.createEmbeddedView(portal.templateRef, portal.context, {
injector: portal.injector
});
viewRef.rootNodes.forEach((rootNode) => this.outletElement.appendChild(rootNode));
viewRef.detectChanges();
this.setDisposeFn(() => {
let index = viewContainer.indexOf(viewRef);
if (index !== -1) {
viewContainer.remove(index);
}
});
this._attachedPortal = portal;
return viewRef;
}
/**
* Attaches a DOM portal by transferring its content into the outlet.
* @param portal Portal to be attached.
* @deprecated To be turned into a method.
* @breaking-change 10.0.0
*/
attachDomPortal = (portal) => {
const element = portal.element;
if (!element.parentNode && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error("DOM portal content must be attached to a parent node.");
}
const anchorNode = this._document.createComment("dom-portal");
element.parentNode.insertBefore(anchorNode, element);
this.outletElement.appendChild(element);
this._attachedPortal = portal;
super.setDisposeFn(() => {
if (anchorNode.parentNode) {
anchorNode.parentNode.replaceChild(element, anchorNode);
}
});
};
/**
* Clears out a portal from the DOM.
*/
dispose() {
super.dispose();
this.outletElement.remove();
}
/** Gets the root HTMLElement for an instantiated component. */
_getComponentRootNode(componentRef) {
return componentRef.hostView.rootNodes[0];
}
};
var CdkPortal = class _CdkPortal extends TemplatePortal {
constructor() {
const templateRef = inject(TemplateRef);
const viewContainerRef = inject(ViewContainerRef);
super(templateRef, viewContainerRef);
}
static \u0275fac = function CdkPortal_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkPortal)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkPortal,
selectors: [["", "cdkPortal", ""]],
exportAs: ["cdkPortal"],
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkPortal, [{
type: Directive,
args: [{
selector: "[cdkPortal]",
exportAs: "cdkPortal"
}]
}], () => [], null);
})();
var TemplatePortalDirective = class _TemplatePortalDirective extends CdkPortal {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275TemplatePortalDirective_BaseFactory;
return function TemplatePortalDirective_Factory(__ngFactoryType__) {
return (\u0275TemplatePortalDirective_BaseFactory || (\u0275TemplatePortalDirective_BaseFactory = \u0275\u0275getInheritedFactory(_TemplatePortalDirective)))(__ngFactoryType__ || _TemplatePortalDirective);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _TemplatePortalDirective,
selectors: [["", "cdk-portal", ""], ["", "portal", ""]],
exportAs: ["cdkPortal"],
features: [\u0275\u0275ProvidersFeature([{
provide: CdkPortal,
useExisting: _TemplatePortalDirective
}]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TemplatePortalDirective, [{
type: Directive,
args: [{
selector: "[cdk-portal], [portal]",
exportAs: "cdkPortal",
providers: [{
provide: CdkPortal,
useExisting: TemplatePortalDirective
}]
}]
}], null, null);
})();
var CdkPortalOutlet = class _CdkPortalOutlet extends BasePortalOutlet {
_moduleRef = inject(NgModuleRef$1, {
optional: true
});
_document = inject(DOCUMENT);
_viewContainerRef = inject(ViewContainerRef);
/** Whether the portal component is initialized. */
_isInitialized = false;
/** Reference to the currently-attached component/view ref. */
_attachedRef;
constructor() {
super();
}
/** Portal associated with the Portal outlet. */
get portal() {
return this._attachedPortal;
}
set portal(portal) {
if (this.hasAttached() && !portal && !this._isInitialized) {
return;
}
if (this.hasAttached()) {
super.detach();
}
if (portal) {
super.attach(portal);
}
this._attachedPortal = portal || null;
}
/** Emits when a portal is attached to the outlet. */
attached = new EventEmitter();
/** Component or view reference that is attached to the portal. */
get attachedRef() {
return this._attachedRef;
}
ngOnInit() {
this._isInitialized = true;
}
ngOnDestroy() {
super.dispose();
this._attachedRef = this._attachedPortal = null;
}
/**
* Attach the given ComponentPortal to this PortalOutlet.
*
* @param portal Portal to be attached to the portal outlet.
* @returns Reference to the created component.
*/
attachComponentPortal(portal) {
portal.setAttachedHost(this);
const viewContainerRef = portal.viewContainerRef != null ? portal.viewContainerRef : this._viewContainerRef;
const ref = viewContainerRef.createComponent(portal.component, {
index: viewContainerRef.length,
injector: portal.injector || viewContainerRef.injector,
projectableNodes: portal.projectableNodes || void 0,
ngModuleRef: this._moduleRef || void 0
});
if (viewContainerRef !== this._viewContainerRef) {
this._getRootNode().appendChild(ref.hostView.rootNodes[0]);
}
super.setDisposeFn(() => ref.destroy());
this._attachedPortal = portal;
this._attachedRef = ref;
this.attached.emit(ref);
return ref;
}
/**
* Attach the given TemplatePortal to this PortalHost as an embedded View.
* @param portal Portal to be attached.
* @returns Reference to the created embedded view.
*/
attachTemplatePortal(portal) {
portal.setAttachedHost(this);
const viewRef = this._viewContainerRef.createEmbeddedView(portal.templateRef, portal.context, {
injector: portal.injector
});
super.setDisposeFn(() => this._viewContainerRef.clear());
this._attachedPortal = portal;
this._attachedRef = viewRef;
this.attached.emit(viewRef);
return viewRef;
}
/**
* Attaches the given DomPortal to this PortalHost by moving all of the portal content into it.
* @param portal Portal to be attached.
* @deprecated To be turned into a method.
* @breaking-change 10.0.0
*/
attachDomPortal = (portal) => {
const element = portal.element;
if (!element.parentNode && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error("DOM portal content must be attached to a parent node.");
}
const anchorNode = this._document.createComment("dom-portal");
portal.setAttachedHost(this);
element.parentNode.insertBefore(anchorNode, element);
this._getRootNode().appendChild(element);
this._attachedPortal = portal;
super.setDisposeFn(() => {
if (anchorNode.parentNode) {
anchorNode.parentNode.replaceChild(element, anchorNode);
}
});
};
/** Gets the root node of the portal outlet. */
_getRootNode() {
const nativeElement = this._viewContainerRef.element.nativeElement;
return nativeElement.nodeType === nativeElement.ELEMENT_NODE ? nativeElement : nativeElement.parentNode;
}
static \u0275fac = function CdkPortalOutlet_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkPortalOutlet)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkPortalOutlet,
selectors: [["", "cdkPortalOutlet", ""]],
inputs: {
portal: [0, "cdkPortalOutlet", "portal"]
},
outputs: {
attached: "attached"
},
exportAs: ["cdkPortalOutlet"],
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkPortalOutlet, [{
type: Directive,
args: [{
selector: "[cdkPortalOutlet]",
exportAs: "cdkPortalOutlet"
}]
}], () => [], {
portal: [{
type: Input,
args: ["cdkPortalOutlet"]
}],
attached: [{
type: Output
}]
});
})();
var PortalHostDirective = class _PortalHostDirective extends CdkPortalOutlet {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275PortalHostDirective_BaseFactory;
return function PortalHostDirective_Factory(__ngFactoryType__) {
return (\u0275PortalHostDirective_BaseFactory || (\u0275PortalHostDirective_BaseFactory = \u0275\u0275getInheritedFactory(_PortalHostDirective)))(__ngFactoryType__ || _PortalHostDirective);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _PortalHostDirective,
selectors: [["", "cdkPortalHost", ""], ["", "portalHost", ""]],
inputs: {
portal: [0, "cdkPortalHost", "portal"]
},
exportAs: ["cdkPortalHost"],
features: [\u0275\u0275ProvidersFeature([{
provide: CdkPortalOutlet,
useExisting: _PortalHostDirective
}]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PortalHostDirective, [{
type: Directive,
args: [{
selector: "[cdkPortalHost], [portalHost]",
exportAs: "cdkPortalHost",
inputs: [{
name: "portal",
alias: "cdkPortalHost"
}],
providers: [{
provide: CdkPortalOutlet,
useExisting: PortalHostDirective
}]
}]
}], null, null);
})();
var PortalModule = class _PortalModule {
static \u0275fac = function PortalModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PortalModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _PortalModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PortalModule, [{
type: NgModule,
args: [{
imports: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective],
exports: [CdkPortal, CdkPortalOutlet, TemplatePortalDirective, PortalHostDirective]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/fake-event-detection-DWOdFTFz.mjs
function isFakeMousedownFromScreenReader(event) {
return event.buttons === 0 || event.detail === 0;
}
function isFakeTouchstartFromScreenReader(event) {
const touch = event.touches && event.touches[0] || event.changedTouches && event.changedTouches[0];
return !!touch && touch.identifier === -1 && (touch.radiusX == null || touch.radiusX === 1) && (touch.radiusY == null || touch.radiusY === 1);
}
// node_modules/@angular/cdk/fesm2022/keycodes-CpHkExLC.mjs
var SHIFT = 16;
var CONTROL = 17;
var ALT = 18;
var ESCAPE = 27;
var META = 91;
var MAC_META = 224;
// node_modules/@angular/cdk/fesm2022/shadow-dom-B0oHn41l.mjs
var shadowDomIsSupported;
function _supportsShadowDom() {
if (shadowDomIsSupported == null) {
const head = typeof document !== "undefined" ? document.head : null;
shadowDomIsSupported = !!(head && (head.createShadowRoot || head.attachShadow));
}
return shadowDomIsSupported;
}
function _getShadowRoot(element) {
if (_supportsShadowDom()) {
const rootNode = element.getRootNode ? element.getRootNode() : null;
if (typeof ShadowRoot !== "undefined" && ShadowRoot && rootNode instanceof ShadowRoot) {
return rootNode;
}
}
return null;
}
function _getFocusedElementPierceShadowDom() {
let activeElement = typeof document !== "undefined" && document ? document.activeElement : null;
while (activeElement && activeElement.shadowRoot) {
const newActiveElement = activeElement.shadowRoot.activeElement;
if (newActiveElement === activeElement) {
break;
} else {
activeElement = newActiveElement;
}
}
return activeElement;
}
function _getEventTarget(event) {
return event.composedPath ? event.composedPath()[0] : event.target;
}
// node_modules/@angular/cdk/fesm2022/backwards-compatibility-DHR38MsD.mjs
function _bindEventWithOptions(renderer, target, eventName, callback, options) {
const major = parseInt(VERSION.major);
const minor = parseInt(VERSION.minor);
if (major > 19 || major === 19 && minor > 0 || major === 0 && minor === 0) {
return renderer.listen(target, eventName, callback, options);
}
target.addEventListener(eventName, callback, options);
return () => {
target.removeEventListener(eventName, callback, options);
};
}
// node_modules/@angular/cdk/fesm2022/platform-DmdVEw_C.mjs
var hasV8BreakIterator;
try {
hasV8BreakIterator = typeof Intl !== "undefined" && Intl.v8BreakIterator;
} catch {
hasV8BreakIterator = false;
}
var Platform = class _Platform {
_platformId = inject(PLATFORM_ID);
// We want to use the Angular platform check because if the Document is shimmed
// without the navigator, the following checks will fail. This is preferred because
// sometimes the Document may be shimmed without the user's knowledge or intention
/** Whether the Angular application is being rendered in the browser. */
isBrowser = this._platformId ? isPlatformBrowser(this._platformId) : typeof document === "object" && !!document;
/** Whether the current browser is Microsoft Edge. */
EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent);
/** Whether the current rendering engine is Microsoft Trident. */
TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);
// EdgeHTML and Trident mock Blink specific things and need to be excluded from this check.
/** Whether the current rendering engine is Blink. */
BLINK = this.isBrowser && !!(window.chrome || hasV8BreakIterator) && typeof CSS !== "undefined" && !this.EDGE && !this.TRIDENT;
// Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
// ensure that Webkit runs standalone and is not used as another engine's base.
/** Whether the current rendering engine is WebKit. */
WEBKIT = this.isBrowser && /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
/** Whether the current platform is Apple iOS. */
IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !("MSStream" in window);
// It's difficult to detect the plain Gecko engine, because most of the browsers identify
// them self as Gecko-like browsers and modify the userAgent's according to that.
// Since we only cover one explicit Firefox case, we can simply check for Firefox
// instead of having an unstable check for Gecko.
/** Whether the current browser is Firefox. */
FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
/** Whether the current platform is Android. */
// Trident on mobile adds the android platform to the userAgent to trick detections.
ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT;
// Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake
// this and just place the Safari keyword in the userAgent. To be more safe about Safari every
// Safari browser should also use Webkit as its layout engine.
/** Whether the current browser is Safari. */
SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;
constructor() {
}
static \u0275fac = function Platform_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Platform)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Platform,
factory: _Platform.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Platform, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/cdk/fesm2022/passive-listeners-esHZRgIN.mjs
var supportsPassiveEvents;
function supportsPassiveEventListeners() {
if (supportsPassiveEvents == null && typeof window !== "undefined") {
try {
window.addEventListener("test", null, Object.defineProperty({}, "passive", {
get: () => supportsPassiveEvents = true
}));
} finally {
supportsPassiveEvents = supportsPassiveEvents || false;
}
}
return supportsPassiveEvents;
}
function normalizePassiveListenerOptions(options) {
return supportsPassiveEventListeners() ? options : !!options.capture;
}
// node_modules/@angular/cdk/fesm2022/element-x4z00URv.mjs
function coerceNumberProperty(value, fallbackValue = 0) {
if (_isNumberValue(value)) {
return Number(value);
}
return arguments.length === 2 ? fallbackValue : 0;
}
function _isNumberValue(value) {
return !isNaN(parseFloat(value)) && !isNaN(Number(value));
}
function coerceElement(elementOrRef) {
return elementOrRef instanceof ElementRef ? elementOrRef.nativeElement : elementOrRef;
}
// node_modules/@angular/cdk/fesm2022/focus-monitor-e2l_RpN3.mjs
var INPUT_MODALITY_DETECTOR_OPTIONS = new InjectionToken("cdk-input-modality-detector-options");
var INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS = {
ignoreKeys: [ALT, CONTROL, MAC_META, META, SHIFT]
};
var TOUCH_BUFFER_MS = 650;
var modalityEventListenerOptions = {
passive: true,
capture: true
};
var InputModalityDetector = class _InputModalityDetector {
_platform = inject(Platform);
_listenerCleanups;
/** Emits whenever an input modality is detected. */
modalityDetected;
/** Emits when the input modality changes. */
modalityChanged;
/** The most recently detected input modality. */
get mostRecentModality() {
return this._modality.value;
}
/**
* The most recently detected input modality event target. Is null if no input modality has been
* detected or if the associated event target is null for some unknown reason.
*/
_mostRecentTarget = null;
/** The underlying BehaviorSubject that emits whenever an input modality is detected. */
_modality = new BehaviorSubject(null);
/** Options for this InputModalityDetector. */
_options;
/**
* The timestamp of the last touch input modality. Used to determine whether mousedown events
* should be attributed to mouse or touch.
*/
_lastTouchMs = 0;
/**
* Handles keydown events. Must be an arrow function in order to preserve the context when it gets
* bound.
*/
_onKeydown = (event) => {
if (this._options?.ignoreKeys?.some((keyCode) => keyCode === event.keyCode)) {
return;
}
this._modality.next("keyboard");
this._mostRecentTarget = _getEventTarget(event);
};
/**
* Handles mousedown events. Must be an arrow function in order to preserve the context when it
* gets bound.
*/
_onMousedown = (event) => {
if (Date.now() - this._lastTouchMs < TOUCH_BUFFER_MS) {
return;
}
this._modality.next(isFakeMousedownFromScreenReader(event) ? "keyboard" : "mouse");
this._mostRecentTarget = _getEventTarget(event);
};
/**
* Handles touchstart events. Must be an arrow function in order to preserve the context when it
* gets bound.
*/
_onTouchstart = (event) => {
if (isFakeTouchstartFromScreenReader(event)) {
this._modality.next("keyboard");
return;
}
this._lastTouchMs = Date.now();
this._modality.next("touch");
this._mostRecentTarget = _getEventTarget(event);
};
constructor() {
const ngZone = inject(NgZone);
const document2 = inject(DOCUMENT);
const options = inject(INPUT_MODALITY_DETECTOR_OPTIONS, {
optional: true
});
this._options = __spreadValues(__spreadValues({}, INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS), options);
this.modalityDetected = this._modality.pipe(skip(1));
this.modalityChanged = this.modalityDetected.pipe(distinctUntilChanged());
if (this._platform.isBrowser) {
const renderer = inject(RendererFactory2).createRenderer(null, null);
this._listenerCleanups = ngZone.runOutsideAngular(() => {
return [_bindEventWithOptions(renderer, document2, "keydown", this._onKeydown, modalityEventListenerOptions), _bindEventWithOptions(renderer, document2, "mousedown", this._onMousedown, modalityEventListenerOptions), _bindEventWithOptions(renderer, document2, "touchstart", this._onTouchstart, modalityEventListenerOptions)];
});
}
}
ngOnDestroy() {
this._modality.complete();
this._listenerCleanups?.forEach((cleanup) => cleanup());
}
static \u0275fac = function InputModalityDetector_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _InputModalityDetector)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _InputModalityDetector,
factory: _InputModalityDetector.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(InputModalityDetector, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var FocusMonitorDetectionMode;
(function(FocusMonitorDetectionMode2) {
FocusMonitorDetectionMode2[FocusMonitorDetectionMode2["IMMEDIATE"] = 0] = "IMMEDIATE";
FocusMonitorDetectionMode2[FocusMonitorDetectionMode2["EVENTUAL"] = 1] = "EVENTUAL";
})(FocusMonitorDetectionMode || (FocusMonitorDetectionMode = {}));
var FOCUS_MONITOR_DEFAULT_OPTIONS = new InjectionToken("cdk-focus-monitor-default-options");
var captureEventListenerOptions = normalizePassiveListenerOptions({
passive: true,
capture: true
});
var FocusMonitor = class _FocusMonitor {
_ngZone = inject(NgZone);
_platform = inject(Platform);
_inputModalityDetector = inject(InputModalityDetector);
/** The focus origin that the next focus event is a result of. */
_origin = null;
/** The FocusOrigin of the last focus event tracked by the FocusMonitor. */
_lastFocusOrigin;
/** Whether the window has just been focused. */
_windowFocused = false;
/** The timeout id of the window focus timeout. */
_windowFocusTimeoutId;
/** The timeout id of the origin clearing timeout. */
_originTimeoutId;
/**
* Whether the origin was determined via a touch interaction. Necessary as properly attributing
* focus events to touch interactions requires special logic.
*/
_originFromTouchInteraction = false;
/** Map of elements being monitored to their info. */
_elementInfo = /* @__PURE__ */ new Map();
/** The number of elements currently being monitored. */
_monitoredElementCount = 0;
/**
* Keeps track of the root nodes to which we've currently bound a focus/blur handler,
* as well as the number of monitored elements that they contain. We have to treat focus/blur
* handlers differently from the rest of the events, because the browser won't emit events
* to the document when focus moves inside of a shadow root.
*/
_rootNodeFocusListenerCount = /* @__PURE__ */ new Map();
/**
* The specified detection mode, used for attributing the origin of a focus
* event.
*/
_detectionMode;
/**
* Event listener for `focus` events on the window.
* Needs to be an arrow function in order to preserve the context when it gets bound.
*/
_windowFocusListener = () => {
this._windowFocused = true;
this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);
};
/** Used to reference correct document/window */
_document = inject(DOCUMENT, {
optional: true
});
/** Subject for stopping our InputModalityDetector subscription. */
_stopInputModalityDetector = new Subject();
constructor() {
const options = inject(FOCUS_MONITOR_DEFAULT_OPTIONS, {
optional: true
});
this._detectionMode = options?.detectionMode || FocusMonitorDetectionMode.IMMEDIATE;
}
/**
* Event listener for `focus` and 'blur' events on the document.
* Needs to be an arrow function in order to preserve the context when it gets bound.
*/
_rootNodeFocusAndBlurListener = (event) => {
const target = _getEventTarget(event);
for (let element = target; element; element = element.parentElement) {
if (event.type === "focus") {
this._onFocus(event, element);
} else {
this._onBlur(event, element);
}
}
};
monitor(element, checkChildren = false) {
const nativeElement = coerceElement(element);
if (!this._platform.isBrowser || nativeElement.nodeType !== 1) {
return of();
}
const rootNode = _getShadowRoot(nativeElement) || this._getDocument();
const cachedInfo = this._elementInfo.get(nativeElement);
if (cachedInfo) {
if (checkChildren) {
cachedInfo.checkChildren = true;
}
return cachedInfo.subject;
}
const info = {
checkChildren,
subject: new Subject(),
rootNode
};
this._elementInfo.set(nativeElement, info);
this._registerGlobalListeners(info);
return info.subject;
}
stopMonitoring(element) {
const nativeElement = coerceElement(element);
const elementInfo = this._elementInfo.get(nativeElement);
if (elementInfo) {
elementInfo.subject.complete();
this._setClasses(nativeElement);
this._elementInfo.delete(nativeElement);
this._removeGlobalListeners(elementInfo);
}
}
focusVia(element, origin, options) {
const nativeElement = coerceElement(element);
const focusedElement = this._getDocument().activeElement;
if (nativeElement === focusedElement) {
this._getClosestElementsInfo(nativeElement).forEach(([currentElement, info]) => this._originChanged(currentElement, origin, info));
} else {
this._setOrigin(origin);
if (typeof nativeElement.focus === "function") {
nativeElement.focus(options);
}
}
}
ngOnDestroy() {
this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));
}
/** Access injected document if available or fallback to global document reference */
_getDocument() {
return this._document || document;
}
/** Use defaultView of injected document if available or fallback to global window reference */
_getWindow() {
const doc = this._getDocument();
return doc.defaultView || window;
}
_getFocusOrigin(focusEventTarget) {
if (this._origin) {
if (this._originFromTouchInteraction) {
return this._shouldBeAttributedToTouch(focusEventTarget) ? "touch" : "program";
} else {
return this._origin;
}
}
if (this._windowFocused && this._lastFocusOrigin) {
return this._lastFocusOrigin;
}
if (focusEventTarget && this._isLastInteractionFromInputLabel(focusEventTarget)) {
return "mouse";
}
return "program";
}
/**
* Returns whether the focus event should be attributed to touch. Recall that in IMMEDIATE mode, a
* touch origin isn't immediately reset at the next tick (see _setOrigin). This means that when we
* handle a focus event following a touch interaction, we need to determine whether (1) the focus
* event was directly caused by the touch interaction or (2) the focus event was caused by a
* subsequent programmatic focus call triggered by the touch interaction.
* @param focusEventTarget The target of the focus event under examination.
*/
_shouldBeAttributedToTouch(focusEventTarget) {
return this._detectionMode === FocusMonitorDetectionMode.EVENTUAL || !!focusEventTarget?.contains(this._inputModalityDetector._mostRecentTarget);
}
/**
* Sets the focus classes on the element based on the given focus origin.
* @param element The element to update the classes on.
* @param origin The focus origin.
*/
_setClasses(element, origin) {
element.classList.toggle("cdk-focused", !!origin);
element.classList.toggle("cdk-touch-focused", origin === "touch");
element.classList.toggle("cdk-keyboard-focused", origin === "keyboard");
element.classList.toggle("cdk-mouse-focused", origin === "mouse");
element.classList.toggle("cdk-program-focused", origin === "program");
}
/**
* Updates the focus origin. If we're using immediate detection mode, we schedule an async
* function to clear the origin at the end of a timeout. The duration of the timeout depends on
* the origin being set.
* @param origin The origin to set.
* @param isFromInteraction Whether we are setting the origin from an interaction event.
*/
_setOrigin(origin, isFromInteraction = false) {
this._ngZone.runOutsideAngular(() => {
this._origin = origin;
this._originFromTouchInteraction = origin === "touch" && isFromInteraction;
if (this._detectionMode === FocusMonitorDetectionMode.IMMEDIATE) {
clearTimeout(this._originTimeoutId);
const ms = this._originFromTouchInteraction ? TOUCH_BUFFER_MS : 1;
this._originTimeoutId = setTimeout(() => this._origin = null, ms);
}
});
}
/**
* Handles focus events on a registered element.
* @param event The focus event.
* @param element The monitored element.
*/
_onFocus(event, element) {
const elementInfo = this._elementInfo.get(element);
const focusEventTarget = _getEventTarget(event);
if (!elementInfo || !elementInfo.checkChildren && element !== focusEventTarget) {
return;
}
this._originChanged(element, this._getFocusOrigin(focusEventTarget), elementInfo);
}
/**
* Handles blur events on a registered element.
* @param event The blur event.
* @param element The monitored element.
*/
_onBlur(event, element) {
const elementInfo = this._elementInfo.get(element);
if (!elementInfo || elementInfo.checkChildren && event.relatedTarget instanceof Node && element.contains(event.relatedTarget)) {
return;
}
this._setClasses(element);
this._emitOrigin(elementInfo, null);
}
_emitOrigin(info, origin) {
if (info.subject.observers.length) {
this._ngZone.run(() => info.subject.next(origin));
}
}
_registerGlobalListeners(elementInfo) {
if (!this._platform.isBrowser) {
return;
}
const rootNode = elementInfo.rootNode;
const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;
if (!rootNodeFocusListeners) {
this._ngZone.runOutsideAngular(() => {
rootNode.addEventListener("focus", this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
rootNode.addEventListener("blur", this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
});
}
this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1);
if (++this._monitoredElementCount === 1) {
this._ngZone.runOutsideAngular(() => {
const window2 = this._getWindow();
window2.addEventListener("focus", this._windowFocusListener);
});
this._inputModalityDetector.modalityDetected.pipe(takeUntil(this._stopInputModalityDetector)).subscribe((modality) => {
this._setOrigin(
modality,
true
/* isFromInteraction */
);
});
}
}
_removeGlobalListeners(elementInfo) {
const rootNode = elementInfo.rootNode;
if (this._rootNodeFocusListenerCount.has(rootNode)) {
const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode);
if (rootNodeFocusListeners > 1) {
this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);
} else {
rootNode.removeEventListener("focus", this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
rootNode.removeEventListener("blur", this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
this._rootNodeFocusListenerCount.delete(rootNode);
}
}
if (!--this._monitoredElementCount) {
const window2 = this._getWindow();
window2.removeEventListener("focus", this._windowFocusListener);
this._stopInputModalityDetector.next();
clearTimeout(this._windowFocusTimeoutId);
clearTimeout(this._originTimeoutId);
}
}
/** Updates all the state on an element once its focus origin has changed. */
_originChanged(element, origin, elementInfo) {
this._setClasses(element, origin);
this._emitOrigin(elementInfo, origin);
this._lastFocusOrigin = origin;
}
/**
* Collects the `MonitoredElementInfo` of a particular element and
* all of its ancestors that have enabled `checkChildren`.
* @param element Element from which to start the search.
*/
_getClosestElementsInfo(element) {
const results = [];
this._elementInfo.forEach((info, currentElement) => {
if (currentElement === element || info.checkChildren && currentElement.contains(element)) {
results.push([currentElement, info]);
}
});
return results;
}
/**
* Returns whether an interaction is likely to have come from the user clicking the `label` of
* an `input` or `textarea` in order to focus it.
* @param focusEventTarget Target currently receiving focus.
*/
_isLastInteractionFromInputLabel(focusEventTarget) {
const {
_mostRecentTarget: mostRecentTarget,
mostRecentModality
} = this._inputModalityDetector;
if (mostRecentModality !== "mouse" || !mostRecentTarget || mostRecentTarget === focusEventTarget || focusEventTarget.nodeName !== "INPUT" && focusEventTarget.nodeName !== "TEXTAREA" || focusEventTarget.disabled) {
return false;
}
const labels = focusEventTarget.labels;
if (labels) {
for (let i = 0; i < labels.length; i++) {
if (labels[i].contains(mostRecentTarget)) {
return true;
}
}
}
return false;
}
static \u0275fac = function FocusMonitor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FocusMonitor)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FocusMonitor,
factory: _FocusMonitor.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FocusMonitor, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkMonitorFocus = class _CdkMonitorFocus {
_elementRef = inject(ElementRef);
_focusMonitor = inject(FocusMonitor);
_monitorSubscription;
_focusOrigin = null;
cdkFocusChange = new EventEmitter();
constructor() {
}
get focusOrigin() {
return this._focusOrigin;
}
ngAfterViewInit() {
const element = this._elementRef.nativeElement;
this._monitorSubscription = this._focusMonitor.monitor(element, element.nodeType === 1 && element.hasAttribute("cdkMonitorSubtreeFocus")).subscribe((origin) => {
this._focusOrigin = origin;
this.cdkFocusChange.emit(origin);
});
}
ngOnDestroy() {
this._focusMonitor.stopMonitoring(this._elementRef);
if (this._monitorSubscription) {
this._monitorSubscription.unsubscribe();
}
}
static \u0275fac = function CdkMonitorFocus_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkMonitorFocus)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkMonitorFocus,
selectors: [["", "cdkMonitorElementFocus", ""], ["", "cdkMonitorSubtreeFocus", ""]],
outputs: {
cdkFocusChange: "cdkFocusChange"
},
exportAs: ["cdkMonitorFocus"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkMonitorFocus, [{
type: Directive,
args: [{
selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]",
exportAs: "cdkMonitorFocus"
}]
}], () => [], {
cdkFocusChange: [{
type: Output
}]
});
})();
// node_modules/@angular/cdk/fesm2022/style-loader-Cu9AvjH9.mjs
var appsWithLoaders = /* @__PURE__ */ new WeakMap();
var _CdkPrivateStyleLoader = class __CdkPrivateStyleLoader {
_appRef;
_injector = inject(Injector);
_environmentInjector = inject(EnvironmentInjector);
/**
* Loads a set of styles.
* @param loader Component which will be instantiated to load the styles.
*/
load(loader) {
const appRef = this._appRef = this._appRef || this._injector.get(ApplicationRef);
let data = appsWithLoaders.get(appRef);
if (!data) {
data = {
loaders: /* @__PURE__ */ new Set(),
refs: []
};
appsWithLoaders.set(appRef, data);
appRef.onDestroy(() => {
appsWithLoaders.get(appRef)?.refs.forEach((ref) => ref.destroy());
appsWithLoaders.delete(appRef);
});
}
if (!data.loaders.has(loader)) {
data.loaders.add(loader);
data.refs.push(createComponent(loader, {
environmentInjector: this._environmentInjector
}));
}
}
static \u0275fac = function _CdkPrivateStyleLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __CdkPrivateStyleLoader)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: __CdkPrivateStyleLoader,
factory: __CdkPrivateStyleLoader.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_CdkPrivateStyleLoader, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/private.mjs
var _VisuallyHiddenLoader = class __VisuallyHiddenLoader {
static \u0275fac = function _VisuallyHiddenLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __VisuallyHiddenLoader)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: __VisuallyHiddenLoader,
selectors: [["ng-component"]],
exportAs: ["cdkVisuallyHidden"],
decls: 0,
vars: 0,
template: function _VisuallyHiddenLoader_Template(rf, ctx) {
},
styles: [".cdk-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap;outline:0;-webkit-appearance:none;-moz-appearance:none;left:0}[dir=rtl] .cdk-visually-hidden{left:auto;right:0}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_VisuallyHiddenLoader, [{
type: Component,
args: [{
exportAs: "cdkVisuallyHidden",
encapsulation: ViewEncapsulation.None,
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
styles: [".cdk-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap;outline:0;-webkit-appearance:none;-moz-appearance:none;left:0}[dir=rtl] .cdk-visually-hidden{left:auto;right:0}\n"]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/array-I1yfCXUO.mjs
function coerceArray(value) {
return Array.isArray(value) ? value : [value];
}
// node_modules/@angular/cdk/fesm2022/breakpoints-observer-CljOfYGy.mjs
var mediaQueriesForWebkitCompatibility = /* @__PURE__ */ new Set();
var mediaQueryStyleNode;
var MediaMatcher = class _MediaMatcher {
_platform = inject(Platform);
_nonce = inject(CSP_NONCE, {
optional: true
});
/** The internal matchMedia method to return back a MediaQueryList like object. */
_matchMedia;
constructor() {
this._matchMedia = this._platform.isBrowser && window.matchMedia ? (
// matchMedia is bound to the window scope intentionally as it is an illegal invocation to
// call it from a different scope.
window.matchMedia.bind(window)
) : noopMatchMedia;
}
/**
* Evaluates the given media query and returns the native MediaQueryList from which results
* can be retrieved.
* Confirms the layout engine will trigger for the selector query provided and returns the
* MediaQueryList for the query provided.
*/
matchMedia(query) {
if (this._platform.WEBKIT || this._platform.BLINK) {
createEmptyStyleRule(query, this._nonce);
}
return this._matchMedia(query);
}
static \u0275fac = function MediaMatcher_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MediaMatcher)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _MediaMatcher,
factory: _MediaMatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MediaMatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function createEmptyStyleRule(query, nonce) {
if (mediaQueriesForWebkitCompatibility.has(query)) {
return;
}
try {
if (!mediaQueryStyleNode) {
mediaQueryStyleNode = document.createElement("style");
if (nonce) {
mediaQueryStyleNode.setAttribute("nonce", nonce);
}
mediaQueryStyleNode.setAttribute("type", "text/css");
document.head.appendChild(mediaQueryStyleNode);
}
if (mediaQueryStyleNode.sheet) {
mediaQueryStyleNode.sheet.insertRule(`@media ${query} {body{ }}`, 0);
mediaQueriesForWebkitCompatibility.add(query);
}
} catch (e) {
console.error(e);
}
}
function noopMatchMedia(query) {
return {
matches: query === "all" || query === "",
media: query,
addListener: () => {
},
removeListener: () => {
}
};
}
var BreakpointObserver = class _BreakpointObserver {
_mediaMatcher = inject(MediaMatcher);
_zone = inject(NgZone);
/** A map of all media queries currently being listened for. */
_queries = /* @__PURE__ */ new Map();
/** A subject for all other observables to takeUntil based on. */
_destroySubject = new Subject();
constructor() {
}
/** Completes the active subject, signalling to all other observables to complete. */
ngOnDestroy() {
this._destroySubject.next();
this._destroySubject.complete();
}
/**
* Whether one or more media queries match the current viewport size.
* @param value One or more media queries to check.
* @returns Whether any of the media queries match.
*/
isMatched(value) {
const queries = splitQueries(coerceArray(value));
return queries.some((mediaQuery) => this._registerQuery(mediaQuery).mql.matches);
}
/**
* Gets an observable of results for the given queries that will emit new results for any changes
* in matching of the given queries.
* @param value One or more media queries to check.
* @returns A stream of matches for the given queries.
*/
observe(value) {
const queries = splitQueries(coerceArray(value));
const observables = queries.map((query) => this._registerQuery(query).observable);
let stateObservable = combineLatest(observables);
stateObservable = concat(stateObservable.pipe(take(1)), stateObservable.pipe(skip(1), debounceTime(0)));
return stateObservable.pipe(map((breakpointStates) => {
const response = {
matches: false,
breakpoints: {}
};
breakpointStates.forEach(({
matches,
query
}) => {
response.matches = response.matches || matches;
response.breakpoints[query] = matches;
});
return response;
}));
}
/** Registers a specific query to be listened for. */
_registerQuery(query) {
if (this._queries.has(query)) {
return this._queries.get(query);
}
const mql = this._mediaMatcher.matchMedia(query);
const queryObservable = new Observable((observer) => {
const handler = (e) => this._zone.run(() => observer.next(e));
mql.addListener(handler);
return () => {
mql.removeListener(handler);
};
}).pipe(startWith(mql), map(({
matches
}) => ({
query,
matches
})), takeUntil(this._destroySubject));
const output = {
observable: queryObservable,
mql
};
this._queries.set(query, output);
return output;
}
static \u0275fac = function BreakpointObserver_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BreakpointObserver)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _BreakpointObserver,
factory: _BreakpointObserver.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BreakpointObserver, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function splitQueries(queries) {
return queries.map((query) => query.split(",")).reduce((a1, a2) => a1.concat(a2)).map((query) => query.trim());
}
// node_modules/@angular/cdk/fesm2022/observers.mjs
function shouldIgnoreRecord(record) {
if (record.type === "characterData" && record.target instanceof Comment) {
return true;
}
if (record.type === "childList") {
for (let i = 0; i < record.addedNodes.length; i++) {
if (!(record.addedNodes[i] instanceof Comment)) {
return false;
}
}
for (let i = 0; i < record.removedNodes.length; i++) {
if (!(record.removedNodes[i] instanceof Comment)) {
return false;
}
}
return true;
}
return false;
}
var MutationObserverFactory = class _MutationObserverFactory {
create(callback) {
return typeof MutationObserver === "undefined" ? null : new MutationObserver(callback);
}
static \u0275fac = function MutationObserverFactory_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MutationObserverFactory)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _MutationObserverFactory,
factory: _MutationObserverFactory.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MutationObserverFactory, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var ContentObserver = class _ContentObserver {
_mutationObserverFactory = inject(MutationObserverFactory);
/** Keeps track of the existing MutationObservers so they can be reused. */
_observedElements = /* @__PURE__ */ new Map();
_ngZone = inject(NgZone);
constructor() {
}
ngOnDestroy() {
this._observedElements.forEach((_, element) => this._cleanupObserver(element));
}
observe(elementOrRef) {
const element = coerceElement(elementOrRef);
return new Observable((observer) => {
const stream = this._observeElement(element);
const subscription = stream.pipe(map((records) => records.filter((record) => !shouldIgnoreRecord(record))), filter((records) => !!records.length)).subscribe((records) => {
this._ngZone.run(() => {
observer.next(records);
});
});
return () => {
subscription.unsubscribe();
this._unobserveElement(element);
};
});
}
/**
* Observes the given element by using the existing MutationObserver if available, or creating a
* new one if not.
*/
_observeElement(element) {
return this._ngZone.runOutsideAngular(() => {
if (!this._observedElements.has(element)) {
const stream = new Subject();
const observer = this._mutationObserverFactory.create((mutations) => stream.next(mutations));
if (observer) {
observer.observe(element, {
characterData: true,
childList: true,
subtree: true
});
}
this._observedElements.set(element, {
observer,
stream,
count: 1
});
} else {
this._observedElements.get(element).count++;
}
return this._observedElements.get(element).stream;
});
}
/**
* Un-observes the given element and cleans up the underlying MutationObserver if nobody else is
* observing this element.
*/
_unobserveElement(element) {
if (this._observedElements.has(element)) {
this._observedElements.get(element).count--;
if (!this._observedElements.get(element).count) {
this._cleanupObserver(element);
}
}
}
/** Clean up the underlying MutationObserver for the specified element. */
_cleanupObserver(element) {
if (this._observedElements.has(element)) {
const {
observer,
stream
} = this._observedElements.get(element);
if (observer) {
observer.disconnect();
}
stream.complete();
this._observedElements.delete(element);
}
}
static \u0275fac = function ContentObserver_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ContentObserver)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ContentObserver,
factory: _ContentObserver.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ContentObserver, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkObserveContent = class _CdkObserveContent {
_contentObserver = inject(ContentObserver);
_elementRef = inject(ElementRef);
/** Event emitted for each change in the element's content. */
event = new EventEmitter();
/**
* Whether observing content is disabled. This option can be used
* to disconnect the underlying MutationObserver until it is needed.
*/
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = value;
this._disabled ? this._unsubscribe() : this._subscribe();
}
_disabled = false;
/** Debounce interval for emitting the changes. */
get debounce() {
return this._debounce;
}
set debounce(value) {
this._debounce = coerceNumberProperty(value);
this._subscribe();
}
_debounce;
_currentSubscription = null;
constructor() {
}
ngAfterContentInit() {
if (!this._currentSubscription && !this.disabled) {
this._subscribe();
}
}
ngOnDestroy() {
this._unsubscribe();
}
_subscribe() {
this._unsubscribe();
const stream = this._contentObserver.observe(this._elementRef);
this._currentSubscription = (this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream).subscribe(this.event);
}
_unsubscribe() {
this._currentSubscription?.unsubscribe();
}
static \u0275fac = function CdkObserveContent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkObserveContent)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkObserveContent,
selectors: [["", "cdkObserveContent", ""]],
inputs: {
disabled: [2, "cdkObserveContentDisabled", "disabled", booleanAttribute],
debounce: "debounce"
},
outputs: {
event: "cdkObserveContent"
},
exportAs: ["cdkObserveContent"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkObserveContent, [{
type: Directive,
args: [{
selector: "[cdkObserveContent]",
exportAs: "cdkObserveContent"
}]
}], () => [], {
event: [{
type: Output,
args: ["cdkObserveContent"]
}],
disabled: [{
type: Input,
args: [{
alias: "cdkObserveContentDisabled",
transform: booleanAttribute
}]
}],
debounce: [{
type: Input
}]
});
})();
var ObserversModule = class _ObserversModule {
static \u0275fac = function ObserversModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ObserversModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _ObserversModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [MutationObserverFactory]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ObserversModule, [{
type: NgModule,
args: [{
imports: [CdkObserveContent],
exports: [CdkObserveContent],
providers: [MutationObserverFactory]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/a11y-module-BYox5gpI.mjs
var InteractivityChecker = class _InteractivityChecker {
_platform = inject(Platform);
constructor() {
}
/**
* Gets whether an element is disabled.
*
* @param element Element to be checked.
* @returns Whether the element is disabled.
*/
isDisabled(element) {
return element.hasAttribute("disabled");
}
/**
* Gets whether an element is visible for the purposes of interactivity.
*
* This will capture states like `display: none` and `visibility: hidden`, but not things like
* being clipped by an `overflow: hidden` parent or being outside the viewport.
*
* @returns Whether the element is visible.
*/
isVisible(element) {
return hasGeometry(element) && getComputedStyle(element).visibility === "visible";
}
/**
* Gets whether an element can be reached via Tab key.
* Assumes that the element has already been checked with isFocusable.
*
* @param element Element to be checked.
* @returns Whether the element is tabbable.
*/
isTabbable(element) {
if (!this._platform.isBrowser) {
return false;
}
const frameElement = getFrameElement(getWindow(element));
if (frameElement) {
if (getTabIndexValue(frameElement) === -1) {
return false;
}
if (!this.isVisible(frameElement)) {
return false;
}
}
let nodeName = element.nodeName.toLowerCase();
let tabIndexValue = getTabIndexValue(element);
if (element.hasAttribute("contenteditable")) {
return tabIndexValue !== -1;
}
if (nodeName === "iframe" || nodeName === "object") {
return false;
}
if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {
return false;
}
if (nodeName === "audio") {
if (!element.hasAttribute("controls")) {
return false;
}
return tabIndexValue !== -1;
}
if (nodeName === "video") {
if (tabIndexValue === -1) {
return false;
}
if (tabIndexValue !== null) {
return true;
}
return this._platform.FIREFOX || element.hasAttribute("controls");
}
return element.tabIndex >= 0;
}
/**
* Gets whether an element can be focused by the user.
*
* @param element Element to be checked.
* @param config The config object with options to customize this method's behavior
* @returns Whether the element is focusable.
*/
isFocusable(element, config) {
return isPotentiallyFocusable(element) && !this.isDisabled(element) && (config?.ignoreVisibility || this.isVisible(element));
}
static \u0275fac = function InteractivityChecker_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _InteractivityChecker)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _InteractivityChecker,
factory: _InteractivityChecker.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(InteractivityChecker, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function getFrameElement(window2) {
try {
return window2.frameElement;
} catch {
return null;
}
}
function hasGeometry(element) {
return !!(element.offsetWidth || element.offsetHeight || typeof element.getClientRects === "function" && element.getClientRects().length);
}
function isNativeFormElement(element) {
let nodeName = element.nodeName.toLowerCase();
return nodeName === "input" || nodeName === "select" || nodeName === "button" || nodeName === "textarea";
}
function isHiddenInput(element) {
return isInputElement(element) && element.type == "hidden";
}
function isAnchorWithHref(element) {
return isAnchorElement(element) && element.hasAttribute("href");
}
function isInputElement(element) {
return element.nodeName.toLowerCase() == "input";
}
function isAnchorElement(element) {
return element.nodeName.toLowerCase() == "a";
}
function hasValidTabIndex(element) {
if (!element.hasAttribute("tabindex") || element.tabIndex === void 0) {
return false;
}
let tabIndex = element.getAttribute("tabindex");
return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));
}
function getTabIndexValue(element) {
if (!hasValidTabIndex(element)) {
return null;
}
const tabIndex = parseInt(element.getAttribute("tabindex") || "", 10);
return isNaN(tabIndex) ? -1 : tabIndex;
}
function isPotentiallyTabbableIOS(element) {
let nodeName = element.nodeName.toLowerCase();
let inputType = nodeName === "input" && element.type;
return inputType === "text" || inputType === "password" || nodeName === "select" || nodeName === "textarea";
}
function isPotentiallyFocusable(element) {
if (isHiddenInput(element)) {
return false;
}
return isNativeFormElement(element) || isAnchorWithHref(element) || element.hasAttribute("contenteditable") || hasValidTabIndex(element);
}
function getWindow(node) {
return node.ownerDocument && node.ownerDocument.defaultView || window;
}
var FocusTrap = class {
_element;
_checker;
_ngZone;
_document;
_injector;
_startAnchor;
_endAnchor;
_hasAttached = false;
// Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
startAnchorListener = () => this.focusLastTabbableElement();
endAnchorListener = () => this.focusFirstTabbableElement();
/** Whether the focus trap is active. */
get enabled() {
return this._enabled;
}
set enabled(value) {
this._enabled = value;
if (this._startAnchor && this._endAnchor) {
this._toggleAnchorTabIndex(value, this._startAnchor);
this._toggleAnchorTabIndex(value, this._endAnchor);
}
}
_enabled = true;
constructor(_element, _checker, _ngZone, _document2, deferAnchors = false, _injector) {
this._element = _element;
this._checker = _checker;
this._ngZone = _ngZone;
this._document = _document2;
this._injector = _injector;
if (!deferAnchors) {
this.attachAnchors();
}
}
/** Destroys the focus trap by cleaning up the anchors. */
destroy() {
const startAnchor = this._startAnchor;
const endAnchor = this._endAnchor;
if (startAnchor) {
startAnchor.removeEventListener("focus", this.startAnchorListener);
startAnchor.remove();
}
if (endAnchor) {
endAnchor.removeEventListener("focus", this.endAnchorListener);
endAnchor.remove();
}
this._startAnchor = this._endAnchor = null;
this._hasAttached = false;
}
/**
* Inserts the anchors into the DOM. This is usually done automatically
* in the constructor, but can be deferred for cases like directives with `*ngIf`.
* @returns Whether the focus trap managed to attach successfully. This may not be the case
* if the target element isn't currently in the DOM.
*/
attachAnchors() {
if (this._hasAttached) {
return true;
}
this._ngZone.runOutsideAngular(() => {
if (!this._startAnchor) {
this._startAnchor = this._createAnchor();
this._startAnchor.addEventListener("focus", this.startAnchorListener);
}
if (!this._endAnchor) {
this._endAnchor = this._createAnchor();
this._endAnchor.addEventListener("focus", this.endAnchorListener);
}
});
if (this._element.parentNode) {
this._element.parentNode.insertBefore(this._startAnchor, this._element);
this._element.parentNode.insertBefore(this._endAnchor, this._element.nextSibling);
this._hasAttached = true;
}
return this._hasAttached;
}
/**
* Waits for the zone to stabilize, then focuses the first tabbable element.
* @returns Returns a promise that resolves with a boolean, depending
* on whether focus was moved successfully.
*/
focusInitialElementWhenReady(options) {
return new Promise((resolve) => {
this._executeOnStable(() => resolve(this.focusInitialElement(options)));
});
}
/**
* Waits for the zone to stabilize, then focuses
* the first tabbable element within the focus trap region.
* @returns Returns a promise that resolves with a boolean, depending
* on whether focus was moved successfully.
*/
focusFirstTabbableElementWhenReady(options) {
return new Promise((resolve) => {
this._executeOnStable(() => resolve(this.focusFirstTabbableElement(options)));
});
}
/**
* Waits for the zone to stabilize, then focuses
* the last tabbable element within the focus trap region.
* @returns Returns a promise that resolves with a boolean, depending
* on whether focus was moved successfully.
*/
focusLastTabbableElementWhenReady(options) {
return new Promise((resolve) => {
this._executeOnStable(() => resolve(this.focusLastTabbableElement(options)));
});
}
/**
* Get the specified boundary element of the trapped region.
* @param bound The boundary to get (start or end of trapped region).
* @returns The boundary element.
*/
_getRegionBoundary(bound) {
const markers = this._element.querySelectorAll(`[cdk-focus-region-${bound}], [cdkFocusRegion${bound}], [cdk-focus-${bound}]`);
if (typeof ngDevMode === "undefined" || ngDevMode) {
for (let i = 0; i < markers.length; i++) {
if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {
console.warn(`Found use of deprecated attribute 'cdk-focus-${bound}', use 'cdkFocusRegion${bound}' instead. The deprecated attribute will be removed in 8.0.0.`, markers[i]);
} else if (markers[i].hasAttribute(`cdk-focus-region-${bound}`)) {
console.warn(`Found use of deprecated attribute 'cdk-focus-region-${bound}', use 'cdkFocusRegion${bound}' instead. The deprecated attribute will be removed in 8.0.0.`, markers[i]);
}
}
}
if (bound == "start") {
return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);
}
return markers.length ? markers[markers.length - 1] : this._getLastTabbableElement(this._element);
}
/**
* Focuses the element that should be focused when the focus trap is initialized.
* @returns Whether focus was moved successfully.
*/
focusInitialElement(options) {
const redirectToElement = this._element.querySelector(`[cdk-focus-initial], [cdkFocusInitial]`);
if (redirectToElement) {
if ((typeof ngDevMode === "undefined" || ngDevMode) && redirectToElement.hasAttribute(`cdk-focus-initial`)) {
console.warn(`Found use of deprecated attribute 'cdk-focus-initial', use 'cdkFocusInitial' instead. The deprecated attribute will be removed in 8.0.0`, redirectToElement);
}
if ((typeof ngDevMode === "undefined" || ngDevMode) && !this._checker.isFocusable(redirectToElement)) {
console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);
}
if (!this._checker.isFocusable(redirectToElement)) {
const focusableChild = this._getFirstTabbableElement(redirectToElement);
focusableChild?.focus(options);
return !!focusableChild;
}
redirectToElement.focus(options);
return true;
}
return this.focusFirstTabbableElement(options);
}
/**
* Focuses the first tabbable element within the focus trap region.
* @returns Whether focus was moved successfully.
*/
focusFirstTabbableElement(options) {
const redirectToElement = this._getRegionBoundary("start");
if (redirectToElement) {
redirectToElement.focus(options);
}
return !!redirectToElement;
}
/**
* Focuses the last tabbable element within the focus trap region.
* @returns Whether focus was moved successfully.
*/
focusLastTabbableElement(options) {
const redirectToElement = this._getRegionBoundary("end");
if (redirectToElement) {
redirectToElement.focus(options);
}
return !!redirectToElement;
}
/**
* Checks whether the focus trap has successfully been attached.
*/
hasAttached() {
return this._hasAttached;
}
/** Get the first tabbable element from a DOM subtree (inclusive). */
_getFirstTabbableElement(root) {
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
return root;
}
const children = root.children;
for (let i = 0; i < children.length; i++) {
const tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getFirstTabbableElement(children[i]) : null;
if (tabbableChild) {
return tabbableChild;
}
}
return null;
}
/** Get the last tabbable element from a DOM subtree (inclusive). */
_getLastTabbableElement(root) {
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
return root;
}
const children = root.children;
for (let i = children.length - 1; i >= 0; i--) {
const tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getLastTabbableElement(children[i]) : null;
if (tabbableChild) {
return tabbableChild;
}
}
return null;
}
/** Creates an anchor element. */
_createAnchor() {
const anchor = this._document.createElement("div");
this._toggleAnchorTabIndex(this._enabled, anchor);
anchor.classList.add("cdk-visually-hidden");
anchor.classList.add("cdk-focus-trap-anchor");
anchor.setAttribute("aria-hidden", "true");
return anchor;
}
/**
* Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
* @param isEnabled Whether the focus trap is enabled.
* @param anchor Anchor on which to toggle the tabindex.
*/
_toggleAnchorTabIndex(isEnabled, anchor) {
isEnabled ? anchor.setAttribute("tabindex", "0") : anchor.removeAttribute("tabindex");
}
/**
* Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.
* @param enabled: Whether the anchors should trap Tab.
*/
toggleAnchors(enabled) {
if (this._startAnchor && this._endAnchor) {
this._toggleAnchorTabIndex(enabled, this._startAnchor);
this._toggleAnchorTabIndex(enabled, this._endAnchor);
}
}
/** Executes a function when the zone is stable. */
_executeOnStable(fn) {
if (this._injector) {
afterNextRender(fn, {
injector: this._injector
});
} else {
setTimeout(fn);
}
}
};
var FocusTrapFactory = class _FocusTrapFactory {
_checker = inject(InteractivityChecker);
_ngZone = inject(NgZone);
_document = inject(DOCUMENT);
_injector = inject(Injector);
constructor() {
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
}
/**
* Creates a focus-trapped region around the given element.
* @param element The element around which focus will be trapped.
* @param deferCaptureElements Defers the creation of focus-capturing elements to be done
* manually by the user.
* @returns The created focus trap instance.
*/
create(element, deferCaptureElements = false) {
return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements, this._injector);
}
static \u0275fac = function FocusTrapFactory_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FocusTrapFactory)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FocusTrapFactory,
factory: _FocusTrapFactory.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FocusTrapFactory, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkTrapFocus = class _CdkTrapFocus {
_elementRef = inject(ElementRef);
_focusTrapFactory = inject(FocusTrapFactory);
/** Underlying FocusTrap instance. */
focusTrap;
/** Previously focused element to restore focus to upon destroy when using autoCapture. */
_previouslyFocusedElement = null;
/** Whether the focus trap is active. */
get enabled() {
return this.focusTrap?.enabled || false;
}
set enabled(value) {
if (this.focusTrap) {
this.focusTrap.enabled = value;
}
}
/**
* Whether the directive should automatically move focus into the trapped region upon
* initialization and return focus to the previous activeElement upon destruction.
*/
autoCapture;
constructor() {
const platform = inject(Platform);
if (platform.isBrowser) {
this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
}
}
ngOnDestroy() {
this.focusTrap?.destroy();
if (this._previouslyFocusedElement) {
this._previouslyFocusedElement.focus();
this._previouslyFocusedElement = null;
}
}
ngAfterContentInit() {
this.focusTrap?.attachAnchors();
if (this.autoCapture) {
this._captureFocus();
}
}
ngDoCheck() {
if (this.focusTrap && !this.focusTrap.hasAttached()) {
this.focusTrap.attachAnchors();
}
}
ngOnChanges(changes) {
const autoCaptureChange = changes["autoCapture"];
if (autoCaptureChange && !autoCaptureChange.firstChange && this.autoCapture && this.focusTrap?.hasAttached()) {
this._captureFocus();
}
}
_captureFocus() {
this._previouslyFocusedElement = _getFocusedElementPierceShadowDom();
this.focusTrap?.focusInitialElementWhenReady();
}
static \u0275fac = function CdkTrapFocus_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkTrapFocus)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkTrapFocus,
selectors: [["", "cdkTrapFocus", ""]],
inputs: {
enabled: [2, "cdkTrapFocus", "enabled", booleanAttribute],
autoCapture: [2, "cdkTrapFocusAutoCapture", "autoCapture", booleanAttribute]
},
exportAs: ["cdkTrapFocus"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkTrapFocus, [{
type: Directive,
args: [{
selector: "[cdkTrapFocus]",
exportAs: "cdkTrapFocus"
}]
}], () => [], {
enabled: [{
type: Input,
args: [{
alias: "cdkTrapFocus",
transform: booleanAttribute
}]
}],
autoCapture: [{
type: Input,
args: [{
alias: "cdkTrapFocusAutoCapture",
transform: booleanAttribute
}]
}]
});
})();
var LIVE_ANNOUNCER_ELEMENT_TOKEN = new InjectionToken("liveAnnouncerElement", {
providedIn: "root",
factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY
});
function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
return null;
}
var LIVE_ANNOUNCER_DEFAULT_OPTIONS = new InjectionToken("LIVE_ANNOUNCER_DEFAULT_OPTIONS");
var uniqueIds = 0;
var LiveAnnouncer = class _LiveAnnouncer {
_ngZone = inject(NgZone);
_defaultOptions = inject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, {
optional: true
});
_liveElement;
_document = inject(DOCUMENT);
_previousTimeout;
_currentPromise;
_currentResolve;
constructor() {
const elementToken = inject(LIVE_ANNOUNCER_ELEMENT_TOKEN, {
optional: true
});
this._liveElement = elementToken || this._createLiveElement();
}
announce(message, ...args) {
const defaultOptions = this._defaultOptions;
let politeness;
let duration;
if (args.length === 1 && typeof args[0] === "number") {
duration = args[0];
} else {
[politeness, duration] = args;
}
this.clear();
clearTimeout(this._previousTimeout);
if (!politeness) {
politeness = defaultOptions && defaultOptions.politeness ? defaultOptions.politeness : "polite";
}
if (duration == null && defaultOptions) {
duration = defaultOptions.duration;
}
this._liveElement.setAttribute("aria-live", politeness);
if (this._liveElement.id) {
this._exposeAnnouncerToModals(this._liveElement.id);
}
return this._ngZone.runOutsideAngular(() => {
if (!this._currentPromise) {
this._currentPromise = new Promise((resolve) => this._currentResolve = resolve);
}
clearTimeout(this._previousTimeout);
this._previousTimeout = setTimeout(() => {
this._liveElement.textContent = message;
if (typeof duration === "number") {
this._previousTimeout = setTimeout(() => this.clear(), duration);
}
this._currentResolve?.();
this._currentPromise = this._currentResolve = void 0;
}, 100);
return this._currentPromise;
});
}
/**
* Clears the current text from the announcer element. Can be used to prevent
* screen readers from reading the text out again while the user is going
* through the page landmarks.
*/
clear() {
if (this._liveElement) {
this._liveElement.textContent = "";
}
}
ngOnDestroy() {
clearTimeout(this._previousTimeout);
this._liveElement?.remove();
this._liveElement = null;
this._currentResolve?.();
this._currentPromise = this._currentResolve = void 0;
}
_createLiveElement() {
const elementClass = "cdk-live-announcer-element";
const previousElements = this._document.getElementsByClassName(elementClass);
const liveEl = this._document.createElement("div");
for (let i = 0; i < previousElements.length; i++) {
previousElements[i].remove();
}
liveEl.classList.add(elementClass);
liveEl.classList.add("cdk-visually-hidden");
liveEl.setAttribute("aria-atomic", "true");
liveEl.setAttribute("aria-live", "polite");
liveEl.id = `cdk-live-announcer-${uniqueIds++}`;
this._document.body.appendChild(liveEl);
return liveEl;
}
/**
* Some browsers won't expose the accessibility node of the live announcer element if there is an
* `aria-modal` and the live announcer is outside of it. This method works around the issue by
* pointing the `aria-owns` of all modals to the live announcer element.
*/
_exposeAnnouncerToModals(id) {
const modals = this._document.querySelectorAll('body > .cdk-overlay-container [aria-modal="true"]');
for (let i = 0; i < modals.length; i++) {
const modal = modals[i];
const ariaOwns = modal.getAttribute("aria-owns");
if (!ariaOwns) {
modal.setAttribute("aria-owns", id);
} else if (ariaOwns.indexOf(id) === -1) {
modal.setAttribute("aria-owns", ariaOwns + " " + id);
}
}
}
static \u0275fac = function LiveAnnouncer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _LiveAnnouncer)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _LiveAnnouncer,
factory: _LiveAnnouncer.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(LiveAnnouncer, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkAriaLive = class _CdkAriaLive {
_elementRef = inject(ElementRef);
_liveAnnouncer = inject(LiveAnnouncer);
_contentObserver = inject(ContentObserver);
_ngZone = inject(NgZone);
/** The aria-live politeness level to use when announcing messages. */
get politeness() {
return this._politeness;
}
set politeness(value) {
this._politeness = value === "off" || value === "assertive" ? value : "polite";
if (this._politeness === "off") {
if (this._subscription) {
this._subscription.unsubscribe();
this._subscription = null;
}
} else if (!this._subscription) {
this._subscription = this._ngZone.runOutsideAngular(() => {
return this._contentObserver.observe(this._elementRef).subscribe(() => {
const elementText = this._elementRef.nativeElement.textContent;
if (elementText !== this._previousAnnouncedText) {
this._liveAnnouncer.announce(elementText, this._politeness, this.duration);
this._previousAnnouncedText = elementText;
}
});
});
}
}
_politeness = "polite";
/** Time in milliseconds after which to clear out the announcer element. */
duration;
_previousAnnouncedText;
_subscription;
constructor() {
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
}
ngOnDestroy() {
if (this._subscription) {
this._subscription.unsubscribe();
}
}
static \u0275fac = function CdkAriaLive_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkAriaLive)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkAriaLive,
selectors: [["", "cdkAriaLive", ""]],
inputs: {
politeness: [0, "cdkAriaLive", "politeness"],
duration: [0, "cdkAriaLiveDuration", "duration"]
},
exportAs: ["cdkAriaLive"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkAriaLive, [{
type: Directive,
args: [{
selector: "[cdkAriaLive]",
exportAs: "cdkAriaLive"
}]
}], () => [], {
politeness: [{
type: Input,
args: ["cdkAriaLive"]
}],
duration: [{
type: Input,
args: ["cdkAriaLiveDuration"]
}]
});
})();
var HighContrastMode;
(function(HighContrastMode2) {
HighContrastMode2[HighContrastMode2["NONE"] = 0] = "NONE";
HighContrastMode2[HighContrastMode2["BLACK_ON_WHITE"] = 1] = "BLACK_ON_WHITE";
HighContrastMode2[HighContrastMode2["WHITE_ON_BLACK"] = 2] = "WHITE_ON_BLACK";
})(HighContrastMode || (HighContrastMode = {}));
var BLACK_ON_WHITE_CSS_CLASS = "cdk-high-contrast-black-on-white";
var WHITE_ON_BLACK_CSS_CLASS = "cdk-high-contrast-white-on-black";
var HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = "cdk-high-contrast-active";
var HighContrastModeDetector = class _HighContrastModeDetector {
_platform = inject(Platform);
/**
* Figuring out the high contrast mode and adding the body classes can cause
* some expensive layouts. This flag is used to ensure that we only do it once.
*/
_hasCheckedHighContrastMode;
_document = inject(DOCUMENT);
_breakpointSubscription;
constructor() {
this._breakpointSubscription = inject(BreakpointObserver).observe("(forced-colors: active)").subscribe(() => {
if (this._hasCheckedHighContrastMode) {
this._hasCheckedHighContrastMode = false;
this._applyBodyHighContrastModeCssClasses();
}
});
}
/** Gets the current high-contrast-mode for the page. */
getHighContrastMode() {
if (!this._platform.isBrowser) {
return HighContrastMode.NONE;
}
const testElement = this._document.createElement("div");
testElement.style.backgroundColor = "rgb(1,2,3)";
testElement.style.position = "absolute";
this._document.body.appendChild(testElement);
const documentWindow = this._document.defaultView || window;
const computedStyle = documentWindow && documentWindow.getComputedStyle ? documentWindow.getComputedStyle(testElement) : null;
const computedColor = (computedStyle && computedStyle.backgroundColor || "").replace(/ /g, "");
testElement.remove();
switch (computedColor) {
// Pre Windows 11 dark theme.
case "rgb(0,0,0)":
// Windows 11 dark themes.
case "rgb(45,50,54)":
case "rgb(32,32,32)":
return HighContrastMode.WHITE_ON_BLACK;
// Pre Windows 11 light theme.
case "rgb(255,255,255)":
// Windows 11 light theme.
case "rgb(255,250,239)":
return HighContrastMode.BLACK_ON_WHITE;
}
return HighContrastMode.NONE;
}
ngOnDestroy() {
this._breakpointSubscription.unsubscribe();
}
/** Applies CSS classes indicating high-contrast mode to document body (browser-only). */
_applyBodyHighContrastModeCssClasses() {
if (!this._hasCheckedHighContrastMode && this._platform.isBrowser && this._document.body) {
const bodyClasses = this._document.body.classList;
bodyClasses.remove(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS, BLACK_ON_WHITE_CSS_CLASS, WHITE_ON_BLACK_CSS_CLASS);
this._hasCheckedHighContrastMode = true;
const mode = this.getHighContrastMode();
if (mode === HighContrastMode.BLACK_ON_WHITE) {
bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS, BLACK_ON_WHITE_CSS_CLASS);
} else if (mode === HighContrastMode.WHITE_ON_BLACK) {
bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS, WHITE_ON_BLACK_CSS_CLASS);
}
}
}
static \u0275fac = function HighContrastModeDetector_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _HighContrastModeDetector)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _HighContrastModeDetector,
factory: _HighContrastModeDetector.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(HighContrastModeDetector, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var A11yModule = class _A11yModule {
constructor() {
inject(HighContrastModeDetector)._applyBodyHighContrastModeCssClasses();
}
static \u0275fac = function A11yModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _A11yModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _A11yModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [ObserversModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(A11yModule, [{
type: NgModule,
args: [{
imports: [ObserversModule, CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus]
}]
}], () => [], null);
})();
// node_modules/@angular/cdk/fesm2022/test-environment-CT0XxPyp.mjs
function _isTestEnvironment() {
return (
// @ts-ignore
typeof __karma__ !== "undefined" && !!__karma__ || // @ts-ignore
typeof jasmine !== "undefined" && !!jasmine || // @ts-ignore
typeof jest !== "undefined" && !!jest || // @ts-ignore
typeof Mocha !== "undefined" && !!Mocha
);
}
// node_modules/@angular/cdk/fesm2022/css-pixel-value-C_HEqLhI.mjs
function coerceCssPixelValue(value) {
if (value == null) {
return "";
}
return typeof value === "string" ? value : `${value}px`;
}
// node_modules/@angular/cdk/fesm2022/directionality-CBXD4hga.mjs
var DIR_DOCUMENT = new InjectionToken("cdk-dir-doc", {
providedIn: "root",
factory: DIR_DOCUMENT_FACTORY
});
function DIR_DOCUMENT_FACTORY() {
return inject(DOCUMENT);
}
var RTL_LOCALE_PATTERN = /^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Adlm|Arab|Hebr|Nkoo|Rohg|Thaa))(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)/i;
function _resolveDirectionality(rawValue) {
const value = rawValue?.toLowerCase() || "";
if (value === "auto" && typeof navigator !== "undefined" && navigator?.language) {
return RTL_LOCALE_PATTERN.test(navigator.language) ? "rtl" : "ltr";
}
return value === "rtl" ? "rtl" : "ltr";
}
var Directionality = class _Directionality {
/** The current 'ltr' or 'rtl' value. */
value = "ltr";
/** Stream that emits whenever the 'ltr' / 'rtl' state changes. */
change = new EventEmitter();
constructor() {
const _document2 = inject(DIR_DOCUMENT, {
optional: true
});
if (_document2) {
const bodyDir = _document2.body ? _document2.body.dir : null;
const htmlDir = _document2.documentElement ? _document2.documentElement.dir : null;
this.value = _resolveDirectionality(bodyDir || htmlDir || "ltr");
}
}
ngOnDestroy() {
this.change.complete();
}
static \u0275fac = function Directionality_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Directionality)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Directionality,
factory: _Directionality.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Directionality, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/cdk/fesm2022/scrolling-BkvA05C8.mjs
var RtlScrollAxisType;
(function(RtlScrollAxisType2) {
RtlScrollAxisType2[RtlScrollAxisType2["NORMAL"] = 0] = "NORMAL";
RtlScrollAxisType2[RtlScrollAxisType2["NEGATED"] = 1] = "NEGATED";
RtlScrollAxisType2[RtlScrollAxisType2["INVERTED"] = 2] = "INVERTED";
})(RtlScrollAxisType || (RtlScrollAxisType = {}));
var rtlScrollAxisType;
var scrollBehaviorSupported;
function supportsScrollBehavior() {
if (scrollBehaviorSupported == null) {
if (typeof document !== "object" || !document || typeof Element !== "function" || !Element) {
scrollBehaviorSupported = false;
return scrollBehaviorSupported;
}
if ("scrollBehavior" in document.documentElement.style) {
scrollBehaviorSupported = true;
} else {
const scrollToFunction = Element.prototype.scrollTo;
if (scrollToFunction) {
scrollBehaviorSupported = !/\{\s*\[native code\]\s*\}/.test(scrollToFunction.toString());
} else {
scrollBehaviorSupported = false;
}
}
}
return scrollBehaviorSupported;
}
function getRtlScrollAxisType() {
if (typeof document !== "object" || !document) {
return RtlScrollAxisType.NORMAL;
}
if (rtlScrollAxisType == null) {
const scrollContainer = document.createElement("div");
const containerStyle = scrollContainer.style;
scrollContainer.dir = "rtl";
containerStyle.width = "1px";
containerStyle.overflow = "auto";
containerStyle.visibility = "hidden";
containerStyle.pointerEvents = "none";
containerStyle.position = "absolute";
const content = document.createElement("div");
const contentStyle = content.style;
contentStyle.width = "2px";
contentStyle.height = "1px";
scrollContainer.appendChild(content);
document.body.appendChild(scrollContainer);
rtlScrollAxisType = RtlScrollAxisType.NORMAL;
if (scrollContainer.scrollLeft === 0) {
scrollContainer.scrollLeft = 1;
rtlScrollAxisType = scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED;
}
scrollContainer.remove();
}
return rtlScrollAxisType;
}
// node_modules/@angular/cdk/fesm2022/bidi.mjs
var Dir = class _Dir {
/** Normalized direction that accounts for invalid/unsupported values. */
_dir = "ltr";
/** Whether the `value` has been set to its initial value. */
_isInitialized = false;
/** Direction as passed in by the consumer. */
_rawDir;
/** Event emitted when the direction changes. */
change = new EventEmitter();
/** @docs-private */
get dir() {
return this._dir;
}
set dir(value) {
const previousValue = this._dir;
this._dir = _resolveDirectionality(value);
this._rawDir = value;
if (previousValue !== this._dir && this._isInitialized) {
this.change.emit(this._dir);
}
}
/** Current layout direction of the element. */
get value() {
return this.dir;
}
/** Initialize once default value has been set. */
ngAfterContentInit() {
this._isInitialized = true;
}
ngOnDestroy() {
this.change.complete();
}
static \u0275fac = function Dir_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Dir)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _Dir,
selectors: [["", "dir", ""]],
hostVars: 1,
hostBindings: function Dir_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("dir", ctx._rawDir);
}
},
inputs: {
dir: "dir"
},
outputs: {
change: "dirChange"
},
exportAs: ["dir"],
features: [\u0275\u0275ProvidersFeature([{
provide: Directionality,
useExisting: _Dir
}])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Dir, [{
type: Directive,
args: [{
selector: "[dir]",
providers: [{
provide: Directionality,
useExisting: Dir
}],
host: {
"[attr.dir]": "_rawDir"
},
exportAs: "dir"
}]
}], null, {
change: [{
type: Output,
args: ["dirChange"]
}],
dir: [{
type: Input
}]
});
})();
var BidiModule = class _BidiModule {
static \u0275fac = function BidiModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BidiModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _BidiModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BidiModule, [{
type: NgModule,
args: [{
imports: [Dir],
exports: [Dir]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/data-source-D34wiQZj.mjs
var DataSource = class {
};
function isDataSource(value) {
return value && typeof value.connect === "function" && !(value instanceof ConnectableObservable);
}
// node_modules/@angular/cdk/fesm2022/recycle-view-repeater-strategy-DoWdPqVw.mjs
var ArrayDataSource = class extends DataSource {
_data;
constructor(_data) {
super();
this._data = _data;
}
connect() {
return isObservable(this._data) ? this._data : of(this._data);
}
disconnect() {
}
};
var _ViewRepeaterOperation;
(function(_ViewRepeaterOperation2) {
_ViewRepeaterOperation2[_ViewRepeaterOperation2["REPLACED"] = 0] = "REPLACED";
_ViewRepeaterOperation2[_ViewRepeaterOperation2["INSERTED"] = 1] = "INSERTED";
_ViewRepeaterOperation2[_ViewRepeaterOperation2["MOVED"] = 2] = "MOVED";
_ViewRepeaterOperation2[_ViewRepeaterOperation2["REMOVED"] = 3] = "REMOVED";
})(_ViewRepeaterOperation || (_ViewRepeaterOperation = {}));
var _VIEW_REPEATER_STRATEGY = new InjectionToken("_ViewRepeater");
var _RecycleViewRepeaterStrategy = class {
/**
* The size of the cache used to store unused views.
* Setting the cache size to `0` will disable caching. Defaults to 20 views.
*/
viewCacheSize = 20;
/**
* View cache that stores embedded view instances that have been previously stamped out,
* but don't are not currently rendered. The view repeater will reuse these views rather than
* creating brand new ones.
*
* TODO(michaeljamesparsons) Investigate whether using a linked list would improve performance.
*/
_viewCache = [];
/** Apply changes to the DOM. */
applyChanges(changes, viewContainerRef, itemContextFactory, itemValueResolver, itemViewChanged) {
changes.forEachOperation((record, adjustedPreviousIndex, currentIndex) => {
let view;
let operation;
if (record.previousIndex == null) {
const viewArgsFactory = () => itemContextFactory(record, adjustedPreviousIndex, currentIndex);
view = this._insertView(viewArgsFactory, currentIndex, viewContainerRef, itemValueResolver(record));
operation = view ? _ViewRepeaterOperation.INSERTED : _ViewRepeaterOperation.REPLACED;
} else if (currentIndex == null) {
this._detachAndCacheView(adjustedPreviousIndex, viewContainerRef);
operation = _ViewRepeaterOperation.REMOVED;
} else {
view = this._moveView(adjustedPreviousIndex, currentIndex, viewContainerRef, itemValueResolver(record));
operation = _ViewRepeaterOperation.MOVED;
}
if (itemViewChanged) {
itemViewChanged({
context: view?.context,
operation,
record
});
}
});
}
detach() {
for (const view of this._viewCache) {
view.destroy();
}
this._viewCache = [];
}
/**
* Inserts a view for a new item, either from the cache or by creating a new
* one. Returns `undefined` if the item was inserted into a cached view.
*/
_insertView(viewArgsFactory, currentIndex, viewContainerRef, value) {
const cachedView = this._insertViewFromCache(currentIndex, viewContainerRef);
if (cachedView) {
cachedView.context.$implicit = value;
return void 0;
}
const viewArgs = viewArgsFactory();
return viewContainerRef.createEmbeddedView(viewArgs.templateRef, viewArgs.context, viewArgs.index);
}
/** Detaches the view at the given index and inserts into the view cache. */
_detachAndCacheView(index, viewContainerRef) {
const detachedView = viewContainerRef.detach(index);
this._maybeCacheView(detachedView, viewContainerRef);
}
/** Moves view at the previous index to the current index. */
_moveView(adjustedPreviousIndex, currentIndex, viewContainerRef, value) {
const view = viewContainerRef.get(adjustedPreviousIndex);
viewContainerRef.move(view, currentIndex);
view.context.$implicit = value;
return view;
}
/**
* Cache the given detached view. If the cache is full, the view will be
* destroyed.
*/
_maybeCacheView(view, viewContainerRef) {
if (this._viewCache.length < this.viewCacheSize) {
this._viewCache.push(view);
} else {
const index = viewContainerRef.indexOf(view);
if (index === -1) {
view.destroy();
} else {
viewContainerRef.remove(index);
}
}
}
/** Inserts a recycled view from the cache at the given index. */
_insertViewFromCache(index, viewContainerRef) {
const cachedView = this._viewCache.pop();
if (cachedView) {
viewContainerRef.insert(cachedView, index);
}
return cachedView || null;
}
};
// node_modules/@angular/cdk/fesm2022/scrolling.mjs
var _c02 = ["contentWrapper"];
var _c1 = ["*"];
var VIRTUAL_SCROLL_STRATEGY = new InjectionToken("VIRTUAL_SCROLL_STRATEGY");
var FixedSizeVirtualScrollStrategy = class {
_scrolledIndexChange = new Subject();
/** @docs-private Implemented as part of VirtualScrollStrategy. */
scrolledIndexChange = this._scrolledIndexChange.pipe(distinctUntilChanged());
/** The attached viewport. */
_viewport = null;
/** The size of the items in the virtually scrolling list. */
_itemSize;
/** The minimum amount of buffer rendered beyond the viewport (in pixels). */
_minBufferPx;
/** The number of buffer items to render beyond the edge of the viewport (in pixels). */
_maxBufferPx;
/**
* @param itemSize The size of the items in the virtually scrolling list.
* @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more
* @param maxBufferPx The amount of buffer (in pixels) to render when rendering more.
*/
constructor(itemSize, minBufferPx, maxBufferPx) {
this._itemSize = itemSize;
this._minBufferPx = minBufferPx;
this._maxBufferPx = maxBufferPx;
}
/**
* Attaches this scroll strategy to a viewport.
* @param viewport The viewport to attach this strategy to.
*/
attach(viewport) {
this._viewport = viewport;
this._updateTotalContentSize();
this._updateRenderedRange();
}
/** Detaches this scroll strategy from the currently attached viewport. */
detach() {
this._scrolledIndexChange.complete();
this._viewport = null;
}
/**
* Update the item size and buffer size.
* @param itemSize The size of the items in the virtually scrolling list.
* @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more
* @param maxBufferPx The amount of buffer (in pixels) to render when rendering more.
*/
updateItemAndBufferSize(itemSize, minBufferPx, maxBufferPx) {
if (maxBufferPx < minBufferPx && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error("CDK virtual scroll: maxBufferPx must be greater than or equal to minBufferPx");
}
this._itemSize = itemSize;
this._minBufferPx = minBufferPx;
this._maxBufferPx = maxBufferPx;
this._updateTotalContentSize();
this._updateRenderedRange();
}
/** @docs-private Implemented as part of VirtualScrollStrategy. */
onContentScrolled() {
this._updateRenderedRange();
}
/** @docs-private Implemented as part of VirtualScrollStrategy. */
onDataLengthChanged() {
this._updateTotalContentSize();
this._updateRenderedRange();
}
/** @docs-private Implemented as part of VirtualScrollStrategy. */
onContentRendered() {
}
/** @docs-private Implemented as part of VirtualScrollStrategy. */
onRenderedOffsetChanged() {
}
/**
* Scroll to the offset for the given index.
* @param index The index of the element to scroll to.
* @param behavior The ScrollBehavior to use when scrolling.
*/
scrollToIndex(index, behavior) {
if (this._viewport) {
this._viewport.scrollToOffset(index * this._itemSize, behavior);
}
}
/** Update the viewport's total content size. */
_updateTotalContentSize() {
if (!this._viewport) {
return;
}
this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSize);
}
/** Update the viewport's rendered range. */
_updateRenderedRange() {
if (!this._viewport) {
return;
}
const renderedRange = this._viewport.getRenderedRange();
const newRange = {
start: renderedRange.start,
end: renderedRange.end
};
const viewportSize = this._viewport.getViewportSize();
const dataLength = this._viewport.getDataLength();
let scrollOffset = this._viewport.measureScrollOffset();
let firstVisibleIndex = this._itemSize > 0 ? scrollOffset / this._itemSize : 0;
if (newRange.end > dataLength) {
const maxVisibleItems = Math.ceil(viewportSize / this._itemSize);
const newVisibleIndex = Math.max(0, Math.min(firstVisibleIndex, dataLength - maxVisibleItems));
if (firstVisibleIndex != newVisibleIndex) {
firstVisibleIndex = newVisibleIndex;
scrollOffset = newVisibleIndex * this._itemSize;
newRange.start = Math.floor(firstVisibleIndex);
}
newRange.end = Math.max(0, Math.min(dataLength, newRange.start + maxVisibleItems));
}
const startBuffer = scrollOffset - newRange.start * this._itemSize;
if (startBuffer < this._minBufferPx && newRange.start != 0) {
const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSize);
newRange.start = Math.max(0, newRange.start - expandStart);
newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSize));
} else {
const endBuffer = newRange.end * this._itemSize - (scrollOffset + viewportSize);
if (endBuffer < this._minBufferPx && newRange.end != dataLength) {
const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSize);
if (expandEnd > 0) {
newRange.end = Math.min(dataLength, newRange.end + expandEnd);
newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSize));
}
}
}
this._viewport.setRenderedRange(newRange);
this._viewport.setRenderedContentOffset(this._itemSize * newRange.start);
this._scrolledIndexChange.next(Math.floor(firstVisibleIndex));
}
};
function _fixedSizeVirtualScrollStrategyFactory(fixedSizeDir) {
return fixedSizeDir._scrollStrategy;
}
var CdkFixedSizeVirtualScroll = class _CdkFixedSizeVirtualScroll {
/** The size of the items in the list (in pixels). */
get itemSize() {
return this._itemSize;
}
set itemSize(value) {
this._itemSize = coerceNumberProperty(value);
}
_itemSize = 20;
/**
* The minimum amount of buffer rendered beyond the viewport (in pixels).
* If the amount of buffer dips below this number, more items will be rendered. Defaults to 100px.
*/
get minBufferPx() {
return this._minBufferPx;
}
set minBufferPx(value) {
this._minBufferPx = coerceNumberProperty(value);
}
_minBufferPx = 100;
/**
* The number of pixels worth of buffer to render for when rendering new items. Defaults to 200px.
*/
get maxBufferPx() {
return this._maxBufferPx;
}
set maxBufferPx(value) {
this._maxBufferPx = coerceNumberProperty(value);
}
_maxBufferPx = 200;
/** The scroll strategy used by this directive. */
_scrollStrategy = new FixedSizeVirtualScrollStrategy(this.itemSize, this.minBufferPx, this.maxBufferPx);
ngOnChanges() {
this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.minBufferPx, this.maxBufferPx);
}
static \u0275fac = function CdkFixedSizeVirtualScroll_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkFixedSizeVirtualScroll)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkFixedSizeVirtualScroll,
selectors: [["cdk-virtual-scroll-viewport", "itemSize", ""]],
inputs: {
itemSize: "itemSize",
minBufferPx: "minBufferPx",
maxBufferPx: "maxBufferPx"
},
features: [\u0275\u0275ProvidersFeature([{
provide: VIRTUAL_SCROLL_STRATEGY,
useFactory: _fixedSizeVirtualScrollStrategyFactory,
deps: [forwardRef(() => _CdkFixedSizeVirtualScroll)]
}]), \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkFixedSizeVirtualScroll, [{
type: Directive,
args: [{
selector: "cdk-virtual-scroll-viewport[itemSize]",
providers: [{
provide: VIRTUAL_SCROLL_STRATEGY,
useFactory: _fixedSizeVirtualScrollStrategyFactory,
deps: [forwardRef(() => CdkFixedSizeVirtualScroll)]
}]
}]
}], null, {
itemSize: [{
type: Input
}],
minBufferPx: [{
type: Input
}],
maxBufferPx: [{
type: Input
}]
});
})();
var DEFAULT_SCROLL_TIME = 20;
var ScrollDispatcher = class _ScrollDispatcher {
_ngZone = inject(NgZone);
_platform = inject(Platform);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_cleanupGlobalListener;
constructor() {
}
/** Subject for notifying that a registered scrollable reference element has been scrolled. */
_scrolled = new Subject();
/** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */
_scrolledCount = 0;
/**
* Map of all the scrollable references that are registered with the service and their
* scroll event subscriptions.
*/
scrollContainers = /* @__PURE__ */ new Map();
/**
* Registers a scrollable instance with the service and listens for its scrolled events. When the
* scrollable is scrolled, the service emits the event to its scrolled observable.
* @param scrollable Scrollable instance to be registered.
*/
register(scrollable) {
if (!this.scrollContainers.has(scrollable)) {
this.scrollContainers.set(scrollable, scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable)));
}
}
/**
* De-registers a Scrollable reference and unsubscribes from its scroll event observable.
* @param scrollable Scrollable instance to be deregistered.
*/
deregister(scrollable) {
const scrollableReference = this.scrollContainers.get(scrollable);
if (scrollableReference) {
scrollableReference.unsubscribe();
this.scrollContainers.delete(scrollable);
}
}
/**
* Returns an observable that emits an event whenever any of the registered Scrollable
* references (or window, document, or body) fire a scrolled event. Can provide a time in ms
* to override the default "throttle" time.
*
* **Note:** in order to avoid hitting change detection for every scroll event,
* all of the events emitted from this stream will be run outside the Angular zone.
* If you need to update any data bindings as a result of a scroll event, you have
* to run the callback using `NgZone.run`.
*/
scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) {
if (!this._platform.isBrowser) {
return of();
}
return new Observable((observer) => {
if (!this._cleanupGlobalListener) {
this._cleanupGlobalListener = this._ngZone.runOutsideAngular(() => this._renderer.listen("document", "scroll", () => this._scrolled.next()));
}
const subscription = auditTimeInMs > 0 ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer) : this._scrolled.subscribe(observer);
this._scrolledCount++;
return () => {
subscription.unsubscribe();
this._scrolledCount--;
if (!this._scrolledCount) {
this._cleanupGlobalListener?.();
this._cleanupGlobalListener = void 0;
}
};
});
}
ngOnDestroy() {
this._cleanupGlobalListener?.();
this._cleanupGlobalListener = void 0;
this.scrollContainers.forEach((_, container) => this.deregister(container));
this._scrolled.complete();
}
/**
* Returns an observable that emits whenever any of the
* scrollable ancestors of an element are scrolled.
* @param elementOrElementRef Element whose ancestors to listen for.
* @param auditTimeInMs Time to throttle the scroll events.
*/
ancestorScrolled(elementOrElementRef, auditTimeInMs) {
const ancestors = this.getAncestorScrollContainers(elementOrElementRef);
return this.scrolled(auditTimeInMs).pipe(filter((target) => !target || ancestors.indexOf(target) > -1));
}
/** Returns all registered Scrollables that contain the provided element. */
getAncestorScrollContainers(elementOrElementRef) {
const scrollingContainers = [];
this.scrollContainers.forEach((_subscription, scrollable) => {
if (this._scrollableContainsElement(scrollable, elementOrElementRef)) {
scrollingContainers.push(scrollable);
}
});
return scrollingContainers;
}
/** Returns true if the element is contained within the provided Scrollable. */
_scrollableContainsElement(scrollable, elementOrElementRef) {
let element = coerceElement(elementOrElementRef);
let scrollableElement = scrollable.getElementRef().nativeElement;
do {
if (element == scrollableElement) {
return true;
}
} while (element = element.parentElement);
return false;
}
static \u0275fac = function ScrollDispatcher_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ScrollDispatcher)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ScrollDispatcher,
factory: _ScrollDispatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ScrollDispatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkScrollable = class _CdkScrollable {
elementRef = inject(ElementRef);
scrollDispatcher = inject(ScrollDispatcher);
ngZone = inject(NgZone);
dir = inject(Directionality, {
optional: true
});
_scrollElement = this.elementRef.nativeElement;
_destroyed = new Subject();
_renderer = inject(Renderer2);
_cleanupScroll;
_elementScrolled = new Subject();
constructor() {
}
ngOnInit() {
this._cleanupScroll = this.ngZone.runOutsideAngular(() => this._renderer.listen(this._scrollElement, "scroll", (event) => this._elementScrolled.next(event)));
this.scrollDispatcher.register(this);
}
ngOnDestroy() {
this._cleanupScroll?.();
this._elementScrolled.complete();
this.scrollDispatcher.deregister(this);
this._destroyed.next();
this._destroyed.complete();
}
/** Returns observable that emits when a scroll event is fired on the host element. */
elementScrolled() {
return this._elementScrolled;
}
/** Gets the ElementRef for the viewport. */
getElementRef() {
return this.elementRef;
}
/**
* Scrolls to the specified offsets. This is a normalized version of the browser's native scrollTo
* method, since browsers are not consistent about what scrollLeft means in RTL. For this method
* left and right always refer to the left and right side of the scrolling container irrespective
* of the layout direction. start and end refer to left and right in an LTR context and vice-versa
* in an RTL context.
* @param options specified the offsets to scroll to.
*/
scrollTo(options) {
const el = this.elementRef.nativeElement;
const isRtl = this.dir && this.dir.value == "rtl";
if (options.left == null) {
options.left = isRtl ? options.end : options.start;
}
if (options.right == null) {
options.right = isRtl ? options.start : options.end;
}
if (options.bottom != null) {
options.top = el.scrollHeight - el.clientHeight - options.bottom;
}
if (isRtl && getRtlScrollAxisType() != RtlScrollAxisType.NORMAL) {
if (options.left != null) {
options.right = el.scrollWidth - el.clientWidth - options.left;
}
if (getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {
options.left = options.right;
} else if (getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {
options.left = options.right ? -options.right : options.right;
}
} else {
if (options.right != null) {
options.left = el.scrollWidth - el.clientWidth - options.right;
}
}
this._applyScrollToOptions(options);
}
_applyScrollToOptions(options) {
const el = this.elementRef.nativeElement;
if (supportsScrollBehavior()) {
el.scrollTo(options);
} else {
if (options.top != null) {
el.scrollTop = options.top;
}
if (options.left != null) {
el.scrollLeft = options.left;
}
}
}
/**
* Measures the scroll offset relative to the specified edge of the viewport. This method can be
* used instead of directly checking scrollLeft or scrollTop, since browsers are not consistent
* about what scrollLeft means in RTL. The values returned by this method are normalized such that
* left and right always refer to the left and right side of the scrolling container irrespective
* of the layout direction. start and end refer to left and right in an LTR context and vice-versa
* in an RTL context.
* @param from The edge to measure from.
*/
measureScrollOffset(from2) {
const LEFT = "left";
const RIGHT = "right";
const el = this.elementRef.nativeElement;
if (from2 == "top") {
return el.scrollTop;
}
if (from2 == "bottom") {
return el.scrollHeight - el.clientHeight - el.scrollTop;
}
const isRtl = this.dir && this.dir.value == "rtl";
if (from2 == "start") {
from2 = isRtl ? RIGHT : LEFT;
} else if (from2 == "end") {
from2 = isRtl ? LEFT : RIGHT;
}
if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.INVERTED) {
if (from2 == LEFT) {
return el.scrollWidth - el.clientWidth - el.scrollLeft;
} else {
return el.scrollLeft;
}
} else if (isRtl && getRtlScrollAxisType() == RtlScrollAxisType.NEGATED) {
if (from2 == LEFT) {
return el.scrollLeft + el.scrollWidth - el.clientWidth;
} else {
return -el.scrollLeft;
}
} else {
if (from2 == LEFT) {
return el.scrollLeft;
} else {
return el.scrollWidth - el.clientWidth - el.scrollLeft;
}
}
}
static \u0275fac = function CdkScrollable_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkScrollable)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkScrollable,
selectors: [["", "cdk-scrollable", ""], ["", "cdkScrollable", ""]]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkScrollable, [{
type: Directive,
args: [{
selector: "[cdk-scrollable], [cdkScrollable]"
}]
}], () => [], null);
})();
var DEFAULT_RESIZE_TIME = 20;
var ViewportRuler = class _ViewportRuler {
_platform = inject(Platform);
_listeners;
/** Cached viewport dimensions. */
_viewportSize;
/** Stream of viewport change events. */
_change = new Subject();
/** Used to reference correct document/window */
_document = inject(DOCUMENT, {
optional: true
});
constructor() {
const ngZone = inject(NgZone);
const renderer = inject(RendererFactory2).createRenderer(null, null);
ngZone.runOutsideAngular(() => {
if (this._platform.isBrowser) {
const changeListener = (event) => this._change.next(event);
this._listeners = [renderer.listen("window", "resize", changeListener), renderer.listen("window", "orientationchange", changeListener)];
}
this.change().subscribe(() => this._viewportSize = null);
});
}
ngOnDestroy() {
this._listeners?.forEach((cleanup) => cleanup());
this._change.complete();
}
/** Returns the viewport's width and height. */
getViewportSize() {
if (!this._viewportSize) {
this._updateViewportSize();
}
const output = {
width: this._viewportSize.width,
height: this._viewportSize.height
};
if (!this._platform.isBrowser) {
this._viewportSize = null;
}
return output;
}
/** Gets a DOMRect for the viewport's bounds. */
getViewportRect() {
const scrollPosition = this.getViewportScrollPosition();
const {
width,
height
} = this.getViewportSize();
return {
top: scrollPosition.top,
left: scrollPosition.left,
bottom: scrollPosition.top + height,
right: scrollPosition.left + width,
height,
width
};
}
/** Gets the (top, left) scroll position of the viewport. */
getViewportScrollPosition() {
if (!this._platform.isBrowser) {
return {
top: 0,
left: 0
};
}
const document2 = this._document;
const window2 = this._getWindow();
const documentElement = document2.documentElement;
const documentRect = documentElement.getBoundingClientRect();
const top = -documentRect.top || document2.body.scrollTop || window2.scrollY || documentElement.scrollTop || 0;
const left = -documentRect.left || document2.body.scrollLeft || window2.scrollX || documentElement.scrollLeft || 0;
return {
top,
left
};
}
/**
* Returns a stream that emits whenever the size of the viewport changes.
* This stream emits outside of the Angular zone.
* @param throttleTime Time in milliseconds to throttle the stream.
*/
change(throttleTime = DEFAULT_RESIZE_TIME) {
return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change;
}
/** Use defaultView of injected document if available or fallback to global window reference */
_getWindow() {
return this._document.defaultView || window;
}
/** Updates the cached viewport size. */
_updateViewportSize() {
const window2 = this._getWindow();
this._viewportSize = this._platform.isBrowser ? {
width: window2.innerWidth,
height: window2.innerHeight
} : {
width: 0,
height: 0
};
}
static \u0275fac = function ViewportRuler_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ViewportRuler)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ViewportRuler,
factory: _ViewportRuler.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ViewportRuler, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var VIRTUAL_SCROLLABLE = new InjectionToken("VIRTUAL_SCROLLABLE");
var CdkVirtualScrollable = class _CdkVirtualScrollable extends CdkScrollable {
constructor() {
super();
}
/**
* Measure the viewport size for the provided orientation.
*
* @param orientation The orientation to measure the size from.
*/
measureViewportSize(orientation) {
const viewportEl = this.elementRef.nativeElement;
return orientation === "horizontal" ? viewportEl.clientWidth : viewportEl.clientHeight;
}
static \u0275fac = function CdkVirtualScrollable_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkVirtualScrollable)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkVirtualScrollable,
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollable, [{
type: Directive
}], () => [], null);
})();
function rangesEqual(r1, r2) {
return r1.start == r2.start && r1.end == r2.end;
}
var SCROLL_SCHEDULER = typeof requestAnimationFrame !== "undefined" ? animationFrameScheduler : asapScheduler;
var CdkVirtualScrollViewport = class _CdkVirtualScrollViewport extends CdkVirtualScrollable {
elementRef = inject(ElementRef);
_changeDetectorRef = inject(ChangeDetectorRef);
_scrollStrategy = inject(VIRTUAL_SCROLL_STRATEGY, {
optional: true
});
scrollable = inject(VIRTUAL_SCROLLABLE, {
optional: true
});
_platform = inject(Platform);
/** Emits when the viewport is detached from a CdkVirtualForOf. */
_detachedSubject = new Subject();
/** Emits when the rendered range changes. */
_renderedRangeSubject = new Subject();
/** The direction the viewport scrolls. */
get orientation() {
return this._orientation;
}
set orientation(orientation) {
if (this._orientation !== orientation) {
this._orientation = orientation;
this._calculateSpacerSize();
}
}
_orientation = "vertical";
/**
* Whether rendered items should persist in the DOM after scrolling out of view. By default, items
* will be removed.
*/
appendOnly = false;
// Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll
// strategy lazily (i.e. only if the user is actually listening to the events). We do this because
// depending on how the strategy calculates the scrolled index, it may come at a cost to
// performance.
/** Emits when the index of the first element visible in the viewport changes. */
scrolledIndexChange = new Observable((observer) => this._scrollStrategy.scrolledIndexChange.subscribe((index) => Promise.resolve().then(() => this.ngZone.run(() => observer.next(index)))));
/** The element that wraps the rendered content. */
_contentWrapper;
/** A stream that emits whenever the rendered range changes. */
renderedRangeStream = this._renderedRangeSubject;
/**
* The total size of all content (in pixels), including content that is not currently rendered.
*/
_totalContentSize = 0;
/** A string representing the `style.width` property value to be used for the spacer element. */
_totalContentWidth = "";
/** A string representing the `style.height` property value to be used for the spacer element. */
_totalContentHeight = "";
/**
* The CSS transform applied to the rendered subset of items so that they appear within the bounds
* of the visible viewport.
*/
_renderedContentTransform;
/** The currently rendered range of indices. */
_renderedRange = {
start: 0,
end: 0
};
/** The length of the data bound to this viewport (in number of items). */
_dataLength = 0;
/** The size of the viewport (in pixels). */
_viewportSize = 0;
/** the currently attached CdkVirtualScrollRepeater. */
_forOf;
/** The last rendered content offset that was set. */
_renderedContentOffset = 0;
/**
* Whether the last rendered content offset was to the end of the content (and therefore needs to
* be rewritten as an offset to the start of the content).
*/
_renderedContentOffsetNeedsRewrite = false;
/** Whether there is a pending change detection cycle. */
_isChangeDetectionPending = false;
/** A list of functions to run after the next change detection cycle. */
_runAfterChangeDetection = [];
/** Subscription to changes in the viewport size. */
_viewportChanges = Subscription.EMPTY;
_injector = inject(Injector);
_isDestroyed = false;
constructor() {
super();
const viewportRuler = inject(ViewportRuler);
if (!this._scrollStrategy && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.');
}
this._viewportChanges = viewportRuler.change().subscribe(() => {
this.checkViewportSize();
});
if (!this.scrollable) {
this.elementRef.nativeElement.classList.add("cdk-virtual-scrollable");
this.scrollable = this;
}
}
ngOnInit() {
if (!this._platform.isBrowser) {
return;
}
if (this.scrollable === this) {
super.ngOnInit();
}
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {
this._measureViewportSize();
this._scrollStrategy.attach(this);
this.scrollable.elementScrolled().pipe(
// Start off with a fake scroll event so we properly detect our initial position.
startWith(null),
// Collect multiple events into one until the next animation frame. This way if
// there are multiple scroll events in the same frame we only need to recheck
// our layout once.
auditTime(0, SCROLL_SCHEDULER),
// Usually `elementScrolled` is completed when the scrollable is destroyed, but
// that may not be the case if a `CdkVirtualScrollableElement` is used so we have
// to unsubscribe here just in case.
takeUntil(this._destroyed)
).subscribe(() => this._scrollStrategy.onContentScrolled());
this._markChangeDetectionNeeded();
}));
}
ngOnDestroy() {
this.detach();
this._scrollStrategy.detach();
this._renderedRangeSubject.complete();
this._detachedSubject.complete();
this._viewportChanges.unsubscribe();
this._isDestroyed = true;
super.ngOnDestroy();
}
/** Attaches a `CdkVirtualScrollRepeater` to this viewport. */
attach(forOf) {
if (this._forOf && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error("CdkVirtualScrollViewport is already attached.");
}
this.ngZone.runOutsideAngular(() => {
this._forOf = forOf;
this._forOf.dataStream.pipe(takeUntil(this._detachedSubject)).subscribe((data) => {
const newLength = data.length;
if (newLength !== this._dataLength) {
this._dataLength = newLength;
this._scrollStrategy.onDataLengthChanged();
}
this._doChangeDetection();
});
});
}
/** Detaches the current `CdkVirtualForOf`. */
detach() {
this._forOf = null;
this._detachedSubject.next();
}
/** Gets the length of the data bound to this viewport (in number of items). */
getDataLength() {
return this._dataLength;
}
/** Gets the size of the viewport (in pixels). */
getViewportSize() {
return this._viewportSize;
}
// TODO(mmalerba): This is technically out of sync with what's really rendered until a render
// cycle happens. I'm being careful to only call it after the render cycle is complete and before
// setting it to something else, but its error prone and should probably be split into
// `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM.
/** Get the current rendered range of items. */
getRenderedRange() {
return this._renderedRange;
}
measureBoundingClientRectWithScrollOffset(from2) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from2];
}
/**
* Sets the total size of all content (in pixels), including content that is not currently
* rendered.
*/
setTotalContentSize(size) {
if (this._totalContentSize !== size) {
this._totalContentSize = size;
this._calculateSpacerSize();
this._markChangeDetectionNeeded();
}
}
/** Sets the currently rendered range of indices. */
setRenderedRange(range) {
if (!rangesEqual(this._renderedRange, range)) {
if (this.appendOnly) {
range = {
start: 0,
end: Math.max(this._renderedRange.end, range.end)
};
}
this._renderedRangeSubject.next(this._renderedRange = range);
this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered());
}
}
/**
* Gets the offset from the start of the viewport to the start of the rendered data (in pixels).
*/
getOffsetToRenderedContentStart() {
return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset;
}
/**
* Sets the offset from the start of the viewport to either the start or end of the rendered data
* (in pixels).
*/
setRenderedContentOffset(offset, to = "to-start") {
offset = this.appendOnly && to === "to-start" ? 0 : offset;
const isRtl = this.dir && this.dir.value == "rtl";
const isHorizontal = this.orientation == "horizontal";
const axis = isHorizontal ? "X" : "Y";
const axisDirection = isHorizontal && isRtl ? -1 : 1;
let transform = `translate${axis}(${Number(axisDirection * offset)}px)`;
this._renderedContentOffset = offset;
if (to === "to-end") {
transform += ` translate${axis}(-100%)`;
this._renderedContentOffsetNeedsRewrite = true;
}
if (this._renderedContentTransform != transform) {
this._renderedContentTransform = transform;
this._markChangeDetectionNeeded(() => {
if (this._renderedContentOffsetNeedsRewrite) {
this._renderedContentOffset -= this.measureRenderedContentSize();
this._renderedContentOffsetNeedsRewrite = false;
this.setRenderedContentOffset(this._renderedContentOffset);
} else {
this._scrollStrategy.onRenderedOffsetChanged();
}
});
}
}
/**
* Scrolls to the given offset from the start of the viewport. Please note that this is not always
* the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left
* direction, this would be the equivalent of setting a fictional `scrollRight` property.
* @param offset The offset to scroll to.
* @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.
*/
scrollToOffset(offset, behavior = "auto") {
const options = {
behavior
};
if (this.orientation === "horizontal") {
options.start = offset;
} else {
options.top = offset;
}
this.scrollable.scrollTo(options);
}
/**
* Scrolls to the offset for the given index.
* @param index The index of the element to scroll to.
* @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.
*/
scrollToIndex(index, behavior = "auto") {
this._scrollStrategy.scrollToIndex(index, behavior);
}
/**
* Gets the current scroll offset from the start of the scrollable (in pixels).
* @param from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start'
* in horizontal mode.
*/
measureScrollOffset(from2) {
let measureScrollOffset;
if (this.scrollable == this) {
measureScrollOffset = (_from) => super.measureScrollOffset(_from);
} else {
measureScrollOffset = (_from) => this.scrollable.measureScrollOffset(_from);
}
return Math.max(0, measureScrollOffset(from2 ?? (this.orientation === "horizontal" ? "start" : "top")) - this.measureViewportOffset());
}
/**
* Measures the offset of the viewport from the scrolling container
* @param from The edge to measure from.
*/
measureViewportOffset(from2) {
let fromRect;
const LEFT = "left";
const RIGHT = "right";
const isRtl = this.dir?.value == "rtl";
if (from2 == "start") {
fromRect = isRtl ? RIGHT : LEFT;
} else if (from2 == "end") {
fromRect = isRtl ? LEFT : RIGHT;
} else if (from2) {
fromRect = from2;
} else {
fromRect = this.orientation === "horizontal" ? "left" : "top";
}
const scrollerClientRect = this.scrollable.measureBoundingClientRectWithScrollOffset(fromRect);
const viewportClientRect = this.elementRef.nativeElement.getBoundingClientRect()[fromRect];
return viewportClientRect - scrollerClientRect;
}
/** Measure the combined size of all of the rendered items. */
measureRenderedContentSize() {
const contentEl = this._contentWrapper.nativeElement;
return this.orientation === "horizontal" ? contentEl.offsetWidth : contentEl.offsetHeight;
}
/**
* Measure the total combined size of the given range. Throws if the range includes items that are
* not rendered.
*/
measureRangeSize(range) {
if (!this._forOf) {
return 0;
}
return this._forOf.measureRangeSize(range, this.orientation);
}
/** Update the viewport dimensions and re-render. */
checkViewportSize() {
this._measureViewportSize();
this._scrollStrategy.onDataLengthChanged();
}
/** Measure the viewport size. */
_measureViewportSize() {
this._viewportSize = this.scrollable.measureViewportSize(this.orientation);
}
/** Queue up change detection to run. */
_markChangeDetectionNeeded(runAfter) {
if (runAfter) {
this._runAfterChangeDetection.push(runAfter);
}
if (!this._isChangeDetectionPending) {
this._isChangeDetectionPending = true;
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {
this._doChangeDetection();
}));
}
}
/** Run change detection. */
_doChangeDetection() {
if (this._isDestroyed) {
return;
}
this.ngZone.run(() => {
this._changeDetectorRef.markForCheck();
this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform;
afterNextRender(() => {
this._isChangeDetectionPending = false;
const runAfterChangeDetection = this._runAfterChangeDetection;
this._runAfterChangeDetection = [];
for (const fn of runAfterChangeDetection) {
fn();
}
}, {
injector: this._injector
});
});
}
/** Calculates the `style.width` and `style.height` for the spacer element. */
_calculateSpacerSize() {
this._totalContentHeight = this.orientation === "horizontal" ? "" : `${this._totalContentSize}px`;
this._totalContentWidth = this.orientation === "horizontal" ? `${this._totalContentSize}px` : "";
}
static \u0275fac = function CdkVirtualScrollViewport_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkVirtualScrollViewport)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _CdkVirtualScrollViewport,
selectors: [["cdk-virtual-scroll-viewport"]],
viewQuery: function CdkVirtualScrollViewport_Query(rf, ctx) {
if (rf & 1) {
\u0275\u0275viewQuery(_c02, 7);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._contentWrapper = _t.first);
}
},
hostAttrs: [1, "cdk-virtual-scroll-viewport"],
hostVars: 4,
hostBindings: function CdkVirtualScrollViewport_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("cdk-virtual-scroll-orientation-horizontal", ctx.orientation === "horizontal")("cdk-virtual-scroll-orientation-vertical", ctx.orientation !== "horizontal");
}
},
inputs: {
orientation: "orientation",
appendOnly: [2, "appendOnly", "appendOnly", booleanAttribute]
},
outputs: {
scrolledIndexChange: "scrolledIndexChange"
},
features: [\u0275\u0275ProvidersFeature([{
provide: CdkScrollable,
useFactory: (virtualScrollable, viewport) => virtualScrollable || viewport,
deps: [[new Optional(), new Inject(VIRTUAL_SCROLLABLE)], _CdkVirtualScrollViewport]
}]), \u0275\u0275InheritDefinitionFeature],
ngContentSelectors: _c1,
decls: 4,
vars: 4,
consts: [["contentWrapper", ""], [1, "cdk-virtual-scroll-content-wrapper"], [1, "cdk-virtual-scroll-spacer"]],
template: function CdkVirtualScrollViewport_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef();
\u0275\u0275elementStart(0, "div", 1, 0);
\u0275\u0275projection(2);
\u0275\u0275elementEnd();
\u0275\u0275element(3, "div", 2);
}
if (rf & 2) {
\u0275\u0275advance(3);
\u0275\u0275styleProp("width", ctx._totalContentWidth)("height", ctx._totalContentHeight);
}
},
styles: ["cdk-virtual-scroll-viewport{display:block;position:relative;transform:translateZ(0)}.cdk-virtual-scrollable{overflow:auto;will-change:scroll-position;contain:strict}.cdk-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .cdk-virtual-scroll-content-wrapper{right:0;left:auto}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper{min-height:100%}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper{min-width:100%}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.cdk-virtual-scroll-spacer{height:1px;transform-origin:0 0;flex:0 0 auto}[dir=rtl] .cdk-virtual-scroll-spacer{transform-origin:100% 0}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollViewport, [{
type: Component,
args: [{
selector: "cdk-virtual-scroll-viewport",
host: {
"class": "cdk-virtual-scroll-viewport",
"[class.cdk-virtual-scroll-orientation-horizontal]": 'orientation === "horizontal"',
"[class.cdk-virtual-scroll-orientation-vertical]": 'orientation !== "horizontal"'
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [{
provide: CdkScrollable,
useFactory: (virtualScrollable, viewport) => virtualScrollable || viewport,
deps: [[new Optional(), new Inject(VIRTUAL_SCROLLABLE)], CdkVirtualScrollViewport]
}],
template: '<!--\n Wrap the rendered content in an element that will be used to offset it based on the scroll\n position.\n-->\n<div #contentWrapper class="cdk-virtual-scroll-content-wrapper">\n <ng-content></ng-content>\n</div>\n<!--\n Spacer used to force the scrolling container to the correct size for the *total* number of items\n so that the scrollbar captures the size of the entire data set.\n-->\n<div class="cdk-virtual-scroll-spacer"\n [style.width]="_totalContentWidth" [style.height]="_totalContentHeight"></div>\n',
styles: ["cdk-virtual-scroll-viewport{display:block;position:relative;transform:translateZ(0)}.cdk-virtual-scrollable{overflow:auto;will-change:scroll-position;contain:strict}.cdk-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .cdk-virtual-scroll-content-wrapper{right:0;left:auto}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper{min-height:100%}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper{min-width:100%}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.cdk-virtual-scroll-spacer{height:1px;transform-origin:0 0;flex:0 0 auto}[dir=rtl] .cdk-virtual-scroll-spacer{transform-origin:100% 0}\n"]
}]
}], () => [], {
orientation: [{
type: Input
}],
appendOnly: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
scrolledIndexChange: [{
type: Output
}],
_contentWrapper: [{
type: ViewChild,
args: ["contentWrapper", {
static: true
}]
}]
});
})();
function getOffset(orientation, direction, node) {
const el = node;
if (!el.getBoundingClientRect) {
return 0;
}
const rect = el.getBoundingClientRect();
if (orientation === "horizontal") {
return direction === "start" ? rect.left : rect.right;
}
return direction === "start" ? rect.top : rect.bottom;
}
var CdkVirtualForOf = class _CdkVirtualForOf {
_viewContainerRef = inject(ViewContainerRef);
_template = inject(TemplateRef);
_differs = inject(IterableDiffers);
_viewRepeater = inject(_VIEW_REPEATER_STRATEGY);
_viewport = inject(CdkVirtualScrollViewport, {
skipSelf: true
});
/** Emits when the rendered view of the data changes. */
viewChange = new Subject();
/** Subject that emits when a new DataSource instance is given. */
_dataSourceChanges = new Subject();
/** The DataSource to display. */
get cdkVirtualForOf() {
return this._cdkVirtualForOf;
}
set cdkVirtualForOf(value) {
this._cdkVirtualForOf = value;
if (isDataSource(value)) {
this._dataSourceChanges.next(value);
} else {
this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || [])));
}
}
_cdkVirtualForOf;
/**
* The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and
* the item and produces a value to be used as the item's identity when tracking changes.
*/
get cdkVirtualForTrackBy() {
return this._cdkVirtualForTrackBy;
}
set cdkVirtualForTrackBy(fn) {
this._needsUpdate = true;
this._cdkVirtualForTrackBy = fn ? (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) : void 0;
}
_cdkVirtualForTrackBy;
/** The template used to stamp out new elements. */
set cdkVirtualForTemplate(value) {
if (value) {
this._needsUpdate = true;
this._template = value;
}
}
/**
* The size of the cache used to store templates that are not being used for re-use later.
* Setting the cache size to `0` will disable caching. Defaults to 20 templates.
*/
get cdkVirtualForTemplateCacheSize() {
return this._viewRepeater.viewCacheSize;
}
set cdkVirtualForTemplateCacheSize(size) {
this._viewRepeater.viewCacheSize = coerceNumberProperty(size);
}
/** Emits whenever the data in the current DataSource changes. */
dataStream = this._dataSourceChanges.pipe(
// Start off with null `DataSource`.
startWith(null),
// Bundle up the previous and current data sources so we can work with both.
pairwise(),
// Use `_changeDataSource` to disconnect from the previous data source and connect to the
// new one, passing back a stream of data changes which we run through `switchMap` to give
// us a data stream that emits the latest data from whatever the current `DataSource` is.
switchMap(([prev, cur]) => this._changeDataSource(prev, cur)),
// Replay the last emitted data when someone subscribes.
shareReplay(1)
);
/** The differ used to calculate changes to the data. */
_differ = null;
/** The most recent data emitted from the DataSource. */
_data;
/** The currently rendered items. */
_renderedItems;
/** The currently rendered range of indices. */
_renderedRange;
/** Whether the rendered data should be updated during the next ngDoCheck cycle. */
_needsUpdate = false;
_destroyed = new Subject();
constructor() {
const ngZone = inject(NgZone);
this.dataStream.subscribe((data) => {
this._data = data;
this._onRenderedDataChange();
});
this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe((range) => {
this._renderedRange = range;
if (this.viewChange.observers.length) {
ngZone.run(() => this.viewChange.next(this._renderedRange));
}
this._onRenderedDataChange();
});
this._viewport.attach(this);
}
/**
* Measures the combined size (width for horizontal orientation, height for vertical) of all items
* in the specified range. Throws an error if the range includes items that are not currently
* rendered.
*/
measureRangeSize(range, orientation) {
if (range.start >= range.end) {
return 0;
}
if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error(`Error: attempted to measure an item that isn't rendered.`);
}
const renderedStartIndex = range.start - this._renderedRange.start;
const rangeLen = range.end - range.start;
let firstNode;
let lastNode;
for (let i = 0; i < rangeLen; i++) {
const view = this._viewContainerRef.get(i + renderedStartIndex);
if (view && view.rootNodes.length) {
firstNode = lastNode = view.rootNodes[0];
break;
}
}
for (let i = rangeLen - 1; i > -1; i--) {
const view = this._viewContainerRef.get(i + renderedStartIndex);
if (view && view.rootNodes.length) {
lastNode = view.rootNodes[view.rootNodes.length - 1];
break;
}
}
return firstNode && lastNode ? getOffset(orientation, "end", lastNode) - getOffset(orientation, "start", firstNode) : 0;
}
ngDoCheck() {
if (this._differ && this._needsUpdate) {
const changes = this._differ.diff(this._renderedItems);
if (!changes) {
this._updateContext();
} else {
this._applyChanges(changes);
}
this._needsUpdate = false;
}
}
ngOnDestroy() {
this._viewport.detach();
this._dataSourceChanges.next(void 0);
this._dataSourceChanges.complete();
this.viewChange.complete();
this._destroyed.next();
this._destroyed.complete();
this._viewRepeater.detach();
}
/** React to scroll state changes in the viewport. */
_onRenderedDataChange() {
if (!this._renderedRange) {
return;
}
this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end);
if (!this._differ) {
this._differ = this._differs.find(this._renderedItems).create((index, item) => {
return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item;
});
}
this._needsUpdate = true;
}
/** Swap out one `DataSource` for another. */
_changeDataSource(oldDs, newDs) {
if (oldDs) {
oldDs.disconnect(this);
}
this._needsUpdate = true;
return newDs ? newDs.connect(this) : of();
}
/** Update the `CdkVirtualForOfContext` for all views. */
_updateContext() {
const count = this._data.length;
let i = this._viewContainerRef.length;
while (i--) {
const view = this._viewContainerRef.get(i);
view.context.index = this._renderedRange.start + i;
view.context.count = count;
this._updateComputedContextProperties(view.context);
view.detectChanges();
}
}
/** Apply changes to the DOM. */
_applyChanges(changes) {
this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), (record) => record.item);
changes.forEachIdentityChange((record) => {
const view = this._viewContainerRef.get(record.currentIndex);
view.context.$implicit = record.item;
});
const count = this._data.length;
let i = this._viewContainerRef.length;
while (i--) {
const view = this._viewContainerRef.get(i);
view.context.index = this._renderedRange.start + i;
view.context.count = count;
this._updateComputedContextProperties(view.context);
}
}
/** Update the computed properties on the `CdkVirtualForOfContext`. */
_updateComputedContextProperties(context) {
context.first = context.index === 0;
context.last = context.index === context.count - 1;
context.even = context.index % 2 === 0;
context.odd = !context.even;
}
_getEmbeddedViewArgs(record, index) {
return {
templateRef: this._template,
context: {
$implicit: record.item,
// It's guaranteed that the iterable is not "undefined" or "null" because we only
// generate views for elements if the "cdkVirtualForOf" iterable has elements.
cdkVirtualForOf: this._cdkVirtualForOf,
index: -1,
count: -1,
first: false,
last: false,
odd: false,
even: false
},
index
};
}
static ngTemplateContextGuard(directive, context) {
return true;
}
static \u0275fac = function CdkVirtualForOf_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkVirtualForOf)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkVirtualForOf,
selectors: [["", "cdkVirtualFor", "", "cdkVirtualForOf", ""]],
inputs: {
cdkVirtualForOf: "cdkVirtualForOf",
cdkVirtualForTrackBy: "cdkVirtualForTrackBy",
cdkVirtualForTemplate: "cdkVirtualForTemplate",
cdkVirtualForTemplateCacheSize: "cdkVirtualForTemplateCacheSize"
},
features: [\u0275\u0275ProvidersFeature([{
provide: _VIEW_REPEATER_STRATEGY,
useClass: _RecycleViewRepeaterStrategy
}])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualForOf, [{
type: Directive,
args: [{
selector: "[cdkVirtualFor][cdkVirtualForOf]",
providers: [{
provide: _VIEW_REPEATER_STRATEGY,
useClass: _RecycleViewRepeaterStrategy
}]
}]
}], () => [], {
cdkVirtualForOf: [{
type: Input
}],
cdkVirtualForTrackBy: [{
type: Input
}],
cdkVirtualForTemplate: [{
type: Input
}],
cdkVirtualForTemplateCacheSize: [{
type: Input
}]
});
})();
var CdkVirtualScrollableElement = class _CdkVirtualScrollableElement extends CdkVirtualScrollable {
constructor() {
super();
}
measureBoundingClientRectWithScrollOffset(from2) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from2] - this.measureScrollOffset(from2);
}
static \u0275fac = function CdkVirtualScrollableElement_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkVirtualScrollableElement)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkVirtualScrollableElement,
selectors: [["", "cdkVirtualScrollingElement", ""]],
hostAttrs: [1, "cdk-virtual-scrollable"],
features: [\u0275\u0275ProvidersFeature([{
provide: VIRTUAL_SCROLLABLE,
useExisting: _CdkVirtualScrollableElement
}]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollableElement, [{
type: Directive,
args: [{
selector: "[cdkVirtualScrollingElement]",
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableElement
}],
host: {
"class": "cdk-virtual-scrollable"
}
}]
}], () => [], null);
})();
var CdkVirtualScrollableWindow = class _CdkVirtualScrollableWindow extends CdkVirtualScrollable {
constructor() {
super();
const document2 = inject(DOCUMENT);
this.elementRef = new ElementRef(document2.documentElement);
this._scrollElement = document2;
}
measureBoundingClientRectWithScrollOffset(from2) {
return this.getElementRef().nativeElement.getBoundingClientRect()[from2];
}
static \u0275fac = function CdkVirtualScrollableWindow_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkVirtualScrollableWindow)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkVirtualScrollableWindow,
selectors: [["cdk-virtual-scroll-viewport", "scrollWindow", ""]],
features: [\u0275\u0275ProvidersFeature([{
provide: VIRTUAL_SCROLLABLE,
useExisting: _CdkVirtualScrollableWindow
}]), \u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkVirtualScrollableWindow, [{
type: Directive,
args: [{
selector: "cdk-virtual-scroll-viewport[scrollWindow]",
providers: [{
provide: VIRTUAL_SCROLLABLE,
useExisting: CdkVirtualScrollableWindow
}]
}]
}], () => [], null);
})();
var CdkScrollableModule = class _CdkScrollableModule {
static \u0275fac = function CdkScrollableModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkScrollableModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _CdkScrollableModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkScrollableModule, [{
type: NgModule,
args: [{
exports: [CdkScrollable],
imports: [CdkScrollable]
}]
}], null, null);
})();
var ScrollingModule = class _ScrollingModule {
static \u0275fac = function ScrollingModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ScrollingModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _ScrollingModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [BidiModule, CdkScrollableModule, BidiModule, CdkScrollableModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ScrollingModule, [{
type: NgModule,
args: [{
imports: [BidiModule, CdkScrollableModule, CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollableWindow, CdkVirtualScrollableElement],
exports: [BidiModule, CdkScrollableModule, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport, CdkVirtualScrollableWindow, CdkVirtualScrollableElement]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/id-generator-Dw_9dSDu.mjs
var counters = {};
var _IdGenerator = class __IdGenerator {
_appId = inject(APP_ID);
/**
* Generates a unique ID with a specific prefix.
* @param prefix Prefix to add to the ID.
*/
getId(prefix) {
if (this._appId !== "ng") {
prefix += this._appId;
}
if (!counters.hasOwnProperty(prefix)) {
counters[prefix] = 0;
}
return `${prefix}${counters[prefix]++}`;
}
static \u0275fac = function _IdGenerator_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __IdGenerator)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: __IdGenerator,
factory: __IdGenerator.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_IdGenerator, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/keycodes.mjs
function hasModifierKey(event, ...modifiers) {
if (modifiers.length) {
return modifiers.some((modifier) => event[modifier]);
}
return event.altKey || event.shiftKey || event.ctrlKey || event.metaKey;
}
// node_modules/@angular/cdk/fesm2022/overlay-module-BUj0D19H.mjs
var scrollBehaviorSupported2 = supportsScrollBehavior();
var BlockScrollStrategy = class {
_viewportRuler;
_previousHTMLStyles = {
top: "",
left: ""
};
_previousScrollPosition;
_isEnabled = false;
_document;
constructor(_viewportRuler, document2) {
this._viewportRuler = _viewportRuler;
this._document = document2;
}
/** Attaches this scroll strategy to an overlay. */
attach() {
}
/** Blocks page-level scroll while the attached overlay is open. */
enable() {
if (this._canBeEnabled()) {
const root = this._document.documentElement;
this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition();
this._previousHTMLStyles.left = root.style.left || "";
this._previousHTMLStyles.top = root.style.top || "";
root.style.left = coerceCssPixelValue(-this._previousScrollPosition.left);
root.style.top = coerceCssPixelValue(-this._previousScrollPosition.top);
root.classList.add("cdk-global-scrollblock");
this._isEnabled = true;
}
}
/** Unblocks page-level scroll while the attached overlay is open. */
disable() {
if (this._isEnabled) {
const html = this._document.documentElement;
const body = this._document.body;
const htmlStyle = html.style;
const bodyStyle = body.style;
const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || "";
const previousBodyScrollBehavior = bodyStyle.scrollBehavior || "";
this._isEnabled = false;
htmlStyle.left = this._previousHTMLStyles.left;
htmlStyle.top = this._previousHTMLStyles.top;
html.classList.remove("cdk-global-scrollblock");
if (scrollBehaviorSupported2) {
htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = "auto";
}
window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top);
if (scrollBehaviorSupported2) {
htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
bodyStyle.scrollBehavior = previousBodyScrollBehavior;
}
}
}
_canBeEnabled() {
const html = this._document.documentElement;
if (html.classList.contains("cdk-global-scrollblock") || this._isEnabled) {
return false;
}
const rootElement = this._document.documentElement;
const viewport = this._viewportRuler.getViewportSize();
return rootElement.scrollHeight > viewport.height || rootElement.scrollWidth > viewport.width;
}
};
function getMatScrollStrategyAlreadyAttachedError() {
return Error(`Scroll strategy has already been attached.`);
}
var CloseScrollStrategy = class {
_scrollDispatcher;
_ngZone;
_viewportRuler;
_config;
_scrollSubscription = null;
_overlayRef;
_initialScrollPosition;
constructor(_scrollDispatcher, _ngZone, _viewportRuler, _config) {
this._scrollDispatcher = _scrollDispatcher;
this._ngZone = _ngZone;
this._viewportRuler = _viewportRuler;
this._config = _config;
}
/** Attaches this scroll strategy to an overlay. */
attach(overlayRef) {
if (this._overlayRef && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw getMatScrollStrategyAlreadyAttachedError();
}
this._overlayRef = overlayRef;
}
/** Enables the closing of the attached overlay on scroll. */
enable() {
if (this._scrollSubscription) {
return;
}
const stream = this._scrollDispatcher.scrolled(0).pipe(filter((scrollable) => {
return !scrollable || !this._overlayRef.overlayElement.contains(scrollable.getElementRef().nativeElement);
}));
if (this._config && this._config.threshold && this._config.threshold > 1) {
this._initialScrollPosition = this._viewportRuler.getViewportScrollPosition().top;
this._scrollSubscription = stream.subscribe(() => {
const scrollPosition = this._viewportRuler.getViewportScrollPosition().top;
if (Math.abs(scrollPosition - this._initialScrollPosition) > this._config.threshold) {
this._detach();
} else {
this._overlayRef.updatePosition();
}
});
} else {
this._scrollSubscription = stream.subscribe(this._detach);
}
}
/** Disables the closing the attached overlay on scroll. */
disable() {
if (this._scrollSubscription) {
this._scrollSubscription.unsubscribe();
this._scrollSubscription = null;
}
}
detach() {
this.disable();
this._overlayRef = null;
}
/** Detaches the overlay ref and disables the scroll strategy. */
_detach = () => {
this.disable();
if (this._overlayRef.hasAttached()) {
this._ngZone.run(() => this._overlayRef.detach());
}
};
};
var NoopScrollStrategy = class {
/** Does nothing, as this scroll strategy is a no-op. */
enable() {
}
/** Does nothing, as this scroll strategy is a no-op. */
disable() {
}
/** Does nothing, as this scroll strategy is a no-op. */
attach() {
}
};
function isElementScrolledOutsideView(element, scrollContainers) {
return scrollContainers.some((containerBounds) => {
const outsideAbove = element.bottom < containerBounds.top;
const outsideBelow = element.top > containerBounds.bottom;
const outsideLeft = element.right < containerBounds.left;
const outsideRight = element.left > containerBounds.right;
return outsideAbove || outsideBelow || outsideLeft || outsideRight;
});
}
function isElementClippedByScrolling(element, scrollContainers) {
return scrollContainers.some((scrollContainerRect) => {
const clippedAbove = element.top < scrollContainerRect.top;
const clippedBelow = element.bottom > scrollContainerRect.bottom;
const clippedLeft = element.left < scrollContainerRect.left;
const clippedRight = element.right > scrollContainerRect.right;
return clippedAbove || clippedBelow || clippedLeft || clippedRight;
});
}
var RepositionScrollStrategy = class {
_scrollDispatcher;
_viewportRuler;
_ngZone;
_config;
_scrollSubscription = null;
_overlayRef;
constructor(_scrollDispatcher, _viewportRuler, _ngZone, _config) {
this._scrollDispatcher = _scrollDispatcher;
this._viewportRuler = _viewportRuler;
this._ngZone = _ngZone;
this._config = _config;
}
/** Attaches this scroll strategy to an overlay. */
attach(overlayRef) {
if (this._overlayRef && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw getMatScrollStrategyAlreadyAttachedError();
}
this._overlayRef = overlayRef;
}
/** Enables repositioning of the attached overlay on scroll. */
enable() {
if (!this._scrollSubscription) {
const throttle = this._config ? this._config.scrollThrottle : 0;
this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe(() => {
this._overlayRef.updatePosition();
if (this._config && this._config.autoClose) {
const overlayRect = this._overlayRef.overlayElement.getBoundingClientRect();
const {
width,
height
} = this._viewportRuler.getViewportSize();
const parentRects = [{
width,
height,
bottom: height,
right: width,
top: 0,
left: 0
}];
if (isElementScrolledOutsideView(overlayRect, parentRects)) {
this.disable();
this._ngZone.run(() => this._overlayRef.detach());
}
}
});
}
}
/** Disables repositioning of the attached overlay on scroll. */
disable() {
if (this._scrollSubscription) {
this._scrollSubscription.unsubscribe();
this._scrollSubscription = null;
}
}
detach() {
this.disable();
this._overlayRef = null;
}
};
var ScrollStrategyOptions = class _ScrollStrategyOptions {
_scrollDispatcher = inject(ScrollDispatcher);
_viewportRuler = inject(ViewportRuler);
_ngZone = inject(NgZone);
_document = inject(DOCUMENT);
constructor() {
}
/** Do nothing on scroll. */
noop = () => new NoopScrollStrategy();
/**
* Close the overlay as soon as the user scrolls.
* @param config Configuration to be used inside the scroll strategy.
*/
close = (config) => new CloseScrollStrategy(this._scrollDispatcher, this._ngZone, this._viewportRuler, config);
/** Block scrolling. */
block = () => new BlockScrollStrategy(this._viewportRuler, this._document);
/**
* Update the overlay's position on scroll.
* @param config Configuration to be used inside the scroll strategy.
* Allows debouncing the reposition calls.
*/
reposition = (config) => new RepositionScrollStrategy(this._scrollDispatcher, this._viewportRuler, this._ngZone, config);
static \u0275fac = function ScrollStrategyOptions_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ScrollStrategyOptions)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ScrollStrategyOptions,
factory: _ScrollStrategyOptions.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ScrollStrategyOptions, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var OverlayConfig = class {
/** Strategy with which to position the overlay. */
positionStrategy;
/** Strategy to be used when handling scroll events while the overlay is open. */
scrollStrategy = new NoopScrollStrategy();
/** Custom class to add to the overlay pane. */
panelClass = "";
/** Whether the overlay has a backdrop. */
hasBackdrop = false;
/** Custom class to add to the backdrop */
backdropClass = "cdk-overlay-dark-backdrop";
/** The width of the overlay panel. If a number is provided, pixel units are assumed. */
width;
/** The height of the overlay panel. If a number is provided, pixel units are assumed. */
height;
/** The min-width of the overlay panel. If a number is provided, pixel units are assumed. */
minWidth;
/** The min-height of the overlay panel. If a number is provided, pixel units are assumed. */
minHeight;
/** The max-width of the overlay panel. If a number is provided, pixel units are assumed. */
maxWidth;
/** The max-height of the overlay panel. If a number is provided, pixel units are assumed. */
maxHeight;
/**
* Direction of the text in the overlay panel. If a `Directionality` instance
* is passed in, the overlay will handle changes to its value automatically.
*/
direction;
/**
* Whether the overlay should be disposed of when the user goes backwards/forwards in history.
* Note that this usually doesn't include clicking on links (unless the user is using
* the `HashLocationStrategy`).
*/
disposeOnNavigation = false;
constructor(config) {
if (config) {
const configKeys = Object.keys(config);
for (const key of configKeys) {
if (config[key] !== void 0) {
this[key] = config[key];
}
}
}
}
};
var ConnectedOverlayPositionChange = class {
connectionPair;
scrollableViewProperties;
constructor(connectionPair, scrollableViewProperties) {
this.connectionPair = connectionPair;
this.scrollableViewProperties = scrollableViewProperties;
}
};
function validateVerticalPosition(property, value) {
if (value !== "top" && value !== "bottom" && value !== "center") {
throw Error(`ConnectedPosition: Invalid ${property} "${value}". Expected "top", "bottom" or "center".`);
}
}
function validateHorizontalPosition(property, value) {
if (value !== "start" && value !== "end" && value !== "center") {
throw Error(`ConnectedPosition: Invalid ${property} "${value}". Expected "start", "end" or "center".`);
}
}
var BaseOverlayDispatcher = class _BaseOverlayDispatcher {
/** Currently attached overlays in the order they were attached. */
_attachedOverlays = [];
_document = inject(DOCUMENT);
_isAttached;
constructor() {
}
ngOnDestroy() {
this.detach();
}
/** Add a new overlay to the list of attached overlay refs. */
add(overlayRef) {
this.remove(overlayRef);
this._attachedOverlays.push(overlayRef);
}
/** Remove an overlay from the list of attached overlay refs. */
remove(overlayRef) {
const index = this._attachedOverlays.indexOf(overlayRef);
if (index > -1) {
this._attachedOverlays.splice(index, 1);
}
if (this._attachedOverlays.length === 0) {
this.detach();
}
}
static \u0275fac = function BaseOverlayDispatcher_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _BaseOverlayDispatcher)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _BaseOverlayDispatcher,
factory: _BaseOverlayDispatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(BaseOverlayDispatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var OverlayKeyboardDispatcher = class _OverlayKeyboardDispatcher extends BaseOverlayDispatcher {
_ngZone = inject(NgZone);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_cleanupKeydown;
/** Add a new overlay to the list of attached overlay refs. */
add(overlayRef) {
super.add(overlayRef);
if (!this._isAttached) {
this._ngZone.runOutsideAngular(() => {
this._cleanupKeydown = this._renderer.listen("body", "keydown", this._keydownListener);
});
this._isAttached = true;
}
}
/** Detaches the global keyboard event listener. */
detach() {
if (this._isAttached) {
this._cleanupKeydown?.();
this._isAttached = false;
}
}
/** Keyboard event listener that will be attached to the body. */
_keydownListener = (event) => {
const overlays = this._attachedOverlays;
for (let i = overlays.length - 1; i > -1; i--) {
if (overlays[i]._keydownEvents.observers.length > 0) {
this._ngZone.run(() => overlays[i]._keydownEvents.next(event));
break;
}
}
};
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275OverlayKeyboardDispatcher_BaseFactory;
return function OverlayKeyboardDispatcher_Factory(__ngFactoryType__) {
return (\u0275OverlayKeyboardDispatcher_BaseFactory || (\u0275OverlayKeyboardDispatcher_BaseFactory = \u0275\u0275getInheritedFactory(_OverlayKeyboardDispatcher)))(__ngFactoryType__ || _OverlayKeyboardDispatcher);
};
})();
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _OverlayKeyboardDispatcher,
factory: _OverlayKeyboardDispatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(OverlayKeyboardDispatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var OverlayOutsideClickDispatcher = class _OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
_platform = inject(Platform);
_ngZone = inject(NgZone);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_cursorOriginalValue;
_cursorStyleIsSet = false;
_pointerDownEventTarget;
_cleanups;
/** Add a new overlay to the list of attached overlay refs. */
add(overlayRef) {
super.add(overlayRef);
if (!this._isAttached) {
const body = this._document.body;
const eventOptions = {
capture: true
};
this._cleanups = this._ngZone.runOutsideAngular(() => [_bindEventWithOptions(this._renderer, body, "pointerdown", this._pointerDownListener, eventOptions), _bindEventWithOptions(this._renderer, body, "click", this._clickListener, eventOptions), _bindEventWithOptions(this._renderer, body, "auxclick", this._clickListener, eventOptions), _bindEventWithOptions(this._renderer, body, "contextmenu", this._clickListener, eventOptions)]);
if (this._platform.IOS && !this._cursorStyleIsSet) {
this._cursorOriginalValue = body.style.cursor;
body.style.cursor = "pointer";
this._cursorStyleIsSet = true;
}
this._isAttached = true;
}
}
/** Detaches the global keyboard event listener. */
detach() {
if (this._isAttached) {
this._cleanups?.forEach((cleanup) => cleanup());
this._cleanups = void 0;
if (this._platform.IOS && this._cursorStyleIsSet) {
this._document.body.style.cursor = this._cursorOriginalValue;
this._cursorStyleIsSet = false;
}
this._isAttached = false;
}
}
/** Store pointerdown event target to track origin of click. */
_pointerDownListener = (event) => {
this._pointerDownEventTarget = _getEventTarget(event);
};
/** Click event listener that will be attached to the body propagate phase. */
_clickListener = (event) => {
const target = _getEventTarget(event);
const origin = event.type === "click" && this._pointerDownEventTarget ? this._pointerDownEventTarget : target;
this._pointerDownEventTarget = null;
const overlays = this._attachedOverlays.slice();
for (let i = overlays.length - 1; i > -1; i--) {
const overlayRef = overlays[i];
if (overlayRef._outsidePointerEvents.observers.length < 1 || !overlayRef.hasAttached()) {
continue;
}
if (containsPierceShadowDom(overlayRef.overlayElement, target) || containsPierceShadowDom(overlayRef.overlayElement, origin)) {
break;
}
const outsidePointerEvents = overlayRef._outsidePointerEvents;
if (this._ngZone) {
this._ngZone.run(() => outsidePointerEvents.next(event));
} else {
outsidePointerEvents.next(event);
}
}
};
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275OverlayOutsideClickDispatcher_BaseFactory;
return function OverlayOutsideClickDispatcher_Factory(__ngFactoryType__) {
return (\u0275OverlayOutsideClickDispatcher_BaseFactory || (\u0275OverlayOutsideClickDispatcher_BaseFactory = \u0275\u0275getInheritedFactory(_OverlayOutsideClickDispatcher)))(__ngFactoryType__ || _OverlayOutsideClickDispatcher);
};
})();
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _OverlayOutsideClickDispatcher,
factory: _OverlayOutsideClickDispatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(OverlayOutsideClickDispatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
function containsPierceShadowDom(parent, child) {
const supportsShadowRoot = typeof ShadowRoot !== "undefined" && ShadowRoot;
let current = child;
while (current) {
if (current === parent) {
return true;
}
current = supportsShadowRoot && current instanceof ShadowRoot ? current.host : current.parentNode;
}
return false;
}
var _CdkOverlayStyleLoader = class __CdkOverlayStyleLoader {
static \u0275fac = function _CdkOverlayStyleLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __CdkOverlayStyleLoader)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: __CdkOverlayStyleLoader,
selectors: [["ng-component"]],
hostAttrs: ["cdk-overlay-style-loader", ""],
decls: 0,
vars: 0,
template: function _CdkOverlayStyleLoader_Template(rf, ctx) {
},
styles: [".cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed}@layer cdk-overlay{.cdk-overlay-container{z-index:1000}}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute}@layer cdk-overlay{.cdk-global-overlay-wrapper{z-index:1000}}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;display:flex;max-width:100%;max-height:100%}@layer cdk-overlay{.cdk-overlay-pane{z-index:1000}}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;pointer-events:auto;-webkit-tap-highlight-color:rgba(0,0,0,0);opacity:0;touch-action:manipulation}@layer cdk-overlay{.cdk-overlay-backdrop{z-index:1000;transition:opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1)}}@media(prefers-reduced-motion){.cdk-overlay-backdrop{transition-duration:1ms}}.cdk-overlay-backdrop-showing{opacity:1}@media(forced-colors: active){.cdk-overlay-backdrop-showing{opacity:.6}}@layer cdk-overlay{.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.32)}}.cdk-overlay-transparent-backdrop{transition:visibility 1ms linear,opacity 1ms linear;visibility:hidden;opacity:1}.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing,.cdk-high-contrast-active .cdk-overlay-transparent-backdrop{opacity:0;visibility:visible}.cdk-overlay-backdrop-noop-animation{transition:none}.cdk-overlay-connected-position-bounding-box{position:absolute;display:flex;flex-direction:column;min-width:1px;min-height:1px}@layer cdk-overlay{.cdk-overlay-connected-position-bounding-box{z-index:1000}}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_CdkOverlayStyleLoader, [{
type: Component,
args: [{
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: {
"cdk-overlay-style-loader": ""
},
styles: [".cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed}@layer cdk-overlay{.cdk-overlay-container{z-index:1000}}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute}@layer cdk-overlay{.cdk-global-overlay-wrapper{z-index:1000}}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;display:flex;max-width:100%;max-height:100%}@layer cdk-overlay{.cdk-overlay-pane{z-index:1000}}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;pointer-events:auto;-webkit-tap-highlight-color:rgba(0,0,0,0);opacity:0;touch-action:manipulation}@layer cdk-overlay{.cdk-overlay-backdrop{z-index:1000;transition:opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1)}}@media(prefers-reduced-motion){.cdk-overlay-backdrop{transition-duration:1ms}}.cdk-overlay-backdrop-showing{opacity:1}@media(forced-colors: active){.cdk-overlay-backdrop-showing{opacity:.6}}@layer cdk-overlay{.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.32)}}.cdk-overlay-transparent-backdrop{transition:visibility 1ms linear,opacity 1ms linear;visibility:hidden;opacity:1}.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing,.cdk-high-contrast-active .cdk-overlay-transparent-backdrop{opacity:0;visibility:visible}.cdk-overlay-backdrop-noop-animation{transition:none}.cdk-overlay-connected-position-bounding-box{position:absolute;display:flex;flex-direction:column;min-width:1px;min-height:1px}@layer cdk-overlay{.cdk-overlay-connected-position-bounding-box{z-index:1000}}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}\n"]
}]
}], null, null);
})();
var OverlayContainer = class _OverlayContainer {
_platform = inject(Platform);
_containerElement;
_document = inject(DOCUMENT);
_styleLoader = inject(_CdkPrivateStyleLoader);
constructor() {
}
ngOnDestroy() {
this._containerElement?.remove();
}
/**
* This method returns the overlay container element. It will lazily
* create the element the first time it is called to facilitate using
* the container in non-browser environments.
* @returns the container element
*/
getContainerElement() {
this._loadStyles();
if (!this._containerElement) {
this._createContainer();
}
return this._containerElement;
}
/**
* Create the overlay container element, which is simply a div
* with the 'cdk-overlay-container' class on the document body.
*/
_createContainer() {
const containerClass = "cdk-overlay-container";
if (this._platform.isBrowser || _isTestEnvironment()) {
const oppositePlatformContainers = this._document.querySelectorAll(`.${containerClass}[platform="server"], .${containerClass}[platform="test"]`);
for (let i = 0; i < oppositePlatformContainers.length; i++) {
oppositePlatformContainers[i].remove();
}
}
const container = this._document.createElement("div");
container.classList.add(containerClass);
if (_isTestEnvironment()) {
container.setAttribute("platform", "test");
} else if (!this._platform.isBrowser) {
container.setAttribute("platform", "server");
}
this._document.body.appendChild(container);
this._containerElement = container;
}
/** Loads the structural styles necessary for the overlay to work. */
_loadStyles() {
this._styleLoader.load(_CdkOverlayStyleLoader);
}
static \u0275fac = function OverlayContainer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _OverlayContainer)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _OverlayContainer,
factory: _OverlayContainer.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(OverlayContainer, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var BackdropRef = class {
_renderer;
_ngZone;
element;
_cleanupClick;
_cleanupTransitionEnd;
_fallbackTimeout;
constructor(document2, _renderer, _ngZone, onClick) {
this._renderer = _renderer;
this._ngZone = _ngZone;
this.element = document2.createElement("div");
this.element.classList.add("cdk-overlay-backdrop");
this._cleanupClick = _renderer.listen(this.element, "click", onClick);
}
detach() {
this._ngZone.runOutsideAngular(() => {
const element = this.element;
clearTimeout(this._fallbackTimeout);
this._cleanupTransitionEnd?.();
this._cleanupTransitionEnd = this._renderer.listen(element, "transitionend", this.dispose);
this._fallbackTimeout = setTimeout(this.dispose, 500);
element.style.pointerEvents = "none";
element.classList.remove("cdk-overlay-backdrop-showing");
});
}
dispose = () => {
clearTimeout(this._fallbackTimeout);
this._cleanupClick?.();
this._cleanupTransitionEnd?.();
this._cleanupClick = this._cleanupTransitionEnd = this._fallbackTimeout = void 0;
this.element.remove();
};
};
var OverlayRef = class {
_portalOutlet;
_host;
_pane;
_config;
_ngZone;
_keyboardDispatcher;
_document;
_location;
_outsideClickDispatcher;
_animationsDisabled;
_injector;
_renderer;
_backdropClick = new Subject();
_attachments = new Subject();
_detachments = new Subject();
_positionStrategy;
_scrollStrategy;
_locationChanges = Subscription.EMPTY;
_backdropRef = null;
/**
* Reference to the parent of the `_host` at the time it was detached. Used to restore
* the `_host` to its original position in the DOM when it gets re-attached.
*/
_previousHostParent;
/** Stream of keydown events dispatched to this overlay. */
_keydownEvents = new Subject();
/** Stream of mouse outside events dispatched to this overlay. */
_outsidePointerEvents = new Subject();
_renders = new Subject();
_afterRenderRef;
/** Reference to the currently-running `afterNextRender` call. */
_afterNextRenderRef;
constructor(_portalOutlet, _host, _pane, _config, _ngZone, _keyboardDispatcher, _document2, _location, _outsideClickDispatcher, _animationsDisabled = false, _injector, _renderer) {
this._portalOutlet = _portalOutlet;
this._host = _host;
this._pane = _pane;
this._config = _config;
this._ngZone = _ngZone;
this._keyboardDispatcher = _keyboardDispatcher;
this._document = _document2;
this._location = _location;
this._outsideClickDispatcher = _outsideClickDispatcher;
this._animationsDisabled = _animationsDisabled;
this._injector = _injector;
this._renderer = _renderer;
if (_config.scrollStrategy) {
this._scrollStrategy = _config.scrollStrategy;
this._scrollStrategy.attach(this);
}
this._positionStrategy = _config.positionStrategy;
this._afterRenderRef = untracked(() => afterRender(() => {
this._renders.next();
}, {
injector: this._injector
}));
}
/** The overlay's HTML element */
get overlayElement() {
return this._pane;
}
/** The overlay's backdrop HTML element. */
get backdropElement() {
return this._backdropRef?.element || null;
}
/**
* Wrapper around the panel element. Can be used for advanced
* positioning where a wrapper with specific styling is
* required around the overlay pane.
*/
get hostElement() {
return this._host;
}
/**
* Attaches content, given via a Portal, to the overlay.
* If the overlay is configured to have a backdrop, it will be created.
*
* @param portal Portal instance to which to attach the overlay.
* @returns The portal attachment result.
*/
attach(portal) {
if (!this._host.parentElement && this._previousHostParent) {
this._previousHostParent.appendChild(this._host);
}
const attachResult = this._portalOutlet.attach(portal);
if (this._positionStrategy) {
this._positionStrategy.attach(this);
}
this._updateStackingOrder();
this._updateElementSize();
this._updateElementDirection();
if (this._scrollStrategy) {
this._scrollStrategy.enable();
}
this._afterNextRenderRef?.destroy();
this._afterNextRenderRef = afterNextRender(() => {
if (this.hasAttached()) {
this.updatePosition();
}
}, {
injector: this._injector
});
this._togglePointerEvents(true);
if (this._config.hasBackdrop) {
this._attachBackdrop();
}
if (this._config.panelClass) {
this._toggleClasses(this._pane, this._config.panelClass, true);
}
this._attachments.next();
this._keyboardDispatcher.add(this);
if (this._config.disposeOnNavigation) {
this._locationChanges = this._location.subscribe(() => this.dispose());
}
this._outsideClickDispatcher.add(this);
if (typeof attachResult?.onDestroy === "function") {
attachResult.onDestroy(() => {
if (this.hasAttached()) {
this._ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.detach()));
}
});
}
return attachResult;
}
/**
* Detaches an overlay from a portal.
* @returns The portal detachment result.
*/
detach() {
if (!this.hasAttached()) {
return;
}
this.detachBackdrop();
this._togglePointerEvents(false);
if (this._positionStrategy && this._positionStrategy.detach) {
this._positionStrategy.detach();
}
if (this._scrollStrategy) {
this._scrollStrategy.disable();
}
const detachmentResult = this._portalOutlet.detach();
this._detachments.next();
this._keyboardDispatcher.remove(this);
this._detachContentWhenEmpty();
this._locationChanges.unsubscribe();
this._outsideClickDispatcher.remove(this);
return detachmentResult;
}
/** Cleans up the overlay from the DOM. */
dispose() {
const isAttached = this.hasAttached();
if (this._positionStrategy) {
this._positionStrategy.dispose();
}
this._disposeScrollStrategy();
this._backdropRef?.dispose();
this._locationChanges.unsubscribe();
this._keyboardDispatcher.remove(this);
this._portalOutlet.dispose();
this._attachments.complete();
this._backdropClick.complete();
this._keydownEvents.complete();
this._outsidePointerEvents.complete();
this._outsideClickDispatcher.remove(this);
this._host?.remove();
this._afterNextRenderRef?.destroy();
this._previousHostParent = this._pane = this._host = this._backdropRef = null;
if (isAttached) {
this._detachments.next();
}
this._detachments.complete();
this._afterRenderRef.destroy();
this._renders.complete();
}
/** Whether the overlay has attached content. */
hasAttached() {
return this._portalOutlet.hasAttached();
}
/** Gets an observable that emits when the backdrop has been clicked. */
backdropClick() {
return this._backdropClick;
}
/** Gets an observable that emits when the overlay has been attached. */
attachments() {
return this._attachments;
}
/** Gets an observable that emits when the overlay has been detached. */
detachments() {
return this._detachments;
}
/** Gets an observable of keydown events targeted to this overlay. */
keydownEvents() {
return this._keydownEvents;
}
/** Gets an observable of pointer events targeted outside this overlay. */
outsidePointerEvents() {
return this._outsidePointerEvents;
}
/** Gets the current overlay configuration, which is immutable. */
getConfig() {
return this._config;
}
/** Updates the position of the overlay based on the position strategy. */
updatePosition() {
if (this._positionStrategy) {
this._positionStrategy.apply();
}
}
/** Switches to a new position strategy and updates the overlay position. */
updatePositionStrategy(strategy) {
if (strategy === this._positionStrategy) {
return;
}
if (this._positionStrategy) {
this._positionStrategy.dispose();
}
this._positionStrategy = strategy;
if (this.hasAttached()) {
strategy.attach(this);
this.updatePosition();
}
}
/** Update the size properties of the overlay. */
updateSize(sizeConfig) {
this._config = __spreadValues(__spreadValues({}, this._config), sizeConfig);
this._updateElementSize();
}
/** Sets the LTR/RTL direction for the overlay. */
setDirection(dir) {
this._config = __spreadProps(__spreadValues({}, this._config), {
direction: dir
});
this._updateElementDirection();
}
/** Add a CSS class or an array of classes to the overlay pane. */
addPanelClass(classes) {
if (this._pane) {
this._toggleClasses(this._pane, classes, true);
}
}
/** Remove a CSS class or an array of classes from the overlay pane. */
removePanelClass(classes) {
if (this._pane) {
this._toggleClasses(this._pane, classes, false);
}
}
/**
* Returns the layout direction of the overlay panel.
*/
getDirection() {
const direction = this._config.direction;
if (!direction) {
return "ltr";
}
return typeof direction === "string" ? direction : direction.value;
}
/** Switches to a new scroll strategy. */
updateScrollStrategy(strategy) {
if (strategy === this._scrollStrategy) {
return;
}
this._disposeScrollStrategy();
this._scrollStrategy = strategy;
if (this.hasAttached()) {
strategy.attach(this);
strategy.enable();
}
}
/** Updates the text direction of the overlay panel. */
_updateElementDirection() {
this._host.setAttribute("dir", this.getDirection());
}
/** Updates the size of the overlay element based on the overlay config. */
_updateElementSize() {
if (!this._pane) {
return;
}
const style = this._pane.style;
style.width = coerceCssPixelValue(this._config.width);
style.height = coerceCssPixelValue(this._config.height);
style.minWidth = coerceCssPixelValue(this._config.minWidth);
style.minHeight = coerceCssPixelValue(this._config.minHeight);
style.maxWidth = coerceCssPixelValue(this._config.maxWidth);
style.maxHeight = coerceCssPixelValue(this._config.maxHeight);
}
/** Toggles the pointer events for the overlay pane element. */
_togglePointerEvents(enablePointer) {
this._pane.style.pointerEvents = enablePointer ? "" : "none";
}
/** Attaches a backdrop for this overlay. */
_attachBackdrop() {
const showingClass = "cdk-overlay-backdrop-showing";
this._backdropRef?.dispose();
this._backdropRef = new BackdropRef(this._document, this._renderer, this._ngZone, (event) => {
this._backdropClick.next(event);
});
if (this._animationsDisabled) {
this._backdropRef.element.classList.add("cdk-overlay-backdrop-noop-animation");
}
if (this._config.backdropClass) {
this._toggleClasses(this._backdropRef.element, this._config.backdropClass, true);
}
this._host.parentElement.insertBefore(this._backdropRef.element, this._host);
if (!this._animationsDisabled && typeof requestAnimationFrame !== "undefined") {
this._ngZone.runOutsideAngular(() => {
requestAnimationFrame(() => this._backdropRef?.element.classList.add(showingClass));
});
} else {
this._backdropRef.element.classList.add(showingClass);
}
}
/**
* Updates the stacking order of the element, moving it to the top if necessary.
* This is required in cases where one overlay was detached, while another one,
* that should be behind it, was destroyed. The next time both of them are opened,
* the stacking will be wrong, because the detached element's pane will still be
* in its original DOM position.
*/
_updateStackingOrder() {
if (this._host.nextSibling) {
this._host.parentNode.appendChild(this._host);
}
}
/** Detaches the backdrop (if any) associated with the overlay. */
detachBackdrop() {
if (this._animationsDisabled) {
this._backdropRef?.dispose();
this._backdropRef = null;
} else {
this._backdropRef?.detach();
}
}
/** Toggles a single CSS class or an array of classes on an element. */
_toggleClasses(element, cssClasses, isAdd) {
const classes = coerceArray(cssClasses || []).filter((c) => !!c);
if (classes.length) {
isAdd ? element.classList.add(...classes) : element.classList.remove(...classes);
}
}
/** Detaches the overlay content next time the zone stabilizes. */
_detachContentWhenEmpty() {
this._ngZone.runOutsideAngular(() => {
const subscription = this._renders.pipe(takeUntil(merge(this._attachments, this._detachments))).subscribe(() => {
if (!this._pane || !this._host || this._pane.children.length === 0) {
if (this._pane && this._config.panelClass) {
this._toggleClasses(this._pane, this._config.panelClass, false);
}
if (this._host && this._host.parentElement) {
this._previousHostParent = this._host.parentElement;
this._host.remove();
}
subscription.unsubscribe();
}
});
});
}
/** Disposes of a scroll strategy. */
_disposeScrollStrategy() {
const scrollStrategy = this._scrollStrategy;
scrollStrategy?.disable();
scrollStrategy?.detach?.();
}
};
var boundingBoxClass = "cdk-overlay-connected-position-bounding-box";
var cssUnitPattern = /([A-Za-z%]+)$/;
var FlexibleConnectedPositionStrategy = class {
_viewportRuler;
_document;
_platform;
_overlayContainer;
/** The overlay to which this strategy is attached. */
_overlayRef;
/** Whether we're performing the very first positioning of the overlay. */
_isInitialRender;
/** Last size used for the bounding box. Used to avoid resizing the overlay after open. */
_lastBoundingBoxSize = {
width: 0,
height: 0
};
/** Whether the overlay was pushed in a previous positioning. */
_isPushed = false;
/** Whether the overlay can be pushed on-screen on the initial open. */
_canPush = true;
/** Whether the overlay can grow via flexible width/height after the initial open. */
_growAfterOpen = false;
/** Whether the overlay's width and height can be constrained to fit within the viewport. */
_hasFlexibleDimensions = true;
/** Whether the overlay position is locked. */
_positionLocked = false;
/** Cached origin dimensions */
_originRect;
/** Cached overlay dimensions */
_overlayRect;
/** Cached viewport dimensions */
_viewportRect;
/** Cached container dimensions */
_containerRect;
/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
_viewportMargin = 0;
/** The Scrollable containers used to check scrollable view properties on position change. */
_scrollables = [];
/** Ordered list of preferred positions, from most to least desirable. */
_preferredPositions = [];
/** The origin element against which the overlay will be positioned. */
_origin;
/** The overlay pane element. */
_pane;
/** Whether the strategy has been disposed of already. */
_isDisposed;
/**
* Parent element for the overlay panel used to constrain the overlay panel's size to fit
* within the viewport.
*/
_boundingBox;
/** The last position to have been calculated as the best fit position. */
_lastPosition;
/** The last calculated scroll visibility. Only tracked */
_lastScrollVisibility;
/** Subject that emits whenever the position changes. */
_positionChanges = new Subject();
/** Subscription to viewport size changes. */
_resizeSubscription = Subscription.EMPTY;
/** Default offset for the overlay along the x axis. */
_offsetX = 0;
/** Default offset for the overlay along the y axis. */
_offsetY = 0;
/** Selector to be used when finding the elements on which to set the transform origin. */
_transformOriginSelector;
/** Keeps track of the CSS classes that the position strategy has applied on the overlay panel. */
_appliedPanelClasses = [];
/** Amount by which the overlay was pushed in each axis during the last time it was positioned. */
_previousPushAmount;
/** Observable sequence of position changes. */
positionChanges = this._positionChanges;
/** Ordered list of preferred positions, from most to least desirable. */
get positions() {
return this._preferredPositions;
}
constructor(connectedTo, _viewportRuler, _document2, _platform, _overlayContainer) {
this._viewportRuler = _viewportRuler;
this._document = _document2;
this._platform = _platform;
this._overlayContainer = _overlayContainer;
this.setOrigin(connectedTo);
}
/** Attaches this position strategy to an overlay. */
attach(overlayRef) {
if (this._overlayRef && overlayRef !== this._overlayRef && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error("This position strategy is already attached to an overlay");
}
this._validatePositions();
overlayRef.hostElement.classList.add(boundingBoxClass);
this._overlayRef = overlayRef;
this._boundingBox = overlayRef.hostElement;
this._pane = overlayRef.overlayElement;
this._isDisposed = false;
this._isInitialRender = true;
this._lastPosition = null;
this._resizeSubscription.unsubscribe();
this._resizeSubscription = this._viewportRuler.change().subscribe(() => {
this._isInitialRender = true;
this.apply();
});
}
/**
* Updates the position of the overlay element, using whichever preferred position relative
* to the origin best fits on-screen.
*
* The selection of a position goes as follows:
* - If any positions fit completely within the viewport as-is,
* choose the first position that does so.
* - If flexible dimensions are enabled and at least one satisfies the given minimum width/height,
* choose the position with the greatest available size modified by the positions' weight.
* - If pushing is enabled, take the position that went off-screen the least and push it
* on-screen.
* - If none of the previous criteria were met, use the position that goes off-screen the least.
* @docs-private
*/
apply() {
if (this._isDisposed || !this._platform.isBrowser) {
return;
}
if (!this._isInitialRender && this._positionLocked && this._lastPosition) {
this.reapplyLastPosition();
return;
}
this._clearPanelClasses();
this._resetOverlayElementStyles();
this._resetBoundingBoxStyles();
this._viewportRect = this._getNarrowedViewportRect();
this._originRect = this._getOriginRect();
this._overlayRect = this._pane.getBoundingClientRect();
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
const originRect = this._originRect;
const overlayRect = this._overlayRect;
const viewportRect = this._viewportRect;
const containerRect = this._containerRect;
const flexibleFits = [];
let fallback;
for (let pos of this._preferredPositions) {
let originPoint = this._getOriginPoint(originRect, containerRect, pos);
let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);
let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos);
if (overlayFit.isCompletelyWithinViewport) {
this._isPushed = false;
this._applyPosition(pos, originPoint);
return;
}
if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) {
flexibleFits.push({
position: pos,
origin: originPoint,
overlayRect,
boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos)
});
continue;
}
if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) {
fallback = {
overlayFit,
overlayPoint,
originPoint,
position: pos,
overlayRect
};
}
}
if (flexibleFits.length) {
let bestFit = null;
let bestScore = -1;
for (const fit of flexibleFits) {
const score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1);
if (score > bestScore) {
bestScore = score;
bestFit = fit;
}
}
this._isPushed = false;
this._applyPosition(bestFit.position, bestFit.origin);
return;
}
if (this._canPush) {
this._isPushed = true;
this._applyPosition(fallback.position, fallback.originPoint);
return;
}
this._applyPosition(fallback.position, fallback.originPoint);
}
detach() {
this._clearPanelClasses();
this._lastPosition = null;
this._previousPushAmount = null;
this._resizeSubscription.unsubscribe();
}
/** Cleanup after the element gets destroyed. */
dispose() {
if (this._isDisposed) {
return;
}
if (this._boundingBox) {
extendStyles(this._boundingBox.style, {
top: "",
left: "",
right: "",
bottom: "",
height: "",
width: "",
alignItems: "",
justifyContent: ""
});
}
if (this._pane) {
this._resetOverlayElementStyles();
}
if (this._overlayRef) {
this._overlayRef.hostElement.classList.remove(boundingBoxClass);
}
this.detach();
this._positionChanges.complete();
this._overlayRef = this._boundingBox = null;
this._isDisposed = true;
}
/**
* This re-aligns the overlay element with the trigger in its last calculated position,
* even if a position higher in the "preferred positions" list would now fit. This
* allows one to re-align the panel without changing the orientation of the panel.
*/
reapplyLastPosition() {
if (this._isDisposed || !this._platform.isBrowser) {
return;
}
const lastPosition = this._lastPosition;
if (lastPosition) {
this._originRect = this._getOriginRect();
this._overlayRect = this._pane.getBoundingClientRect();
this._viewportRect = this._getNarrowedViewportRect();
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
const originPoint = this._getOriginPoint(this._originRect, this._containerRect, lastPosition);
this._applyPosition(lastPosition, originPoint);
} else {
this.apply();
}
}
/**
* Sets the list of Scrollable containers that host the origin element so that
* on reposition we can evaluate if it or the overlay has been clipped or outside view. Every
* Scrollable must be an ancestor element of the strategy's origin element.
*/
withScrollableContainers(scrollables) {
this._scrollables = scrollables;
return this;
}
/**
* Adds new preferred positions.
* @param positions List of positions options for this overlay.
*/
withPositions(positions) {
this._preferredPositions = positions;
if (positions.indexOf(this._lastPosition) === -1) {
this._lastPosition = null;
}
this._validatePositions();
return this;
}
/**
* Sets a minimum distance the overlay may be positioned to the edge of the viewport.
* @param margin Required margin between the overlay and the viewport edge in pixels.
*/
withViewportMargin(margin) {
this._viewportMargin = margin;
return this;
}
/** Sets whether the overlay's width and height can be constrained to fit within the viewport. */
withFlexibleDimensions(flexibleDimensions = true) {
this._hasFlexibleDimensions = flexibleDimensions;
return this;
}
/** Sets whether the overlay can grow after the initial open via flexible width/height. */
withGrowAfterOpen(growAfterOpen = true) {
this._growAfterOpen = growAfterOpen;
return this;
}
/** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */
withPush(canPush = true) {
this._canPush = canPush;
return this;
}
/**
* Sets whether the overlay's position should be locked in after it is positioned
* initially. When an overlay is locked in, it won't attempt to reposition itself
* when the position is re-applied (e.g. when the user scrolls away).
* @param isLocked Whether the overlay should locked in.
*/
withLockedPosition(isLocked = true) {
this._positionLocked = isLocked;
return this;
}
/**
* Sets the origin, relative to which to position the overlay.
* Using an element origin is useful for building components that need to be positioned
* relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be
* used for cases like contextual menus which open relative to the user's pointer.
* @param origin Reference to the new origin.
*/
setOrigin(origin) {
this._origin = origin;
return this;
}
/**
* Sets the default offset for the overlay's connection point on the x-axis.
* @param offset New offset in the X axis.
*/
withDefaultOffsetX(offset) {
this._offsetX = offset;
return this;
}
/**
* Sets the default offset for the overlay's connection point on the y-axis.
* @param offset New offset in the Y axis.
*/
withDefaultOffsetY(offset) {
this._offsetY = offset;
return this;
}
/**
* Configures that the position strategy should set a `transform-origin` on some elements
* inside the overlay, depending on the current position that is being applied. This is
* useful for the cases where the origin of an animation can change depending on the
* alignment of the overlay.
* @param selector CSS selector that will be used to find the target
* elements onto which to set the transform origin.
*/
withTransformOriginOn(selector) {
this._transformOriginSelector = selector;
return this;
}
/**
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
*/
_getOriginPoint(originRect, containerRect, pos) {
let x;
if (pos.originX == "center") {
x = originRect.left + originRect.width / 2;
} else {
const startX = this._isRtl() ? originRect.right : originRect.left;
const endX = this._isRtl() ? originRect.left : originRect.right;
x = pos.originX == "start" ? startX : endX;
}
if (containerRect.left < 0) {
x -= containerRect.left;
}
let y;
if (pos.originY == "center") {
y = originRect.top + originRect.height / 2;
} else {
y = pos.originY == "top" ? originRect.top : originRect.bottom;
}
if (containerRect.top < 0) {
y -= containerRect.top;
}
return {
x,
y
};
}
/**
* Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and
* origin point to which the overlay should be connected.
*/
_getOverlayPoint(originPoint, overlayRect, pos) {
let overlayStartX;
if (pos.overlayX == "center") {
overlayStartX = -overlayRect.width / 2;
} else if (pos.overlayX === "start") {
overlayStartX = this._isRtl() ? -overlayRect.width : 0;
} else {
overlayStartX = this._isRtl() ? 0 : -overlayRect.width;
}
let overlayStartY;
if (pos.overlayY == "center") {
overlayStartY = -overlayRect.height / 2;
} else {
overlayStartY = pos.overlayY == "top" ? 0 : -overlayRect.height;
}
return {
x: originPoint.x + overlayStartX,
y: originPoint.y + overlayStartY
};
}
/** Gets how well an overlay at the given point will fit within the viewport. */
_getOverlayFit(point, rawOverlayRect, viewport, position) {
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
let {
x,
y
} = point;
let offsetX = this._getOffset(position, "x");
let offsetY = this._getOffset(position, "y");
if (offsetX) {
x += offsetX;
}
if (offsetY) {
y += offsetY;
}
let leftOverflow = 0 - x;
let rightOverflow = x + overlay.width - viewport.width;
let topOverflow = 0 - y;
let bottomOverflow = y + overlay.height - viewport.height;
let visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow);
let visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow);
let visibleArea = visibleWidth * visibleHeight;
return {
visibleArea,
isCompletelyWithinViewport: overlay.width * overlay.height === visibleArea,
fitsInViewportVertically: visibleHeight === overlay.height,
fitsInViewportHorizontally: visibleWidth == overlay.width
};
}
/**
* Whether the overlay can fit within the viewport when it may resize either its width or height.
* @param fit How well the overlay fits in the viewport at some position.
* @param point The (x, y) coordinates of the overlay at some position.
* @param viewport The geometry of the viewport.
*/
_canFitWithFlexibleDimensions(fit, point, viewport) {
if (this._hasFlexibleDimensions) {
const availableHeight = viewport.bottom - point.y;
const availableWidth = viewport.right - point.x;
const minHeight = getPixelValue(this._overlayRef.getConfig().minHeight);
const minWidth = getPixelValue(this._overlayRef.getConfig().minWidth);
const verticalFit = fit.fitsInViewportVertically || minHeight != null && minHeight <= availableHeight;
const horizontalFit = fit.fitsInViewportHorizontally || minWidth != null && minWidth <= availableWidth;
return verticalFit && horizontalFit;
}
return false;
}
/**
* Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than
* the viewport, the top-left corner will be pushed on-screen (with overflow occurring on the
* right and bottom).
*
* @param start Starting point from which the overlay is pushed.
* @param rawOverlayRect Dimensions of the overlay.
* @param scrollPosition Current viewport scroll position.
* @returns The point at which to position the overlay after pushing. This is effectively a new
* originPoint.
*/
_pushOverlayOnScreen(start, rawOverlayRect, scrollPosition) {
if (this._previousPushAmount && this._positionLocked) {
return {
x: start.x + this._previousPushAmount.x,
y: start.y + this._previousPushAmount.y
};
}
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
const viewport = this._viewportRect;
const overflowRight = Math.max(start.x + overlay.width - viewport.width, 0);
const overflowBottom = Math.max(start.y + overlay.height - viewport.height, 0);
const overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0);
const overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0);
let pushX = 0;
let pushY = 0;
if (overlay.width <= viewport.width) {
pushX = overflowLeft || -overflowRight;
} else {
pushX = start.x < this._viewportMargin ? viewport.left - scrollPosition.left - start.x : 0;
}
if (overlay.height <= viewport.height) {
pushY = overflowTop || -overflowBottom;
} else {
pushY = start.y < this._viewportMargin ? viewport.top - scrollPosition.top - start.y : 0;
}
this._previousPushAmount = {
x: pushX,
y: pushY
};
return {
x: start.x + pushX,
y: start.y + pushY
};
}
/**
* Applies a computed position to the overlay and emits a position change.
* @param position The position preference
* @param originPoint The point on the origin element where the overlay is connected.
*/
_applyPosition(position, originPoint) {
this._setTransformOrigin(position);
this._setOverlayElementStyles(originPoint, position);
this._setBoundingBoxStyles(originPoint, position);
if (position.panelClass) {
this._addPanelClasses(position.panelClass);
}
if (this._positionChanges.observers.length) {
const scrollVisibility = this._getScrollVisibility();
if (position !== this._lastPosition || !this._lastScrollVisibility || !compareScrollVisibility(this._lastScrollVisibility, scrollVisibility)) {
const changeEvent = new ConnectedOverlayPositionChange(position, scrollVisibility);
this._positionChanges.next(changeEvent);
}
this._lastScrollVisibility = scrollVisibility;
}
this._lastPosition = position;
this._isInitialRender = false;
}
/** Sets the transform origin based on the configured selector and the passed-in position. */
_setTransformOrigin(position) {
if (!this._transformOriginSelector) {
return;
}
const elements = this._boundingBox.querySelectorAll(this._transformOriginSelector);
let xOrigin;
let yOrigin = position.overlayY;
if (position.overlayX === "center") {
xOrigin = "center";
} else if (this._isRtl()) {
xOrigin = position.overlayX === "start" ? "right" : "left";
} else {
xOrigin = position.overlayX === "start" ? "left" : "right";
}
for (let i = 0; i < elements.length; i++) {
elements[i].style.transformOrigin = `${xOrigin} ${yOrigin}`;
}
}
/**
* Gets the position and size of the overlay's sizing container.
*
* This method does no measuring and applies no styles so that we can cheaply compute the
* bounds for all positions and choose the best fit based on these results.
*/
_calculateBoundingBoxRect(origin, position) {
const viewport = this._viewportRect;
const isRtl = this._isRtl();
let height, top, bottom;
if (position.overlayY === "top") {
top = origin.y;
height = viewport.height - top + this._viewportMargin;
} else if (position.overlayY === "bottom") {
bottom = viewport.height - origin.y + this._viewportMargin * 2;
height = viewport.height - bottom + this._viewportMargin;
} else {
const smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y);
const previousHeight = this._lastBoundingBoxSize.height;
height = smallestDistanceToViewportEdge * 2;
top = origin.y - smallestDistanceToViewportEdge;
if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) {
top = origin.y - previousHeight / 2;
}
}
const isBoundedByRightViewportEdge = position.overlayX === "start" && !isRtl || position.overlayX === "end" && isRtl;
const isBoundedByLeftViewportEdge = position.overlayX === "end" && !isRtl || position.overlayX === "start" && isRtl;
let width, left, right;
if (isBoundedByLeftViewportEdge) {
right = viewport.width - origin.x + this._viewportMargin * 2;
width = origin.x - this._viewportMargin;
} else if (isBoundedByRightViewportEdge) {
left = origin.x;
width = viewport.right - origin.x;
} else {
const smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x);
const previousWidth = this._lastBoundingBoxSize.width;
width = smallestDistanceToViewportEdge * 2;
left = origin.x - smallestDistanceToViewportEdge;
if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) {
left = origin.x - previousWidth / 2;
}
}
return {
top,
left,
bottom,
right,
width,
height
};
}
/**
* Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the
* origin's connection point and stretches to the bounds of the viewport.
*
* @param origin The point on the origin element where the overlay is connected.
* @param position The position preference
*/
_setBoundingBoxStyles(origin, position) {
const boundingBoxRect = this._calculateBoundingBoxRect(origin, position);
if (!this._isInitialRender && !this._growAfterOpen) {
boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height);
boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width);
}
const styles = {};
if (this._hasExactPosition()) {
styles.top = styles.left = "0";
styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = "";
styles.width = styles.height = "100%";
} else {
const maxHeight = this._overlayRef.getConfig().maxHeight;
const maxWidth = this._overlayRef.getConfig().maxWidth;
styles.height = coerceCssPixelValue(boundingBoxRect.height);
styles.top = coerceCssPixelValue(boundingBoxRect.top);
styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom);
styles.width = coerceCssPixelValue(boundingBoxRect.width);
styles.left = coerceCssPixelValue(boundingBoxRect.left);
styles.right = coerceCssPixelValue(boundingBoxRect.right);
if (position.overlayX === "center") {
styles.alignItems = "center";
} else {
styles.alignItems = position.overlayX === "end" ? "flex-end" : "flex-start";
}
if (position.overlayY === "center") {
styles.justifyContent = "center";
} else {
styles.justifyContent = position.overlayY === "bottom" ? "flex-end" : "flex-start";
}
if (maxHeight) {
styles.maxHeight = coerceCssPixelValue(maxHeight);
}
if (maxWidth) {
styles.maxWidth = coerceCssPixelValue(maxWidth);
}
}
this._lastBoundingBoxSize = boundingBoxRect;
extendStyles(this._boundingBox.style, styles);
}
/** Resets the styles for the bounding box so that a new positioning can be computed. */
_resetBoundingBoxStyles() {
extendStyles(this._boundingBox.style, {
top: "0",
left: "0",
right: "0",
bottom: "0",
height: "",
width: "",
alignItems: "",
justifyContent: ""
});
}
/** Resets the styles for the overlay pane so that a new positioning can be computed. */
_resetOverlayElementStyles() {
extendStyles(this._pane.style, {
top: "",
left: "",
bottom: "",
right: "",
position: "",
transform: ""
});
}
/** Sets positioning styles to the overlay element. */
_setOverlayElementStyles(originPoint, position) {
const styles = {};
const hasExactPosition = this._hasExactPosition();
const hasFlexibleDimensions = this._hasFlexibleDimensions;
const config = this._overlayRef.getConfig();
if (hasExactPosition) {
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition));
extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition));
} else {
styles.position = "static";
}
let transformString = "";
let offsetX = this._getOffset(position, "x");
let offsetY = this._getOffset(position, "y");
if (offsetX) {
transformString += `translateX(${offsetX}px) `;
}
if (offsetY) {
transformString += `translateY(${offsetY}px)`;
}
styles.transform = transformString.trim();
if (config.maxHeight) {
if (hasExactPosition) {
styles.maxHeight = coerceCssPixelValue(config.maxHeight);
} else if (hasFlexibleDimensions) {
styles.maxHeight = "";
}
}
if (config.maxWidth) {
if (hasExactPosition) {
styles.maxWidth = coerceCssPixelValue(config.maxWidth);
} else if (hasFlexibleDimensions) {
styles.maxWidth = "";
}
}
extendStyles(this._pane.style, styles);
}
/** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */
_getExactOverlayY(position, originPoint, scrollPosition) {
let styles = {
top: "",
bottom: ""
};
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
if (this._isPushed) {
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
}
if (position.overlayY === "bottom") {
const documentHeight = this._document.documentElement.clientHeight;
styles.bottom = `${documentHeight - (overlayPoint.y + this._overlayRect.height)}px`;
} else {
styles.top = coerceCssPixelValue(overlayPoint.y);
}
return styles;
}
/** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */
_getExactOverlayX(position, originPoint, scrollPosition) {
let styles = {
left: "",
right: ""
};
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
if (this._isPushed) {
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
}
let horizontalStyleProperty;
if (this._isRtl()) {
horizontalStyleProperty = position.overlayX === "end" ? "left" : "right";
} else {
horizontalStyleProperty = position.overlayX === "end" ? "right" : "left";
}
if (horizontalStyleProperty === "right") {
const documentWidth = this._document.documentElement.clientWidth;
styles.right = `${documentWidth - (overlayPoint.x + this._overlayRect.width)}px`;
} else {
styles.left = coerceCssPixelValue(overlayPoint.x);
}
return styles;
}
/**
* Gets the view properties of the trigger and overlay, including whether they are clipped
* or completely outside the view of any of the strategy's scrollables.
*/
_getScrollVisibility() {
const originBounds = this._getOriginRect();
const overlayBounds = this._pane.getBoundingClientRect();
const scrollContainerBounds = this._scrollables.map((scrollable) => {
return scrollable.getElementRef().nativeElement.getBoundingClientRect();
});
return {
isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds),
isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds),
isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds),
isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds)
};
}
/** Subtracts the amount that an element is overflowing on an axis from its length. */
_subtractOverflows(length, ...overflows) {
return overflows.reduce((currentValue, currentOverflow) => {
return currentValue - Math.max(currentOverflow, 0);
}, length);
}
/** Narrows the given viewport rect by the current _viewportMargin. */
_getNarrowedViewportRect() {
const width = this._document.documentElement.clientWidth;
const height = this._document.documentElement.clientHeight;
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
return {
top: scrollPosition.top + this._viewportMargin,
left: scrollPosition.left + this._viewportMargin,
right: scrollPosition.left + width - this._viewportMargin,
bottom: scrollPosition.top + height - this._viewportMargin,
width: width - 2 * this._viewportMargin,
height: height - 2 * this._viewportMargin
};
}
/** Whether the we're dealing with an RTL context */
_isRtl() {
return this._overlayRef.getDirection() === "rtl";
}
/** Determines whether the overlay uses exact or flexible positioning. */
_hasExactPosition() {
return !this._hasFlexibleDimensions || this._isPushed;
}
/** Retrieves the offset of a position along the x or y axis. */
_getOffset(position, axis) {
if (axis === "x") {
return position.offsetX == null ? this._offsetX : position.offsetX;
}
return position.offsetY == null ? this._offsetY : position.offsetY;
}
/** Validates that the current position match the expected values. */
_validatePositions() {
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (!this._preferredPositions.length) {
throw Error("FlexibleConnectedPositionStrategy: At least one position is required.");
}
this._preferredPositions.forEach((pair) => {
validateHorizontalPosition("originX", pair.originX);
validateVerticalPosition("originY", pair.originY);
validateHorizontalPosition("overlayX", pair.overlayX);
validateVerticalPosition("overlayY", pair.overlayY);
});
}
}
/** Adds a single CSS class or an array of classes on the overlay panel. */
_addPanelClasses(cssClasses) {
if (this._pane) {
coerceArray(cssClasses).forEach((cssClass) => {
if (cssClass !== "" && this._appliedPanelClasses.indexOf(cssClass) === -1) {
this._appliedPanelClasses.push(cssClass);
this._pane.classList.add(cssClass);
}
});
}
}
/** Clears the classes that the position strategy has applied from the overlay panel. */
_clearPanelClasses() {
if (this._pane) {
this._appliedPanelClasses.forEach((cssClass) => {
this._pane.classList.remove(cssClass);
});
this._appliedPanelClasses = [];
}
}
/** Returns the DOMRect of the current origin. */
_getOriginRect() {
const origin = this._origin;
if (origin instanceof ElementRef) {
return origin.nativeElement.getBoundingClientRect();
}
if (origin instanceof Element) {
return origin.getBoundingClientRect();
}
const width = origin.width || 0;
const height = origin.height || 0;
return {
top: origin.y,
bottom: origin.y + height,
left: origin.x,
right: origin.x + width,
height,
width
};
}
};
function extendStyles(destination, source) {
for (let key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
}
function getPixelValue(input2) {
if (typeof input2 !== "number" && input2 != null) {
const [value, units] = input2.split(cssUnitPattern);
return !units || units === "px" ? parseFloat(value) : null;
}
return input2 || null;
}
function getRoundedBoundingClientRect(clientRect) {
return {
top: Math.floor(clientRect.top),
right: Math.floor(clientRect.right),
bottom: Math.floor(clientRect.bottom),
left: Math.floor(clientRect.left),
width: Math.floor(clientRect.width),
height: Math.floor(clientRect.height)
};
}
function compareScrollVisibility(a, b) {
if (a === b) {
return true;
}
return a.isOriginClipped === b.isOriginClipped && a.isOriginOutsideView === b.isOriginOutsideView && a.isOverlayClipped === b.isOverlayClipped && a.isOverlayOutsideView === b.isOverlayOutsideView;
}
var wrapperClass = "cdk-global-overlay-wrapper";
var GlobalPositionStrategy = class {
/** The overlay to which this strategy is attached. */
_overlayRef;
_cssPosition = "static";
_topOffset = "";
_bottomOffset = "";
_alignItems = "";
_xPosition = "";
_xOffset = "";
_width = "";
_height = "";
_isDisposed = false;
attach(overlayRef) {
const config = overlayRef.getConfig();
this._overlayRef = overlayRef;
if (this._width && !config.width) {
overlayRef.updateSize({
width: this._width
});
}
if (this._height && !config.height) {
overlayRef.updateSize({
height: this._height
});
}
overlayRef.hostElement.classList.add(wrapperClass);
this._isDisposed = false;
}
/**
* Sets the top position of the overlay. Clears any previously set vertical position.
* @param value New top offset.
*/
top(value = "") {
this._bottomOffset = "";
this._topOffset = value;
this._alignItems = "flex-start";
return this;
}
/**
* Sets the left position of the overlay. Clears any previously set horizontal position.
* @param value New left offset.
*/
left(value = "") {
this._xOffset = value;
this._xPosition = "left";
return this;
}
/**
* Sets the bottom position of the overlay. Clears any previously set vertical position.
* @param value New bottom offset.
*/
bottom(value = "") {
this._topOffset = "";
this._bottomOffset = value;
this._alignItems = "flex-end";
return this;
}
/**
* Sets the right position of the overlay. Clears any previously set horizontal position.
* @param value New right offset.
*/
right(value = "") {
this._xOffset = value;
this._xPosition = "right";
return this;
}
/**
* Sets the overlay to the start of the viewport, depending on the overlay direction.
* This will be to the left in LTR layouts and to the right in RTL.
* @param offset Offset from the edge of the screen.
*/
start(value = "") {
this._xOffset = value;
this._xPosition = "start";
return this;
}
/**
* Sets the overlay to the end of the viewport, depending on the overlay direction.
* This will be to the right in LTR layouts and to the left in RTL.
* @param offset Offset from the edge of the screen.
*/
end(value = "") {
this._xOffset = value;
this._xPosition = "end";
return this;
}
/**
* Sets the overlay width and clears any previously set width.
* @param value New width for the overlay
* @deprecated Pass the `width` through the `OverlayConfig`.
* @breaking-change 8.0.0
*/
width(value = "") {
if (this._overlayRef) {
this._overlayRef.updateSize({
width: value
});
} else {
this._width = value;
}
return this;
}
/**
* Sets the overlay height and clears any previously set height.
* @param value New height for the overlay
* @deprecated Pass the `height` through the `OverlayConfig`.
* @breaking-change 8.0.0
*/
height(value = "") {
if (this._overlayRef) {
this._overlayRef.updateSize({
height: value
});
} else {
this._height = value;
}
return this;
}
/**
* Centers the overlay horizontally with an optional offset.
* Clears any previously set horizontal position.
*
* @param offset Overlay offset from the horizontal center.
*/
centerHorizontally(offset = "") {
this.left(offset);
this._xPosition = "center";
return this;
}
/**
* Centers the overlay vertically with an optional offset.
* Clears any previously set vertical position.
*
* @param offset Overlay offset from the vertical center.
*/
centerVertically(offset = "") {
this.top(offset);
this._alignItems = "center";
return this;
}
/**
* Apply the position to the element.
* @docs-private
*/
apply() {
if (!this._overlayRef || !this._overlayRef.hasAttached()) {
return;
}
const styles = this._overlayRef.overlayElement.style;
const parentStyles = this._overlayRef.hostElement.style;
const config = this._overlayRef.getConfig();
const {
width,
height,
maxWidth,
maxHeight
} = config;
const shouldBeFlushHorizontally = (width === "100%" || width === "100vw") && (!maxWidth || maxWidth === "100%" || maxWidth === "100vw");
const shouldBeFlushVertically = (height === "100%" || height === "100vh") && (!maxHeight || maxHeight === "100%" || maxHeight === "100vh");
const xPosition = this._xPosition;
const xOffset = this._xOffset;
const isRtl = this._overlayRef.getConfig().direction === "rtl";
let marginLeft = "";
let marginRight = "";
let justifyContent = "";
if (shouldBeFlushHorizontally) {
justifyContent = "flex-start";
} else if (xPosition === "center") {
justifyContent = "center";
if (isRtl) {
marginRight = xOffset;
} else {
marginLeft = xOffset;
}
} else if (isRtl) {
if (xPosition === "left" || xPosition === "end") {
justifyContent = "flex-end";
marginLeft = xOffset;
} else if (xPosition === "right" || xPosition === "start") {
justifyContent = "flex-start";
marginRight = xOffset;
}
} else if (xPosition === "left" || xPosition === "start") {
justifyContent = "flex-start";
marginLeft = xOffset;
} else if (xPosition === "right" || xPosition === "end") {
justifyContent = "flex-end";
marginRight = xOffset;
}
styles.position = this._cssPosition;
styles.marginLeft = shouldBeFlushHorizontally ? "0" : marginLeft;
styles.marginTop = shouldBeFlushVertically ? "0" : this._topOffset;
styles.marginBottom = this._bottomOffset;
styles.marginRight = shouldBeFlushHorizontally ? "0" : marginRight;
parentStyles.justifyContent = justifyContent;
parentStyles.alignItems = shouldBeFlushVertically ? "flex-start" : this._alignItems;
}
/**
* Cleans up the DOM changes from the position strategy.
* @docs-private
*/
dispose() {
if (this._isDisposed || !this._overlayRef) {
return;
}
const styles = this._overlayRef.overlayElement.style;
const parent = this._overlayRef.hostElement;
const parentStyles = parent.style;
parent.classList.remove(wrapperClass);
parentStyles.justifyContent = parentStyles.alignItems = styles.marginTop = styles.marginBottom = styles.marginLeft = styles.marginRight = styles.position = "";
this._overlayRef = null;
this._isDisposed = true;
}
};
var OverlayPositionBuilder = class _OverlayPositionBuilder {
_viewportRuler = inject(ViewportRuler);
_document = inject(DOCUMENT);
_platform = inject(Platform);
_overlayContainer = inject(OverlayContainer);
constructor() {
}
/**
* Creates a global position strategy.
*/
global() {
return new GlobalPositionStrategy();
}
/**
* Creates a flexible position strategy.
* @param origin Origin relative to which to position the overlay.
*/
flexibleConnectedTo(origin) {
return new FlexibleConnectedPositionStrategy(origin, this._viewportRuler, this._document, this._platform, this._overlayContainer);
}
static \u0275fac = function OverlayPositionBuilder_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _OverlayPositionBuilder)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _OverlayPositionBuilder,
factory: _OverlayPositionBuilder.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(OverlayPositionBuilder, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var Overlay = class _Overlay {
scrollStrategies = inject(ScrollStrategyOptions);
_overlayContainer = inject(OverlayContainer);
_positionBuilder = inject(OverlayPositionBuilder);
_keyboardDispatcher = inject(OverlayKeyboardDispatcher);
_injector = inject(Injector);
_ngZone = inject(NgZone);
_document = inject(DOCUMENT);
_directionality = inject(Directionality);
_location = inject(Location);
_outsideClickDispatcher = inject(OverlayOutsideClickDispatcher);
_animationsModuleType = inject(ANIMATION_MODULE_TYPE, {
optional: true
});
_idGenerator = inject(_IdGenerator);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_appRef;
_styleLoader = inject(_CdkPrivateStyleLoader);
constructor() {
}
/**
* Creates an overlay.
* @param config Configuration applied to the overlay.
* @returns Reference to the created overlay.
*/
create(config) {
this._styleLoader.load(_CdkOverlayStyleLoader);
const host = this._createHostElement();
const pane = this._createPaneElement(host);
const portalOutlet = this._createPortalOutlet(pane);
const overlayConfig = new OverlayConfig(config);
overlayConfig.direction = overlayConfig.direction || this._directionality.value;
return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location, this._outsideClickDispatcher, this._animationsModuleType === "NoopAnimations", this._injector.get(EnvironmentInjector), this._renderer);
}
/**
* Gets a position builder that can be used, via fluent API,
* to construct and configure a position strategy.
* @returns An overlay position builder.
*/
position() {
return this._positionBuilder;
}
/**
* Creates the DOM element for an overlay and appends it to the overlay container.
* @returns Newly-created pane element
*/
_createPaneElement(host) {
const pane = this._document.createElement("div");
pane.id = this._idGenerator.getId("cdk-overlay-");
pane.classList.add("cdk-overlay-pane");
host.appendChild(pane);
return pane;
}
/**
* Creates the host element that wraps around an overlay
* and can be used for advanced positioning.
* @returns Newly-create host element.
*/
_createHostElement() {
const host = this._document.createElement("div");
this._overlayContainer.getContainerElement().appendChild(host);
return host;
}
/**
* Create a DomPortalOutlet into which the overlay content can be loaded.
* @param pane The DOM element to turn into a portal outlet.
* @returns A portal outlet for the given DOM element.
*/
_createPortalOutlet(pane) {
if (!this._appRef) {
this._appRef = this._injector.get(ApplicationRef);
}
return new DomPortalOutlet(pane, null, this._appRef, this._injector, this._document);
}
static \u0275fac = function Overlay_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Overlay)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Overlay,
factory: _Overlay.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Overlay, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var defaultPositionList = [{
originX: "start",
originY: "bottom",
overlayX: "start",
overlayY: "top"
}, {
originX: "start",
originY: "top",
overlayX: "start",
overlayY: "bottom"
}, {
originX: "end",
originY: "top",
overlayX: "end",
overlayY: "bottom"
}, {
originX: "end",
originY: "bottom",
overlayX: "end",
overlayY: "top"
}];
var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = new InjectionToken("cdk-connected-overlay-scroll-strategy", {
providedIn: "root",
factory: () => {
const overlay = inject(Overlay);
return () => overlay.scrollStrategies.reposition();
}
});
var CdkOverlayOrigin = class _CdkOverlayOrigin {
elementRef = inject(ElementRef);
constructor() {
}
static \u0275fac = function CdkOverlayOrigin_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkOverlayOrigin)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkOverlayOrigin,
selectors: [["", "cdk-overlay-origin", ""], ["", "overlay-origin", ""], ["", "cdkOverlayOrigin", ""]],
exportAs: ["cdkOverlayOrigin"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkOverlayOrigin, [{
type: Directive,
args: [{
selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]",
exportAs: "cdkOverlayOrigin"
}]
}], () => [], null);
})();
var CdkConnectedOverlay = class _CdkConnectedOverlay {
_overlay = inject(Overlay);
_dir = inject(Directionality, {
optional: true
});
_overlayRef;
_templatePortal;
_backdropSubscription = Subscription.EMPTY;
_attachSubscription = Subscription.EMPTY;
_detachSubscription = Subscription.EMPTY;
_positionSubscription = Subscription.EMPTY;
_offsetX;
_offsetY;
_position;
_scrollStrategyFactory = inject(CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY);
_disposeOnNavigation = false;
_ngZone = inject(NgZone);
/** Origin for the connected overlay. */
origin;
/** Registered connected position pairs. */
positions;
/**
* This input overrides the positions input if specified. It lets users pass
* in arbitrary positioning strategies.
*/
positionStrategy;
/** The offset in pixels for the overlay connection point on the x-axis */
get offsetX() {
return this._offsetX;
}
set offsetX(offsetX) {
this._offsetX = offsetX;
if (this._position) {
this._updatePositionStrategy(this._position);
}
}
/** The offset in pixels for the overlay connection point on the y-axis */
get offsetY() {
return this._offsetY;
}
set offsetY(offsetY) {
this._offsetY = offsetY;
if (this._position) {
this._updatePositionStrategy(this._position);
}
}
/** The width of the overlay panel. */
width;
/** The height of the overlay panel. */
height;
/** The min width of the overlay panel. */
minWidth;
/** The min height of the overlay panel. */
minHeight;
/** The custom class to be set on the backdrop element. */
backdropClass;
/** The custom class to add to the overlay pane element. */
panelClass;
/** Margin between the overlay and the viewport edges. */
viewportMargin = 0;
/** Strategy to be used when handling scroll events while the overlay is open. */
scrollStrategy;
/** Whether the overlay is open. */
open = false;
/** Whether the overlay can be closed by user interaction. */
disableClose = false;
/** CSS selector which to set the transform origin. */
transformOriginSelector;
/** Whether or not the overlay should attach a backdrop. */
hasBackdrop = false;
/** Whether or not the overlay should be locked when scrolling. */
lockPosition = false;
/** Whether the overlay's width and height can be constrained to fit within the viewport. */
flexibleDimensions = false;
/** Whether the overlay can grow after the initial open when flexible positioning is turned on. */
growAfterOpen = false;
/** Whether the overlay can be pushed on-screen if none of the provided positions fit. */
push = false;
/** Whether the overlay should be disposed of when the user goes backwards/forwards in history. */
get disposeOnNavigation() {
return this._disposeOnNavigation;
}
set disposeOnNavigation(value) {
this._disposeOnNavigation = value;
}
/** Event emitted when the backdrop is clicked. */
backdropClick = new EventEmitter();
/** Event emitted when the position has changed. */
positionChange = new EventEmitter();
/** Event emitted when the overlay has been attached. */
attach = new EventEmitter();
/** Event emitted when the overlay has been detached. */
detach = new EventEmitter();
/** Emits when there are keyboard events that are targeted at the overlay. */
overlayKeydown = new EventEmitter();
/** Emits when there are mouse outside click events that are targeted at the overlay. */
overlayOutsideClick = new EventEmitter();
// TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
constructor() {
const templateRef = inject(TemplateRef);
const viewContainerRef = inject(ViewContainerRef);
this._templatePortal = new TemplatePortal(templateRef, viewContainerRef);
this.scrollStrategy = this._scrollStrategyFactory();
}
/** The associated overlay reference. */
get overlayRef() {
return this._overlayRef;
}
/** The element's layout direction. */
get dir() {
return this._dir ? this._dir.value : "ltr";
}
ngOnDestroy() {
this._attachSubscription.unsubscribe();
this._detachSubscription.unsubscribe();
this._backdropSubscription.unsubscribe();
this._positionSubscription.unsubscribe();
this._overlayRef?.dispose();
}
ngOnChanges(changes) {
if (this._position) {
this._updatePositionStrategy(this._position);
this._overlayRef?.updateSize({
width: this.width,
minWidth: this.minWidth,
height: this.height,
minHeight: this.minHeight
});
if (changes["origin"] && this.open) {
this._position.apply();
}
}
if (changes["open"]) {
this.open ? this.attachOverlay() : this.detachOverlay();
}
}
/** Creates an overlay */
_createOverlay() {
if (!this.positions || !this.positions.length) {
this.positions = defaultPositionList;
}
const overlayRef = this._overlayRef = this._overlay.create(this._buildConfig());
this._attachSubscription = overlayRef.attachments().subscribe(() => this.attach.emit());
this._detachSubscription = overlayRef.detachments().subscribe(() => this.detach.emit());
overlayRef.keydownEvents().subscribe((event) => {
this.overlayKeydown.next(event);
if (event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)) {
event.preventDefault();
this.detachOverlay();
}
});
this._overlayRef.outsidePointerEvents().subscribe((event) => {
const origin = this._getOriginElement();
const target = _getEventTarget(event);
if (!origin || origin !== target && !origin.contains(target)) {
this.overlayOutsideClick.next(event);
}
});
}
/** Builds the overlay config based on the directive's inputs */
_buildConfig() {
const positionStrategy = this._position = this.positionStrategy || this._createPositionStrategy();
const overlayConfig = new OverlayConfig({
direction: this._dir || "ltr",
positionStrategy,
scrollStrategy: this.scrollStrategy,
hasBackdrop: this.hasBackdrop,
disposeOnNavigation: this.disposeOnNavigation
});
if (this.width || this.width === 0) {
overlayConfig.width = this.width;
}
if (this.height || this.height === 0) {
overlayConfig.height = this.height;
}
if (this.minWidth || this.minWidth === 0) {
overlayConfig.minWidth = this.minWidth;
}
if (this.minHeight || this.minHeight === 0) {
overlayConfig.minHeight = this.minHeight;
}
if (this.backdropClass) {
overlayConfig.backdropClass = this.backdropClass;
}
if (this.panelClass) {
overlayConfig.panelClass = this.panelClass;
}
return overlayConfig;
}
/** Updates the state of a position strategy, based on the values of the directive inputs. */
_updatePositionStrategy(positionStrategy) {
const positions = this.positions.map((currentPosition) => ({
originX: currentPosition.originX,
originY: currentPosition.originY,
overlayX: currentPosition.overlayX,
overlayY: currentPosition.overlayY,
offsetX: currentPosition.offsetX || this.offsetX,
offsetY: currentPosition.offsetY || this.offsetY,
panelClass: currentPosition.panelClass || void 0
}));
return positionStrategy.setOrigin(this._getOrigin()).withPositions(positions).withFlexibleDimensions(this.flexibleDimensions).withPush(this.push).withGrowAfterOpen(this.growAfterOpen).withViewportMargin(this.viewportMargin).withLockedPosition(this.lockPosition).withTransformOriginOn(this.transformOriginSelector);
}
/** Returns the position strategy of the overlay to be set on the overlay config */
_createPositionStrategy() {
const strategy = this._overlay.position().flexibleConnectedTo(this._getOrigin());
this._updatePositionStrategy(strategy);
return strategy;
}
_getOrigin() {
if (this.origin instanceof CdkOverlayOrigin) {
return this.origin.elementRef;
} else {
return this.origin;
}
}
_getOriginElement() {
if (this.origin instanceof CdkOverlayOrigin) {
return this.origin.elementRef.nativeElement;
}
if (this.origin instanceof ElementRef) {
return this.origin.nativeElement;
}
if (typeof Element !== "undefined" && this.origin instanceof Element) {
return this.origin;
}
return null;
}
/** Attaches the overlay. */
attachOverlay() {
if (!this._overlayRef) {
this._createOverlay();
} else {
this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop;
}
if (!this._overlayRef.hasAttached()) {
this._overlayRef.attach(this._templatePortal);
}
if (this.hasBackdrop) {
this._backdropSubscription = this._overlayRef.backdropClick().subscribe((event) => {
this.backdropClick.emit(event);
});
} else {
this._backdropSubscription.unsubscribe();
}
this._positionSubscription.unsubscribe();
if (this.positionChange.observers.length > 0) {
this._positionSubscription = this._position.positionChanges.pipe(takeWhile(() => this.positionChange.observers.length > 0)).subscribe((position) => {
this._ngZone.run(() => this.positionChange.emit(position));
if (this.positionChange.observers.length === 0) {
this._positionSubscription.unsubscribe();
}
});
}
this.open = true;
}
/** Detaches the overlay. */
detachOverlay() {
this._overlayRef?.detach();
this._backdropSubscription.unsubscribe();
this._positionSubscription.unsubscribe();
this.open = false;
}
static \u0275fac = function CdkConnectedOverlay_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkConnectedOverlay)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkConnectedOverlay,
selectors: [["", "cdk-connected-overlay", ""], ["", "connected-overlay", ""], ["", "cdkConnectedOverlay", ""]],
inputs: {
origin: [0, "cdkConnectedOverlayOrigin", "origin"],
positions: [0, "cdkConnectedOverlayPositions", "positions"],
positionStrategy: [0, "cdkConnectedOverlayPositionStrategy", "positionStrategy"],
offsetX: [0, "cdkConnectedOverlayOffsetX", "offsetX"],
offsetY: [0, "cdkConnectedOverlayOffsetY", "offsetY"],
width: [0, "cdkConnectedOverlayWidth", "width"],
height: [0, "cdkConnectedOverlayHeight", "height"],
minWidth: [0, "cdkConnectedOverlayMinWidth", "minWidth"],
minHeight: [0, "cdkConnectedOverlayMinHeight", "minHeight"],
backdropClass: [0, "cdkConnectedOverlayBackdropClass", "backdropClass"],
panelClass: [0, "cdkConnectedOverlayPanelClass", "panelClass"],
viewportMargin: [0, "cdkConnectedOverlayViewportMargin", "viewportMargin"],
scrollStrategy: [0, "cdkConnectedOverlayScrollStrategy", "scrollStrategy"],
open: [0, "cdkConnectedOverlayOpen", "open"],
disableClose: [0, "cdkConnectedOverlayDisableClose", "disableClose"],
transformOriginSelector: [0, "cdkConnectedOverlayTransformOriginOn", "transformOriginSelector"],
hasBackdrop: [2, "cdkConnectedOverlayHasBackdrop", "hasBackdrop", booleanAttribute],
lockPosition: [2, "cdkConnectedOverlayLockPosition", "lockPosition", booleanAttribute],
flexibleDimensions: [2, "cdkConnectedOverlayFlexibleDimensions", "flexibleDimensions", booleanAttribute],
growAfterOpen: [2, "cdkConnectedOverlayGrowAfterOpen", "growAfterOpen", booleanAttribute],
push: [2, "cdkConnectedOverlayPush", "push", booleanAttribute],
disposeOnNavigation: [2, "cdkConnectedOverlayDisposeOnNavigation", "disposeOnNavigation", booleanAttribute]
},
outputs: {
backdropClick: "backdropClick",
positionChange: "positionChange",
attach: "attach",
detach: "detach",
overlayKeydown: "overlayKeydown",
overlayOutsideClick: "overlayOutsideClick"
},
exportAs: ["cdkConnectedOverlay"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkConnectedOverlay, [{
type: Directive,
args: [{
selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]",
exportAs: "cdkConnectedOverlay"
}]
}], () => [], {
origin: [{
type: Input,
args: ["cdkConnectedOverlayOrigin"]
}],
positions: [{
type: Input,
args: ["cdkConnectedOverlayPositions"]
}],
positionStrategy: [{
type: Input,
args: ["cdkConnectedOverlayPositionStrategy"]
}],
offsetX: [{
type: Input,
args: ["cdkConnectedOverlayOffsetX"]
}],
offsetY: [{
type: Input,
args: ["cdkConnectedOverlayOffsetY"]
}],
width: [{
type: Input,
args: ["cdkConnectedOverlayWidth"]
}],
height: [{
type: Input,
args: ["cdkConnectedOverlayHeight"]
}],
minWidth: [{
type: Input,
args: ["cdkConnectedOverlayMinWidth"]
}],
minHeight: [{
type: Input,
args: ["cdkConnectedOverlayMinHeight"]
}],
backdropClass: [{
type: Input,
args: ["cdkConnectedOverlayBackdropClass"]
}],
panelClass: [{
type: Input,
args: ["cdkConnectedOverlayPanelClass"]
}],
viewportMargin: [{
type: Input,
args: ["cdkConnectedOverlayViewportMargin"]
}],
scrollStrategy: [{
type: Input,
args: ["cdkConnectedOverlayScrollStrategy"]
}],
open: [{
type: Input,
args: ["cdkConnectedOverlayOpen"]
}],
disableClose: [{
type: Input,
args: ["cdkConnectedOverlayDisableClose"]
}],
transformOriginSelector: [{
type: Input,
args: ["cdkConnectedOverlayTransformOriginOn"]
}],
hasBackdrop: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayHasBackdrop",
transform: booleanAttribute
}]
}],
lockPosition: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayLockPosition",
transform: booleanAttribute
}]
}],
flexibleDimensions: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayFlexibleDimensions",
transform: booleanAttribute
}]
}],
growAfterOpen: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayGrowAfterOpen",
transform: booleanAttribute
}]
}],
push: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayPush",
transform: booleanAttribute
}]
}],
disposeOnNavigation: [{
type: Input,
args: [{
alias: "cdkConnectedOverlayDisposeOnNavigation",
transform: booleanAttribute
}]
}],
backdropClick: [{
type: Output
}],
positionChange: [{
type: Output
}],
attach: [{
type: Output
}],
detach: [{
type: Output
}],
overlayKeydown: [{
type: Output
}],
overlayOutsideClick: [{
type: Output
}]
});
})();
function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
return () => overlay.scrollStrategies.reposition();
}
var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = {
provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,
deps: [Overlay],
useFactory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY
};
var OverlayModule = class _OverlayModule {
static \u0275fac = function OverlayModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _OverlayModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _OverlayModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [Overlay, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER],
imports: [BidiModule, PortalModule, ScrollingModule, ScrollingModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(OverlayModule, [{
type: NgModule,
args: [{
imports: [BidiModule, PortalModule, ScrollingModule, CdkConnectedOverlay, CdkOverlayOrigin],
exports: [CdkConnectedOverlay, CdkOverlayOrigin, ScrollingModule],
providers: [Overlay, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/dialog.mjs
function CdkDialogContainer_ng_template_0_Template(rf, ctx) {
}
var DialogConfig = class {
/**
* Where the attached component should live in Angular's *logical* component tree.
* This affects what is available for injection and the change detection order for the
* component instantiated inside of the dialog. This does not affect where the dialog
* content will be rendered.
*/
viewContainerRef;
/**
* Injector used for the instantiation of the component to be attached. If provided,
* takes precedence over the injector indirectly provided by `ViewContainerRef`.
*/
injector;
/** ID for the dialog. If omitted, a unique one will be generated. */
id;
/** The ARIA role of the dialog element. */
role = "dialog";
/** Optional CSS class or classes applied to the overlay panel. */
panelClass = "";
/** Whether the dialog has a backdrop. */
hasBackdrop = true;
/** Optional CSS class or classes applied to the overlay backdrop. */
backdropClass = "";
/** Whether the dialog closes with the escape key or pointer events outside the panel element. */
disableClose = false;
/** Width of the dialog. */
width = "";
/** Height of the dialog. */
height = "";
/** Min-width of the dialog. If a number is provided, assumes pixel units. */
minWidth;
/** Min-height of the dialog. If a number is provided, assumes pixel units. */
minHeight;
/** Max-width of the dialog. If a number is provided, assumes pixel units. */
maxWidth;
/** Max-height of the dialog. If a number is provided, assumes pixel units. */
maxHeight;
/** Strategy to use when positioning the dialog. Defaults to centering it on the page. */
positionStrategy;
/** Data being injected into the child component. */
data = null;
/** Layout direction for the dialog's content. */
direction;
/** ID of the element that describes the dialog. */
ariaDescribedBy = null;
/** ID of the element that labels the dialog. */
ariaLabelledBy = null;
/** Dialog label applied via `aria-label` */
ariaLabel = null;
/**
* Whether this is a modal dialog. Used to set the `aria-modal` attribute. Off by default,
* because it can interfere with other overlay-based components (e.g. `mat-select`) and because
* it is redundant since the dialog marks all outside content as `aria-hidden` anyway.
*/
ariaModal = false;
/**
* Where the dialog should focus on open.
* @breaking-change 14.0.0 Remove boolean option from autoFocus. Use string or
* AutoFocusTarget instead.
*/
autoFocus = "first-tabbable";
/**
* Whether the dialog should restore focus to the previously-focused element upon closing.
* Has the following behavior based on the type that is passed in:
* - `boolean` - when true, will return focus to the element that was focused before the dialog
* was opened, otherwise won't restore focus at all.
* - `string` - focus will be restored to the first element that matches the CSS selector.
* - `HTMLElement` - focus will be restored to the specific element.
*/
restoreFocus = true;
/**
* Scroll strategy to be used for the dialog. This determines how
* the dialog responds to scrolling underneath the panel element.
*/
scrollStrategy;
/**
* Whether the dialog should close when the user navigates backwards or forwards through browser
* history. This does not apply to navigation via anchor element unless using URL-hash based
* routing (`HashLocationStrategy` in the Angular router).
*/
closeOnNavigation = true;
/**
* Whether the dialog should close when the dialog service is destroyed. This is useful if
* another service is wrapping the dialog and is managing the destruction instead.
*/
closeOnDestroy = true;
/**
* Whether the dialog should close when the underlying overlay is detached. This is useful if
* another service is wrapping the dialog and is managing the destruction instead. E.g. an
* external detachment can happen as a result of a scroll strategy triggering it or when the
* browser location changes.
*/
closeOnOverlayDetachments = true;
/**
* Alternate `ComponentFactoryResolver` to use when resolving the associated component.
* @deprecated No longer used. Will be removed.
* @breaking-change 20.0.0
*/
componentFactoryResolver;
/**
* Providers that will be exposed to the contents of the dialog. Can also
* be provided as a function in order to generate the providers lazily.
*/
providers;
/**
* Component into which the dialog content will be rendered. Defaults to `CdkDialogContainer`.
* A configuration object can be passed in to customize the providers that will be exposed
* to the dialog container.
*/
container;
/**
* Context that will be passed to template-based dialogs.
* A function can be passed in to resolve the context lazily.
*/
templateContext;
};
function throwDialogContentAlreadyAttachedError() {
throw Error("Attempting to attach dialog content after content is already attached");
}
var CdkDialogContainer = class _CdkDialogContainer extends BasePortalOutlet {
_elementRef = inject(ElementRef);
_focusTrapFactory = inject(FocusTrapFactory);
_config;
_interactivityChecker = inject(InteractivityChecker);
_ngZone = inject(NgZone);
_overlayRef = inject(OverlayRef);
_focusMonitor = inject(FocusMonitor);
_renderer = inject(Renderer2);
_changeDetectorRef = inject(ChangeDetectorRef);
_injector = inject(Injector);
_platform = inject(Platform);
_document = inject(DOCUMENT, {
optional: true
});
/** The portal outlet inside of this container into which the dialog content will be loaded. */
_portalOutlet;
_focusTrapped = new Subject();
/** The class that traps and manages focus within the dialog. */
_focusTrap = null;
/** Element that was focused before the dialog was opened. Save this to restore upon close. */
_elementFocusedBeforeDialogWasOpened = null;
/**
* Type of interaction that led to the dialog being closed. This is used to determine
* whether the focus style will be applied when returning focus to its original location
* after the dialog is closed.
*/
_closeInteractionType = null;
/**
* Queue of the IDs of the dialog's label element, based on their definition order. The first
* ID will be used as the `aria-labelledby` value. We use a queue here to handle the case
* where there are two or more titles in the DOM at a time and the first one is destroyed while
* the rest are present.
*/
_ariaLabelledByQueue = [];
_isDestroyed = false;
constructor() {
super();
this._config = inject(DialogConfig, {
optional: true
}) || new DialogConfig();
if (this._config.ariaLabelledBy) {
this._ariaLabelledByQueue.push(this._config.ariaLabelledBy);
}
}
_addAriaLabelledBy(id) {
this._ariaLabelledByQueue.push(id);
this._changeDetectorRef.markForCheck();
}
_removeAriaLabelledBy(id) {
const index = this._ariaLabelledByQueue.indexOf(id);
if (index > -1) {
this._ariaLabelledByQueue.splice(index, 1);
this._changeDetectorRef.markForCheck();
}
}
_contentAttached() {
this._initializeFocusTrap();
this._handleBackdropClicks();
this._captureInitialFocus();
}
/**
* Can be used by child classes to customize the initial focus
* capturing behavior (e.g. if it's tied to an animation).
*/
_captureInitialFocus() {
this._trapFocus();
}
ngOnDestroy() {
this._focusTrapped.complete();
this._isDestroyed = true;
this._restoreFocus();
}
/**
* Attach a ComponentPortal as content to this dialog container.
* @param portal Portal to be attached as the dialog content.
*/
attachComponentPortal(portal) {
if (this._portalOutlet.hasAttached() && (typeof ngDevMode === "undefined" || ngDevMode)) {
throwDialogContentAlreadyAttachedError();
}
const result = this._portalOutlet.attachComponentPortal(portal);
this._contentAttached();
return result;
}
/**
* Attach a TemplatePortal as content to this dialog container.
* @param portal Portal to be attached as the dialog content.
*/
attachTemplatePortal(portal) {
if (this._portalOutlet.hasAttached() && (typeof ngDevMode === "undefined" || ngDevMode)) {
throwDialogContentAlreadyAttachedError();
}
const result = this._portalOutlet.attachTemplatePortal(portal);
this._contentAttached();
return result;
}
/**
* Attaches a DOM portal to the dialog container.
* @param portal Portal to be attached.
* @deprecated To be turned into a method.
* @breaking-change 10.0.0
*/
attachDomPortal = (portal) => {
if (this._portalOutlet.hasAttached() && (typeof ngDevMode === "undefined" || ngDevMode)) {
throwDialogContentAlreadyAttachedError();
}
const result = this._portalOutlet.attachDomPortal(portal);
this._contentAttached();
return result;
};
// TODO(crisbeto): this shouldn't be exposed, but there are internal references to it.
/** Captures focus if it isn't already inside the dialog. */
_recaptureFocus() {
if (!this._containsFocus()) {
this._trapFocus();
}
}
/**
* Focuses the provided element. If the element is not focusable, it will add a tabIndex
* attribute to forcefully focus it. The attribute is removed after focus is moved.
* @param element The element to focus.
*/
_forceFocus(element, options) {
if (!this._interactivityChecker.isFocusable(element)) {
element.tabIndex = -1;
this._ngZone.runOutsideAngular(() => {
const callback = () => {
deregisterBlur();
deregisterMousedown();
element.removeAttribute("tabindex");
};
const deregisterBlur = this._renderer.listen(element, "blur", callback);
const deregisterMousedown = this._renderer.listen(element, "mousedown", callback);
});
}
element.focus(options);
}
/**
* Focuses the first element that matches the given selector within the focus trap.
* @param selector The CSS selector for the element to set focus to.
*/
_focusByCssSelector(selector, options) {
let elementToFocus = this._elementRef.nativeElement.querySelector(selector);
if (elementToFocus) {
this._forceFocus(elementToFocus, options);
}
}
/**
* Moves the focus inside the focus trap. When autoFocus is not set to 'dialog', if focus
* cannot be moved then focus will go to the dialog container.
*/
_trapFocus(options) {
if (this._isDestroyed) {
return;
}
afterNextRender(() => {
const element = this._elementRef.nativeElement;
switch (this._config.autoFocus) {
case false:
case "dialog":
if (!this._containsFocus()) {
element.focus(options);
}
break;
case true:
case "first-tabbable":
const focusedSuccessfully = this._focusTrap?.focusInitialElement(options);
if (!focusedSuccessfully) {
this._focusDialogContainer(options);
}
break;
case "first-heading":
this._focusByCssSelector('h1, h2, h3, h4, h5, h6, [role="heading"]', options);
break;
default:
this._focusByCssSelector(this._config.autoFocus, options);
break;
}
this._focusTrapped.next();
}, {
injector: this._injector
});
}
/** Restores focus to the element that was focused before the dialog opened. */
_restoreFocus() {
const focusConfig = this._config.restoreFocus;
let focusTargetElement = null;
if (typeof focusConfig === "string") {
focusTargetElement = this._document.querySelector(focusConfig);
} else if (typeof focusConfig === "boolean") {
focusTargetElement = focusConfig ? this._elementFocusedBeforeDialogWasOpened : null;
} else if (focusConfig) {
focusTargetElement = focusConfig;
}
if (this._config.restoreFocus && focusTargetElement && typeof focusTargetElement.focus === "function") {
const activeElement = _getFocusedElementPierceShadowDom();
const element = this._elementRef.nativeElement;
if (!activeElement || activeElement === this._document.body || activeElement === element || element.contains(activeElement)) {
if (this._focusMonitor) {
this._focusMonitor.focusVia(focusTargetElement, this._closeInteractionType);
this._closeInteractionType = null;
} else {
focusTargetElement.focus();
}
}
}
if (this._focusTrap) {
this._focusTrap.destroy();
}
}
/** Focuses the dialog container. */
_focusDialogContainer(options) {
if (this._elementRef.nativeElement.focus) {
this._elementRef.nativeElement.focus(options);
}
}
/** Returns whether focus is inside the dialog. */
_containsFocus() {
const element = this._elementRef.nativeElement;
const activeElement = _getFocusedElementPierceShadowDom();
return element === activeElement || element.contains(activeElement);
}
/** Sets up the focus trap. */
_initializeFocusTrap() {
if (this._platform.isBrowser) {
this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
if (this._document) {
this._elementFocusedBeforeDialogWasOpened = _getFocusedElementPierceShadowDom();
}
}
}
/** Sets up the listener that handles clicks on the dialog backdrop. */
_handleBackdropClicks() {
this._overlayRef.backdropClick().subscribe(() => {
if (this._config.disableClose) {
this._recaptureFocus();
}
});
}
static \u0275fac = function CdkDialogContainer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkDialogContainer)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _CdkDialogContainer,
selectors: [["cdk-dialog-container"]],
viewQuery: function CdkDialogContainer_Query(rf, ctx) {
if (rf & 1) {
\u0275\u0275viewQuery(CdkPortalOutlet, 7);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._portalOutlet = _t.first);
}
},
hostAttrs: ["tabindex", "-1", 1, "cdk-dialog-container"],
hostVars: 6,
hostBindings: function CdkDialogContainer_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("id", ctx._config.id || null)("role", ctx._config.role)("aria-modal", ctx._config.ariaModal)("aria-labelledby", ctx._config.ariaLabel ? null : ctx._ariaLabelledByQueue[0])("aria-label", ctx._config.ariaLabel)("aria-describedby", ctx._config.ariaDescribedBy || null);
}
},
features: [\u0275\u0275InheritDefinitionFeature],
decls: 1,
vars: 0,
consts: [["cdkPortalOutlet", ""]],
template: function CdkDialogContainer_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, CdkDialogContainer_ng_template_0_Template, 0, 0, "ng-template", 0);
}
},
dependencies: [CdkPortalOutlet],
styles: [".cdk-dialog-container{display:block;width:100%;height:100%;min-height:inherit;max-height:inherit}\n"],
encapsulation: 2
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkDialogContainer, [{
type: Component,
args: [{
selector: "cdk-dialog-container",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.Default,
imports: [CdkPortalOutlet],
host: {
"class": "cdk-dialog-container",
"tabindex": "-1",
"[attr.id]": "_config.id || null",
"[attr.role]": "_config.role",
"[attr.aria-modal]": "_config.ariaModal",
"[attr.aria-labelledby]": "_config.ariaLabel ? null : _ariaLabelledByQueue[0]",
"[attr.aria-label]": "_config.ariaLabel",
"[attr.aria-describedby]": "_config.ariaDescribedBy || null"
},
template: "<ng-template cdkPortalOutlet />\n",
styles: [".cdk-dialog-container{display:block;width:100%;height:100%;min-height:inherit;max-height:inherit}\n"]
}]
}], () => [], {
_portalOutlet: [{
type: ViewChild,
args: [CdkPortalOutlet, {
static: true
}]
}]
});
})();
var DialogRef = class {
overlayRef;
config;
/**
* Instance of component opened into the dialog. Will be
* null when the dialog is opened using a `TemplateRef`.
*/
componentInstance;
/**
* `ComponentRef` of the component opened into the dialog. Will be
* null when the dialog is opened using a `TemplateRef`.
*/
componentRef;
/** Instance of the container that is rendering out the dialog content. */
containerInstance;
/** Whether the user is allowed to close the dialog. */
disableClose;
/** Emits when the dialog has been closed. */
closed = new Subject();
/** Emits when the backdrop of the dialog is clicked. */
backdropClick;
/** Emits when on keyboard events within the dialog. */
keydownEvents;
/** Emits on pointer events that happen outside of the dialog. */
outsidePointerEvents;
/** Unique ID for the dialog. */
id;
/** Subscription to external detachments of the dialog. */
_detachSubscription;
constructor(overlayRef, config) {
this.overlayRef = overlayRef;
this.config = config;
this.disableClose = config.disableClose;
this.backdropClick = overlayRef.backdropClick();
this.keydownEvents = overlayRef.keydownEvents();
this.outsidePointerEvents = overlayRef.outsidePointerEvents();
this.id = config.id;
this.keydownEvents.subscribe((event) => {
if (event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)) {
event.preventDefault();
this.close(void 0, {
focusOrigin: "keyboard"
});
}
});
this.backdropClick.subscribe(() => {
if (!this.disableClose) {
this.close(void 0, {
focusOrigin: "mouse"
});
}
});
this._detachSubscription = overlayRef.detachments().subscribe(() => {
if (config.closeOnOverlayDetachments !== false) {
this.close();
}
});
}
/**
* Close the dialog.
* @param result Optional result to return to the dialog opener.
* @param options Additional options to customize the closing behavior.
*/
close(result, options) {
if (this.containerInstance) {
const closedSubject = this.closed;
this.containerInstance._closeInteractionType = options?.focusOrigin || "program";
this._detachSubscription.unsubscribe();
this.overlayRef.dispose();
closedSubject.next(result);
closedSubject.complete();
this.componentInstance = this.containerInstance = null;
}
}
/** Updates the position of the dialog based on the current position strategy. */
updatePosition() {
this.overlayRef.updatePosition();
return this;
}
/**
* Updates the dialog's width and height.
* @param width New width of the dialog.
* @param height New height of the dialog.
*/
updateSize(width = "", height = "") {
this.overlayRef.updateSize({
width,
height
});
return this;
}
/** Add a CSS class or an array of classes to the overlay pane. */
addPanelClass(classes) {
this.overlayRef.addPanelClass(classes);
return this;
}
/** Remove a CSS class or an array of classes from the overlay pane. */
removePanelClass(classes) {
this.overlayRef.removePanelClass(classes);
return this;
}
};
var DIALOG_SCROLL_STRATEGY = new InjectionToken("DialogScrollStrategy", {
providedIn: "root",
factory: () => {
const overlay = inject(Overlay);
return () => overlay.scrollStrategies.block();
}
});
var DIALOG_DATA = new InjectionToken("DialogData");
var DEFAULT_DIALOG_CONFIG = new InjectionToken("DefaultDialogConfig");
var Dialog = class _Dialog {
_overlay = inject(Overlay);
_injector = inject(Injector);
_defaultOptions = inject(DEFAULT_DIALOG_CONFIG, {
optional: true
});
_parentDialog = inject(_Dialog, {
optional: true,
skipSelf: true
});
_overlayContainer = inject(OverlayContainer);
_idGenerator = inject(_IdGenerator);
_openDialogsAtThisLevel = [];
_afterAllClosedAtThisLevel = new Subject();
_afterOpenedAtThisLevel = new Subject();
_ariaHiddenElements = /* @__PURE__ */ new Map();
_scrollStrategy = inject(DIALOG_SCROLL_STRATEGY);
/** Keeps track of the currently-open dialogs. */
get openDialogs() {
return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel;
}
/** Stream that emits when a dialog has been opened. */
get afterOpened() {
return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel;
}
/**
* Stream that emits when all open dialog have finished closing.
* Will emit on subscribe if there are no open dialogs to begin with.
*/
afterAllClosed = defer(() => this.openDialogs.length ? this._getAfterAllClosed() : this._getAfterAllClosed().pipe(startWith(void 0)));
constructor() {
}
open(componentOrTemplateRef, config) {
const defaults2 = this._defaultOptions || new DialogConfig();
config = __spreadValues(__spreadValues({}, defaults2), config);
config.id = config.id || this._idGenerator.getId("cdk-dialog-");
if (config.id && this.getDialogById(config.id) && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw Error(`Dialog with id "${config.id}" exists already. The dialog id must be unique.`);
}
const overlayConfig = this._getOverlayConfig(config);
const overlayRef = this._overlay.create(overlayConfig);
const dialogRef = new DialogRef(overlayRef, config);
const dialogContainer = this._attachContainer(overlayRef, dialogRef, config);
dialogRef.containerInstance = dialogContainer;
if (!this.openDialogs.length) {
const overlayContainer = this._overlayContainer.getContainerElement();
if (dialogContainer._focusTrapped) {
dialogContainer._focusTrapped.pipe(take(1)).subscribe(() => {
this._hideNonDialogContentFromAssistiveTechnology(overlayContainer);
});
} else {
this._hideNonDialogContentFromAssistiveTechnology(overlayContainer);
}
}
this._attachDialogContent(componentOrTemplateRef, dialogRef, dialogContainer, config);
this.openDialogs.push(dialogRef);
dialogRef.closed.subscribe(() => this._removeOpenDialog(dialogRef, true));
this.afterOpened.next(dialogRef);
return dialogRef;
}
/**
* Closes all of the currently-open dialogs.
*/
closeAll() {
reverseForEach(this.openDialogs, (dialog) => dialog.close());
}
/**
* Finds an open dialog by its id.
* @param id ID to use when looking up the dialog.
*/
getDialogById(id) {
return this.openDialogs.find((dialog) => dialog.id === id);
}
ngOnDestroy() {
reverseForEach(this._openDialogsAtThisLevel, (dialog) => {
if (dialog.config.closeOnDestroy === false) {
this._removeOpenDialog(dialog, false);
}
});
reverseForEach(this._openDialogsAtThisLevel, (dialog) => dialog.close());
this._afterAllClosedAtThisLevel.complete();
this._afterOpenedAtThisLevel.complete();
this._openDialogsAtThisLevel = [];
}
/**
* Creates an overlay config from a dialog config.
* @param config The dialog configuration.
* @returns The overlay configuration.
*/
_getOverlayConfig(config) {
const state = new OverlayConfig({
positionStrategy: config.positionStrategy || this._overlay.position().global().centerHorizontally().centerVertically(),
scrollStrategy: config.scrollStrategy || this._scrollStrategy(),
panelClass: config.panelClass,
hasBackdrop: config.hasBackdrop,
direction: config.direction,
minWidth: config.minWidth,
minHeight: config.minHeight,
maxWidth: config.maxWidth,
maxHeight: config.maxHeight,
width: config.width,
height: config.height,
disposeOnNavigation: config.closeOnNavigation
});
if (config.backdropClass) {
state.backdropClass = config.backdropClass;
}
return state;
}
/**
* Attaches a dialog container to a dialog's already-created overlay.
* @param overlay Reference to the dialog's underlying overlay.
* @param config The dialog configuration.
* @returns A promise resolving to a ComponentRef for the attached container.
*/
_attachContainer(overlay, dialogRef, config) {
const userInjector = config.injector || config.viewContainerRef?.injector;
const providers = [{
provide: DialogConfig,
useValue: config
}, {
provide: DialogRef,
useValue: dialogRef
}, {
provide: OverlayRef,
useValue: overlay
}];
let containerType;
if (config.container) {
if (typeof config.container === "function") {
containerType = config.container;
} else {
containerType = config.container.type;
providers.push(...config.container.providers(config));
}
} else {
containerType = CdkDialogContainer;
}
const containerPortal = new ComponentPortal(containerType, config.viewContainerRef, Injector.create({
parent: userInjector || this._injector,
providers
}));
const containerRef = overlay.attach(containerPortal);
return containerRef.instance;
}
/**
* Attaches the user-provided component to the already-created dialog container.
* @param componentOrTemplateRef The type of component being loaded into the dialog,
* or a TemplateRef to instantiate as the content.
* @param dialogRef Reference to the dialog being opened.
* @param dialogContainer Component that is going to wrap the dialog content.
* @param config Configuration used to open the dialog.
*/
_attachDialogContent(componentOrTemplateRef, dialogRef, dialogContainer, config) {
if (componentOrTemplateRef instanceof TemplateRef) {
const injector = this._createInjector(config, dialogRef, dialogContainer, void 0);
let context = {
$implicit: config.data,
dialogRef
};
if (config.templateContext) {
context = __spreadValues(__spreadValues({}, context), typeof config.templateContext === "function" ? config.templateContext() : config.templateContext);
}
dialogContainer.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, null, context, injector));
} else {
const injector = this._createInjector(config, dialogRef, dialogContainer, this._injector);
const contentRef = dialogContainer.attachComponentPortal(new ComponentPortal(componentOrTemplateRef, config.viewContainerRef, injector));
dialogRef.componentRef = contentRef;
dialogRef.componentInstance = contentRef.instance;
}
}
/**
* Creates a custom injector to be used inside the dialog. This allows a component loaded inside
* of a dialog to close itself and, optionally, to return a value.
* @param config Config object that is used to construct the dialog.
* @param dialogRef Reference to the dialog being opened.
* @param dialogContainer Component that is going to wrap the dialog content.
* @param fallbackInjector Injector to use as a fallback when a lookup fails in the custom
* dialog injector, if the user didn't provide a custom one.
* @returns The custom injector that can be used inside the dialog.
*/
_createInjector(config, dialogRef, dialogContainer, fallbackInjector) {
const userInjector = config.injector || config.viewContainerRef?.injector;
const providers = [{
provide: DIALOG_DATA,
useValue: config.data
}, {
provide: DialogRef,
useValue: dialogRef
}];
if (config.providers) {
if (typeof config.providers === "function") {
providers.push(...config.providers(dialogRef, config, dialogContainer));
} else {
providers.push(...config.providers);
}
}
if (config.direction && (!userInjector || !userInjector.get(Directionality, null, {
optional: true
}))) {
providers.push({
provide: Directionality,
useValue: {
value: config.direction,
change: of()
}
});
}
return Injector.create({
parent: userInjector || fallbackInjector,
providers
});
}
/**
* Removes a dialog from the array of open dialogs.
* @param dialogRef Dialog to be removed.
* @param emitEvent Whether to emit an event if this is the last dialog.
*/
_removeOpenDialog(dialogRef, emitEvent) {
const index = this.openDialogs.indexOf(dialogRef);
if (index > -1) {
this.openDialogs.splice(index, 1);
if (!this.openDialogs.length) {
this._ariaHiddenElements.forEach((previousValue, element) => {
if (previousValue) {
element.setAttribute("aria-hidden", previousValue);
} else {
element.removeAttribute("aria-hidden");
}
});
this._ariaHiddenElements.clear();
if (emitEvent) {
this._getAfterAllClosed().next();
}
}
}
}
/** Hides all of the content that isn't an overlay from assistive technology. */
_hideNonDialogContentFromAssistiveTechnology(overlayContainer) {
if (overlayContainer.parentElement) {
const siblings = overlayContainer.parentElement.children;
for (let i = siblings.length - 1; i > -1; i--) {
const sibling = siblings[i];
if (sibling !== overlayContainer && sibling.nodeName !== "SCRIPT" && sibling.nodeName !== "STYLE" && !sibling.hasAttribute("aria-live")) {
this._ariaHiddenElements.set(sibling, sibling.getAttribute("aria-hidden"));
sibling.setAttribute("aria-hidden", "true");
}
}
}
}
_getAfterAllClosed() {
const parent = this._parentDialog;
return parent ? parent._getAfterAllClosed() : this._afterAllClosedAtThisLevel;
}
static \u0275fac = function Dialog_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _Dialog)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _Dialog,
factory: _Dialog.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Dialog, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function reverseForEach(items, callback) {
let i = items.length;
while (i--) {
callback(items[i]);
}
}
var DialogModule = class _DialogModule {
static \u0275fac = function DialogModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DialogModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _DialogModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [Dialog],
imports: [
OverlayModule,
PortalModule,
A11yModule,
// Re-export the PortalModule so that people extending the `CdkDialogContainer`
// don't have to remember to import it or be faced with an unhelpful error.
PortalModule
]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DialogModule, [{
type: NgModule,
args: [{
imports: [OverlayModule, PortalModule, A11yModule, CdkDialogContainer],
exports: [
// Re-export the PortalModule so that people extending the `CdkDialogContainer`
// don't have to remember to import it or be faced with an unhelpful error.
PortalModule,
CdkDialogContainer
],
providers: [Dialog]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/overlay.mjs
var FullscreenOverlayContainer = class _FullscreenOverlayContainer extends OverlayContainer {
_renderer = inject(RendererFactory2).createRenderer(null, null);
_fullScreenEventName;
_cleanupFullScreenListener;
constructor() {
super();
}
ngOnDestroy() {
super.ngOnDestroy();
this._cleanupFullScreenListener?.();
}
_createContainer() {
const eventName = this._getEventName();
super._createContainer();
this._adjustParentForFullscreenChange();
if (eventName) {
this._cleanupFullScreenListener?.();
this._cleanupFullScreenListener = this._renderer.listen("document", eventName, () => {
this._adjustParentForFullscreenChange();
});
}
}
_adjustParentForFullscreenChange() {
if (this._containerElement) {
const fullscreenElement = this.getFullscreenElement();
const parent = fullscreenElement || this._document.body;
parent.appendChild(this._containerElement);
}
}
_getEventName() {
if (!this._fullScreenEventName) {
const _document2 = this._document;
if (_document2.fullscreenEnabled) {
this._fullScreenEventName = "fullscreenchange";
} else if (_document2.webkitFullscreenEnabled) {
this._fullScreenEventName = "webkitfullscreenchange";
} else if (_document2.mozFullScreenEnabled) {
this._fullScreenEventName = "mozfullscreenchange";
} else if (_document2.msFullscreenEnabled) {
this._fullScreenEventName = "MSFullscreenChange";
}
}
return this._fullScreenEventName;
}
/**
* When the page is put into fullscreen mode, a specific element is specified.
* Only that element and its children are visible when in fullscreen mode.
*/
getFullscreenElement() {
const _document2 = this._document;
return _document2.fullscreenElement || _document2.webkitFullscreenElement || _document2.mozFullScreenElement || _document2.msFullscreenElement || null;
}
static \u0275fac = function FullscreenOverlayContainer_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FullscreenOverlayContainer)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FullscreenOverlayContainer,
factory: _FullscreenOverlayContainer.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FullscreenOverlayContainer, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/cdk/fesm2022/boolean-property-DaaVhX5A.mjs
function coerceBooleanProperty(value) {
return value != null && `${value}` !== "false";
}
// node_modules/@angular/cdk/fesm2022/a11y.mjs
var ID_DELIMITER = " ";
function addAriaReferencedId(el, attr, id) {
const ids = getAriaReferenceIds(el, attr);
id = id.trim();
if (ids.some((existingId) => existingId.trim() === id)) {
return;
}
ids.push(id);
el.setAttribute(attr, ids.join(ID_DELIMITER));
}
function removeAriaReferencedId(el, attr, id) {
const ids = getAriaReferenceIds(el, attr);
id = id.trim();
const filteredIds = ids.filter((val) => val !== id);
if (filteredIds.length) {
el.setAttribute(attr, filteredIds.join(ID_DELIMITER));
} else {
el.removeAttribute(attr);
}
}
function getAriaReferenceIds(el, attr) {
const attrValue = el.getAttribute(attr);
return attrValue?.match(/\S+/g) ?? [];
}
var CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message";
var CDK_DESCRIBEDBY_HOST_ATTRIBUTE = "cdk-describedby-host";
var nextId = 0;
var AriaDescriber = class _AriaDescriber {
_platform = inject(Platform);
_document = inject(DOCUMENT);
/** Map of all registered message elements that have been placed into the document. */
_messageRegistry = /* @__PURE__ */ new Map();
/** Container for all registered messages. */
_messagesContainer = null;
/** Unique ID for the service. */
_id = `${nextId++}`;
constructor() {
inject(_CdkPrivateStyleLoader).load(_VisuallyHiddenLoader);
this._id = inject(APP_ID) + "-" + nextId++;
}
describe(hostElement, message, role) {
if (!this._canBeDescribed(hostElement, message)) {
return;
}
const key = getKey(message, role);
if (typeof message !== "string") {
setMessageId(message, this._id);
this._messageRegistry.set(key, {
messageElement: message,
referenceCount: 0
});
} else if (!this._messageRegistry.has(key)) {
this._createMessageElement(message, role);
}
if (!this._isElementDescribedByMessage(hostElement, key)) {
this._addMessageReference(hostElement, key);
}
}
removeDescription(hostElement, message, role) {
if (!message || !this._isElementNode(hostElement)) {
return;
}
const key = getKey(message, role);
if (this._isElementDescribedByMessage(hostElement, key)) {
this._removeMessageReference(hostElement, key);
}
if (typeof message === "string") {
const registeredMessage = this._messageRegistry.get(key);
if (registeredMessage && registeredMessage.referenceCount === 0) {
this._deleteMessageElement(key);
}
}
if (this._messagesContainer?.childNodes.length === 0) {
this._messagesContainer.remove();
this._messagesContainer = null;
}
}
/** Unregisters all created message elements and removes the message container. */
ngOnDestroy() {
const describedElements = this._document.querySelectorAll(`[${CDK_DESCRIBEDBY_HOST_ATTRIBUTE}="${this._id}"]`);
for (let i = 0; i < describedElements.length; i++) {
this._removeCdkDescribedByReferenceIds(describedElements[i]);
describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
}
this._messagesContainer?.remove();
this._messagesContainer = null;
this._messageRegistry.clear();
}
/**
* Creates a new element in the visually hidden message container element with the message
* as its content and adds it to the message registry.
*/
_createMessageElement(message, role) {
const messageElement = this._document.createElement("div");
setMessageId(messageElement, this._id);
messageElement.textContent = message;
if (role) {
messageElement.setAttribute("role", role);
}
this._createMessagesContainer();
this._messagesContainer.appendChild(messageElement);
this._messageRegistry.set(getKey(message, role), {
messageElement,
referenceCount: 0
});
}
/** Deletes the message element from the global messages container. */
_deleteMessageElement(key) {
this._messageRegistry.get(key)?.messageElement?.remove();
this._messageRegistry.delete(key);
}
/** Creates the global container for all aria-describedby messages. */
_createMessagesContainer() {
if (this._messagesContainer) {
return;
}
const containerClassName = "cdk-describedby-message-container";
const serverContainers = this._document.querySelectorAll(`.${containerClassName}[platform="server"]`);
for (let i = 0; i < serverContainers.length; i++) {
serverContainers[i].remove();
}
const messagesContainer = this._document.createElement("div");
messagesContainer.style.visibility = "hidden";
messagesContainer.classList.add(containerClassName);
messagesContainer.classList.add("cdk-visually-hidden");
if (!this._platform.isBrowser) {
messagesContainer.setAttribute("platform", "server");
}
this._document.body.appendChild(messagesContainer);
this._messagesContainer = messagesContainer;
}
/** Removes all cdk-describedby messages that are hosted through the element. */
_removeCdkDescribedByReferenceIds(element) {
const originalReferenceIds = getAriaReferenceIds(element, "aria-describedby").filter((id) => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0);
element.setAttribute("aria-describedby", originalReferenceIds.join(" "));
}
/**
* Adds a message reference to the element using aria-describedby and increments the registered
* message's reference count.
*/
_addMessageReference(element, key) {
const registeredMessage = this._messageRegistry.get(key);
addAriaReferencedId(element, "aria-describedby", registeredMessage.messageElement.id);
element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, this._id);
registeredMessage.referenceCount++;
}
/**
* Removes a message reference from the element using aria-describedby
* and decrements the registered message's reference count.
*/
_removeMessageReference(element, key) {
const registeredMessage = this._messageRegistry.get(key);
registeredMessage.referenceCount--;
removeAriaReferencedId(element, "aria-describedby", registeredMessage.messageElement.id);
element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
}
/** Returns true if the element has been described by the provided message ID. */
_isElementDescribedByMessage(element, key) {
const referenceIds = getAriaReferenceIds(element, "aria-describedby");
const registeredMessage = this._messageRegistry.get(key);
const messageId = registeredMessage && registeredMessage.messageElement.id;
return !!messageId && referenceIds.indexOf(messageId) != -1;
}
/** Determines whether a message can be described on a particular element. */
_canBeDescribed(element, message) {
if (!this._isElementNode(element)) {
return false;
}
if (message && typeof message === "object") {
return true;
}
const trimmedMessage = message == null ? "" : `${message}`.trim();
const ariaLabel = element.getAttribute("aria-label");
return trimmedMessage ? !ariaLabel || ariaLabel.trim() !== trimmedMessage : false;
}
/** Checks whether a node is an Element node. */
_isElementNode(element) {
return element.nodeType === this._document.ELEMENT_NODE;
}
static \u0275fac = function AriaDescriber_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AriaDescriber)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _AriaDescriber,
factory: _AriaDescriber.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AriaDescriber, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
function getKey(message, role) {
return typeof message === "string" ? `${role || ""}/${message}` : message;
}
function setMessageId(element, serviceId) {
if (!element.id) {
element.id = `${CDK_DESCRIBEDBY_ID_PREFIX}-${serviceId}-${nextId++}`;
}
}
var ConfigurableFocusTrap = class extends FocusTrap {
_focusTrapManager;
_inertStrategy;
/** Whether the FocusTrap is enabled. */
get enabled() {
return this._enabled;
}
set enabled(value) {
this._enabled = value;
if (this._enabled) {
this._focusTrapManager.register(this);
} else {
this._focusTrapManager.deregister(this);
}
}
constructor(_element, _checker, _ngZone, _document2, _focusTrapManager, _inertStrategy, config, injector) {
super(_element, _checker, _ngZone, _document2, config.defer, injector);
this._focusTrapManager = _focusTrapManager;
this._inertStrategy = _inertStrategy;
this._focusTrapManager.register(this);
}
/** Notifies the FocusTrapManager that this FocusTrap will be destroyed. */
destroy() {
this._focusTrapManager.deregister(this);
super.destroy();
}
/** @docs-private Implemented as part of ManagedFocusTrap. */
_enable() {
this._inertStrategy.preventFocus(this);
this.toggleAnchors(true);
}
/** @docs-private Implemented as part of ManagedFocusTrap. */
_disable() {
this._inertStrategy.allowFocus(this);
this.toggleAnchors(false);
}
};
var EventListenerFocusTrapInertStrategy = class {
/** Focus event handler. */
_listener = null;
/** Adds a document event listener that keeps focus inside the FocusTrap. */
preventFocus(focusTrap) {
if (this._listener) {
focusTrap._document.removeEventListener("focus", this._listener, true);
}
this._listener = (e) => this._trapFocus(focusTrap, e);
focusTrap._ngZone.runOutsideAngular(() => {
focusTrap._document.addEventListener("focus", this._listener, true);
});
}
/** Removes the event listener added in preventFocus. */
allowFocus(focusTrap) {
if (!this._listener) {
return;
}
focusTrap._document.removeEventListener("focus", this._listener, true);
this._listener = null;
}
/**
* Refocuses the first element in the FocusTrap if the focus event target was outside
* the FocusTrap.
*
* This is an event listener callback. The event listener is added in runOutsideAngular,
* so all this code runs outside Angular as well.
*/
_trapFocus(focusTrap, event) {
const target = event.target;
const focusTrapRoot = focusTrap._element;
if (target && !focusTrapRoot.contains(target) && !target.closest?.("div.cdk-overlay-pane")) {
setTimeout(() => {
if (focusTrap.enabled && !focusTrapRoot.contains(focusTrap._document.activeElement)) {
focusTrap.focusFirstTabbableElement();
}
});
}
}
};
var FOCUS_TRAP_INERT_STRATEGY = new InjectionToken("FOCUS_TRAP_INERT_STRATEGY");
var FocusTrapManager = class _FocusTrapManager {
// A stack of the FocusTraps on the page. Only the FocusTrap at the
// top of the stack is active.
_focusTrapStack = [];
/**
* Disables the FocusTrap at the top of the stack, and then pushes
* the new FocusTrap onto the stack.
*/
register(focusTrap) {
this._focusTrapStack = this._focusTrapStack.filter((ft) => ft !== focusTrap);
let stack = this._focusTrapStack;
if (stack.length) {
stack[stack.length - 1]._disable();
}
stack.push(focusTrap);
focusTrap._enable();
}
/**
* Removes the FocusTrap from the stack, and activates the
* FocusTrap that is the new top of the stack.
*/
deregister(focusTrap) {
focusTrap._disable();
const stack = this._focusTrapStack;
const i = stack.indexOf(focusTrap);
if (i !== -1) {
stack.splice(i, 1);
if (stack.length) {
stack[stack.length - 1]._enable();
}
}
}
static \u0275fac = function FocusTrapManager_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _FocusTrapManager)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _FocusTrapManager,
factory: _FocusTrapManager.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(FocusTrapManager, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
var ConfigurableFocusTrapFactory = class _ConfigurableFocusTrapFactory {
_checker = inject(InteractivityChecker);
_ngZone = inject(NgZone);
_focusTrapManager = inject(FocusTrapManager);
_document = inject(DOCUMENT);
_inertStrategy;
_injector = inject(Injector);
constructor() {
const inertStrategy = inject(FOCUS_TRAP_INERT_STRATEGY, {
optional: true
});
this._inertStrategy = inertStrategy || new EventListenerFocusTrapInertStrategy();
}
create(element, config = {
defer: false
}) {
let configObject;
if (typeof config === "boolean") {
configObject = {
defer: config
};
} else {
configObject = config;
}
return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject, this._injector);
}
static \u0275fac = function ConfigurableFocusTrapFactory_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ConfigurableFocusTrapFactory)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ConfigurableFocusTrapFactory,
factory: _ConfigurableFocusTrapFactory.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ConfigurableFocusTrapFactory, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/material/fesm2022/common-module-WayjW0Pb.mjs
var MATERIAL_SANITY_CHECKS = new InjectionToken("mat-sanity-checks", {
providedIn: "root",
factory: () => true
});
var MatCommonModule = class _MatCommonModule {
constructor() {
inject(HighContrastModeDetector)._applyBodyHighContrastModeCssClasses();
}
static \u0275fac = function MatCommonModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatCommonModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatCommonModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [BidiModule, BidiModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatCommonModule, [{
type: NgModule,
args: [{
imports: [BidiModule],
exports: [BidiModule]
}]
}], () => [], null);
})();
// node_modules/@angular/material/fesm2022/module-BnDTus5c.mjs
function MatDialogContainer_ng_template_2_Template(rf, ctx) {
}
var MatDialogConfig = class {
/**
* Where the attached component should live in Angular's *logical* component tree.
* This affects what is available for injection and the change detection order for the
* component instantiated inside of the dialog. This does not affect where the dialog
* content will be rendered.
*/
viewContainerRef;
/**
* Injector used for the instantiation of the component to be attached. If provided,
* takes precedence over the injector indirectly provided by `ViewContainerRef`.
*/
injector;
/** ID for the dialog. If omitted, a unique one will be generated. */
id;
/** The ARIA role of the dialog element. */
role = "dialog";
/** Custom class for the overlay pane. */
panelClass = "";
/** Whether the dialog has a backdrop. */
hasBackdrop = true;
/** Custom class for the backdrop. */
backdropClass = "";
/** Whether the user can use escape or clicking on the backdrop to close the modal. */
disableClose = false;
/** Width of the dialog. */
width = "";
/** Height of the dialog. */
height = "";
/** Min-width of the dialog. If a number is provided, assumes pixel units. */
minWidth;
/** Min-height of the dialog. If a number is provided, assumes pixel units. */
minHeight;
/** Max-width of the dialog. If a number is provided, assumes pixel units. */
maxWidth;
/** Max-height of the dialog. If a number is provided, assumes pixel units. */
maxHeight;
/** Position overrides. */
position;
/** Data being injected into the child component. */
data = null;
/** Layout direction for the dialog's content. */
direction;
/** ID of the element that describes the dialog. */
ariaDescribedBy = null;
/** ID of the element that labels the dialog. */
ariaLabelledBy = null;
/** Aria label to assign to the dialog element. */
ariaLabel = null;
/**
* Whether this is a modal dialog. Used to set the `aria-modal` attribute. Off by default,
* because it can interfere with other overlay-based components (e.g. `mat-select`) and because
* it is redundant since the dialog marks all outside content as `aria-hidden` anyway.
*/
ariaModal = false;
/**
* Where the dialog should focus on open.
* @breaking-change 14.0.0 Remove boolean option from autoFocus. Use string or
* AutoFocusTarget instead.
*/
autoFocus = "first-tabbable";
/**
* Whether the dialog should restore focus to the
* previously-focused element, after it's closed.
*/
restoreFocus = true;
/** Whether to wait for the opening animation to finish before trapping focus. */
delayFocusTrap = true;
/** Scroll strategy to be used for the dialog. */
scrollStrategy;
/**
* Whether the dialog should close when the user goes backwards/forwards in history.
* Note that this usually doesn't include clicking on links (unless the user is using
* the `HashLocationStrategy`).
*/
closeOnNavigation = true;
/**
* Alternate `ComponentFactoryResolver` to use when resolving the associated component.
* @deprecated No longer used. Will be removed.
* @breaking-change 20.0.0
*/
componentFactoryResolver;
/**
* Duration of the enter animation in ms.
* Should be a number, string type is deprecated.
* @breaking-change 17.0.0 Remove string signature.
*/
enterAnimationDuration;
/**
* Duration of the exit animation in ms.
* Should be a number, string type is deprecated.
* @breaking-change 17.0.0 Remove string signature.
*/
exitAnimationDuration;
};
var OPEN_CLASS = "mdc-dialog--open";
var OPENING_CLASS = "mdc-dialog--opening";
var CLOSING_CLASS = "mdc-dialog--closing";
var OPEN_ANIMATION_DURATION = 150;
var CLOSE_ANIMATION_DURATION = 75;
var MatDialogContainer = class _MatDialogContainer extends CdkDialogContainer {
_animationMode = inject(ANIMATION_MODULE_TYPE, {
optional: true
});
/** Emits when an animation state changes. */
_animationStateChanged = new EventEmitter();
/** Whether animations are enabled. */
_animationsEnabled = this._animationMode !== "NoopAnimations";
/** Number of actions projected in the dialog. */
_actionSectionCount = 0;
/** Host element of the dialog container component. */
_hostElement = this._elementRef.nativeElement;
/** Duration of the dialog open animation. */
_enterAnimationDuration = this._animationsEnabled ? parseCssTime(this._config.enterAnimationDuration) ?? OPEN_ANIMATION_DURATION : 0;
/** Duration of the dialog close animation. */
_exitAnimationDuration = this._animationsEnabled ? parseCssTime(this._config.exitAnimationDuration) ?? CLOSE_ANIMATION_DURATION : 0;
/** Current timer for dialog animations. */
_animationTimer = null;
_contentAttached() {
super._contentAttached();
this._startOpenAnimation();
}
/** Starts the dialog open animation if enabled. */
_startOpenAnimation() {
this._animationStateChanged.emit({
state: "opening",
totalTime: this._enterAnimationDuration
});
if (this._animationsEnabled) {
this._hostElement.style.setProperty(TRANSITION_DURATION_PROPERTY, `${this._enterAnimationDuration}ms`);
this._requestAnimationFrame(() => this._hostElement.classList.add(OPENING_CLASS, OPEN_CLASS));
this._waitForAnimationToComplete(this._enterAnimationDuration, this._finishDialogOpen);
} else {
this._hostElement.classList.add(OPEN_CLASS);
Promise.resolve().then(() => this._finishDialogOpen());
}
}
/**
* Starts the exit animation of the dialog if enabled. This method is
* called by the dialog ref.
*/
_startExitAnimation() {
this._animationStateChanged.emit({
state: "closing",
totalTime: this._exitAnimationDuration
});
this._hostElement.classList.remove(OPEN_CLASS);
if (this._animationsEnabled) {
this._hostElement.style.setProperty(TRANSITION_DURATION_PROPERTY, `${this._exitAnimationDuration}ms`);
this._requestAnimationFrame(() => this._hostElement.classList.add(CLOSING_CLASS));
this._waitForAnimationToComplete(this._exitAnimationDuration, this._finishDialogClose);
} else {
Promise.resolve().then(() => this._finishDialogClose());
}
}
/**
* Updates the number action sections.
* @param delta Increase/decrease in the number of sections.
*/
_updateActionSectionCount(delta) {
this._actionSectionCount += delta;
this._changeDetectorRef.markForCheck();
}
/**
* Completes the dialog open by clearing potential animation classes, trapping
* focus and emitting an opened event.
*/
_finishDialogOpen = () => {
this._clearAnimationClasses();
this._openAnimationDone(this._enterAnimationDuration);
};
/**
* Completes the dialog close by clearing potential animation classes, restoring
* focus and emitting a closed event.
*/
_finishDialogClose = () => {
this._clearAnimationClasses();
this._animationStateChanged.emit({
state: "closed",
totalTime: this._exitAnimationDuration
});
};
/** Clears all dialog animation classes. */
_clearAnimationClasses() {
this._hostElement.classList.remove(OPENING_CLASS, CLOSING_CLASS);
}
_waitForAnimationToComplete(duration, callback) {
if (this._animationTimer !== null) {
clearTimeout(this._animationTimer);
}
this._animationTimer = setTimeout(callback, duration);
}
/** Runs a callback in `requestAnimationFrame`, if available. */
_requestAnimationFrame(callback) {
this._ngZone.runOutsideAngular(() => {
if (typeof requestAnimationFrame === "function") {
requestAnimationFrame(callback);
} else {
callback();
}
});
}
_captureInitialFocus() {
if (!this._config.delayFocusTrap) {
this._trapFocus();
}
}
/**
* Callback for when the open dialog animation has finished. Intended to
* be called by sub-classes that use different animation implementations.
*/
_openAnimationDone(totalTime) {
if (this._config.delayFocusTrap) {
this._trapFocus();
}
this._animationStateChanged.next({
state: "opened",
totalTime
});
}
ngOnDestroy() {
super.ngOnDestroy();
if (this._animationTimer !== null) {
clearTimeout(this._animationTimer);
}
}
attachComponentPortal(portal) {
const ref = super.attachComponentPortal(portal);
ref.location.nativeElement.classList.add("mat-mdc-dialog-component-host");
return ref;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatDialogContainer_BaseFactory;
return function MatDialogContainer_Factory(__ngFactoryType__) {
return (\u0275MatDialogContainer_BaseFactory || (\u0275MatDialogContainer_BaseFactory = \u0275\u0275getInheritedFactory(_MatDialogContainer)))(__ngFactoryType__ || _MatDialogContainer);
};
})();
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatDialogContainer,
selectors: [["mat-dialog-container"]],
hostAttrs: ["tabindex", "-1", 1, "mat-mdc-dialog-container", "mdc-dialog"],
hostVars: 10,
hostBindings: function MatDialogContainer_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275hostProperty("id", ctx._config.id);
\u0275\u0275attribute("aria-modal", ctx._config.ariaModal)("role", ctx._config.role)("aria-labelledby", ctx._config.ariaLabel ? null : ctx._ariaLabelledByQueue[0])("aria-label", ctx._config.ariaLabel)("aria-describedby", ctx._config.ariaDescribedBy || null);
\u0275\u0275classProp("_mat-animation-noopable", !ctx._animationsEnabled)("mat-mdc-dialog-container-with-actions", ctx._actionSectionCount > 0);
}
},
features: [\u0275\u0275InheritDefinitionFeature],
decls: 3,
vars: 0,
consts: [[1, "mat-mdc-dialog-inner-container", "mdc-dialog__container"], [1, "mat-mdc-dialog-surface", "mdc-dialog__surface"], ["cdkPortalOutlet", ""]],
template: function MatDialogContainer_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 0)(1, "div", 1);
\u0275\u0275template(2, MatDialogContainer_ng_template_2_Template, 0, 0, "ng-template", 2);
\u0275\u0275elementEnd()();
}
},
dependencies: [CdkPortalOutlet],
styles: ['.mat-mdc-dialog-container{width:100%;height:100%;display:block;box-sizing:border-box;max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit;outline:0}.cdk-overlay-pane.mat-mdc-dialog-panel{max-width:var(--mat-dialog-container-max-width, 560px);min-width:var(--mat-dialog-container-min-width, 280px)}@media(max-width: 599px){.cdk-overlay-pane.mat-mdc-dialog-panel{max-width:var(--mat-dialog-container-small-max-width, calc(100vw - 32px))}}.mat-mdc-dialog-inner-container{display:flex;flex-direction:row;align-items:center;justify-content:space-around;box-sizing:border-box;height:100%;opacity:0;transition:opacity linear var(--mat-dialog-transition-duration, 0ms);max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit}.mdc-dialog--closing .mat-mdc-dialog-inner-container{transition:opacity 75ms linear;transform:none}.mdc-dialog--open .mat-mdc-dialog-inner-container{opacity:1}._mat-animation-noopable .mat-mdc-dialog-inner-container{transition:none}.mat-mdc-dialog-surface{display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;box-sizing:border-box;width:100%;height:100%;position:relative;overflow-y:auto;outline:0;transform:scale(0.8);transition:transform var(--mat-dialog-transition-duration, 0ms) cubic-bezier(0, 0, 0.2, 1);max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit;box-shadow:var(--mat-dialog-container-elevation-shadow, none);border-radius:var(--mdc-dialog-container-shape, var(--mat-sys-corner-extra-large, 4px));background-color:var(--mdc-dialog-container-color, var(--mat-sys-surface, white))}[dir=rtl] .mat-mdc-dialog-surface{text-align:right}.mdc-dialog--open .mat-mdc-dialog-surface,.mdc-dialog--closing .mat-mdc-dialog-surface{transform:none}._mat-animation-noopable .mat-mdc-dialog-surface{transition:none}.mat-mdc-dialog-surface::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:2px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-dialog-title{display:block;position:relative;flex-shrink:0;box-sizing:border-box;margin:0 0 1px;padding:var(--mat-dialog-headline-padding, 6px 24px 13px)}.mat-mdc-dialog-title::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}[dir=rtl] .mat-mdc-dialog-title{text-align:right}.mat-mdc-dialog-container .mat-mdc-dialog-title{color:var(--mdc-dialog-subhead-color, var(--mat-sys-on-surface, rgba(0, 0, 0, 0.87)));font-family:var(--mdc-dialog-subhead-font, var(--mat-sys-headline-small-font, inherit));line-height:var(--mdc-dialog-subhead-line-height, var(--mat-sys-headline-small-line-height, 1.5rem));font-size:var(--mdc-dialog-subhead-size, var(--mat-sys-headline-small-size, 1rem));font-weight:var(--mdc-dialog-subhead-weight, var(--mat-sys-headline-small-weight, 400));letter-spacing:var(--mdc-dialog-subhead-tracking, var(--mat-sys-headline-small-tracking, 0.03125em))}.mat-mdc-dialog-content{display:block;flex-grow:1;box-sizing:border-box;margin:0;overflow:auto;max-height:65vh}.mat-mdc-dialog-content>:first-child{margin-top:0}.mat-mdc-dialog-content>:last-child{margin-bottom:0}.mat-mdc-dialog-container .mat-mdc-dialog-content{color:var(--mdc-dialog-supporting-text-color, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, 0.6)));font-family:var(--mdc-dialog-supporting-text-font, var(--mat-sys-body-medium-font, inherit));line-height:var(--mdc-dialog-supporting-text-line-height, var(--mat-sys-body-medium-line-height, 1.5rem));font-size:var(--mdc-dialog-supporting-text-size, var(--mat-sys-body-medium-size, 1rem));font-weight:var(--mdc-dialog-supporting-text-weight, var(--mat-sys-body-medium-weight, 400));letter-spacing:var(--mdc-dialog-supporting-text-tracking, var(--mat-sys-body-medium-tracking, 0.03125em))}.mat-mdc-dialog-container .mat-mdc-dialog-content{padding:var(--mat-dialog-content-padding, 20px 24px)}.mat-mdc-dialog-container-with-actions .mat-mdc-dialog-content{padding:var(--mat-dialog-with-actions-content-padding, 20px 24px 0)}.mat-mdc-dialog-container .mat-mdc-dialog-title+.mat-mdc-dialog-content{padding-top:0}.mat-mdc-dialog-actions{display:flex;position:relative;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;box-sizing:border-box;min-height:52px;margin:0;padding:8px;border-top:1px solid rgba(0,0,0,0);padding:var(--mat-dialog-actions-padding, 16px 24px);justify-content:var(--mat-dialog-actions-alignment, flex-end)}@media(forced-colors: active){.mat-mdc-dialog-actions{border-top-color:CanvasText}}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-start,.mat-mdc-dialog-actions[align=start]{justify-content:start}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-center,.mat-mdc-dialog-actions[align=center]{justify-content:center}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-end,.mat-mdc-dialog-actions[align=end]{justify-content:flex-end}.mat-mdc-dialog-actions .mat-button-base+.mat-button-base,.mat-mdc-dialog-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:8px}[dir=rtl] .mat-mdc-dialog-actions .mat-button-base+.mat-button-base,[dir=rtl] .mat-mdc-dialog-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:0;margin-right:8px}.mat-mdc-dialog-component-host{display:contents}\n'],
encapsulation: 2
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogContainer, [{
type: Component,
args: [{
selector: "mat-dialog-container",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.Default,
imports: [CdkPortalOutlet],
host: {
"class": "mat-mdc-dialog-container mdc-dialog",
"tabindex": "-1",
"[attr.aria-modal]": "_config.ariaModal",
"[id]": "_config.id",
"[attr.role]": "_config.role",
"[attr.aria-labelledby]": "_config.ariaLabel ? null : _ariaLabelledByQueue[0]",
"[attr.aria-label]": "_config.ariaLabel",
"[attr.aria-describedby]": "_config.ariaDescribedBy || null",
"[class._mat-animation-noopable]": "!_animationsEnabled",
"[class.mat-mdc-dialog-container-with-actions]": "_actionSectionCount > 0"
},
template: '<div class="mat-mdc-dialog-inner-container mdc-dialog__container">\n <div class="mat-mdc-dialog-surface mdc-dialog__surface">\n <ng-template cdkPortalOutlet />\n </div>\n</div>\n',
styles: ['.mat-mdc-dialog-container{width:100%;height:100%;display:block;box-sizing:border-box;max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit;outline:0}.cdk-overlay-pane.mat-mdc-dialog-panel{max-width:var(--mat-dialog-container-max-width, 560px);min-width:var(--mat-dialog-container-min-width, 280px)}@media(max-width: 599px){.cdk-overlay-pane.mat-mdc-dialog-panel{max-width:var(--mat-dialog-container-small-max-width, calc(100vw - 32px))}}.mat-mdc-dialog-inner-container{display:flex;flex-direction:row;align-items:center;justify-content:space-around;box-sizing:border-box;height:100%;opacity:0;transition:opacity linear var(--mat-dialog-transition-duration, 0ms);max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit}.mdc-dialog--closing .mat-mdc-dialog-inner-container{transition:opacity 75ms linear;transform:none}.mdc-dialog--open .mat-mdc-dialog-inner-container{opacity:1}._mat-animation-noopable .mat-mdc-dialog-inner-container{transition:none}.mat-mdc-dialog-surface{display:flex;flex-direction:column;flex-grow:0;flex-shrink:0;box-sizing:border-box;width:100%;height:100%;position:relative;overflow-y:auto;outline:0;transform:scale(0.8);transition:transform var(--mat-dialog-transition-duration, 0ms) cubic-bezier(0, 0, 0.2, 1);max-height:inherit;min-height:inherit;min-width:inherit;max-width:inherit;box-shadow:var(--mat-dialog-container-elevation-shadow, none);border-radius:var(--mdc-dialog-container-shape, var(--mat-sys-corner-extra-large, 4px));background-color:var(--mdc-dialog-container-color, var(--mat-sys-surface, white))}[dir=rtl] .mat-mdc-dialog-surface{text-align:right}.mdc-dialog--open .mat-mdc-dialog-surface,.mdc-dialog--closing .mat-mdc-dialog-surface{transform:none}._mat-animation-noopable .mat-mdc-dialog-surface{transition:none}.mat-mdc-dialog-surface::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:2px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-dialog-title{display:block;position:relative;flex-shrink:0;box-sizing:border-box;margin:0 0 1px;padding:var(--mat-dialog-headline-padding, 6px 24px 13px)}.mat-mdc-dialog-title::before{display:inline-block;width:0;height:40px;content:"";vertical-align:0}[dir=rtl] .mat-mdc-dialog-title{text-align:right}.mat-mdc-dialog-container .mat-mdc-dialog-title{color:var(--mdc-dialog-subhead-color, var(--mat-sys-on-surface, rgba(0, 0, 0, 0.87)));font-family:var(--mdc-dialog-subhead-font, var(--mat-sys-headline-small-font, inherit));line-height:var(--mdc-dialog-subhead-line-height, var(--mat-sys-headline-small-line-height, 1.5rem));font-size:var(--mdc-dialog-subhead-size, var(--mat-sys-headline-small-size, 1rem));font-weight:var(--mdc-dialog-subhead-weight, var(--mat-sys-headline-small-weight, 400));letter-spacing:var(--mdc-dialog-subhead-tracking, var(--mat-sys-headline-small-tracking, 0.03125em))}.mat-mdc-dialog-content{display:block;flex-grow:1;box-sizing:border-box;margin:0;overflow:auto;max-height:65vh}.mat-mdc-dialog-content>:first-child{margin-top:0}.mat-mdc-dialog-content>:last-child{margin-bottom:0}.mat-mdc-dialog-container .mat-mdc-dialog-content{color:var(--mdc-dialog-supporting-text-color, var(--mat-sys-on-surface-variant, rgba(0, 0, 0, 0.6)));font-family:var(--mdc-dialog-supporting-text-font, var(--mat-sys-body-medium-font, inherit));line-height:var(--mdc-dialog-supporting-text-line-height, var(--mat-sys-body-medium-line-height, 1.5rem));font-size:var(--mdc-dialog-supporting-text-size, var(--mat-sys-body-medium-size, 1rem));font-weight:var(--mdc-dialog-supporting-text-weight, var(--mat-sys-body-medium-weight, 400));letter-spacing:var(--mdc-dialog-supporting-text-tracking, var(--mat-sys-body-medium-tracking, 0.03125em))}.mat-mdc-dialog-container .mat-mdc-dialog-content{padding:var(--mat-dialog-content-padding, 20px 24px)}.mat-mdc-dialog-container-with-actions .mat-mdc-dialog-content{padding:var(--mat-dialog-with-actions-content-padding, 20px 24px 0)}.mat-mdc-dialog-container .mat-mdc-dialog-title+.mat-mdc-dialog-content{padding-top:0}.mat-mdc-dialog-actions{display:flex;position:relative;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;box-sizing:border-box;min-height:52px;margin:0;padding:8px;border-top:1px solid rgba(0,0,0,0);padding:var(--mat-dialog-actions-padding, 16px 24px);justify-content:var(--mat-dialog-actions-alignment, flex-end)}@media(forced-colors: active){.mat-mdc-dialog-actions{border-top-color:CanvasText}}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-start,.mat-mdc-dialog-actions[align=start]{justify-content:start}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-center,.mat-mdc-dialog-actions[align=center]{justify-content:center}.mat-mdc-dialog-actions.mat-mdc-dialog-actions-align-end,.mat-mdc-dialog-actions[align=end]{justify-content:flex-end}.mat-mdc-dialog-actions .mat-button-base+.mat-button-base,.mat-mdc-dialog-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:8px}[dir=rtl] .mat-mdc-dialog-actions .mat-button-base+.mat-button-base,[dir=rtl] .mat-mdc-dialog-actions .mat-mdc-button-base+.mat-mdc-button-base{margin-left:0;margin-right:8px}.mat-mdc-dialog-component-host{display:contents}\n']
}]
}], null, null);
})();
var TRANSITION_DURATION_PROPERTY = "--mat-dialog-transition-duration";
function parseCssTime(time) {
if (time == null) {
return null;
}
if (typeof time === "number") {
return time;
}
if (time.endsWith("ms")) {
return coerceNumberProperty(time.substring(0, time.length - 2));
}
if (time.endsWith("s")) {
return coerceNumberProperty(time.substring(0, time.length - 1)) * 1e3;
}
if (time === "0") {
return 0;
}
return null;
}
var MatDialogState;
(function(MatDialogState2) {
MatDialogState2[MatDialogState2["OPEN"] = 0] = "OPEN";
MatDialogState2[MatDialogState2["CLOSING"] = 1] = "CLOSING";
MatDialogState2[MatDialogState2["CLOSED"] = 2] = "CLOSED";
})(MatDialogState || (MatDialogState = {}));
var MatDialogRef = class {
_ref;
_containerInstance;
/** The instance of component opened into the dialog. */
componentInstance;
/**
* `ComponentRef` of the component opened into the dialog. Will be
* null when the dialog is opened using a `TemplateRef`.
*/
componentRef;
/** Whether the user is allowed to close the dialog. */
disableClose;
/** Unique ID for the dialog. */
id;
/** Subject for notifying the user that the dialog has finished opening. */
_afterOpened = new Subject();
/** Subject for notifying the user that the dialog has started closing. */
_beforeClosed = new Subject();
/** Result to be passed to afterClosed. */
_result;
/** Handle to the timeout that's running as a fallback in case the exit animation doesn't fire. */
_closeFallbackTimeout;
/** Current state of the dialog. */
_state = MatDialogState.OPEN;
// TODO(crisbeto): we shouldn't have to declare this property, because `DialogRef.close`
// already has a second `options` parameter that we can use. The problem is that internal tests
// have assertions like `expect(MatDialogRef.close).toHaveBeenCalledWith(foo)` which will break,
// because it'll be called with two arguments by things like `MatDialogClose`.
/** Interaction that caused the dialog to close. */
_closeInteractionType;
constructor(_ref, config, _containerInstance) {
this._ref = _ref;
this._containerInstance = _containerInstance;
this.disableClose = config.disableClose;
this.id = _ref.id;
_ref.addPanelClass("mat-mdc-dialog-panel");
_containerInstance._animationStateChanged.pipe(filter((event) => event.state === "opened"), take(1)).subscribe(() => {
this._afterOpened.next();
this._afterOpened.complete();
});
_containerInstance._animationStateChanged.pipe(filter((event) => event.state === "closed"), take(1)).subscribe(() => {
clearTimeout(this._closeFallbackTimeout);
this._finishDialogClose();
});
_ref.overlayRef.detachments().subscribe(() => {
this._beforeClosed.next(this._result);
this._beforeClosed.complete();
this._finishDialogClose();
});
merge(this.backdropClick(), this.keydownEvents().pipe(filter((event) => event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event)))).subscribe((event) => {
if (!this.disableClose) {
event.preventDefault();
_closeDialogVia(this, event.type === "keydown" ? "keyboard" : "mouse");
}
});
}
/**
* Close the dialog.
* @param dialogResult Optional result to return to the dialog opener.
*/
close(dialogResult) {
this._result = dialogResult;
this._containerInstance._animationStateChanged.pipe(filter((event) => event.state === "closing"), take(1)).subscribe((event) => {
this._beforeClosed.next(dialogResult);
this._beforeClosed.complete();
this._ref.overlayRef.detachBackdrop();
this._closeFallbackTimeout = setTimeout(() => this._finishDialogClose(), event.totalTime + 100);
});
this._state = MatDialogState.CLOSING;
this._containerInstance._startExitAnimation();
}
/**
* Gets an observable that is notified when the dialog is finished opening.
*/
afterOpened() {
return this._afterOpened;
}
/**
* Gets an observable that is notified when the dialog is finished closing.
*/
afterClosed() {
return this._ref.closed;
}
/**
* Gets an observable that is notified when the dialog has started closing.
*/
beforeClosed() {
return this._beforeClosed;
}
/**
* Gets an observable that emits when the overlay's backdrop has been clicked.
*/
backdropClick() {
return this._ref.backdropClick;
}
/**
* Gets an observable that emits when keydown events are targeted on the overlay.
*/
keydownEvents() {
return this._ref.keydownEvents;
}
/**
* Updates the dialog's position.
* @param position New dialog position.
*/
updatePosition(position) {
let strategy = this._ref.config.positionStrategy;
if (position && (position.left || position.right)) {
position.left ? strategy.left(position.left) : strategy.right(position.right);
} else {
strategy.centerHorizontally();
}
if (position && (position.top || position.bottom)) {
position.top ? strategy.top(position.top) : strategy.bottom(position.bottom);
} else {
strategy.centerVertically();
}
this._ref.updatePosition();
return this;
}
/**
* Updates the dialog's width and height.
* @param width New width of the dialog.
* @param height New height of the dialog.
*/
updateSize(width = "", height = "") {
this._ref.updateSize(width, height);
return this;
}
/** Add a CSS class or an array of classes to the overlay pane. */
addPanelClass(classes) {
this._ref.addPanelClass(classes);
return this;
}
/** Remove a CSS class or an array of classes from the overlay pane. */
removePanelClass(classes) {
this._ref.removePanelClass(classes);
return this;
}
/** Gets the current state of the dialog's lifecycle. */
getState() {
return this._state;
}
/**
* Finishes the dialog close by updating the state of the dialog
* and disposing the overlay.
*/
_finishDialogClose() {
this._state = MatDialogState.CLOSED;
this._ref.close(this._result, {
focusOrigin: this._closeInteractionType
});
this.componentInstance = null;
}
};
function _closeDialogVia(ref, interactionType, result) {
ref._closeInteractionType = interactionType;
return ref.close(result);
}
var MAT_DIALOG_DATA = new InjectionToken("MatMdcDialogData");
var MAT_DIALOG_DEFAULT_OPTIONS = new InjectionToken("mat-mdc-dialog-default-options");
var MAT_DIALOG_SCROLL_STRATEGY = new InjectionToken("mat-mdc-dialog-scroll-strategy", {
providedIn: "root",
factory: () => {
const overlay = inject(Overlay);
return () => overlay.scrollStrategies.block();
}
});
var MatDialog = class _MatDialog {
_overlay = inject(Overlay);
_defaultOptions = inject(MAT_DIALOG_DEFAULT_OPTIONS, {
optional: true
});
_scrollStrategy = inject(MAT_DIALOG_SCROLL_STRATEGY);
_parentDialog = inject(_MatDialog, {
optional: true,
skipSelf: true
});
_idGenerator = inject(_IdGenerator);
_dialog = inject(Dialog);
_openDialogsAtThisLevel = [];
_afterAllClosedAtThisLevel = new Subject();
_afterOpenedAtThisLevel = new Subject();
dialogConfigClass = MatDialogConfig;
_dialogRefConstructor;
_dialogContainerType;
_dialogDataToken;
/** Keeps track of the currently-open dialogs. */
get openDialogs() {
return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel;
}
/** Stream that emits when a dialog has been opened. */
get afterOpened() {
return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel;
}
_getAfterAllClosed() {
const parent = this._parentDialog;
return parent ? parent._getAfterAllClosed() : this._afterAllClosedAtThisLevel;
}
/**
* Stream that emits when all open dialog have finished closing.
* Will emit on subscribe if there are no open dialogs to begin with.
*/
afterAllClosed = defer(() => this.openDialogs.length ? this._getAfterAllClosed() : this._getAfterAllClosed().pipe(startWith(void 0)));
constructor() {
this._dialogRefConstructor = MatDialogRef;
this._dialogContainerType = MatDialogContainer;
this._dialogDataToken = MAT_DIALOG_DATA;
}
open(componentOrTemplateRef, config) {
let dialogRef;
config = __spreadValues(__spreadValues({}, this._defaultOptions || new MatDialogConfig()), config);
config.id = config.id || this._idGenerator.getId("mat-mdc-dialog-");
config.scrollStrategy = config.scrollStrategy || this._scrollStrategy();
const cdkRef = this._dialog.open(componentOrTemplateRef, __spreadProps(__spreadValues({}, config), {
positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),
// Disable closing since we need to sync it up to the animation ourselves.
disableClose: true,
// Disable closing on destroy, because this service cleans up its open dialogs as well.
// We want to do the cleanup here, rather than the CDK service, because the CDK destroys
// the dialogs immediately whereas we want it to wait for the animations to finish.
closeOnDestroy: false,
// Disable closing on detachments so that we can sync up the animation.
// The Material dialog ref handles this manually.
closeOnOverlayDetachments: false,
container: {
type: this._dialogContainerType,
providers: () => [
// Provide our config as the CDK config as well since it has the same interface as the
// CDK one, but it contains the actual values passed in by the user for things like
// `disableClose` which we disable for the CDK dialog since we handle it ourselves.
{
provide: this.dialogConfigClass,
useValue: config
},
{
provide: DialogConfig,
useValue: config
}
]
},
templateContext: () => ({
dialogRef
}),
providers: (ref, cdkConfig, dialogContainer) => {
dialogRef = new this._dialogRefConstructor(ref, config, dialogContainer);
dialogRef.updatePosition(config?.position);
return [{
provide: this._dialogContainerType,
useValue: dialogContainer
}, {
provide: this._dialogDataToken,
useValue: cdkConfig.data
}, {
provide: this._dialogRefConstructor,
useValue: dialogRef
}];
}
}));
dialogRef.componentRef = cdkRef.componentRef;
dialogRef.componentInstance = cdkRef.componentInstance;
this.openDialogs.push(dialogRef);
this.afterOpened.next(dialogRef);
dialogRef.afterClosed().subscribe(() => {
const index = this.openDialogs.indexOf(dialogRef);
if (index > -1) {
this.openDialogs.splice(index, 1);
if (!this.openDialogs.length) {
this._getAfterAllClosed().next();
}
}
});
return dialogRef;
}
/**
* Closes all of the currently-open dialogs.
*/
closeAll() {
this._closeDialogs(this.openDialogs);
}
/**
* Finds an open dialog by its id.
* @param id ID to use when looking up the dialog.
*/
getDialogById(id) {
return this.openDialogs.find((dialog) => dialog.id === id);
}
ngOnDestroy() {
this._closeDialogs(this._openDialogsAtThisLevel);
this._afterAllClosedAtThisLevel.complete();
this._afterOpenedAtThisLevel.complete();
}
_closeDialogs(dialogs) {
let i = dialogs.length;
while (i--) {
dialogs[i].close();
}
}
static \u0275fac = function MatDialog_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatDialog)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _MatDialog,
factory: _MatDialog.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialog, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var MatDialogClose = class _MatDialogClose {
dialogRef = inject(MatDialogRef, {
optional: true
});
_elementRef = inject(ElementRef);
_dialog = inject(MatDialog);
/** Screen-reader label for the button. */
ariaLabel;
/** Default to "button" to prevents accidental form submits. */
type = "button";
/** Dialog close input. */
dialogResult;
_matDialogClose;
constructor() {
}
ngOnInit() {
if (!this.dialogRef) {
this.dialogRef = getClosestDialog(this._elementRef, this._dialog.openDialogs);
}
}
ngOnChanges(changes) {
const proxiedChange = changes["_matDialogClose"] || changes["_matDialogCloseResult"];
if (proxiedChange) {
this.dialogResult = proxiedChange.currentValue;
}
}
_onButtonClick(event) {
_closeDialogVia(this.dialogRef, event.screenX === 0 && event.screenY === 0 ? "keyboard" : "mouse", this.dialogResult);
}
static \u0275fac = function MatDialogClose_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatDialogClose)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatDialogClose,
selectors: [["", "mat-dialog-close", ""], ["", "matDialogClose", ""]],
hostVars: 2,
hostBindings: function MatDialogClose_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("click", function MatDialogClose_click_HostBindingHandler($event) {
return ctx._onButtonClick($event);
});
}
if (rf & 2) {
\u0275\u0275attribute("aria-label", ctx.ariaLabel || null)("type", ctx.type);
}
},
inputs: {
ariaLabel: [0, "aria-label", "ariaLabel"],
type: "type",
dialogResult: [0, "mat-dialog-close", "dialogResult"],
_matDialogClose: [0, "matDialogClose", "_matDialogClose"]
},
exportAs: ["matDialogClose"],
features: [\u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogClose, [{
type: Directive,
args: [{
selector: "[mat-dialog-close], [matDialogClose]",
exportAs: "matDialogClose",
host: {
"(click)": "_onButtonClick($event)",
"[attr.aria-label]": "ariaLabel || null",
"[attr.type]": "type"
}
}]
}], () => [], {
ariaLabel: [{
type: Input,
args: ["aria-label"]
}],
type: [{
type: Input
}],
dialogResult: [{
type: Input,
args: ["mat-dialog-close"]
}],
_matDialogClose: [{
type: Input,
args: ["matDialogClose"]
}]
});
})();
var MatDialogLayoutSection = class _MatDialogLayoutSection {
_dialogRef = inject(MatDialogRef, {
optional: true
});
_elementRef = inject(ElementRef);
_dialog = inject(MatDialog);
constructor() {
}
ngOnInit() {
if (!this._dialogRef) {
this._dialogRef = getClosestDialog(this._elementRef, this._dialog.openDialogs);
}
if (this._dialogRef) {
Promise.resolve().then(() => {
this._onAdd();
});
}
}
ngOnDestroy() {
const instance = this._dialogRef?._containerInstance;
if (instance) {
Promise.resolve().then(() => {
this._onRemove();
});
}
}
static \u0275fac = function MatDialogLayoutSection_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatDialogLayoutSection)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatDialogLayoutSection
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogLayoutSection, [{
type: Directive
}], () => [], null);
})();
var MatDialogTitle = class _MatDialogTitle extends MatDialogLayoutSection {
id = inject(_IdGenerator).getId("mat-mdc-dialog-title-");
_onAdd() {
this._dialogRef._containerInstance?._addAriaLabelledBy?.(this.id);
}
_onRemove() {
this._dialogRef?._containerInstance?._removeAriaLabelledBy?.(this.id);
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatDialogTitle_BaseFactory;
return function MatDialogTitle_Factory(__ngFactoryType__) {
return (\u0275MatDialogTitle_BaseFactory || (\u0275MatDialogTitle_BaseFactory = \u0275\u0275getInheritedFactory(_MatDialogTitle)))(__ngFactoryType__ || _MatDialogTitle);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatDialogTitle,
selectors: [["", "mat-dialog-title", ""], ["", "matDialogTitle", ""]],
hostAttrs: [1, "mat-mdc-dialog-title", "mdc-dialog__title"],
hostVars: 1,
hostBindings: function MatDialogTitle_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275hostProperty("id", ctx.id);
}
},
inputs: {
id: "id"
},
exportAs: ["matDialogTitle"],
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogTitle, [{
type: Directive,
args: [{
selector: "[mat-dialog-title], [matDialogTitle]",
exportAs: "matDialogTitle",
host: {
"class": "mat-mdc-dialog-title mdc-dialog__title",
"[id]": "id"
}
}]
}], null, {
id: [{
type: Input
}]
});
})();
var MatDialogContent = class _MatDialogContent {
static \u0275fac = function MatDialogContent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatDialogContent)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatDialogContent,
selectors: [["", "mat-dialog-content", ""], ["mat-dialog-content"], ["", "matDialogContent", ""]],
hostAttrs: [1, "mat-mdc-dialog-content", "mdc-dialog__content"],
features: [\u0275\u0275HostDirectivesFeature([CdkScrollable])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogContent, [{
type: Directive,
args: [{
selector: `[mat-dialog-content], mat-dialog-content, [matDialogContent]`,
host: {
"class": "mat-mdc-dialog-content mdc-dialog__content"
},
hostDirectives: [CdkScrollable]
}]
}], null, null);
})();
var MatDialogActions = class _MatDialogActions extends MatDialogLayoutSection {
/**
* Horizontal alignment of action buttons.
*/
align;
_onAdd() {
this._dialogRef._containerInstance?._updateActionSectionCount?.(1);
}
_onRemove() {
this._dialogRef._containerInstance?._updateActionSectionCount?.(-1);
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatDialogActions_BaseFactory;
return function MatDialogActions_Factory(__ngFactoryType__) {
return (\u0275MatDialogActions_BaseFactory || (\u0275MatDialogActions_BaseFactory = \u0275\u0275getInheritedFactory(_MatDialogActions)))(__ngFactoryType__ || _MatDialogActions);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatDialogActions,
selectors: [["", "mat-dialog-actions", ""], ["mat-dialog-actions"], ["", "matDialogActions", ""]],
hostAttrs: [1, "mat-mdc-dialog-actions", "mdc-dialog__actions"],
hostVars: 6,
hostBindings: function MatDialogActions_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("mat-mdc-dialog-actions-align-start", ctx.align === "start")("mat-mdc-dialog-actions-align-center", ctx.align === "center")("mat-mdc-dialog-actions-align-end", ctx.align === "end");
}
},
inputs: {
align: "align"
},
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogActions, [{
type: Directive,
args: [{
selector: `[mat-dialog-actions], mat-dialog-actions, [matDialogActions]`,
host: {
"class": "mat-mdc-dialog-actions mdc-dialog__actions",
"[class.mat-mdc-dialog-actions-align-start]": 'align === "start"',
"[class.mat-mdc-dialog-actions-align-center]": 'align === "center"',
"[class.mat-mdc-dialog-actions-align-end]": 'align === "end"'
}
}]
}], null, {
align: [{
type: Input
}]
});
})();
function getClosestDialog(element, openDialogs) {
let parent = element.nativeElement.parentElement;
while (parent && !parent.classList.contains("mat-mdc-dialog-container")) {
parent = parent.parentElement;
}
return parent ? openDialogs.find((dialog) => dialog.id === parent.id) : null;
}
var DIRECTIVES = [MatDialogContainer, MatDialogClose, MatDialogTitle, MatDialogActions, MatDialogContent];
var MatDialogModule = class _MatDialogModule {
static \u0275fac = function MatDialogModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatDialogModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatDialogModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
providers: [MatDialog],
imports: [DialogModule, OverlayModule, PortalModule, MatCommonModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatDialogModule, [{
type: NgModule,
args: [{
imports: [DialogModule, OverlayModule, PortalModule, MatCommonModule, ...DIRECTIVES],
exports: [MatCommonModule, ...DIRECTIVES],
providers: [MatDialog]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/platform.mjs
var PlatformModule = class _PlatformModule {
static \u0275fac = function PlatformModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _PlatformModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _PlatformModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformModule, [{
type: NgModule,
args: [{}]
}], null, null);
})();
var supportedInputTypes;
var candidateInputTypes = [
// `color` must come first. Chrome 56 shows a warning if we change the type to `color` after
// first changing it to something else:
// The specified value "" does not conform to the required format.
// The format is "#rrggbb" where rr, gg, bb are two-digit hexadecimal numbers.
"color",
"button",
"checkbox",
"date",
"datetime-local",
"email",
"file",
"hidden",
"image",
"month",
"number",
"password",
"radio",
"range",
"reset",
"search",
"submit",
"tel",
"text",
"time",
"url",
"week"
];
function getSupportedInputTypes() {
if (supportedInputTypes) {
return supportedInputTypes;
}
if (typeof document !== "object" || !document) {
supportedInputTypes = new Set(candidateInputTypes);
return supportedInputTypes;
}
let featureTestInput = document.createElement("input");
supportedInputTypes = new Set(candidateInputTypes.filter((value) => {
featureTestInput.setAttribute("type", value);
return featureTestInput.type === value;
}));
return supportedInputTypes;
}
// node_modules/@angular/material/fesm2022/ripple-BT3tzh6F.mjs
var RippleState;
(function(RippleState2) {
RippleState2[RippleState2["FADING_IN"] = 0] = "FADING_IN";
RippleState2[RippleState2["VISIBLE"] = 1] = "VISIBLE";
RippleState2[RippleState2["FADING_OUT"] = 2] = "FADING_OUT";
RippleState2[RippleState2["HIDDEN"] = 3] = "HIDDEN";
})(RippleState || (RippleState = {}));
var RippleRef = class {
_renderer;
element;
config;
_animationForciblyDisabledThroughCss;
/** Current state of the ripple. */
state = RippleState.HIDDEN;
constructor(_renderer, element, config, _animationForciblyDisabledThroughCss = false) {
this._renderer = _renderer;
this.element = element;
this.config = config;
this._animationForciblyDisabledThroughCss = _animationForciblyDisabledThroughCss;
}
/** Fades out the ripple element. */
fadeOut() {
this._renderer.fadeOutRipple(this);
}
};
var passiveCapturingEventOptions$1 = normalizePassiveListenerOptions({
passive: true,
capture: true
});
var RippleEventManager = class {
_events = /* @__PURE__ */ new Map();
/** Adds an event handler. */
addHandler(ngZone, name, element, handler) {
const handlersForEvent = this._events.get(name);
if (handlersForEvent) {
const handlersForElement = handlersForEvent.get(element);
if (handlersForElement) {
handlersForElement.add(handler);
} else {
handlersForEvent.set(element, /* @__PURE__ */ new Set([handler]));
}
} else {
this._events.set(name, /* @__PURE__ */ new Map([[element, /* @__PURE__ */ new Set([handler])]]));
ngZone.runOutsideAngular(() => {
document.addEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions$1);
});
}
}
/** Removes an event handler. */
removeHandler(name, element, handler) {
const handlersForEvent = this._events.get(name);
if (!handlersForEvent) {
return;
}
const handlersForElement = handlersForEvent.get(element);
if (!handlersForElement) {
return;
}
handlersForElement.delete(handler);
if (handlersForElement.size === 0) {
handlersForEvent.delete(element);
}
if (handlersForEvent.size === 0) {
this._events.delete(name);
document.removeEventListener(name, this._delegateEventHandler, passiveCapturingEventOptions$1);
}
}
/** Event handler that is bound and which dispatches the events to the different targets. */
_delegateEventHandler = (event) => {
const target = _getEventTarget(event);
if (target) {
this._events.get(event.type)?.forEach((handlers, element) => {
if (element === target || element.contains(target)) {
handlers.forEach((handler) => handler.handleEvent(event));
}
});
}
};
};
var defaultRippleAnimationConfig = {
enterDuration: 225,
exitDuration: 150
};
var ignoreMouseEventsTimeout = 800;
var passiveCapturingEventOptions = normalizePassiveListenerOptions({
passive: true,
capture: true
});
var pointerDownEvents = ["mousedown", "touchstart"];
var pointerUpEvents = ["mouseup", "mouseleave", "touchend", "touchcancel"];
var _MatRippleStylesLoader = class __MatRippleStylesLoader {
static \u0275fac = function _MatRippleStylesLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __MatRippleStylesLoader)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: __MatRippleStylesLoader,
selectors: [["ng-component"]],
hostAttrs: ["mat-ripple-style-loader", ""],
decls: 0,
vars: 0,
template: function _MatRippleStylesLoader_Template(rf, ctx) {
},
styles: [".mat-ripple{overflow:hidden;position:relative}.mat-ripple:not(:empty){transform:translateZ(0)}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,transform 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale3d(0, 0, 0);background-color:var(--mat-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface) 10%, transparent))}@media(forced-colors: active){.mat-ripple-element{display:none}}.cdk-drag-preview .mat-ripple-element,.cdk-drag-placeholder .mat-ripple-element{display:none}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_MatRippleStylesLoader, [{
type: Component,
args: [{
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: {
"mat-ripple-style-loader": ""
},
styles: [".mat-ripple{overflow:hidden;position:relative}.mat-ripple:not(:empty){transform:translateZ(0)}.mat-ripple.mat-ripple-unbounded{overflow:visible}.mat-ripple-element{position:absolute;border-radius:50%;pointer-events:none;transition:opacity,transform 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale3d(0, 0, 0);background-color:var(--mat-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface) 10%, transparent))}@media(forced-colors: active){.mat-ripple-element{display:none}}.cdk-drag-preview .mat-ripple-element,.cdk-drag-placeholder .mat-ripple-element{display:none}\n"]
}]
}], null, null);
})();
var RippleRenderer = class _RippleRenderer {
_target;
_ngZone;
_platform;
/** Element where the ripples are being added to. */
_containerElement;
/** Element which triggers the ripple elements on mouse events. */
_triggerElement;
/** Whether the pointer is currently down or not. */
_isPointerDown = false;
/**
* Map of currently active ripple references.
* The ripple reference is mapped to its element event listeners.
* The reason why `| null` is used is that event listeners are added only
* when the condition is truthy (see the `_startFadeOutTransition` method).
*/
_activeRipples = /* @__PURE__ */ new Map();
/** Latest non-persistent ripple that was triggered. */
_mostRecentTransientRipple;
/** Time in milliseconds when the last touchstart event happened. */
_lastTouchStartEvent;
/** Whether pointer-up event listeners have been registered. */
_pointerUpEventsRegistered = false;
/**
* Cached dimensions of the ripple container. Set when the first
* ripple is shown and cleared once no more ripples are visible.
*/
_containerRect;
static _eventManager = new RippleEventManager();
constructor(_target, _ngZone, elementOrElementRef, _platform, injector) {
this._target = _target;
this._ngZone = _ngZone;
this._platform = _platform;
if (_platform.isBrowser) {
this._containerElement = coerceElement(elementOrElementRef);
}
if (injector) {
injector.get(_CdkPrivateStyleLoader).load(_MatRippleStylesLoader);
}
}
/**
* Fades in a ripple at the given coordinates.
* @param x Coordinate within the element, along the X axis at which to start the ripple.
* @param y Coordinate within the element, along the Y axis at which to start the ripple.
* @param config Extra ripple options.
*/
fadeInRipple(x, y, config = {}) {
const containerRect = this._containerRect = this._containerRect || this._containerElement.getBoundingClientRect();
const animationConfig = __spreadValues(__spreadValues({}, defaultRippleAnimationConfig), config.animation);
if (config.centered) {
x = containerRect.left + containerRect.width / 2;
y = containerRect.top + containerRect.height / 2;
}
const radius = config.radius || distanceToFurthestCorner(x, y, containerRect);
const offsetX = x - containerRect.left;
const offsetY = y - containerRect.top;
const enterDuration = animationConfig.enterDuration;
const ripple = document.createElement("div");
ripple.classList.add("mat-ripple-element");
ripple.style.left = `${offsetX - radius}px`;
ripple.style.top = `${offsetY - radius}px`;
ripple.style.height = `${radius * 2}px`;
ripple.style.width = `${radius * 2}px`;
if (config.color != null) {
ripple.style.backgroundColor = config.color;
}
ripple.style.transitionDuration = `${enterDuration}ms`;
this._containerElement.appendChild(ripple);
const computedStyles = window.getComputedStyle(ripple);
const userTransitionProperty = computedStyles.transitionProperty;
const userTransitionDuration = computedStyles.transitionDuration;
const animationForciblyDisabledThroughCss = userTransitionProperty === "none" || // Note: The canonical unit for serialized CSS `<time>` properties is seconds. Additionally
// some browsers expand the duration for every property (in our case `opacity` and `transform`).
userTransitionDuration === "0s" || userTransitionDuration === "0s, 0s" || // If the container is 0x0, it's likely `display: none`.
containerRect.width === 0 && containerRect.height === 0;
const rippleRef = new RippleRef(this, ripple, config, animationForciblyDisabledThroughCss);
ripple.style.transform = "scale3d(1, 1, 1)";
rippleRef.state = RippleState.FADING_IN;
if (!config.persistent) {
this._mostRecentTransientRipple = rippleRef;
}
let eventListeners = null;
if (!animationForciblyDisabledThroughCss && (enterDuration || animationConfig.exitDuration)) {
this._ngZone.runOutsideAngular(() => {
const onTransitionEnd = () => {
if (eventListeners) {
eventListeners.fallbackTimer = null;
}
clearTimeout(fallbackTimer);
this._finishRippleTransition(rippleRef);
};
const onTransitionCancel = () => this._destroyRipple(rippleRef);
const fallbackTimer = setTimeout(onTransitionCancel, enterDuration + 100);
ripple.addEventListener("transitionend", onTransitionEnd);
ripple.addEventListener("transitioncancel", onTransitionCancel);
eventListeners = {
onTransitionEnd,
onTransitionCancel,
fallbackTimer
};
});
}
this._activeRipples.set(rippleRef, eventListeners);
if (animationForciblyDisabledThroughCss || !enterDuration) {
this._finishRippleTransition(rippleRef);
}
return rippleRef;
}
/** Fades out a ripple reference. */
fadeOutRipple(rippleRef) {
if (rippleRef.state === RippleState.FADING_OUT || rippleRef.state === RippleState.HIDDEN) {
return;
}
const rippleEl = rippleRef.element;
const animationConfig = __spreadValues(__spreadValues({}, defaultRippleAnimationConfig), rippleRef.config.animation);
rippleEl.style.transitionDuration = `${animationConfig.exitDuration}ms`;
rippleEl.style.opacity = "0";
rippleRef.state = RippleState.FADING_OUT;
if (rippleRef._animationForciblyDisabledThroughCss || !animationConfig.exitDuration) {
this._finishRippleTransition(rippleRef);
}
}
/** Fades out all currently active ripples. */
fadeOutAll() {
this._getActiveRipples().forEach((ripple) => ripple.fadeOut());
}
/** Fades out all currently active non-persistent ripples. */
fadeOutAllNonPersistent() {
this._getActiveRipples().forEach((ripple) => {
if (!ripple.config.persistent) {
ripple.fadeOut();
}
});
}
/** Sets up the trigger event listeners */
setupTriggerEvents(elementOrElementRef) {
const element = coerceElement(elementOrElementRef);
if (!this._platform.isBrowser || !element || element === this._triggerElement) {
return;
}
this._removeTriggerEvents();
this._triggerElement = element;
pointerDownEvents.forEach((type) => {
_RippleRenderer._eventManager.addHandler(this._ngZone, type, element, this);
});
}
/**
* Handles all registered events.
* @docs-private
*/
handleEvent(event) {
if (event.type === "mousedown") {
this._onMousedown(event);
} else if (event.type === "touchstart") {
this._onTouchStart(event);
} else {
this._onPointerUp();
}
if (!this._pointerUpEventsRegistered) {
this._ngZone.runOutsideAngular(() => {
pointerUpEvents.forEach((type) => {
this._triggerElement.addEventListener(type, this, passiveCapturingEventOptions);
});
});
this._pointerUpEventsRegistered = true;
}
}
/** Method that will be called if the fade-in or fade-in transition completed. */
_finishRippleTransition(rippleRef) {
if (rippleRef.state === RippleState.FADING_IN) {
this._startFadeOutTransition(rippleRef);
} else if (rippleRef.state === RippleState.FADING_OUT) {
this._destroyRipple(rippleRef);
}
}
/**
* Starts the fade-out transition of the given ripple if it's not persistent and the pointer
* is not held down anymore.
*/
_startFadeOutTransition(rippleRef) {
const isMostRecentTransientRipple = rippleRef === this._mostRecentTransientRipple;
const {
persistent
} = rippleRef.config;
rippleRef.state = RippleState.VISIBLE;
if (!persistent && (!isMostRecentTransientRipple || !this._isPointerDown)) {
rippleRef.fadeOut();
}
}
/** Destroys the given ripple by removing it from the DOM and updating its state. */
_destroyRipple(rippleRef) {
const eventListeners = this._activeRipples.get(rippleRef) ?? null;
this._activeRipples.delete(rippleRef);
if (!this._activeRipples.size) {
this._containerRect = null;
}
if (rippleRef === this._mostRecentTransientRipple) {
this._mostRecentTransientRipple = null;
}
rippleRef.state = RippleState.HIDDEN;
if (eventListeners !== null) {
rippleRef.element.removeEventListener("transitionend", eventListeners.onTransitionEnd);
rippleRef.element.removeEventListener("transitioncancel", eventListeners.onTransitionCancel);
if (eventListeners.fallbackTimer !== null) {
clearTimeout(eventListeners.fallbackTimer);
}
}
rippleRef.element.remove();
}
/** Function being called whenever the trigger is being pressed using mouse. */
_onMousedown(event) {
const isFakeMousedown = isFakeMousedownFromScreenReader(event);
const isSyntheticEvent = this._lastTouchStartEvent && Date.now() < this._lastTouchStartEvent + ignoreMouseEventsTimeout;
if (!this._target.rippleDisabled && !isFakeMousedown && !isSyntheticEvent) {
this._isPointerDown = true;
this.fadeInRipple(event.clientX, event.clientY, this._target.rippleConfig);
}
}
/** Function being called whenever the trigger is being pressed using touch. */
_onTouchStart(event) {
if (!this._target.rippleDisabled && !isFakeTouchstartFromScreenReader(event)) {
this._lastTouchStartEvent = Date.now();
this._isPointerDown = true;
const touches = event.changedTouches;
if (touches) {
for (let i = 0; i < touches.length; i++) {
this.fadeInRipple(touches[i].clientX, touches[i].clientY, this._target.rippleConfig);
}
}
}
}
/** Function being called whenever the trigger is being released. */
_onPointerUp() {
if (!this._isPointerDown) {
return;
}
this._isPointerDown = false;
this._getActiveRipples().forEach((ripple) => {
const isVisible = ripple.state === RippleState.VISIBLE || ripple.config.terminateOnPointerUp && ripple.state === RippleState.FADING_IN;
if (!ripple.config.persistent && isVisible) {
ripple.fadeOut();
}
});
}
_getActiveRipples() {
return Array.from(this._activeRipples.keys());
}
/** Removes previously registered event listeners from the trigger element. */
_removeTriggerEvents() {
const trigger = this._triggerElement;
if (trigger) {
pointerDownEvents.forEach((type) => _RippleRenderer._eventManager.removeHandler(type, trigger, this));
if (this._pointerUpEventsRegistered) {
pointerUpEvents.forEach((type) => trigger.removeEventListener(type, this, passiveCapturingEventOptions));
this._pointerUpEventsRegistered = false;
}
}
}
};
function distanceToFurthestCorner(x, y, rect) {
const distX = Math.max(Math.abs(x - rect.left), Math.abs(x - rect.right));
const distY = Math.max(Math.abs(y - rect.top), Math.abs(y - rect.bottom));
return Math.sqrt(distX * distX + distY * distY);
}
var MAT_RIPPLE_GLOBAL_OPTIONS = new InjectionToken("mat-ripple-global-options");
var MatRipple = class _MatRipple {
_elementRef = inject(ElementRef);
_animationMode = inject(ANIMATION_MODULE_TYPE, {
optional: true
});
/** Custom color for all ripples. */
color;
/** Whether the ripples should be visible outside the component's bounds. */
unbounded;
/**
* Whether the ripple always originates from the center of the host element's bounds, rather
* than originating from the location of the click event.
*/
centered;
/**
* If set, the radius in pixels of foreground ripples when fully expanded. If unset, the radius
* will be the distance from the center of the ripple to the furthest corner of the host element's
* bounding rectangle.
*/
radius = 0;
/**
* Configuration for the ripple animation. Allows modifying the enter and exit animation
* duration of the ripples. The animation durations will be overwritten if the
* `NoopAnimationsModule` is being used.
*/
animation;
/**
* Whether click events will not trigger the ripple. Ripples can be still launched manually
* by using the `launch()` method.
*/
get disabled() {
return this._disabled;
}
set disabled(value) {
if (value) {
this.fadeOutAllNonPersistent();
}
this._disabled = value;
this._setupTriggerEventsIfEnabled();
}
_disabled = false;
/**
* The element that triggers the ripple when click events are received.
* Defaults to the directive's host element.
*/
get trigger() {
return this._trigger || this._elementRef.nativeElement;
}
set trigger(trigger) {
this._trigger = trigger;
this._setupTriggerEventsIfEnabled();
}
_trigger;
/** Renderer for the ripple DOM manipulations. */
_rippleRenderer;
/** Options that are set globally for all ripples. */
_globalOptions;
/** @docs-private Whether ripple directive is initialized and the input bindings are set. */
_isInitialized = false;
constructor() {
const ngZone = inject(NgZone);
const platform = inject(Platform);
const globalOptions = inject(MAT_RIPPLE_GLOBAL_OPTIONS, {
optional: true
});
const injector = inject(Injector);
this._globalOptions = globalOptions || {};
this._rippleRenderer = new RippleRenderer(this, ngZone, this._elementRef, platform, injector);
}
ngOnInit() {
this._isInitialized = true;
this._setupTriggerEventsIfEnabled();
}
ngOnDestroy() {
this._rippleRenderer._removeTriggerEvents();
}
/** Fades out all currently showing ripple elements. */
fadeOutAll() {
this._rippleRenderer.fadeOutAll();
}
/** Fades out all currently showing non-persistent ripple elements. */
fadeOutAllNonPersistent() {
this._rippleRenderer.fadeOutAllNonPersistent();
}
/**
* Ripple configuration from the directive's input values.
* @docs-private Implemented as part of RippleTarget
*/
get rippleConfig() {
return {
centered: this.centered,
radius: this.radius,
color: this.color,
animation: __spreadValues(__spreadValues(__spreadValues({}, this._globalOptions.animation), this._animationMode === "NoopAnimations" ? {
enterDuration: 0,
exitDuration: 0
} : {}), this.animation),
terminateOnPointerUp: this._globalOptions.terminateOnPointerUp
};
}
/**
* Whether ripples on pointer-down are disabled or not.
* @docs-private Implemented as part of RippleTarget
*/
get rippleDisabled() {
return this.disabled || !!this._globalOptions.disabled;
}
/** Sets up the trigger event listeners if ripples are enabled. */
_setupTriggerEventsIfEnabled() {
if (!this.disabled && this._isInitialized) {
this._rippleRenderer.setupTriggerEvents(this.trigger);
}
}
/** Launches a manual ripple at the specified coordinated or just by the ripple config. */
launch(configOrX, y = 0, config) {
if (typeof configOrX === "number") {
return this._rippleRenderer.fadeInRipple(configOrX, y, __spreadValues(__spreadValues({}, this.rippleConfig), config));
} else {
return this._rippleRenderer.fadeInRipple(0, 0, __spreadValues(__spreadValues({}, this.rippleConfig), configOrX));
}
}
static \u0275fac = function MatRipple_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatRipple)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatRipple,
selectors: [["", "mat-ripple", ""], ["", "matRipple", ""]],
hostAttrs: [1, "mat-ripple"],
hostVars: 2,
hostBindings: function MatRipple_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("mat-ripple-unbounded", ctx.unbounded);
}
},
inputs: {
color: [0, "matRippleColor", "color"],
unbounded: [0, "matRippleUnbounded", "unbounded"],
centered: [0, "matRippleCentered", "centered"],
radius: [0, "matRippleRadius", "radius"],
animation: [0, "matRippleAnimation", "animation"],
disabled: [0, "matRippleDisabled", "disabled"],
trigger: [0, "matRippleTrigger", "trigger"]
},
exportAs: ["matRipple"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatRipple, [{
type: Directive,
args: [{
selector: "[mat-ripple], [matRipple]",
exportAs: "matRipple",
host: {
"class": "mat-ripple",
"[class.mat-ripple-unbounded]": "unbounded"
}
}]
}], () => [], {
color: [{
type: Input,
args: ["matRippleColor"]
}],
unbounded: [{
type: Input,
args: ["matRippleUnbounded"]
}],
centered: [{
type: Input,
args: ["matRippleCentered"]
}],
radius: [{
type: Input,
args: ["matRippleRadius"]
}],
animation: [{
type: Input,
args: ["matRippleAnimation"]
}],
disabled: [{
type: Input,
args: ["matRippleDisabled"]
}],
trigger: [{
type: Input,
args: ["matRippleTrigger"]
}]
});
})();
// node_modules/@angular/material/fesm2022/ripple-loader-Ce3DAhPW.mjs
var eventListenerOptions = {
capture: true
};
var rippleInteractionEvents = ["focus", "mousedown", "mouseenter", "touchstart"];
var matRippleUninitialized = "mat-ripple-loader-uninitialized";
var matRippleClassName = "mat-ripple-loader-class-name";
var matRippleCentered = "mat-ripple-loader-centered";
var matRippleDisabled = "mat-ripple-loader-disabled";
var MatRippleLoader = class _MatRippleLoader {
_document = inject(DOCUMENT);
_animationMode = inject(ANIMATION_MODULE_TYPE, {
optional: true
});
_globalRippleOptions = inject(MAT_RIPPLE_GLOBAL_OPTIONS, {
optional: true
});
_platform = inject(Platform);
_ngZone = inject(NgZone);
_injector = inject(Injector);
_eventCleanups;
_hosts = /* @__PURE__ */ new Map();
constructor() {
const renderer = inject(RendererFactory2).createRenderer(null, null);
this._eventCleanups = this._ngZone.runOutsideAngular(() => {
return rippleInteractionEvents.map((name) => _bindEventWithOptions(renderer, this._document, name, this._onInteraction, eventListenerOptions));
});
}
ngOnDestroy() {
const hosts = this._hosts.keys();
for (const host of hosts) {
this.destroyRipple(host);
}
this._eventCleanups.forEach((cleanup) => cleanup());
}
/**
* Configures the ripple that will be rendered by the ripple loader.
*
* Stores the given information about how the ripple should be configured on the host
* element so that it can later be retrived & used when the ripple is actually created.
*/
configureRipple(host, config) {
host.setAttribute(matRippleUninitialized, this._globalRippleOptions?.namespace ?? "");
if (config.className || !host.hasAttribute(matRippleClassName)) {
host.setAttribute(matRippleClassName, config.className || "");
}
if (config.centered) {
host.setAttribute(matRippleCentered, "");
}
if (config.disabled) {
host.setAttribute(matRippleDisabled, "");
}
}
/** Sets the disabled state on the ripple instance corresponding to the given host element. */
setDisabled(host, disabled) {
const ripple = this._hosts.get(host);
if (ripple) {
ripple.target.rippleDisabled = disabled;
if (!disabled && !ripple.hasSetUpEvents) {
ripple.hasSetUpEvents = true;
ripple.renderer.setupTriggerEvents(host);
}
} else if (disabled) {
host.setAttribute(matRippleDisabled, "");
} else {
host.removeAttribute(matRippleDisabled);
}
}
/**
* Handles creating and attaching component internals
* when a component is initially interacted with.
*/
_onInteraction = (event) => {
const eventTarget = _getEventTarget(event);
if (eventTarget instanceof HTMLElement) {
const element = eventTarget.closest(`[${matRippleUninitialized}="${this._globalRippleOptions?.namespace ?? ""}"]`);
if (element) {
this._createRipple(element);
}
}
};
/** Creates a MatRipple and appends it to the given element. */
_createRipple(host) {
if (!this._document || this._hosts.has(host)) {
return;
}
host.querySelector(".mat-ripple")?.remove();
const rippleEl = this._document.createElement("span");
rippleEl.classList.add("mat-ripple", host.getAttribute(matRippleClassName));
host.append(rippleEl);
const isNoopAnimations = this._animationMode === "NoopAnimations";
const globalOptions = this._globalRippleOptions;
const enterDuration = isNoopAnimations ? 0 : globalOptions?.animation?.enterDuration ?? defaultRippleAnimationConfig.enterDuration;
const exitDuration = isNoopAnimations ? 0 : globalOptions?.animation?.exitDuration ?? defaultRippleAnimationConfig.exitDuration;
const target = {
rippleDisabled: isNoopAnimations || globalOptions?.disabled || host.hasAttribute(matRippleDisabled),
rippleConfig: {
centered: host.hasAttribute(matRippleCentered),
terminateOnPointerUp: globalOptions?.terminateOnPointerUp,
animation: {
enterDuration,
exitDuration
}
}
};
const renderer = new RippleRenderer(target, this._ngZone, rippleEl, this._platform, this._injector);
const hasSetUpEvents = !target.rippleDisabled;
if (hasSetUpEvents) {
renderer.setupTriggerEvents(host);
}
this._hosts.set(host, {
target,
renderer,
hasSetUpEvents
});
host.removeAttribute(matRippleUninitialized);
}
destroyRipple(host) {
const ripple = this._hosts.get(host);
if (ripple) {
ripple.renderer._removeTriggerEvents();
this._hosts.delete(host);
}
}
static \u0275fac = function MatRippleLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatRippleLoader)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _MatRippleLoader,
factory: _MatRippleLoader.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatRippleLoader, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/material/fesm2022/structural-styles-BQUT6wsL.mjs
var _StructuralStylesLoader = class __StructuralStylesLoader {
static \u0275fac = function _StructuralStylesLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __StructuralStylesLoader)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: __StructuralStylesLoader,
selectors: [["structural-styles"]],
decls: 0,
vars: 0,
template: function _StructuralStylesLoader_Template(rf, ctx) {
},
styles: ['.mat-focus-indicator{position:relative}.mat-focus-indicator::before{top:0;left:0;right:0;bottom:0;position:absolute;box-sizing:border-box;pointer-events:none;display:var(--mat-focus-indicator-display, none);border-width:var(--mat-focus-indicator-border-width, 3px);border-style:var(--mat-focus-indicator-border-style, solid);border-color:var(--mat-focus-indicator-border-color, transparent);border-radius:var(--mat-focus-indicator-border-radius, 4px)}.mat-focus-indicator:focus::before{content:""}@media(forced-colors: active){html{--mat-focus-indicator-display: block}}\n'],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_StructuralStylesLoader, [{
type: Component,
args: [{
selector: "structural-styles",
encapsulation: ViewEncapsulation.None,
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
styles: ['.mat-focus-indicator{position:relative}.mat-focus-indicator::before{top:0;left:0;right:0;bottom:0;position:absolute;box-sizing:border-box;pointer-events:none;display:var(--mat-focus-indicator-display, none);border-width:var(--mat-focus-indicator-border-width, 3px);border-style:var(--mat-focus-indicator-border-style, solid);border-color:var(--mat-focus-indicator-border-color, transparent);border-radius:var(--mat-focus-indicator-border-radius, 4px)}.mat-focus-indicator:focus::before{content:""}@media(forced-colors: active){html{--mat-focus-indicator-display: block}}\n']
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/icon-button-D1J0zeqv.mjs
var _c03 = ["mat-icon-button", ""];
var _c12 = ["*"];
var _c2 = '.mat-mdc-icon-button{-webkit-user-select:none;user-select:none;display:inline-block;position:relative;box-sizing:border-box;border:none;outline:none;background-color:rgba(0,0,0,0);fill:currentColor;color:inherit;text-decoration:none;cursor:pointer;z-index:0;overflow:visible;border-radius:50%;flex-shrink:0;text-align:center;width:var(--mdc-icon-button-state-layer-size, 40px);height:var(--mdc-icon-button-state-layer-size, 40px);padding:calc(calc(var(--mdc-icon-button-state-layer-size, 40px) - var(--mdc-icon-button-icon-size, 24px)) / 2);font-size:var(--mdc-icon-button-icon-size, 24px);color:var(--mdc-icon-button-icon-color, var(--mat-sys-on-surface-variant));-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-icon-button .mat-mdc-button-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-icon-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-icon-button .mdc-button__label,.mat-mdc-icon-button .mat-icon{z-index:1;position:relative}.mat-mdc-icon-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-icon-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-icon-button .mat-ripple-element{background-color:var(--mat-icon-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface-variant) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-icon-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-icon-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-icon-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-icon-button-touch-target-display, block)}.mat-mdc-icon-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-icon-button[disabled],.mat-mdc-icon-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-icon-button-disabled-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-icon-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-icon-button img,.mat-mdc-icon-button svg{width:var(--mdc-icon-button-icon-size, 24px);height:var(--mdc-icon-button-icon-size, 24px);vertical-align:baseline}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:50%}.mat-mdc-icon-button[hidden]{display:none}.mat-mdc-icon-button.mat-unthemed:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-primary:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-accent:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-warn:not(.mdc-ripple-upgraded):focus::before{background:rgba(0,0,0,0);opacity:1}\n';
var _c3 = "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n";
var MAT_BUTTON_CONFIG = new InjectionToken("MAT_BUTTON_CONFIG");
var MAT_BUTTON_HOST = {
"[attr.disabled]": "_getDisabledAttribute()",
"[attr.aria-disabled]": "_getAriaDisabled()",
"[class.mat-mdc-button-disabled]": "disabled",
"[class.mat-mdc-button-disabled-interactive]": "disabledInteractive",
"[class._mat-animation-noopable]": '_animationMode === "NoopAnimations"',
// MDC automatically applies the primary theme color to the button, but we want to support
// an unthemed version. If color is undefined, apply a CSS class that makes it easy to
// select and style this "theme".
"[class.mat-unthemed]": "!color",
// Add a class that applies to all buttons. This makes it easier to target if somebody
// wants to target all Material buttons.
"[class.mat-mdc-button-base]": "true",
"[class]": 'color ? "mat-" + color : ""'
};
var HOST_SELECTOR_MDC_CLASS_PAIR = [{
attribute: "mat-button",
mdcClasses: ["mdc-button", "mat-mdc-button"]
}, {
attribute: "mat-flat-button",
mdcClasses: ["mdc-button", "mdc-button--unelevated", "mat-mdc-unelevated-button"]
}, {
attribute: "mat-raised-button",
mdcClasses: ["mdc-button", "mdc-button--raised", "mat-mdc-raised-button"]
}, {
attribute: "mat-stroked-button",
mdcClasses: ["mdc-button", "mdc-button--outlined", "mat-mdc-outlined-button"]
}, {
attribute: "mat-fab",
mdcClasses: ["mdc-fab", "mat-mdc-fab-base", "mat-mdc-fab"]
}, {
attribute: "mat-mini-fab",
mdcClasses: ["mdc-fab", "mat-mdc-fab-base", "mdc-fab--mini", "mat-mdc-mini-fab"]
}, {
attribute: "mat-icon-button",
mdcClasses: ["mdc-icon-button", "mat-mdc-icon-button"]
}];
var MatButtonBase = class _MatButtonBase {
_elementRef = inject(ElementRef);
_ngZone = inject(NgZone);
_animationMode = inject(ANIMATION_MODULE_TYPE, {
optional: true
});
_focusMonitor = inject(FocusMonitor);
/**
* Handles the lazy creation of the MatButton ripple.
* Used to improve initial load time of large applications.
*/
_rippleLoader = inject(MatRippleLoader);
/** Whether this button is a FAB. Used to apply the correct class on the ripple. */
_isFab = false;
/**
* Theme color of the button. This API is supported in M2 themes only, it has
* no effect in M3 themes. For color customization in M3, see https://material.angular.dev/components/button/styling.
*
* For information on applying color variants in M3, see
* https://material.angular.dev/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
*/
color;
/** Whether the ripple effect is disabled or not. */
get disableRipple() {
return this._disableRipple;
}
set disableRipple(value) {
this._disableRipple = value;
this._updateRippleDisabled();
}
_disableRipple = false;
/** Whether the button is disabled. */
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = value;
this._updateRippleDisabled();
}
_disabled = false;
/** `aria-disabled` value of the button. */
ariaDisabled;
/**
* Natively disabled buttons prevent focus and any pointer events from reaching the button.
* In some scenarios this might not be desirable, because it can prevent users from finding out
* why the button is disabled (e.g. via tooltip). This is also useful for buttons that may
* become disabled when activated, which would cause focus to be transferred to the document
* body instead of remaining on the button.
*
* Enabling this input will change the button so that it is styled to be disabled and will be
* marked as `aria-disabled`, but it will allow the button to receive events and focus.
*
* Note that by enabling this, you need to set the `tabindex` yourself if the button isn't
* meant to be tabbable and you have to prevent the button action (e.g. form submissions).
*/
disabledInteractive;
constructor() {
inject(_CdkPrivateStyleLoader).load(_StructuralStylesLoader);
const config = inject(MAT_BUTTON_CONFIG, {
optional: true
});
const element = this._elementRef.nativeElement;
const classList = element.classList;
this.disabledInteractive = config?.disabledInteractive ?? false;
this.color = config?.color ?? null;
this._rippleLoader?.configureRipple(element, {
className: "mat-mdc-button-ripple"
});
for (const {
attribute,
mdcClasses
} of HOST_SELECTOR_MDC_CLASS_PAIR) {
if (element.hasAttribute(attribute)) {
classList.add(...mdcClasses);
}
}
}
ngAfterViewInit() {
this._focusMonitor.monitor(this._elementRef, true);
}
ngOnDestroy() {
this._focusMonitor.stopMonitoring(this._elementRef);
this._rippleLoader?.destroyRipple(this._elementRef.nativeElement);
}
/** Focuses the button. */
focus(origin = "program", options) {
if (origin) {
this._focusMonitor.focusVia(this._elementRef.nativeElement, origin, options);
} else {
this._elementRef.nativeElement.focus(options);
}
}
_getAriaDisabled() {
if (this.ariaDisabled != null) {
return this.ariaDisabled;
}
return this.disabled && this.disabledInteractive ? true : null;
}
_getDisabledAttribute() {
return this.disabledInteractive || !this.disabled ? null : true;
}
_updateRippleDisabled() {
this._rippleLoader?.setDisabled(this._elementRef.nativeElement, this.disableRipple || this.disabled);
}
static \u0275fac = function MatButtonBase_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatButtonBase)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatButtonBase,
inputs: {
color: "color",
disableRipple: [2, "disableRipple", "disableRipple", booleanAttribute],
disabled: [2, "disabled", "disabled", booleanAttribute],
ariaDisabled: [2, "aria-disabled", "ariaDisabled", booleanAttribute],
disabledInteractive: [2, "disabledInteractive", "disabledInteractive", booleanAttribute]
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatButtonBase, [{
type: Directive
}], () => [], {
color: [{
type: Input
}],
disableRipple: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
disabled: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
ariaDisabled: [{
type: Input,
args: [{
transform: booleanAttribute,
alias: "aria-disabled"
}]
}],
disabledInteractive: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}]
});
})();
var MAT_ANCHOR_HOST = {
// Note that this is basically a noop on anchors,
// but it appears that some internal apps depend on it.
"[attr.disabled]": "_getDisabledAttribute()",
"[class.mat-mdc-button-disabled]": "disabled",
"[class.mat-mdc-button-disabled-interactive]": "disabledInteractive",
"[class._mat-animation-noopable]": '_animationMode === "NoopAnimations"',
// Note that we ignore the user-specified tabindex when it's disabled for
// consistency with the `mat-button` applied on native buttons where even
// though they have an index, they're not tabbable.
"[attr.tabindex]": "disabled && !disabledInteractive ? -1 : tabIndex",
"[attr.aria-disabled]": "_getAriaDisabled()",
// MDC automatically applies the primary theme color to the button, but we want to support
// an unthemed version. If color is undefined, apply a CSS class that makes it easy to
// select and style this "theme".
"[class.mat-unthemed]": "!color",
// Add a class that applies to all buttons. This makes it easier to target if somebody
// wants to target all Material buttons.
"[class.mat-mdc-button-base]": "true",
"[class]": 'color ? "mat-" + color : ""'
};
var MatAnchorBase = class _MatAnchorBase extends MatButtonBase {
_renderer = inject(Renderer2);
_cleanupClick;
tabIndex;
ngOnInit() {
this._ngZone.runOutsideAngular(() => {
this._cleanupClick = this._renderer.listen(this._elementRef.nativeElement, "click", this._haltDisabledEvents);
});
}
ngOnDestroy() {
super.ngOnDestroy();
this._cleanupClick?.();
}
_haltDisabledEvents = (event) => {
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
};
_getAriaDisabled() {
if (this.ariaDisabled != null) {
return this.ariaDisabled;
}
return this.disabled || null;
}
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatAnchorBase_BaseFactory;
return function MatAnchorBase_Factory(__ngFactoryType__) {
return (\u0275MatAnchorBase_BaseFactory || (\u0275MatAnchorBase_BaseFactory = \u0275\u0275getInheritedFactory(_MatAnchorBase)))(__ngFactoryType__ || _MatAnchorBase);
};
})();
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatAnchorBase,
inputs: {
tabIndex: [2, "tabIndex", "tabIndex", (value) => {
return value == null ? void 0 : numberAttribute(value);
}]
},
features: [\u0275\u0275InheritDefinitionFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatAnchorBase, [{
type: Directive
}], null, {
tabIndex: [{
type: Input,
args: [{
transform: (value) => {
return value == null ? void 0 : numberAttribute(value);
}
}]
}]
});
})();
var MatIconButton = class _MatIconButton extends MatButtonBase {
constructor() {
super();
this._rippleLoader.configureRipple(this._elementRef.nativeElement, {
centered: true
});
}
static \u0275fac = function MatIconButton_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatIconButton)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatIconButton,
selectors: [["button", "mat-icon-button", ""]],
hostVars: 14,
hostBindings: function MatIconButton_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c03,
ngContentSelectors: _c12,
decls: 4,
vars: 0,
consts: [[1, "mat-mdc-button-persistent-ripple", "mdc-icon-button__ripple"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatIconButton_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef();
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275element(2, "span", 1)(3, "span", 2);
}
},
styles: ['.mat-mdc-icon-button{-webkit-user-select:none;user-select:none;display:inline-block;position:relative;box-sizing:border-box;border:none;outline:none;background-color:rgba(0,0,0,0);fill:currentColor;color:inherit;text-decoration:none;cursor:pointer;z-index:0;overflow:visible;border-radius:50%;flex-shrink:0;text-align:center;width:var(--mdc-icon-button-state-layer-size, 40px);height:var(--mdc-icon-button-state-layer-size, 40px);padding:calc(calc(var(--mdc-icon-button-state-layer-size, 40px) - var(--mdc-icon-button-icon-size, 24px)) / 2);font-size:var(--mdc-icon-button-icon-size, 24px);color:var(--mdc-icon-button-icon-color, var(--mat-sys-on-surface-variant));-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-icon-button .mat-mdc-button-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-icon-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-icon-button .mdc-button__label,.mat-mdc-icon-button .mat-icon{z-index:1;position:relative}.mat-mdc-icon-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-icon-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-icon-button .mat-ripple-element{background-color:var(--mat-icon-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface-variant) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-icon-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-icon-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-icon-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-icon-button-touch-target-display, block)}.mat-mdc-icon-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-icon-button[disabled],.mat-mdc-icon-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-icon-button-disabled-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-icon-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-icon-button img,.mat-mdc-icon-button svg{width:var(--mdc-icon-button-icon-size, 24px);height:var(--mdc-icon-button-icon-size, 24px);vertical-align:baseline}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:50%}.mat-mdc-icon-button[hidden]{display:none}.mat-mdc-icon-button.mat-unthemed:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-primary:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-accent:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-warn:not(.mdc-ripple-upgraded):focus::before{background:rgba(0,0,0,0);opacity:1}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatIconButton, [{
type: Component,
args: [{
selector: `button[mat-icon-button]`,
host: MAT_BUTTON_HOST,
exportAs: "matButton",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"></span>
<ng-content></ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-icon-button{-webkit-user-select:none;user-select:none;display:inline-block;position:relative;box-sizing:border-box;border:none;outline:none;background-color:rgba(0,0,0,0);fill:currentColor;color:inherit;text-decoration:none;cursor:pointer;z-index:0;overflow:visible;border-radius:50%;flex-shrink:0;text-align:center;width:var(--mdc-icon-button-state-layer-size, 40px);height:var(--mdc-icon-button-state-layer-size, 40px);padding:calc(calc(var(--mdc-icon-button-state-layer-size, 40px) - var(--mdc-icon-button-icon-size, 24px)) / 2);font-size:var(--mdc-icon-button-icon-size, 24px);color:var(--mdc-icon-button-icon-color, var(--mat-sys-on-surface-variant));-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-icon-button .mat-mdc-button-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-icon-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-icon-button .mdc-button__label,.mat-mdc-icon-button .mat-icon{z-index:1;position:relative}.mat-mdc-icon-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-icon-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-icon-button .mat-ripple-element{background-color:var(--mat-icon-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface-variant) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-icon-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-icon-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-icon-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-icon-button-touch-target-display, block)}.mat-mdc-icon-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-icon-button[disabled],.mat-mdc-icon-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-icon-button-disabled-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-icon-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-icon-button img,.mat-mdc-icon-button svg{width:var(--mdc-icon-button-icon-size, 24px);height:var(--mdc-icon-button-icon-size, 24px);vertical-align:baseline}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:50%}.mat-mdc-icon-button[hidden]{display:none}.mat-mdc-icon-button.mat-unthemed:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-primary:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-accent:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-warn:not(.mdc-ripple-upgraded):focus::before{background:rgba(0,0,0,0);opacity:1}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"]
}]
}], () => [], null);
})();
var MatIconAnchor = class _MatIconAnchor extends MatAnchorBase {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatIconAnchor_BaseFactory;
return function MatIconAnchor_Factory(__ngFactoryType__) {
return (\u0275MatIconAnchor_BaseFactory || (\u0275MatIconAnchor_BaseFactory = \u0275\u0275getInheritedFactory(_MatIconAnchor)))(__ngFactoryType__ || _MatIconAnchor);
};
})();
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatIconAnchor,
selectors: [["a", "mat-icon-button", ""]],
hostVars: 15,
hostBindings: function MatIconAnchor_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("tabindex", ctx.disabled && !ctx.disabledInteractive ? -1 : ctx.tabIndex)("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton", "matAnchor"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c03,
ngContentSelectors: _c12,
decls: 4,
vars: 0,
consts: [[1, "mat-mdc-button-persistent-ripple", "mdc-icon-button__ripple"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatIconAnchor_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef();
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275element(2, "span", 1)(3, "span", 2);
}
},
styles: [_c2, _c3],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatIconAnchor, [{
type: Component,
args: [{
selector: `a[mat-icon-button]`,
host: MAT_ANCHOR_HOST,
exportAs: "matButton, matAnchor",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"></span>
<ng-content></ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-icon-button{-webkit-user-select:none;user-select:none;display:inline-block;position:relative;box-sizing:border-box;border:none;outline:none;background-color:rgba(0,0,0,0);fill:currentColor;color:inherit;text-decoration:none;cursor:pointer;z-index:0;overflow:visible;border-radius:50%;flex-shrink:0;text-align:center;width:var(--mdc-icon-button-state-layer-size, 40px);height:var(--mdc-icon-button-state-layer-size, 40px);padding:calc(calc(var(--mdc-icon-button-state-layer-size, 40px) - var(--mdc-icon-button-icon-size, 24px)) / 2);font-size:var(--mdc-icon-button-icon-size, 24px);color:var(--mdc-icon-button-icon-color, var(--mat-sys-on-surface-variant));-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-icon-button .mat-mdc-button-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple,.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-icon-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-icon-button .mdc-button__label,.mat-mdc-icon-button .mat-icon{z-index:1;position:relative}.mat-mdc-icon-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-icon-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-icon-button .mat-ripple-element{background-color:var(--mat-icon-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-surface-variant) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-icon-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-icon-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-icon-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-icon-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-icon-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-icon-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-icon-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-icon-button-touch-target-display, block)}.mat-mdc-icon-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-icon-button[disabled],.mat-mdc-icon-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-icon-button-disabled-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-icon-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-icon-button img,.mat-mdc-icon-button svg{width:var(--mdc-icon-button-icon-size, 24px);height:var(--mdc-icon-button-icon-size, 24px);vertical-align:baseline}.mat-mdc-icon-button .mat-mdc-button-persistent-ripple{border-radius:50%}.mat-mdc-icon-button[hidden]{display:none}.mat-mdc-icon-button.mat-unthemed:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-primary:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-accent:not(.mdc-ripple-upgraded):focus::before,.mat-mdc-icon-button.mat-warn:not(.mdc-ripple-upgraded):focus::before{background:rgba(0,0,0,0);opacity:1}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"]
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/index-SYVYjXwK.mjs
var MatRippleModule = class _MatRippleModule {
static \u0275fac = function MatRippleModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatRippleModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatRippleModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatRippleModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, MatRipple],
exports: [MatRipple, MatCommonModule]
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/button.mjs
var _c04 = ["mat-button", ""];
var _c13 = [[["", 8, "material-icons", 3, "iconPositionEnd", ""], ["mat-icon", 3, "iconPositionEnd", ""], ["", "matButtonIcon", "", 3, "iconPositionEnd", ""]], "*", [["", "iconPositionEnd", "", 8, "material-icons"], ["mat-icon", "iconPositionEnd", ""], ["", "matButtonIcon", "", "iconPositionEnd", ""]]];
var _c22 = [".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])", "*", ".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]"];
var _c32 = '.mat-mdc-button-base{text-decoration:none}.mdc-button{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:visible;vertical-align:middle;background:rgba(0,0,0,0);padding:0 8px}.mdc-button::-moz-focus-inner{padding:0;border:0}.mdc-button:active{outline:none}.mdc-button:hover{cursor:pointer}.mdc-button:disabled{cursor:default;pointer-events:none}.mdc-button[hidden]{display:none}.mdc-button .mdc-button__label{position:relative}.mat-mdc-button{padding:0 var(--mat-text-button-horizontal-padding, 12px);height:var(--mdc-text-button-container-height, 40px);font-family:var(--mdc-text-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-text-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-text-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-text-button-label-text-transform);font-weight:var(--mdc-text-button-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-button,.mat-mdc-button .mdc-button__ripple{border-radius:var(--mdc-text-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-button:not(:disabled){color:var(--mdc-text-button-label-text-color, var(--mat-sys-primary))}.mat-mdc-button[disabled],.mat-mdc-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-text-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button:has(.material-icons,mat-icon,[matButtonIcon]){padding:0 var(--mat-text-button-with-icon-horizontal-padding, 16px)}.mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}[dir=rtl] .mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}.mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}.mat-mdc-button .mat-ripple-element{background-color:var(--mat-text-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-text-button-touch-target-display, block)}.mat-mdc-unelevated-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-filled-button-container-height, 40px);font-family:var(--mdc-filled-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-filled-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-filled-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-filled-button-label-text-transform);font-weight:var(--mdc-filled-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-filled-button-horizontal-padding, 24px)}.mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}.mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}.mat-mdc-unelevated-button .mat-ripple-element{background-color:var(--mat-filled-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-state-layer-color, var(--mat-sys-on-primary))}.mat-mdc-unelevated-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-unelevated-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-unelevated-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-unelevated-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-unelevated-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-filled-button-touch-target-display, block)}.mat-mdc-unelevated-button:not(:disabled){color:var(--mdc-filled-button-label-text-color, var(--mat-sys-on-primary));background-color:var(--mdc-filled-button-container-color, var(--mat-sys-primary))}.mat-mdc-unelevated-button,.mat-mdc-unelevated-button .mdc-button__ripple{border-radius:var(--mdc-filled-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-unelevated-button[disabled],.mat-mdc-unelevated-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-filled-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-filled-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-raised-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);box-shadow:var(--mdc-protected-button-container-elevation-shadow, var(--mat-sys-level1));height:var(--mdc-protected-button-container-height, 40px);font-family:var(--mdc-protected-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-protected-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-protected-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-protected-button-label-text-transform);font-weight:var(--mdc-protected-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-protected-button-horizontal-padding, 24px)}.mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}.mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}.mat-mdc-raised-button .mat-ripple-element{background-color:var(--mat-protected-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-raised-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-raised-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-raised-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-raised-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-raised-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-protected-button-touch-target-display, block)}.mat-mdc-raised-button:not(:disabled){color:var(--mdc-protected-button-label-text-color, var(--mat-sys-primary));background-color:var(--mdc-protected-button-container-color, var(--mat-sys-surface))}.mat-mdc-raised-button,.mat-mdc-raised-button .mdc-button__ripple{border-radius:var(--mdc-protected-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-raised-button:hover{box-shadow:var(--mdc-protected-button-hover-container-elevation-shadow, var(--mat-sys-level2))}.mat-mdc-raised-button:focus{box-shadow:var(--mdc-protected-button-focus-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button:active,.mat-mdc-raised-button:focus:active{box-shadow:var(--mdc-protected-button-pressed-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button[disabled],.mat-mdc-raised-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-protected-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-protected-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-raised-button[disabled].mat-mdc-button-disabled,.mat-mdc-raised-button.mat-mdc-button-disabled.mat-mdc-button-disabled{box-shadow:var(--mdc-protected-button-disabled-container-elevation-shadow, var(--mat-sys-level0))}.mat-mdc-raised-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-outlined-button{border-style:solid;transition:border 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-outlined-button-container-height, 40px);font-family:var(--mdc-outlined-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-outlined-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-outlined-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-outlined-button-label-text-transform);font-weight:var(--mdc-outlined-button-label-text-weight, var(--mat-sys-label-large-weight));border-radius:var(--mdc-outlined-button-container-shape, var(--mat-sys-corner-full));border-width:var(--mdc-outlined-button-outline-width, 1px);padding:0 var(--mat-outlined-button-horizontal-padding, 24px)}.mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}.mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}.mat-mdc-outlined-button .mat-ripple-element{background-color:var(--mat-outlined-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-outlined-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-outlined-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-outlined-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-outlined-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-outlined-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-outlined-button-touch-target-display, block)}.mat-mdc-outlined-button:not(:disabled){color:var(--mdc-outlined-button-label-text-color, var(--mat-sys-primary));border-color:var(--mdc-outlined-button-outline-color, var(--mat-sys-outline))}.mat-mdc-outlined-button[disabled],.mat-mdc-outlined-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-outlined-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));border-color:var(--mdc-outlined-button-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button,.mat-mdc-unelevated-button,.mat-mdc-raised-button,.mat-mdc-outlined-button{-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-button .mdc-button__label,.mat-mdc-button .mat-icon,.mat-mdc-unelevated-button .mdc-button__label,.mat-mdc-unelevated-button .mat-icon,.mat-mdc-raised-button .mdc-button__label,.mat-mdc-raised-button .mat-icon,.mat-mdc-outlined-button .mdc-button__label,.mat-mdc-outlined-button .mat-icon{z-index:1;position:relative}.mat-mdc-button .mat-focus-indicator,.mat-mdc-unelevated-button .mat-focus-indicator,.mat-mdc-raised-button .mat-focus-indicator,.mat-mdc-outlined-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-button:focus>.mat-focus-indicator::before,.mat-mdc-unelevated-button:focus>.mat-focus-indicator::before,.mat-mdc-raised-button:focus>.mat-focus-indicator::before,.mat-mdc-outlined-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-button._mat-animation-noopable,.mat-mdc-unelevated-button._mat-animation-noopable,.mat-mdc-raised-button._mat-animation-noopable,.mat-mdc-outlined-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-button>.mat-icon,.mat-mdc-unelevated-button>.mat-icon,.mat-mdc-raised-button>.mat-icon,.mat-mdc-outlined-button>.mat-icon{display:inline-block;position:relative;vertical-align:top;font-size:1.125rem;height:1.125rem;width:1.125rem}.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mdc-button__ripple{top:-1px;left:-1px;bottom:-1px;right:-1px}.mat-mdc-unelevated-button .mat-focus-indicator::before,.mat-mdc-raised-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-outlined-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 3px)*-1)}\n';
var _c4 = "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n";
var _c5 = ["mat-fab", ""];
var _c6 = ["mat-mini-fab", ""];
var _c7 = '.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n';
var MatButton = class _MatButton extends MatButtonBase {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatButton_BaseFactory;
return function MatButton_Factory(__ngFactoryType__) {
return (\u0275MatButton_BaseFactory || (\u0275MatButton_BaseFactory = \u0275\u0275getInheritedFactory(_MatButton)))(__ngFactoryType__ || _MatButton);
};
})();
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatButton,
selectors: [["button", "mat-button", ""], ["button", "mat-raised-button", ""], ["button", "mat-flat-button", ""], ["button", "mat-stroked-button", ""]],
hostVars: 14,
hostBindings: function MatButton_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c04,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatButton_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: ['.mat-mdc-button-base{text-decoration:none}.mdc-button{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:visible;vertical-align:middle;background:rgba(0,0,0,0);padding:0 8px}.mdc-button::-moz-focus-inner{padding:0;border:0}.mdc-button:active{outline:none}.mdc-button:hover{cursor:pointer}.mdc-button:disabled{cursor:default;pointer-events:none}.mdc-button[hidden]{display:none}.mdc-button .mdc-button__label{position:relative}.mat-mdc-button{padding:0 var(--mat-text-button-horizontal-padding, 12px);height:var(--mdc-text-button-container-height, 40px);font-family:var(--mdc-text-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-text-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-text-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-text-button-label-text-transform);font-weight:var(--mdc-text-button-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-button,.mat-mdc-button .mdc-button__ripple{border-radius:var(--mdc-text-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-button:not(:disabled){color:var(--mdc-text-button-label-text-color, var(--mat-sys-primary))}.mat-mdc-button[disabled],.mat-mdc-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-text-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button:has(.material-icons,mat-icon,[matButtonIcon]){padding:0 var(--mat-text-button-with-icon-horizontal-padding, 16px)}.mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}[dir=rtl] .mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}.mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}.mat-mdc-button .mat-ripple-element{background-color:var(--mat-text-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-text-button-touch-target-display, block)}.mat-mdc-unelevated-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-filled-button-container-height, 40px);font-family:var(--mdc-filled-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-filled-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-filled-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-filled-button-label-text-transform);font-weight:var(--mdc-filled-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-filled-button-horizontal-padding, 24px)}.mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}.mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}.mat-mdc-unelevated-button .mat-ripple-element{background-color:var(--mat-filled-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-state-layer-color, var(--mat-sys-on-primary))}.mat-mdc-unelevated-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-unelevated-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-unelevated-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-unelevated-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-unelevated-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-filled-button-touch-target-display, block)}.mat-mdc-unelevated-button:not(:disabled){color:var(--mdc-filled-button-label-text-color, var(--mat-sys-on-primary));background-color:var(--mdc-filled-button-container-color, var(--mat-sys-primary))}.mat-mdc-unelevated-button,.mat-mdc-unelevated-button .mdc-button__ripple{border-radius:var(--mdc-filled-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-unelevated-button[disabled],.mat-mdc-unelevated-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-filled-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-filled-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-raised-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);box-shadow:var(--mdc-protected-button-container-elevation-shadow, var(--mat-sys-level1));height:var(--mdc-protected-button-container-height, 40px);font-family:var(--mdc-protected-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-protected-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-protected-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-protected-button-label-text-transform);font-weight:var(--mdc-protected-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-protected-button-horizontal-padding, 24px)}.mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}.mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}.mat-mdc-raised-button .mat-ripple-element{background-color:var(--mat-protected-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-raised-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-raised-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-raised-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-raised-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-raised-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-protected-button-touch-target-display, block)}.mat-mdc-raised-button:not(:disabled){color:var(--mdc-protected-button-label-text-color, var(--mat-sys-primary));background-color:var(--mdc-protected-button-container-color, var(--mat-sys-surface))}.mat-mdc-raised-button,.mat-mdc-raised-button .mdc-button__ripple{border-radius:var(--mdc-protected-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-raised-button:hover{box-shadow:var(--mdc-protected-button-hover-container-elevation-shadow, var(--mat-sys-level2))}.mat-mdc-raised-button:focus{box-shadow:var(--mdc-protected-button-focus-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button:active,.mat-mdc-raised-button:focus:active{box-shadow:var(--mdc-protected-button-pressed-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button[disabled],.mat-mdc-raised-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-protected-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-protected-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-raised-button[disabled].mat-mdc-button-disabled,.mat-mdc-raised-button.mat-mdc-button-disabled.mat-mdc-button-disabled{box-shadow:var(--mdc-protected-button-disabled-container-elevation-shadow, var(--mat-sys-level0))}.mat-mdc-raised-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-outlined-button{border-style:solid;transition:border 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-outlined-button-container-height, 40px);font-family:var(--mdc-outlined-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-outlined-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-outlined-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-outlined-button-label-text-transform);font-weight:var(--mdc-outlined-button-label-text-weight, var(--mat-sys-label-large-weight));border-radius:var(--mdc-outlined-button-container-shape, var(--mat-sys-corner-full));border-width:var(--mdc-outlined-button-outline-width, 1px);padding:0 var(--mat-outlined-button-horizontal-padding, 24px)}.mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}.mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}.mat-mdc-outlined-button .mat-ripple-element{background-color:var(--mat-outlined-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-outlined-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-outlined-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-outlined-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-outlined-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-outlined-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-outlined-button-touch-target-display, block)}.mat-mdc-outlined-button:not(:disabled){color:var(--mdc-outlined-button-label-text-color, var(--mat-sys-primary));border-color:var(--mdc-outlined-button-outline-color, var(--mat-sys-outline))}.mat-mdc-outlined-button[disabled],.mat-mdc-outlined-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-outlined-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));border-color:var(--mdc-outlined-button-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button,.mat-mdc-unelevated-button,.mat-mdc-raised-button,.mat-mdc-outlined-button{-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-button .mdc-button__label,.mat-mdc-button .mat-icon,.mat-mdc-unelevated-button .mdc-button__label,.mat-mdc-unelevated-button .mat-icon,.mat-mdc-raised-button .mdc-button__label,.mat-mdc-raised-button .mat-icon,.mat-mdc-outlined-button .mdc-button__label,.mat-mdc-outlined-button .mat-icon{z-index:1;position:relative}.mat-mdc-button .mat-focus-indicator,.mat-mdc-unelevated-button .mat-focus-indicator,.mat-mdc-raised-button .mat-focus-indicator,.mat-mdc-outlined-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-button:focus>.mat-focus-indicator::before,.mat-mdc-unelevated-button:focus>.mat-focus-indicator::before,.mat-mdc-raised-button:focus>.mat-focus-indicator::before,.mat-mdc-outlined-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-button._mat-animation-noopable,.mat-mdc-unelevated-button._mat-animation-noopable,.mat-mdc-raised-button._mat-animation-noopable,.mat-mdc-outlined-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-button>.mat-icon,.mat-mdc-unelevated-button>.mat-icon,.mat-mdc-raised-button>.mat-icon,.mat-mdc-outlined-button>.mat-icon{display:inline-block;position:relative;vertical-align:top;font-size:1.125rem;height:1.125rem;width:1.125rem}.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mdc-button__ripple{top:-1px;left:-1px;bottom:-1px;right:-1px}.mat-mdc-unelevated-button .mat-focus-indicator::before,.mat-mdc-raised-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-outlined-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 3px)*-1)}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatButton, [{
type: Component,
args: [{
selector: `
button[mat-button], button[mat-raised-button], button[mat-flat-button],
button[mat-stroked-button]
`,
host: MAT_BUTTON_HOST,
exportAs: "matButton",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-button-base{text-decoration:none}.mdc-button{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:visible;vertical-align:middle;background:rgba(0,0,0,0);padding:0 8px}.mdc-button::-moz-focus-inner{padding:0;border:0}.mdc-button:active{outline:none}.mdc-button:hover{cursor:pointer}.mdc-button:disabled{cursor:default;pointer-events:none}.mdc-button[hidden]{display:none}.mdc-button .mdc-button__label{position:relative}.mat-mdc-button{padding:0 var(--mat-text-button-horizontal-padding, 12px);height:var(--mdc-text-button-container-height, 40px);font-family:var(--mdc-text-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-text-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-text-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-text-button-label-text-transform);font-weight:var(--mdc-text-button-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-button,.mat-mdc-button .mdc-button__ripple{border-radius:var(--mdc-text-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-button:not(:disabled){color:var(--mdc-text-button-label-text-color, var(--mat-sys-primary))}.mat-mdc-button[disabled],.mat-mdc-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-text-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button:has(.material-icons,mat-icon,[matButtonIcon]){padding:0 var(--mat-text-button-with-icon-horizontal-padding, 16px)}.mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}[dir=rtl] .mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}.mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}.mat-mdc-button .mat-ripple-element{background-color:var(--mat-text-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-text-button-touch-target-display, block)}.mat-mdc-unelevated-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-filled-button-container-height, 40px);font-family:var(--mdc-filled-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-filled-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-filled-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-filled-button-label-text-transform);font-weight:var(--mdc-filled-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-filled-button-horizontal-padding, 24px)}.mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}.mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}.mat-mdc-unelevated-button .mat-ripple-element{background-color:var(--mat-filled-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-state-layer-color, var(--mat-sys-on-primary))}.mat-mdc-unelevated-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-unelevated-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-unelevated-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-unelevated-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-unelevated-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-filled-button-touch-target-display, block)}.mat-mdc-unelevated-button:not(:disabled){color:var(--mdc-filled-button-label-text-color, var(--mat-sys-on-primary));background-color:var(--mdc-filled-button-container-color, var(--mat-sys-primary))}.mat-mdc-unelevated-button,.mat-mdc-unelevated-button .mdc-button__ripple{border-radius:var(--mdc-filled-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-unelevated-button[disabled],.mat-mdc-unelevated-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-filled-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-filled-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-raised-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);box-shadow:var(--mdc-protected-button-container-elevation-shadow, var(--mat-sys-level1));height:var(--mdc-protected-button-container-height, 40px);font-family:var(--mdc-protected-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-protected-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-protected-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-protected-button-label-text-transform);font-weight:var(--mdc-protected-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-protected-button-horizontal-padding, 24px)}.mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}.mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}.mat-mdc-raised-button .mat-ripple-element{background-color:var(--mat-protected-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-raised-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-raised-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-raised-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-raised-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-raised-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-protected-button-touch-target-display, block)}.mat-mdc-raised-button:not(:disabled){color:var(--mdc-protected-button-label-text-color, var(--mat-sys-primary));background-color:var(--mdc-protected-button-container-color, var(--mat-sys-surface))}.mat-mdc-raised-button,.mat-mdc-raised-button .mdc-button__ripple{border-radius:var(--mdc-protected-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-raised-button:hover{box-shadow:var(--mdc-protected-button-hover-container-elevation-shadow, var(--mat-sys-level2))}.mat-mdc-raised-button:focus{box-shadow:var(--mdc-protected-button-focus-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button:active,.mat-mdc-raised-button:focus:active{box-shadow:var(--mdc-protected-button-pressed-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button[disabled],.mat-mdc-raised-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-protected-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-protected-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-raised-button[disabled].mat-mdc-button-disabled,.mat-mdc-raised-button.mat-mdc-button-disabled.mat-mdc-button-disabled{box-shadow:var(--mdc-protected-button-disabled-container-elevation-shadow, var(--mat-sys-level0))}.mat-mdc-raised-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-outlined-button{border-style:solid;transition:border 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-outlined-button-container-height, 40px);font-family:var(--mdc-outlined-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-outlined-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-outlined-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-outlined-button-label-text-transform);font-weight:var(--mdc-outlined-button-label-text-weight, var(--mat-sys-label-large-weight));border-radius:var(--mdc-outlined-button-container-shape, var(--mat-sys-corner-full));border-width:var(--mdc-outlined-button-outline-width, 1px);padding:0 var(--mat-outlined-button-horizontal-padding, 24px)}.mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}.mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}.mat-mdc-outlined-button .mat-ripple-element{background-color:var(--mat-outlined-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-outlined-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-outlined-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-outlined-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-outlined-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-outlined-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-outlined-button-touch-target-display, block)}.mat-mdc-outlined-button:not(:disabled){color:var(--mdc-outlined-button-label-text-color, var(--mat-sys-primary));border-color:var(--mdc-outlined-button-outline-color, var(--mat-sys-outline))}.mat-mdc-outlined-button[disabled],.mat-mdc-outlined-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-outlined-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));border-color:var(--mdc-outlined-button-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button,.mat-mdc-unelevated-button,.mat-mdc-raised-button,.mat-mdc-outlined-button{-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-button .mdc-button__label,.mat-mdc-button .mat-icon,.mat-mdc-unelevated-button .mdc-button__label,.mat-mdc-unelevated-button .mat-icon,.mat-mdc-raised-button .mdc-button__label,.mat-mdc-raised-button .mat-icon,.mat-mdc-outlined-button .mdc-button__label,.mat-mdc-outlined-button .mat-icon{z-index:1;position:relative}.mat-mdc-button .mat-focus-indicator,.mat-mdc-unelevated-button .mat-focus-indicator,.mat-mdc-raised-button .mat-focus-indicator,.mat-mdc-outlined-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-button:focus>.mat-focus-indicator::before,.mat-mdc-unelevated-button:focus>.mat-focus-indicator::before,.mat-mdc-raised-button:focus>.mat-focus-indicator::before,.mat-mdc-outlined-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-button._mat-animation-noopable,.mat-mdc-unelevated-button._mat-animation-noopable,.mat-mdc-raised-button._mat-animation-noopable,.mat-mdc-outlined-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-button>.mat-icon,.mat-mdc-unelevated-button>.mat-icon,.mat-mdc-raised-button>.mat-icon,.mat-mdc-outlined-button>.mat-icon{display:inline-block;position:relative;vertical-align:top;font-size:1.125rem;height:1.125rem;width:1.125rem}.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mdc-button__ripple{top:-1px;left:-1px;bottom:-1px;right:-1px}.mat-mdc-unelevated-button .mat-focus-indicator::before,.mat-mdc-raised-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-outlined-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 3px)*-1)}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"]
}]
}], null, null);
})();
var MatAnchor = class _MatAnchor extends MatAnchorBase {
static \u0275fac = /* @__PURE__ */ (() => {
let \u0275MatAnchor_BaseFactory;
return function MatAnchor_Factory(__ngFactoryType__) {
return (\u0275MatAnchor_BaseFactory || (\u0275MatAnchor_BaseFactory = \u0275\u0275getInheritedFactory(_MatAnchor)))(__ngFactoryType__ || _MatAnchor);
};
})();
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatAnchor,
selectors: [["a", "mat-button", ""], ["a", "mat-raised-button", ""], ["a", "mat-flat-button", ""], ["a", "mat-stroked-button", ""]],
hostVars: 15,
hostBindings: function MatAnchor_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("tabindex", ctx.disabled && !ctx.disabledInteractive ? -1 : ctx.tabIndex)("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton", "matAnchor"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c04,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatAnchor_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: [_c32, _c4],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatAnchor, [{
type: Component,
args: [{
selector: `a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]`,
exportAs: "matButton, matAnchor",
host: MAT_ANCHOR_HOST,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-button-base{text-decoration:none}.mdc-button{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;border:none;outline:none;line-height:inherit;-webkit-appearance:none;overflow:visible;vertical-align:middle;background:rgba(0,0,0,0);padding:0 8px}.mdc-button::-moz-focus-inner{padding:0;border:0}.mdc-button:active{outline:none}.mdc-button:hover{cursor:pointer}.mdc-button:disabled{cursor:default;pointer-events:none}.mdc-button[hidden]{display:none}.mdc-button .mdc-button__label{position:relative}.mat-mdc-button{padding:0 var(--mat-text-button-horizontal-padding, 12px);height:var(--mdc-text-button-container-height, 40px);font-family:var(--mdc-text-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-text-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-text-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-text-button-label-text-transform);font-weight:var(--mdc-text-button-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-button,.mat-mdc-button .mdc-button__ripple{border-radius:var(--mdc-text-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-button:not(:disabled){color:var(--mdc-text-button-label-text-color, var(--mat-sys-primary))}.mat-mdc-button[disabled],.mat-mdc-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-text-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button:has(.material-icons,mat-icon,[matButtonIcon]){padding:0 var(--mat-text-button-with-icon-horizontal-padding, 16px)}.mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}[dir=rtl] .mat-mdc-button>.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}.mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-offset, -4px);margin-left:var(--mat-text-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-button .mdc-button__label+.mat-icon{margin-right:var(--mat-text-button-icon-spacing, 8px);margin-left:var(--mat-text-button-icon-offset, -4px)}.mat-mdc-button .mat-ripple-element{background-color:var(--mat-text-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-text-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-text-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-text-button-touch-target-display, block)}.mat-mdc-unelevated-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-filled-button-container-height, 40px);font-family:var(--mdc-filled-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-filled-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-filled-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-filled-button-label-text-transform);font-weight:var(--mdc-filled-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-filled-button-horizontal-padding, 24px)}.mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-unelevated-button>.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}.mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-offset, -8px);margin-left:var(--mat-filled-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-unelevated-button .mdc-button__label+.mat-icon{margin-right:var(--mat-filled-button-icon-spacing, 8px);margin-left:var(--mat-filled-button-icon-offset, -8px)}.mat-mdc-unelevated-button .mat-ripple-element{background-color:var(--mat-filled-button-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-state-layer-color, var(--mat-sys-on-primary))}.mat-mdc-unelevated-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-filled-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-unelevated-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-unelevated-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-unelevated-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-filled-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-unelevated-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-filled-button-touch-target-display, block)}.mat-mdc-unelevated-button:not(:disabled){color:var(--mdc-filled-button-label-text-color, var(--mat-sys-on-primary));background-color:var(--mdc-filled-button-container-color, var(--mat-sys-primary))}.mat-mdc-unelevated-button,.mat-mdc-unelevated-button .mdc-button__ripple{border-radius:var(--mdc-filled-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-unelevated-button[disabled],.mat-mdc-unelevated-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-filled-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-filled-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-unelevated-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-raised-button{transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);box-shadow:var(--mdc-protected-button-container-elevation-shadow, var(--mat-sys-level1));height:var(--mdc-protected-button-container-height, 40px);font-family:var(--mdc-protected-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-protected-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-protected-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-protected-button-label-text-transform);font-weight:var(--mdc-protected-button-label-text-weight, var(--mat-sys-label-large-weight));padding:0 var(--mat-protected-button-horizontal-padding, 24px)}.mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-raised-button>.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}.mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-offset, -8px);margin-left:var(--mat-protected-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-raised-button .mdc-button__label+.mat-icon{margin-right:var(--mat-protected-button-icon-spacing, 8px);margin-left:var(--mat-protected-button-icon-offset, -8px)}.mat-mdc-raised-button .mat-ripple-element{background-color:var(--mat-protected-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-raised-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-protected-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-raised-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-raised-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-raised-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-protected-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-raised-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-protected-button-touch-target-display, block)}.mat-mdc-raised-button:not(:disabled){color:var(--mdc-protected-button-label-text-color, var(--mat-sys-primary));background-color:var(--mdc-protected-button-container-color, var(--mat-sys-surface))}.mat-mdc-raised-button,.mat-mdc-raised-button .mdc-button__ripple{border-radius:var(--mdc-protected-button-container-shape, var(--mat-sys-corner-full))}.mat-mdc-raised-button:hover{box-shadow:var(--mdc-protected-button-hover-container-elevation-shadow, var(--mat-sys-level2))}.mat-mdc-raised-button:focus{box-shadow:var(--mdc-protected-button-focus-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button:active,.mat-mdc-raised-button:focus:active{box-shadow:var(--mdc-protected-button-pressed-container-elevation-shadow, var(--mat-sys-level1))}.mat-mdc-raised-button[disabled],.mat-mdc-raised-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-protected-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mdc-protected-button-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-raised-button[disabled].mat-mdc-button-disabled,.mat-mdc-raised-button.mat-mdc-button-disabled.mat-mdc-button-disabled{box-shadow:var(--mdc-protected-button-disabled-container-elevation-shadow, var(--mat-sys-level0))}.mat-mdc-raised-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-outlined-button{border-style:solid;transition:border 280ms cubic-bezier(0.4, 0, 0.2, 1);height:var(--mdc-outlined-button-container-height, 40px);font-family:var(--mdc-outlined-button-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-outlined-button-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mdc-outlined-button-label-text-tracking, var(--mat-sys-label-large-tracking));text-transform:var(--mdc-outlined-button-label-text-transform);font-weight:var(--mdc-outlined-button-label-text-weight, var(--mat-sys-label-large-weight));border-radius:var(--mdc-outlined-button-container-shape, var(--mat-sys-corner-full));border-width:var(--mdc-outlined-button-outline-width, 1px);padding:0 var(--mat-outlined-button-horizontal-padding, 24px)}.mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}[dir=rtl] .mat-mdc-outlined-button>.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}.mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-offset, -8px);margin-left:var(--mat-outlined-button-icon-spacing, 8px)}[dir=rtl] .mat-mdc-outlined-button .mdc-button__label+.mat-icon{margin-right:var(--mat-outlined-button-icon-spacing, 8px);margin-left:var(--mat-outlined-button-icon-offset, -8px)}.mat-mdc-outlined-button .mat-ripple-element{background-color:var(--mat-outlined-button-ripple-color, color-mix(in srgb, var(--mat-sys-primary) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-state-layer-color, var(--mat-sys-primary))}.mat-mdc-outlined-button.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-outlined-button-disabled-state-layer-color, var(--mat-sys-on-surface-variant))}.mat-mdc-outlined-button:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-outlined-button.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-outlined-button:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-outlined-button-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-outlined-button .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:0;right:0;transform:translateY(-50%);display:var(--mat-outlined-button-touch-target-display, block)}.mat-mdc-outlined-button:not(:disabled){color:var(--mdc-outlined-button-label-text-color, var(--mat-sys-primary));border-color:var(--mdc-outlined-button-outline-color, var(--mat-sys-outline))}.mat-mdc-outlined-button[disabled],.mat-mdc-outlined-button.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mdc-outlined-button-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));border-color:var(--mdc-outlined-button-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-outlined-button.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-button,.mat-mdc-unelevated-button,.mat-mdc-raised-button,.mat-mdc-outlined-button{-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple,.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-button .mat-mdc-button-ripple,.mat-mdc-unelevated-button .mat-mdc-button-ripple,.mat-mdc-raised-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-unelevated-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-raised-button .mat-mdc-button-persistent-ripple::before,.mat-mdc-outlined-button .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-button .mdc-button__label,.mat-mdc-button .mat-icon,.mat-mdc-unelevated-button .mdc-button__label,.mat-mdc-unelevated-button .mat-icon,.mat-mdc-raised-button .mdc-button__label,.mat-mdc-raised-button .mat-icon,.mat-mdc-outlined-button .mdc-button__label,.mat-mdc-outlined-button .mat-icon{z-index:1;position:relative}.mat-mdc-button .mat-focus-indicator,.mat-mdc-unelevated-button .mat-focus-indicator,.mat-mdc-raised-button .mat-focus-indicator,.mat-mdc-outlined-button .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute;border-radius:inherit}.mat-mdc-button:focus>.mat-focus-indicator::before,.mat-mdc-unelevated-button:focus>.mat-focus-indicator::before,.mat-mdc-raised-button:focus>.mat-focus-indicator::before,.mat-mdc-outlined-button:focus>.mat-focus-indicator::before{content:"";border-radius:inherit}.mat-mdc-button._mat-animation-noopable,.mat-mdc-unelevated-button._mat-animation-noopable,.mat-mdc-raised-button._mat-animation-noopable,.mat-mdc-outlined-button._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-button>.mat-icon,.mat-mdc-unelevated-button>.mat-icon,.mat-mdc-raised-button>.mat-icon,.mat-mdc-outlined-button>.mat-icon{display:inline-block;position:relative;vertical-align:top;font-size:1.125rem;height:1.125rem;width:1.125rem}.mat-mdc-outlined-button .mat-mdc-button-ripple,.mat-mdc-outlined-button .mdc-button__ripple{top:-1px;left:-1px;bottom:-1px;right:-1px}.mat-mdc-unelevated-button .mat-focus-indicator::before,.mat-mdc-raised-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-outlined-button .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 3px)*-1)}\n', "@media(forced-colors: active){.mat-mdc-button:not(.mdc-button--outlined),.mat-mdc-unelevated-button:not(.mdc-button--outlined),.mat-mdc-raised-button:not(.mdc-button--outlined),.mat-mdc-outlined-button:not(.mdc-button--outlined),.mat-mdc-icon-button.mat-mdc-icon-button,.mat-mdc-outlined-button .mdc-button__ripple{outline:solid 1px}}\n"]
}]
}], null, null);
})();
var MAT_FAB_DEFAULT_OPTIONS = new InjectionToken("mat-mdc-fab-default-options", {
providedIn: "root",
factory: MAT_FAB_DEFAULT_OPTIONS_FACTORY
});
function MAT_FAB_DEFAULT_OPTIONS_FACTORY() {
return {
// The FAB by default has its color set to accent.
color: "accent"
};
}
var defaults = MAT_FAB_DEFAULT_OPTIONS_FACTORY();
var MatFabButton = class _MatFabButton extends MatButtonBase {
_options = inject(MAT_FAB_DEFAULT_OPTIONS, {
optional: true
});
_isFab = true;
extended;
constructor() {
super();
this._options = this._options || defaults;
this.color = this._options.color || defaults.color;
}
static \u0275fac = function MatFabButton_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFabButton)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatFabButton,
selectors: [["button", "mat-fab", ""]],
hostVars: 18,
hostBindings: function MatFabButton_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true)("mdc-fab--extended", ctx.extended)("mat-mdc-extended-fab", ctx.extended);
}
},
inputs: {
extended: [2, "extended", "extended", booleanAttribute]
},
exportAs: ["matButton"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c5,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatFabButton_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: ['.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n'],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFabButton, [{
type: Component,
args: [{
selector: `button[mat-fab]`,
host: __spreadProps(__spreadValues({}, MAT_BUTTON_HOST), {
"[class.mdc-fab--extended]": "extended",
"[class.mat-mdc-extended-fab]": "extended"
}),
exportAs: "matButton",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n']
}]
}], () => [], {
extended: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}]
});
})();
var MatMiniFabButton = class _MatMiniFabButton extends MatButtonBase {
_options = inject(MAT_FAB_DEFAULT_OPTIONS, {
optional: true
});
_isFab = true;
constructor() {
super();
this._options = this._options || defaults;
this.color = this._options.color || defaults.color;
}
static \u0275fac = function MatMiniFabButton_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatMiniFabButton)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatMiniFabButton,
selectors: [["button", "mat-mini-fab", ""]],
hostVars: 14,
hostBindings: function MatMiniFabButton_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c6,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatMiniFabButton_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: [_c7],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatMiniFabButton, [{
type: Component,
args: [{
selector: `button[mat-mini-fab]`,
host: MAT_BUTTON_HOST,
exportAs: "matButton",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n']
}]
}], () => [], null);
})();
var MatFabAnchor = class _MatFabAnchor extends MatAnchor {
_options = inject(MAT_FAB_DEFAULT_OPTIONS, {
optional: true
});
_isFab = true;
extended;
constructor() {
super();
this._options = this._options || defaults;
this.color = this._options.color || defaults.color;
}
static \u0275fac = function MatFabAnchor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFabAnchor)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatFabAnchor,
selectors: [["a", "mat-fab", ""]],
hostVars: 19,
hostBindings: function MatFabAnchor_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("tabindex", ctx.disabled && !ctx.disabledInteractive ? -1 : ctx.tabIndex)("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true)("mdc-fab--extended", ctx.extended)("mat-mdc-extended-fab", ctx.extended);
}
},
inputs: {
extended: [2, "extended", "extended", booleanAttribute]
},
exportAs: ["matButton", "matAnchor"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c5,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatFabAnchor_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: [_c7],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFabAnchor, [{
type: Component,
args: [{
selector: `a[mat-fab]`,
host: __spreadProps(__spreadValues({}, MAT_ANCHOR_HOST), {
"[class.mdc-fab--extended]": "extended",
"[class.mat-mdc-extended-fab]": "extended"
}),
exportAs: "matButton, matAnchor",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n']
}]
}], () => [], {
extended: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}]
});
})();
var MatMiniFabAnchor = class _MatMiniFabAnchor extends MatAnchor {
_options = inject(MAT_FAB_DEFAULT_OPTIONS, {
optional: true
});
_isFab = true;
constructor() {
super();
this._options = this._options || defaults;
this.color = this._options.color || defaults.color;
}
static \u0275fac = function MatMiniFabAnchor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatMiniFabAnchor)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatMiniFabAnchor,
selectors: [["a", "mat-mini-fab", ""]],
hostVars: 15,
hostBindings: function MatMiniFabAnchor_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("disabled", ctx._getDisabledAttribute())("tabindex", ctx.disabled && !ctx.disabledInteractive ? -1 : ctx.tabIndex)("aria-disabled", ctx._getAriaDisabled());
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-mdc-button-disabled", ctx.disabled)("mat-mdc-button-disabled-interactive", ctx.disabledInteractive)("_mat-animation-noopable", ctx._animationMode === "NoopAnimations")("mat-unthemed", !ctx.color)("mat-mdc-button-base", true);
}
},
exportAs: ["matButton", "matAnchor"],
features: [\u0275\u0275InheritDefinitionFeature],
attrs: _c6,
ngContentSelectors: _c22,
decls: 7,
vars: 4,
consts: [[1, "mat-mdc-button-persistent-ripple"], [1, "mdc-button__label"], [1, "mat-focus-indicator"], [1, "mat-mdc-button-touch-target"]],
template: function MatMiniFabAnchor_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c13);
\u0275\u0275element(0, "span", 0);
\u0275\u0275projection(1);
\u0275\u0275elementStart(2, "span", 1);
\u0275\u0275projection(3, 1);
\u0275\u0275elementEnd();
\u0275\u0275projection(4, 2);
\u0275\u0275element(5, "span", 2)(6, "span", 3);
}
if (rf & 2) {
\u0275\u0275classProp("mdc-button__ripple", !ctx._isFab)("mdc-fab__ripple", ctx._isFab);
}
},
styles: [_c7],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatMiniFabAnchor, [{
type: Component,
args: [{
selector: `a[mat-mini-fab]`,
host: MAT_ANCHOR_HOST,
exportAs: "matButton, matAnchor",
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span
class="mat-mdc-button-persistent-ripple"
[class.mdc-button__ripple]="!_isFab"
[class.mdc-fab__ripple]="_isFab"></span>
<ng-content select=".material-icons:not([iconPositionEnd]), mat-icon:not([iconPositionEnd]), [matButtonIcon]:not([iconPositionEnd])">
</ng-content>
<span class="mdc-button__label"><ng-content></ng-content></span>
<ng-content select=".material-icons[iconPositionEnd], mat-icon[iconPositionEnd], [matButtonIcon][iconPositionEnd]">
</ng-content>
<!--
The indicator can't be directly on the button, because MDC uses ::before for high contrast
indication and it can't be on the ripple, because it has a border radius and overflow: hidden.
-->
<span class="mat-focus-indicator"></span>
<span class="mat-mdc-button-touch-target"></span>
`,
styles: ['.mat-mdc-fab-base{-webkit-user-select:none;user-select:none;position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:56px;height:56px;padding:0;border:none;fill:currentColor;text-decoration:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;overflow:visible;transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1),opacity 15ms linear 30ms,transform 270ms 0ms cubic-bezier(0, 0, 0.2, 1);flex-shrink:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-fab-base .mat-mdc-button-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple,.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none;border-radius:inherit}.mat-mdc-fab-base .mat-mdc-button-ripple{overflow:hidden}.mat-mdc-fab-base .mat-mdc-button-persistent-ripple::before{content:"";opacity:0}.mat-mdc-fab-base .mdc-button__label,.mat-mdc-fab-base .mat-icon{z-index:1;position:relative}.mat-mdc-fab-base .mat-focus-indicator{top:0;left:0;right:0;bottom:0;position:absolute}.mat-mdc-fab-base:focus>.mat-focus-indicator::before{content:""}.mat-mdc-fab-base._mat-animation-noopable{transition:none !important;animation:none !important}.mat-mdc-fab-base::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:"";pointer-events:none}.mat-mdc-fab-base[hidden]{display:none}.mat-mdc-fab-base::-moz-focus-inner{padding:0;border:0}.mat-mdc-fab-base:active,.mat-mdc-fab-base:focus{outline:none}.mat-mdc-fab-base:hover{cursor:pointer}.mat-mdc-fab-base>svg{width:100%}.mat-mdc-fab-base .mat-icon,.mat-mdc-fab-base .material-icons{transition:transform 180ms 90ms cubic-bezier(0, 0, 0.2, 1);fill:currentColor;will-change:transform}.mat-mdc-fab-base .mat-focus-indicator::before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px)*-1)}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-fab-base[disabled],.mat-mdc-fab-base[disabled]:focus,.mat-mdc-fab-base.mat-mdc-button-disabled,.mat-mdc-fab-base.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-fab-base.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab{background-color:var(--mdc-fab-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-container-shape, var(--mat-sys-corner-large));color:var(--mat-fab-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:hover{box-shadow:var(--mdc-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-fab:focus{box-shadow:var(--mdc-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab:active,.mat-mdc-fab:focus:active{box-shadow:var(--mdc-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-fab[disabled],.mat-mdc-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-touch-target-display, block)}.mat-mdc-fab .mat-ripple-element{background-color:var(--mat-fab-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-disabled-state-layer-color)}.mat-mdc-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-mini-fab{width:40px;height:40px;background-color:var(--mdc-fab-small-container-color, var(--mat-sys-primary-container));border-radius:var(--mdc-fab-small-container-shape, var(--mat-sys-corner-medium));color:var(--mat-fab-small-foreground-color, var(--mat-sys-on-primary-container, inherit));box-shadow:var(--mdc-fab-small-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:hover{box-shadow:var(--mdc-fab-small-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-mini-fab:focus{box-shadow:var(--mdc-fab-small-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab:active,.mat-mdc-mini-fab:focus:active{box-shadow:var(--mdc-fab-small-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-mini-fab[disabled],.mat-mdc-mini-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none;color:var(--mat-fab-small-disabled-state-foreground-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent));background-color:var(--mat-fab-small-disabled-state-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}.mat-mdc-mini-fab .mat-mdc-button-touch-target{position:absolute;top:50%;height:48px;left:50%;width:48px;transform:translate(-50%, -50%);display:var(--mat-fab-small-touch-target-display)}.mat-mdc-mini-fab .mat-ripple-element{background-color:var(--mat-fab-small-ripple-color, color-mix(in srgb, var(--mat-sys-on-primary-container) calc(var(--mat-sys-pressed-state-layer-opacity) * 100%), transparent))}.mat-mdc-mini-fab .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-state-layer-color, var(--mat-sys-on-primary-container))}.mat-mdc-mini-fab.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before{background-color:var(--mat-fab-small-disabled-state-layer-color)}.mat-mdc-mini-fab:hover>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-mini-fab.cdk-program-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.cdk-keyboard-focused>.mat-mdc-button-persistent-ripple::before,.mat-mdc-mini-fab.mat-mdc-button-disabled-interactive:focus>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-focus-state-layer-opacity, var(--mat-sys-focus-state-layer-opacity))}.mat-mdc-mini-fab:active>.mat-mdc-button-persistent-ripple::before{opacity:var(--mat-fab-small-pressed-state-layer-opacity, var(--mat-sys-pressed-state-layer-opacity))}.mat-mdc-extended-fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;border-radius:24px;padding-left:20px;padding-right:20px;width:auto;max-width:100%;line-height:normal;height:var(--mdc-extended-fab-container-height, 56px);border-radius:var(--mdc-extended-fab-container-shape, var(--mat-sys-corner-large));font-family:var(--mdc-extended-fab-label-text-font, var(--mat-sys-label-large-font));font-size:var(--mdc-extended-fab-label-text-size, var(--mat-sys-label-large-size));font-weight:var(--mdc-extended-fab-label-text-weight, var(--mat-sys-label-large-weight));letter-spacing:var(--mdc-extended-fab-label-text-tracking, var(--mat-sys-label-large-tracking));box-shadow:var(--mdc-extended-fab-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:hover{box-shadow:var(--mdc-extended-fab-hover-container-elevation-shadow, var(--mat-sys-level4))}.mat-mdc-extended-fab:focus{box-shadow:var(--mdc-extended-fab-focus-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab:active,.mat-mdc-extended-fab:focus:active{box-shadow:var(--mdc-extended-fab-pressed-container-elevation-shadow, var(--mat-sys-level3))}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab.mat-mdc-button-disabled{cursor:default;pointer-events:none}.mat-mdc-extended-fab[disabled],.mat-mdc-extended-fab[disabled]:focus,.mat-mdc-extended-fab.mat-mdc-button-disabled,.mat-mdc-extended-fab.mat-mdc-button-disabled:focus{box-shadow:none}.mat-mdc-extended-fab.mat-mdc-button-disabled-interactive{pointer-events:auto}[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.mat-icon,[dir=rtl] .mat-mdc-extended-fab .mdc-button__label+.material-icons,.mat-mdc-extended-fab>.mat-icon,.mat-mdc-extended-fab>.material-icons{margin-left:-8px;margin-right:12px}.mat-mdc-extended-fab .mdc-button__label+.mat-icon,.mat-mdc-extended-fab .mdc-button__label+.material-icons,[dir=rtl] .mat-mdc-extended-fab>.mat-icon,[dir=rtl] .mat-mdc-extended-fab>.material-icons{margin-left:12px;margin-right:-8px}.mat-mdc-extended-fab .mat-mdc-button-touch-target{width:100%}\n']
}]
}], () => [], null);
})();
var MatButtonModule = class _MatButtonModule {
static \u0275fac = function MatButtonModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatButtonModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatButtonModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, MatRippleModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatButtonModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, MatRippleModule, MatAnchor, MatButton, MatIconAnchor, MatMiniFabAnchor, MatMiniFabButton, MatIconButton, MatFabAnchor, MatFabButton],
exports: [MatAnchor, MatButton, MatIconAnchor, MatIconButton, MatMiniFabAnchor, MatMiniFabButton, MatFabAnchor, MatFabButton, MatCommonModule]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/observers/private.mjs
var loopLimitExceededErrorHandler = (e) => {
if (e instanceof ErrorEvent && e.message === "ResizeObserver loop limit exceeded") {
console.error(`${e.message}. This could indicate a performance issue with your app. See https://github.com/WICG/resize-observer/blob/master/explainer.md#error-handling`);
}
};
var SingleBoxSharedResizeObserver = class {
_box;
/** Stream that emits when the shared observer is destroyed. */
_destroyed = new Subject();
/** Stream of all events from the ResizeObserver. */
_resizeSubject = new Subject();
/** ResizeObserver used to observe element resize events. */
_resizeObserver;
/** A map of elements to streams of their resize events. */
_elementObservables = /* @__PURE__ */ new Map();
constructor(_box) {
this._box = _box;
if (typeof ResizeObserver !== "undefined") {
this._resizeObserver = new ResizeObserver((entries) => this._resizeSubject.next(entries));
}
}
/**
* Gets a stream of resize events for the given element.
* @param target The element to observe.
* @return The stream of resize events for the element.
*/
observe(target) {
if (!this._elementObservables.has(target)) {
this._elementObservables.set(target, new Observable((observer) => {
const subscription = this._resizeSubject.subscribe(observer);
this._resizeObserver?.observe(target, {
box: this._box
});
return () => {
this._resizeObserver?.unobserve(target);
subscription.unsubscribe();
this._elementObservables.delete(target);
};
}).pipe(
filter((entries) => entries.some((entry) => entry.target === target)),
// Share a replay of the last event so that subsequent calls to observe the same element
// receive initial sizing info like the first one. Also enable ref counting so the
// element will be automatically unobserved when there are no more subscriptions.
shareReplay({
bufferSize: 1,
refCount: true
}),
takeUntil(this._destroyed)
));
}
return this._elementObservables.get(target);
}
/** Destroys this instance. */
destroy() {
this._destroyed.next();
this._destroyed.complete();
this._resizeSubject.complete();
this._elementObservables.clear();
}
};
var SharedResizeObserver = class _SharedResizeObserver {
_cleanupErrorListener;
/** Map of box type to shared resize observer. */
_observers = /* @__PURE__ */ new Map();
/** The Angular zone. */
_ngZone = inject(NgZone);
constructor() {
if (typeof ResizeObserver !== "undefined" && (typeof ngDevMode === "undefined" || ngDevMode)) {
this._ngZone.runOutsideAngular(() => {
const renderer = inject(RendererFactory2).createRenderer(null, null);
this._cleanupErrorListener = renderer.listen("window", "error", loopLimitExceededErrorHandler);
});
}
}
ngOnDestroy() {
for (const [, observer] of this._observers) {
observer.destroy();
}
this._observers.clear();
this._cleanupErrorListener?.();
}
/**
* Gets a stream of resize events for the given target element and box type.
* @param target The element to observe for resizes.
* @param options Options to pass to the `ResizeObserver`
* @return The stream of resize events for the element.
*/
observe(target, options) {
const box = options?.box || "content-box";
if (!this._observers.has(box)) {
this._observers.set(box, new SingleBoxSharedResizeObserver(box));
}
return this._observers.get(box).observe(target);
}
static \u0275fac = function SharedResizeObserver_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _SharedResizeObserver)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _SharedResizeObserver,
factory: _SharedResizeObserver.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(SharedResizeObserver, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
// node_modules/@angular/material/fesm2022/form-field-DqPi4knt.mjs
var _c05 = ["notch"];
var _c14 = ["matFormFieldNotchedOutline", ""];
var _c23 = ["*"];
var _c33 = ["textField"];
var _c42 = ["iconPrefixContainer"];
var _c52 = ["textPrefixContainer"];
var _c62 = ["iconSuffixContainer"];
var _c72 = ["textSuffixContainer"];
var _c8 = ["*", [["mat-label"]], [["", "matPrefix", ""], ["", "matIconPrefix", ""]], [["", "matTextPrefix", ""]], [["", "matTextSuffix", ""]], [["", "matSuffix", ""], ["", "matIconSuffix", ""]], [["mat-error"], ["", "matError", ""]], [["mat-hint", 3, "align", "end"]], [["mat-hint", "align", "end"]]];
var _c9 = ["*", "mat-label", "[matPrefix], [matIconPrefix]", "[matTextPrefix]", "[matTextSuffix]", "[matSuffix], [matIconSuffix]", "mat-error, [matError]", "mat-hint:not([align='end'])", "mat-hint[align='end']"];
function MatFormField_ng_template_0_Conditional_0_Conditional_2_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "span", 20);
}
}
function MatFormField_ng_template_0_Conditional_0_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "label", 19);
\u0275\u0275projection(1, 1);
\u0275\u0275template(2, MatFormField_ng_template_0_Conditional_0_Conditional_2_Template, 1, 0, "span", 20);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275property("floating", ctx_r1._shouldLabelFloat())("monitorResize", ctx_r1._hasOutline())("id", ctx_r1._labelId);
\u0275\u0275attribute("for", ctx_r1._control.disableAutomaticLabeling ? null : ctx_r1._control.id);
\u0275\u0275advance(2);
\u0275\u0275conditional(!ctx_r1.hideRequiredMarker && ctx_r1._control.required ? 2 : -1);
}
}
function MatFormField_ng_template_0_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, MatFormField_ng_template_0_Conditional_0_Template, 3, 5, "label", 19);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275conditional(ctx_r1._hasFloatingLabel() ? 0 : -1);
}
}
function MatFormField_Conditional_4_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "div", 7);
}
}
function MatFormField_Conditional_6_Conditional_1_ng_template_0_Template(rf, ctx) {
}
function MatFormField_Conditional_6_Conditional_1_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, MatFormField_Conditional_6_Conditional_1_ng_template_0_Template, 0, 0, "ng-template", 13);
}
if (rf & 2) {
\u0275\u0275nextContext(2);
const labelTemplate_r3 = \u0275\u0275reference(1);
\u0275\u0275property("ngTemplateOutlet", labelTemplate_r3);
}
}
function MatFormField_Conditional_6_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 9);
\u0275\u0275template(1, MatFormField_Conditional_6_Conditional_1_Template, 1, 1, null, 13);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275property("matFormFieldNotchedOutlineOpen", ctx_r1._shouldLabelFloat());
\u0275\u0275advance();
\u0275\u0275conditional(!ctx_r1._forceDisplayInfixLabel() ? 1 : -1);
}
}
function MatFormField_Conditional_7_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 10, 2);
\u0275\u0275projection(2, 2);
\u0275\u0275elementEnd();
}
}
function MatFormField_Conditional_8_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 11, 3);
\u0275\u0275projection(2, 3);
\u0275\u0275elementEnd();
}
}
function MatFormField_Conditional_10_ng_template_0_Template(rf, ctx) {
}
function MatFormField_Conditional_10_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, MatFormField_Conditional_10_ng_template_0_Template, 0, 0, "ng-template", 13);
}
if (rf & 2) {
\u0275\u0275nextContext();
const labelTemplate_r3 = \u0275\u0275reference(1);
\u0275\u0275property("ngTemplateOutlet", labelTemplate_r3);
}
}
function MatFormField_Conditional_12_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 14, 4);
\u0275\u0275projection(2, 4);
\u0275\u0275elementEnd();
}
}
function MatFormField_Conditional_13_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div", 15, 5);
\u0275\u0275projection(2, 5);
\u0275\u0275elementEnd();
}
}
function MatFormField_Conditional_14_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275element(0, "div", 16);
}
}
function MatFormField_Case_18_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projection(0, 6);
}
}
function MatFormField_Case_19_Conditional_0_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "mat-hint", 21);
\u0275\u0275text(1);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext(2);
\u0275\u0275property("id", ctx_r1._hintLabelId);
\u0275\u0275advance();
\u0275\u0275textInterpolate(ctx_r1.hintLabel);
}
}
function MatFormField_Case_19_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275template(0, MatFormField_Case_19_Conditional_0_Template, 2, 2, "mat-hint", 21);
\u0275\u0275projection(1, 7);
\u0275\u0275element(2, "div", 22);
\u0275\u0275projection(3, 8);
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275conditional(ctx_r1.hintLabel ? 0 : -1);
}
}
var MatLabel = class _MatLabel {
static \u0275fac = function MatLabel_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatLabel)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatLabel,
selectors: [["mat-label"]]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatLabel, [{
type: Directive,
args: [{
selector: "mat-label"
}]
}], null, null);
})();
var MAT_ERROR = new InjectionToken("MatError");
var MatError = class _MatError {
id = inject(_IdGenerator).getId("mat-mdc-error-");
constructor() {
}
static \u0275fac = function MatError_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatError)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatError,
selectors: [["mat-error"], ["", "matError", ""]],
hostAttrs: [1, "mat-mdc-form-field-error", "mat-mdc-form-field-bottom-align"],
hostVars: 1,
hostBindings: function MatError_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275hostProperty("id", ctx.id);
}
},
inputs: {
id: "id"
},
features: [\u0275\u0275ProvidersFeature([{
provide: MAT_ERROR,
useExisting: _MatError
}])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatError, [{
type: Directive,
args: [{
selector: "mat-error, [matError]",
host: {
"class": "mat-mdc-form-field-error mat-mdc-form-field-bottom-align",
"[id]": "id"
},
providers: [{
provide: MAT_ERROR,
useExisting: MatError
}]
}]
}], () => [], {
id: [{
type: Input
}]
});
})();
var MatHint = class _MatHint {
/** Whether to align the hint label at the start or end of the line. */
align = "start";
/** Unique ID for the hint. Used for the aria-describedby on the form field control. */
id = inject(_IdGenerator).getId("mat-mdc-hint-");
static \u0275fac = function MatHint_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatHint)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatHint,
selectors: [["mat-hint"]],
hostAttrs: [1, "mat-mdc-form-field-hint", "mat-mdc-form-field-bottom-align"],
hostVars: 4,
hostBindings: function MatHint_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275hostProperty("id", ctx.id);
\u0275\u0275attribute("align", null);
\u0275\u0275classProp("mat-mdc-form-field-hint-end", ctx.align === "end");
}
},
inputs: {
align: "align",
id: "id"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatHint, [{
type: Directive,
args: [{
selector: "mat-hint",
host: {
"class": "mat-mdc-form-field-hint mat-mdc-form-field-bottom-align",
"[class.mat-mdc-form-field-hint-end]": 'align === "end"',
"[id]": "id",
// Remove align attribute to prevent it from interfering with layout.
"[attr.align]": "null"
}
}]
}], null, {
align: [{
type: Input
}],
id: [{
type: Input
}]
});
})();
var MAT_PREFIX = new InjectionToken("MatPrefix");
var MatPrefix = class _MatPrefix {
set _isTextSelector(value) {
this._isText = true;
}
_isText = false;
static \u0275fac = function MatPrefix_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatPrefix)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatPrefix,
selectors: [["", "matPrefix", ""], ["", "matIconPrefix", ""], ["", "matTextPrefix", ""]],
inputs: {
_isTextSelector: [0, "matTextPrefix", "_isTextSelector"]
},
features: [\u0275\u0275ProvidersFeature([{
provide: MAT_PREFIX,
useExisting: _MatPrefix
}])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatPrefix, [{
type: Directive,
args: [{
selector: "[matPrefix], [matIconPrefix], [matTextPrefix]",
providers: [{
provide: MAT_PREFIX,
useExisting: MatPrefix
}]
}]
}], null, {
_isTextSelector: [{
type: Input,
args: ["matTextPrefix"]
}]
});
})();
var MAT_SUFFIX = new InjectionToken("MatSuffix");
var MatSuffix = class _MatSuffix {
set _isTextSelector(value) {
this._isText = true;
}
_isText = false;
static \u0275fac = function MatSuffix_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatSuffix)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatSuffix,
selectors: [["", "matSuffix", ""], ["", "matIconSuffix", ""], ["", "matTextSuffix", ""]],
inputs: {
_isTextSelector: [0, "matTextSuffix", "_isTextSelector"]
},
features: [\u0275\u0275ProvidersFeature([{
provide: MAT_SUFFIX,
useExisting: _MatSuffix
}])]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatSuffix, [{
type: Directive,
args: [{
selector: "[matSuffix], [matIconSuffix], [matTextSuffix]",
providers: [{
provide: MAT_SUFFIX,
useExisting: MatSuffix
}]
}]
}], null, {
_isTextSelector: [{
type: Input,
args: ["matTextSuffix"]
}]
});
})();
var FLOATING_LABEL_PARENT = new InjectionToken("FloatingLabelParent");
var MatFormFieldFloatingLabel = class _MatFormFieldFloatingLabel {
_elementRef = inject(ElementRef);
/** Whether the label is floating. */
get floating() {
return this._floating;
}
set floating(value) {
this._floating = value;
if (this.monitorResize) {
this._handleResize();
}
}
_floating = false;
/** Whether to monitor for resize events on the floating label. */
get monitorResize() {
return this._monitorResize;
}
set monitorResize(value) {
this._monitorResize = value;
if (this._monitorResize) {
this._subscribeToResize();
} else {
this._resizeSubscription.unsubscribe();
}
}
_monitorResize = false;
/** The shared ResizeObserver. */
_resizeObserver = inject(SharedResizeObserver);
/** The Angular zone. */
_ngZone = inject(NgZone);
/** The parent form-field. */
_parent = inject(FLOATING_LABEL_PARENT);
/** The current resize event subscription. */
_resizeSubscription = new Subscription();
constructor() {
}
ngOnDestroy() {
this._resizeSubscription.unsubscribe();
}
/** Gets the width of the label. Used for the outline notch. */
getWidth() {
return estimateScrollWidth(this._elementRef.nativeElement);
}
/** Gets the HTML element for the floating label. */
get element() {
return this._elementRef.nativeElement;
}
/** Handles resize events from the ResizeObserver. */
_handleResize() {
setTimeout(() => this._parent._handleLabelResized());
}
/** Subscribes to resize events. */
_subscribeToResize() {
this._resizeSubscription.unsubscribe();
this._ngZone.runOutsideAngular(() => {
this._resizeSubscription = this._resizeObserver.observe(this._elementRef.nativeElement, {
box: "border-box"
}).subscribe(() => this._handleResize());
});
}
static \u0275fac = function MatFormFieldFloatingLabel_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormFieldFloatingLabel)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatFormFieldFloatingLabel,
selectors: [["label", "matFormFieldFloatingLabel", ""]],
hostAttrs: [1, "mdc-floating-label", "mat-mdc-floating-label"],
hostVars: 2,
hostBindings: function MatFormFieldFloatingLabel_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("mdc-floating-label--float-above", ctx.floating);
}
},
inputs: {
floating: "floating",
monitorResize: "monitorResize"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormFieldFloatingLabel, [{
type: Directive,
args: [{
selector: "label[matFormFieldFloatingLabel]",
host: {
"class": "mdc-floating-label mat-mdc-floating-label",
"[class.mdc-floating-label--float-above]": "floating"
}
}]
}], () => [], {
floating: [{
type: Input
}],
monitorResize: [{
type: Input
}]
});
})();
function estimateScrollWidth(element) {
const htmlEl = element;
if (htmlEl.offsetParent !== null) {
return htmlEl.scrollWidth;
}
const clone = htmlEl.cloneNode(true);
clone.style.setProperty("position", "absolute");
clone.style.setProperty("transform", "translate(-9999px, -9999px)");
document.documentElement.appendChild(clone);
const scrollWidth = clone.scrollWidth;
clone.remove();
return scrollWidth;
}
var ACTIVATE_CLASS = "mdc-line-ripple--active";
var DEACTIVATING_CLASS = "mdc-line-ripple--deactivating";
var MatFormFieldLineRipple = class _MatFormFieldLineRipple {
_elementRef = inject(ElementRef);
_cleanupTransitionEnd;
constructor() {
const ngZone = inject(NgZone);
const renderer = inject(Renderer2);
ngZone.runOutsideAngular(() => {
this._cleanupTransitionEnd = renderer.listen(this._elementRef.nativeElement, "transitionend", this._handleTransitionEnd);
});
}
activate() {
const classList = this._elementRef.nativeElement.classList;
classList.remove(DEACTIVATING_CLASS);
classList.add(ACTIVATE_CLASS);
}
deactivate() {
this._elementRef.nativeElement.classList.add(DEACTIVATING_CLASS);
}
_handleTransitionEnd = (event) => {
const classList = this._elementRef.nativeElement.classList;
const isDeactivating = classList.contains(DEACTIVATING_CLASS);
if (event.propertyName === "opacity" && isDeactivating) {
classList.remove(ACTIVATE_CLASS, DEACTIVATING_CLASS);
}
};
ngOnDestroy() {
this._cleanupTransitionEnd();
}
static \u0275fac = function MatFormFieldLineRipple_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormFieldLineRipple)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatFormFieldLineRipple,
selectors: [["div", "matFormFieldLineRipple", ""]],
hostAttrs: [1, "mdc-line-ripple"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormFieldLineRipple, [{
type: Directive,
args: [{
selector: "div[matFormFieldLineRipple]",
host: {
"class": "mdc-line-ripple"
}
}]
}], () => [], null);
})();
var MatFormFieldNotchedOutline = class _MatFormFieldNotchedOutline {
_elementRef = inject(ElementRef);
_ngZone = inject(NgZone);
/** Whether the notch should be opened. */
open = false;
_notch;
constructor() {
}
ngAfterViewInit() {
const label = this._elementRef.nativeElement.querySelector(".mdc-floating-label");
if (label) {
this._elementRef.nativeElement.classList.add("mdc-notched-outline--upgraded");
if (typeof requestAnimationFrame === "function") {
label.style.transitionDuration = "0s";
this._ngZone.runOutsideAngular(() => {
requestAnimationFrame(() => label.style.transitionDuration = "");
});
}
} else {
this._elementRef.nativeElement.classList.add("mdc-notched-outline--no-label");
}
}
_setNotchWidth(labelWidth) {
if (!this.open || !labelWidth) {
this._notch.nativeElement.style.width = "";
} else {
const NOTCH_ELEMENT_PADDING = 8;
const NOTCH_ELEMENT_BORDER = 1;
this._notch.nativeElement.style.width = `calc(${labelWidth}px * var(--mat-mdc-form-field-floating-label-scale, 0.75) + ${NOTCH_ELEMENT_PADDING + NOTCH_ELEMENT_BORDER}px)`;
}
}
static \u0275fac = function MatFormFieldNotchedOutline_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormFieldNotchedOutline)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatFormFieldNotchedOutline,
selectors: [["div", "matFormFieldNotchedOutline", ""]],
viewQuery: function MatFormFieldNotchedOutline_Query(rf, ctx) {
if (rf & 1) {
\u0275\u0275viewQuery(_c05, 5);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._notch = _t.first);
}
},
hostAttrs: [1, "mdc-notched-outline"],
hostVars: 2,
hostBindings: function MatFormFieldNotchedOutline_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("mdc-notched-outline--notched", ctx.open);
}
},
inputs: {
open: [0, "matFormFieldNotchedOutlineOpen", "open"]
},
attrs: _c14,
ngContentSelectors: _c23,
decls: 5,
vars: 0,
consts: [["notch", ""], [1, "mat-mdc-notch-piece", "mdc-notched-outline__leading"], [1, "mat-mdc-notch-piece", "mdc-notched-outline__notch"], [1, "mat-mdc-notch-piece", "mdc-notched-outline__trailing"]],
template: function MatFormFieldNotchedOutline_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef();
\u0275\u0275element(0, "div", 1);
\u0275\u0275elementStart(1, "div", 2, 0);
\u0275\u0275projection(3);
\u0275\u0275elementEnd();
\u0275\u0275element(4, "div", 3);
}
},
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormFieldNotchedOutline, [{
type: Component,
args: [{
selector: "div[matFormFieldNotchedOutline]",
host: {
"class": "mdc-notched-outline",
// Besides updating the notch state through the MDC component, we toggle this class through
// a host binding in order to ensure that the notched-outline renders correctly on the server.
"[class.mdc-notched-outline--notched]": "open"
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
template: '<div class="mat-mdc-notch-piece mdc-notched-outline__leading"></div>\n<div class="mat-mdc-notch-piece mdc-notched-outline__notch" #notch>\n <ng-content></ng-content>\n</div>\n<div class="mat-mdc-notch-piece mdc-notched-outline__trailing"></div>\n'
}]
}], () => [], {
open: [{
type: Input,
args: ["matFormFieldNotchedOutlineOpen"]
}],
_notch: [{
type: ViewChild,
args: ["notch"]
}]
});
})();
var MatFormFieldControl = class _MatFormFieldControl {
/** The value of the control. */
value;
/**
* Stream that emits whenever the state of the control changes such that the parent `MatFormField`
* needs to run change detection.
*/
stateChanges;
/** The element ID for this control. */
id;
/** The placeholder for this control. */
placeholder;
/** Gets the AbstractControlDirective for this control. */
ngControl;
/** Whether the control is focused. */
focused;
/** Whether the control is empty. */
empty;
/** Whether the `MatFormField` label should try to float. */
shouldLabelFloat;
/** Whether the control is required. */
required;
/** Whether the control is disabled. */
disabled;
/** Whether the control is in an error state. */
errorState;
/**
* An optional name for the control type that can be used to distinguish `mat-form-field` elements
* based on their control type. The form field will add a class,
* `mat-form-field-type-{{controlType}}` to its root element.
*/
controlType;
/**
* Whether the input is currently in an autofilled state. If property is not present on the
* control it is assumed to be false.
*/
autofilled;
/**
* Value of `aria-describedby` that should be merged with the described-by ids
* which are set by the form-field.
*/
userAriaDescribedBy;
/**
* Whether to automatically assign the ID of the form field as the `for` attribute
* on the `<label>` inside the form field. Set this to true to prevent the form
* field from associating the label with non-native elements.
*/
disableAutomaticLabeling;
static \u0275fac = function MatFormFieldControl_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormFieldControl)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatFormFieldControl
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormFieldControl, [{
type: Directive
}], null, null);
})();
function getMatFormFieldDuplicatedHintError(align) {
return Error(`A hint was already declared for 'align="${align}"'.`);
}
function getMatFormFieldMissingControlError() {
return Error("mat-form-field must contain a MatFormFieldControl.");
}
var MAT_FORM_FIELD = new InjectionToken("MatFormField");
var MAT_FORM_FIELD_DEFAULT_OPTIONS = new InjectionToken("MAT_FORM_FIELD_DEFAULT_OPTIONS");
var DEFAULT_APPEARANCE = "fill";
var DEFAULT_FLOAT_LABEL = "auto";
var DEFAULT_SUBSCRIPT_SIZING = "fixed";
var FLOATING_LABEL_DEFAULT_DOCKED_TRANSFORM = `translateY(-50%)`;
var MatFormField = class _MatFormField {
_elementRef = inject(ElementRef);
_changeDetectorRef = inject(ChangeDetectorRef);
_dir = inject(Directionality);
_platform = inject(Platform);
_idGenerator = inject(_IdGenerator);
_ngZone = inject(NgZone);
_injector = inject(Injector);
_defaults = inject(MAT_FORM_FIELD_DEFAULT_OPTIONS, {
optional: true
});
_textField;
_iconPrefixContainer;
_textPrefixContainer;
_iconSuffixContainer;
_textSuffixContainer;
_floatingLabel;
_notchedOutline;
_lineRipple;
_formFieldControl;
_prefixChildren;
_suffixChildren;
_errorChildren;
_hintChildren;
_labelChild = contentChild(MatLabel);
/** Whether the required marker should be hidden. */
get hideRequiredMarker() {
return this._hideRequiredMarker;
}
set hideRequiredMarker(value) {
this._hideRequiredMarker = coerceBooleanProperty(value);
}
_hideRequiredMarker = false;
/**
* Theme color of the form field. This API is supported in M2 themes only, it
* has no effect in M3 themes. For color customization in M3, see https://material.angular.dev/components/form-field/styling.
*
* For information on applying color variants in M3, see
* https://material.angular.dev/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
*/
color = "primary";
/** Whether the label should always float or float as the user types. */
get floatLabel() {
return this._floatLabel || this._defaults?.floatLabel || DEFAULT_FLOAT_LABEL;
}
set floatLabel(value) {
if (value !== this._floatLabel) {
this._floatLabel = value;
this._changeDetectorRef.markForCheck();
}
}
_floatLabel;
/** The form field appearance style. */
get appearance() {
return this._appearance;
}
set appearance(value) {
const oldValue = this._appearance;
const newAppearance = value || this._defaults?.appearance || DEFAULT_APPEARANCE;
if (typeof ngDevMode === "undefined" || ngDevMode) {
if (newAppearance !== "fill" && newAppearance !== "outline") {
throw new Error(`MatFormField: Invalid appearance "${newAppearance}", valid values are "fill" or "outline".`);
}
}
this._appearance = newAppearance;
if (this._appearance === "outline" && this._appearance !== oldValue) {
this._needsOutlineLabelOffsetUpdate = true;
}
}
_appearance = DEFAULT_APPEARANCE;
/**
* Whether the form field should reserve space for one line of hint/error text (default)
* or to have the spacing grow from 0px as needed based on the size of the hint/error content.
* Note that when using dynamic sizing, layout shifts will occur when hint/error text changes.
*/
get subscriptSizing() {
return this._subscriptSizing || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
}
set subscriptSizing(value) {
this._subscriptSizing = value || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
}
_subscriptSizing = null;
/** Text for the form field hint. */
get hintLabel() {
return this._hintLabel;
}
set hintLabel(value) {
this._hintLabel = value;
this._processHints();
}
_hintLabel = "";
_hasIconPrefix = false;
_hasTextPrefix = false;
_hasIconSuffix = false;
_hasTextSuffix = false;
// Unique id for the internal form field label.
_labelId = this._idGenerator.getId("mat-mdc-form-field-label-");
// Unique id for the hint label.
_hintLabelId = this._idGenerator.getId("mat-mdc-hint-");
/** Gets the current form field control */
get _control() {
return this._explicitFormFieldControl || this._formFieldControl;
}
set _control(value) {
this._explicitFormFieldControl = value;
}
_destroyed = new Subject();
_isFocused = null;
_explicitFormFieldControl;
_needsOutlineLabelOffsetUpdate = false;
_previousControl = null;
_previousControlValidatorFn = null;
_stateChanges;
_valueChanges;
_describedByChanges;
_animationsDisabled;
constructor() {
const defaults2 = this._defaults;
if (defaults2) {
if (defaults2.appearance) {
this.appearance = defaults2.appearance;
}
this._hideRequiredMarker = Boolean(defaults2?.hideRequiredMarker);
if (defaults2.color) {
this.color = defaults2.color;
}
}
this._animationsDisabled = inject(ANIMATION_MODULE_TYPE, {
optional: true
}) === "NoopAnimations";
}
ngAfterViewInit() {
this._updateFocusState();
if (!this._animationsDisabled) {
this._ngZone.runOutsideAngular(() => {
setTimeout(() => {
this._elementRef.nativeElement.classList.add("mat-form-field-animations-enabled");
}, 300);
});
}
this._changeDetectorRef.detectChanges();
}
ngAfterContentInit() {
this._assertFormFieldControl();
this._initializeSubscript();
this._initializePrefixAndSuffix();
this._initializeOutlineLabelOffsetSubscriptions();
}
ngAfterContentChecked() {
this._assertFormFieldControl();
if (this._control !== this._previousControl) {
this._initializeControl(this._previousControl);
if (this._control.ngControl && this._control.ngControl.control) {
this._previousControlValidatorFn = this._control.ngControl.control.validator;
}
this._previousControl = this._control;
}
if (this._control.ngControl && this._control.ngControl.control) {
const validatorFn = this._control.ngControl.control.validator;
if (validatorFn !== this._previousControlValidatorFn) {
this._changeDetectorRef.markForCheck();
}
}
}
ngOnDestroy() {
this._stateChanges?.unsubscribe();
this._valueChanges?.unsubscribe();
this._describedByChanges?.unsubscribe();
this._destroyed.next();
this._destroyed.complete();
}
/**
* Gets the id of the label element. If no label is present, returns `null`.
*/
getLabelId = computed(() => this._hasFloatingLabel() ? this._labelId : null);
/**
* Gets an ElementRef for the element that a overlay attached to the form field
* should be positioned relative to.
*/
getConnectedOverlayOrigin() {
return this._textField || this._elementRef;
}
/** Animates the placeholder up and locks it in position. */
_animateAndLockLabel() {
if (this._hasFloatingLabel()) {
this.floatLabel = "always";
}
}
/** Initializes the registered form field control. */
_initializeControl(previousControl) {
const control = this._control;
const classPrefix = "mat-mdc-form-field-type-";
if (previousControl) {
this._elementRef.nativeElement.classList.remove(classPrefix + previousControl.controlType);
}
if (control.controlType) {
this._elementRef.nativeElement.classList.add(classPrefix + control.controlType);
}
this._stateChanges?.unsubscribe();
this._stateChanges = control.stateChanges.subscribe(() => {
this._updateFocusState();
this._changeDetectorRef.markForCheck();
});
this._describedByChanges?.unsubscribe();
this._describedByChanges = control.stateChanges.pipe(startWith([void 0, void 0]), map(() => [control.errorState, control.userAriaDescribedBy]), pairwise(), filter(([[prevErrorState, prevDescribedBy], [currentErrorState, currentDescribedBy]]) => {
return prevErrorState !== currentErrorState || prevDescribedBy !== currentDescribedBy;
})).subscribe(() => this._syncDescribedByIds());
this._valueChanges?.unsubscribe();
if (control.ngControl && control.ngControl.valueChanges) {
this._valueChanges = control.ngControl.valueChanges.pipe(takeUntil(this._destroyed)).subscribe(() => this._changeDetectorRef.markForCheck());
}
}
_checkPrefixAndSuffixTypes() {
this._hasIconPrefix = !!this._prefixChildren.find((p) => !p._isText);
this._hasTextPrefix = !!this._prefixChildren.find((p) => p._isText);
this._hasIconSuffix = !!this._suffixChildren.find((s) => !s._isText);
this._hasTextSuffix = !!this._suffixChildren.find((s) => s._isText);
}
/** Initializes the prefix and suffix containers. */
_initializePrefixAndSuffix() {
this._checkPrefixAndSuffixTypes();
merge(this._prefixChildren.changes, this._suffixChildren.changes).subscribe(() => {
this._checkPrefixAndSuffixTypes();
this._changeDetectorRef.markForCheck();
});
}
/**
* Initializes the subscript by validating hints and synchronizing "aria-describedby" ids
* with the custom form field control. Also subscribes to hint and error changes in order
* to be able to validate and synchronize ids on change.
*/
_initializeSubscript() {
this._hintChildren.changes.subscribe(() => {
this._processHints();
this._changeDetectorRef.markForCheck();
});
this._errorChildren.changes.subscribe(() => {
this._syncDescribedByIds();
this._changeDetectorRef.markForCheck();
});
this._validateHints();
this._syncDescribedByIds();
}
/** Throws an error if the form field's control is missing. */
_assertFormFieldControl() {
if (!this._control && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw getMatFormFieldMissingControlError();
}
}
_updateFocusState() {
if (this._control.focused && !this._isFocused) {
this._isFocused = true;
this._lineRipple?.activate();
} else if (!this._control.focused && (this._isFocused || this._isFocused === null)) {
this._isFocused = false;
this._lineRipple?.deactivate();
}
this._textField?.nativeElement.classList.toggle("mdc-text-field--focused", this._control.focused);
}
/**
* The floating label in the docked state needs to account for prefixes. The horizontal offset
* is calculated whenever the appearance changes to `outline`, the prefixes change, or when the
* form field is added to the DOM. This method sets up all subscriptions which are needed to
* trigger the label offset update.
*/
_initializeOutlineLabelOffsetSubscriptions() {
this._prefixChildren.changes.subscribe(() => this._needsOutlineLabelOffsetUpdate = true);
afterRender(() => {
if (this._needsOutlineLabelOffsetUpdate) {
this._needsOutlineLabelOffsetUpdate = false;
this._updateOutlineLabelOffset();
}
}, {
injector: this._injector
});
this._dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => this._needsOutlineLabelOffsetUpdate = true);
}
/** Whether the floating label should always float or not. */
_shouldAlwaysFloat() {
return this.floatLabel === "always";
}
_hasOutline() {
return this.appearance === "outline";
}
/**
* Whether the label should display in the infix. Labels in the outline appearance are
* displayed as part of the notched-outline and are horizontally offset to account for
* form field prefix content. This won't work in server side rendering since we cannot
* measure the width of the prefix container. To make the docked label appear as if the
* right offset has been calculated, we forcibly render the label inside the infix. Since
* the label is part of the infix, the label cannot overflow the prefix content.
*/
_forceDisplayInfixLabel() {
return !this._platform.isBrowser && this._prefixChildren.length && !this._shouldLabelFloat();
}
_hasFloatingLabel = computed(() => !!this._labelChild());
_shouldLabelFloat() {
if (!this._hasFloatingLabel()) {
return false;
}
return this._control.shouldLabelFloat || this._shouldAlwaysFloat();
}
/**
* Determines whether a class from the AbstractControlDirective
* should be forwarded to the host element.
*/
_shouldForward(prop) {
const control = this._control ? this._control.ngControl : null;
return control && control[prop];
}
/** Gets the type of subscript message to render (error or hint). */
_getSubscriptMessageType() {
return this._errorChildren && this._errorChildren.length > 0 && this._control.errorState ? "error" : "hint";
}
/** Handle label resize events. */
_handleLabelResized() {
this._refreshOutlineNotchWidth();
}
/** Refreshes the width of the outline-notch, if present. */
_refreshOutlineNotchWidth() {
if (!this._hasOutline() || !this._floatingLabel || !this._shouldLabelFloat()) {
this._notchedOutline?._setNotchWidth(0);
} else {
this._notchedOutline?._setNotchWidth(this._floatingLabel.getWidth());
}
}
/** Does any extra processing that is required when handling the hints. */
_processHints() {
this._validateHints();
this._syncDescribedByIds();
}
/**
* Ensure that there is a maximum of one of each "mat-hint" alignment specified. The hint
* label specified set through the input is being considered as "start" aligned.
*
* This method is a noop if Angular runs in production mode.
*/
_validateHints() {
if (this._hintChildren && (typeof ngDevMode === "undefined" || ngDevMode)) {
let startHint;
let endHint;
this._hintChildren.forEach((hint) => {
if (hint.align === "start") {
if (startHint || this.hintLabel) {
throw getMatFormFieldDuplicatedHintError("start");
}
startHint = hint;
} else if (hint.align === "end") {
if (endHint) {
throw getMatFormFieldDuplicatedHintError("end");
}
endHint = hint;
}
});
}
}
/**
* Sets the list of element IDs that describe the child control. This allows the control to update
* its `aria-describedby` attribute accordingly.
*/
_syncDescribedByIds() {
if (this._control) {
let ids = [];
if (this._control.userAriaDescribedBy && typeof this._control.userAriaDescribedBy === "string") {
ids.push(...this._control.userAriaDescribedBy.split(" "));
}
if (this._getSubscriptMessageType() === "hint") {
const startHint = this._hintChildren ? this._hintChildren.find((hint) => hint.align === "start") : null;
const endHint = this._hintChildren ? this._hintChildren.find((hint) => hint.align === "end") : null;
if (startHint) {
ids.push(startHint.id);
} else if (this._hintLabel) {
ids.push(this._hintLabelId);
}
if (endHint) {
ids.push(endHint.id);
}
} else if (this._errorChildren) {
ids.push(...this._errorChildren.map((error) => error.id));
}
this._control.setDescribedByIds(ids);
}
}
/**
* Updates the horizontal offset of the label in the outline appearance. In the outline
* appearance, the notched-outline and label are not relative to the infix container because
* the outline intends to surround prefixes, suffixes and the infix. This means that the
* floating label by default overlaps prefixes in the docked state. To avoid this, we need to
* horizontally offset the label by the width of the prefix container. The MDC text-field does
* not need to do this because they use a fixed width for prefixes. Hence, they can simply
* incorporate the horizontal offset into their default text-field styles.
*/
_updateOutlineLabelOffset() {
if (!this._hasOutline() || !this._floatingLabel) {
return;
}
const floatingLabel = this._floatingLabel.element;
if (!(this._iconPrefixContainer || this._textPrefixContainer)) {
floatingLabel.style.transform = "";
return;
}
if (!this._isAttachedToDom()) {
this._needsOutlineLabelOffsetUpdate = true;
return;
}
const iconPrefixContainer = this._iconPrefixContainer?.nativeElement;
const textPrefixContainer = this._textPrefixContainer?.nativeElement;
const iconSuffixContainer = this._iconSuffixContainer?.nativeElement;
const textSuffixContainer = this._textSuffixContainer?.nativeElement;
const iconPrefixContainerWidth = iconPrefixContainer?.getBoundingClientRect().width ?? 0;
const textPrefixContainerWidth = textPrefixContainer?.getBoundingClientRect().width ?? 0;
const iconSuffixContainerWidth = iconSuffixContainer?.getBoundingClientRect().width ?? 0;
const textSuffixContainerWidth = textSuffixContainer?.getBoundingClientRect().width ?? 0;
const negate = this._dir.value === "rtl" ? "-1" : "1";
const prefixWidth = `${iconPrefixContainerWidth + textPrefixContainerWidth}px`;
const labelOffset = `var(--mat-mdc-form-field-label-offset-x, 0px)`;
const labelHorizontalOffset = `calc(${negate} * (${prefixWidth} + ${labelOffset}))`;
floatingLabel.style.transform = `var(
--mat-mdc-form-field-label-transform,
${FLOATING_LABEL_DEFAULT_DOCKED_TRANSFORM} translateX(${labelHorizontalOffset})
)`;
const prefixAndSuffixWidth = iconPrefixContainerWidth + textPrefixContainerWidth + iconSuffixContainerWidth + textSuffixContainerWidth;
this._elementRef.nativeElement.style.setProperty("--mat-form-field-notch-max-width", `calc(100% - ${prefixAndSuffixWidth}px)`);
}
/** Checks whether the form field is attached to the DOM. */
_isAttachedToDom() {
const element = this._elementRef.nativeElement;
if (element.getRootNode) {
const rootNode = element.getRootNode();
return rootNode && rootNode !== element;
}
return document.documentElement.contains(element);
}
static \u0275fac = function MatFormField_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormField)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatFormField,
selectors: [["mat-form-field"]],
contentQueries: function MatFormField_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
\u0275\u0275contentQuerySignal(dirIndex, ctx._labelChild, MatLabel, 5);
\u0275\u0275contentQuery(dirIndex, MatFormFieldControl, 5);
\u0275\u0275contentQuery(dirIndex, MAT_PREFIX, 5);
\u0275\u0275contentQuery(dirIndex, MAT_SUFFIX, 5);
\u0275\u0275contentQuery(dirIndex, MAT_ERROR, 5);
\u0275\u0275contentQuery(dirIndex, MatHint, 5);
}
if (rf & 2) {
\u0275\u0275queryAdvance();
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._formFieldControl = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._prefixChildren = _t);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._suffixChildren = _t);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._errorChildren = _t);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._hintChildren = _t);
}
},
viewQuery: function MatFormField_Query(rf, ctx) {
if (rf & 1) {
\u0275\u0275viewQuery(_c33, 5);
\u0275\u0275viewQuery(_c42, 5);
\u0275\u0275viewQuery(_c52, 5);
\u0275\u0275viewQuery(_c62, 5);
\u0275\u0275viewQuery(_c72, 5);
\u0275\u0275viewQuery(MatFormFieldFloatingLabel, 5);
\u0275\u0275viewQuery(MatFormFieldNotchedOutline, 5);
\u0275\u0275viewQuery(MatFormFieldLineRipple, 5);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._textField = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._iconPrefixContainer = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._textPrefixContainer = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._iconSuffixContainer = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._textSuffixContainer = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._floatingLabel = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._notchedOutline = _t.first);
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._lineRipple = _t.first);
}
},
hostAttrs: [1, "mat-mdc-form-field"],
hostVars: 40,
hostBindings: function MatFormField_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classProp("mat-mdc-form-field-label-always-float", ctx._shouldAlwaysFloat())("mat-mdc-form-field-has-icon-prefix", ctx._hasIconPrefix)("mat-mdc-form-field-has-icon-suffix", ctx._hasIconSuffix)("mat-form-field-invalid", ctx._control.errorState)("mat-form-field-disabled", ctx._control.disabled)("mat-form-field-autofilled", ctx._control.autofilled)("mat-form-field-appearance-fill", ctx.appearance == "fill")("mat-form-field-appearance-outline", ctx.appearance == "outline")("mat-form-field-hide-placeholder", ctx._hasFloatingLabel() && !ctx._shouldLabelFloat())("mat-focused", ctx._control.focused)("mat-primary", ctx.color !== "accent" && ctx.color !== "warn")("mat-accent", ctx.color === "accent")("mat-warn", ctx.color === "warn")("ng-untouched", ctx._shouldForward("untouched"))("ng-touched", ctx._shouldForward("touched"))("ng-pristine", ctx._shouldForward("pristine"))("ng-dirty", ctx._shouldForward("dirty"))("ng-valid", ctx._shouldForward("valid"))("ng-invalid", ctx._shouldForward("invalid"))("ng-pending", ctx._shouldForward("pending"));
}
},
inputs: {
hideRequiredMarker: "hideRequiredMarker",
color: "color",
floatLabel: "floatLabel",
appearance: "appearance",
subscriptSizing: "subscriptSizing",
hintLabel: "hintLabel"
},
exportAs: ["matFormField"],
features: [\u0275\u0275ProvidersFeature([{
provide: MAT_FORM_FIELD,
useExisting: _MatFormField
}, {
provide: FLOATING_LABEL_PARENT,
useExisting: _MatFormField
}])],
ngContentSelectors: _c9,
decls: 20,
vars: 25,
consts: [["labelTemplate", ""], ["textField", ""], ["iconPrefixContainer", ""], ["textPrefixContainer", ""], ["textSuffixContainer", ""], ["iconSuffixContainer", ""], [1, "mat-mdc-text-field-wrapper", "mdc-text-field", 3, "click"], [1, "mat-mdc-form-field-focus-overlay"], [1, "mat-mdc-form-field-flex"], ["matFormFieldNotchedOutline", "", 3, "matFormFieldNotchedOutlineOpen"], [1, "mat-mdc-form-field-icon-prefix"], [1, "mat-mdc-form-field-text-prefix"], [1, "mat-mdc-form-field-infix"], [3, "ngTemplateOutlet"], [1, "mat-mdc-form-field-text-suffix"], [1, "mat-mdc-form-field-icon-suffix"], ["matFormFieldLineRipple", ""], [1, "mat-mdc-form-field-subscript-wrapper", "mat-mdc-form-field-bottom-align"], ["aria-atomic", "true", "aria-live", "polite"], ["matFormFieldFloatingLabel", "", 3, "floating", "monitorResize", "id"], ["aria-hidden", "true", 1, "mat-mdc-form-field-required-marker", "mdc-floating-label--required"], [3, "id"], [1, "mat-mdc-form-field-hint-spacer"]],
template: function MatFormField_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275projectionDef(_c8);
\u0275\u0275template(0, MatFormField_ng_template_0_Template, 1, 1, "ng-template", null, 0, \u0275\u0275templateRefExtractor);
\u0275\u0275elementStart(2, "div", 6, 1);
\u0275\u0275listener("click", function MatFormField_Template_div_click_2_listener($event) {
\u0275\u0275restoreView(_r1);
return \u0275\u0275resetView(ctx._control.onContainerClick($event));
});
\u0275\u0275template(4, MatFormField_Conditional_4_Template, 1, 0, "div", 7);
\u0275\u0275elementStart(5, "div", 8);
\u0275\u0275template(6, MatFormField_Conditional_6_Template, 2, 2, "div", 9)(7, MatFormField_Conditional_7_Template, 3, 0, "div", 10)(8, MatFormField_Conditional_8_Template, 3, 0, "div", 11);
\u0275\u0275elementStart(9, "div", 12);
\u0275\u0275template(10, MatFormField_Conditional_10_Template, 1, 1, null, 13);
\u0275\u0275projection(11);
\u0275\u0275elementEnd();
\u0275\u0275template(12, MatFormField_Conditional_12_Template, 3, 0, "div", 14)(13, MatFormField_Conditional_13_Template, 3, 0, "div", 15);
\u0275\u0275elementEnd();
\u0275\u0275template(14, MatFormField_Conditional_14_Template, 1, 0, "div", 16);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(15, "div", 17);
\u0275\u0275declareLet(16);
\u0275\u0275elementStart(17, "div", 18);
\u0275\u0275template(18, MatFormField_Case_18_Template, 1, 0)(19, MatFormField_Case_19_Template, 4, 1);
\u0275\u0275elementEnd()();
}
if (rf & 2) {
let tmp_19_0;
\u0275\u0275advance(2);
\u0275\u0275classProp("mdc-text-field--filled", !ctx._hasOutline())("mdc-text-field--outlined", ctx._hasOutline())("mdc-text-field--no-label", !ctx._hasFloatingLabel())("mdc-text-field--disabled", ctx._control.disabled)("mdc-text-field--invalid", ctx._control.errorState);
\u0275\u0275advance(2);
\u0275\u0275conditional(!ctx._hasOutline() && !ctx._control.disabled ? 4 : -1);
\u0275\u0275advance(2);
\u0275\u0275conditional(ctx._hasOutline() ? 6 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx._hasIconPrefix ? 7 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx._hasTextPrefix ? 8 : -1);
\u0275\u0275advance(2);
\u0275\u0275conditional(!ctx._hasOutline() || ctx._forceDisplayInfixLabel() ? 10 : -1);
\u0275\u0275advance(2);
\u0275\u0275conditional(ctx._hasTextSuffix ? 12 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(ctx._hasIconSuffix ? 13 : -1);
\u0275\u0275advance();
\u0275\u0275conditional(!ctx._hasOutline() ? 14 : -1);
\u0275\u0275advance();
\u0275\u0275classProp("mat-mdc-form-field-subscript-dynamic-size", ctx.subscriptSizing === "dynamic");
const subscriptMessageType_r4 = ctx._getSubscriptMessageType();
\u0275\u0275advance(2);
\u0275\u0275classProp("mat-mdc-form-field-error-wrapper", subscriptMessageType_r4 === "error")("mat-mdc-form-field-hint-wrapper", subscriptMessageType_r4 === "hint");
\u0275\u0275advance();
\u0275\u0275conditional((tmp_19_0 = subscriptMessageType_r4) === "error" ? 18 : tmp_19_0 === "hint" ? 19 : -1);
}
},
dependencies: [MatFormFieldFloatingLabel, MatFormFieldNotchedOutline, NgTemplateOutlet, MatFormFieldLineRipple, MatHint],
styles: ['.mdc-text-field{display:inline-flex;align-items:baseline;padding:0 16px;position:relative;box-sizing:border-box;overflow:hidden;will-change:opacity,transform,color;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.mdc-text-field__input{width:100%;min-width:0;border:none;border-radius:0;background:none;padding:0;-moz-appearance:none;-webkit-appearance:none;height:28px}.mdc-text-field__input::-webkit-calendar-picker-indicator{display:none}.mdc-text-field__input::-ms-clear{display:none}.mdc-text-field__input:focus{outline:none}.mdc-text-field__input:invalid{box-shadow:none}.mdc-text-field__input::placeholder{opacity:0}.mdc-text-field__input::-moz-placeholder{opacity:0}.mdc-text-field__input::-webkit-input-placeholder{opacity:0}.mdc-text-field__input:-ms-input-placeholder{opacity:0}.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mdc-text-field--focused .mdc-text-field__input::placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input::-moz-placeholder,.mdc-text-field--focused .mdc-text-field__input::-moz-placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input::-webkit-input-placeholder,.mdc-text-field--focused .mdc-text-field__input::-webkit-input-placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{opacity:1}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::-moz-placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::-webkit-input-placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive:-ms-input-placeholder{opacity:0}.mdc-text-field--outlined .mdc-text-field__input,.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{height:100%}.mdc-text-field--outlined .mdc-text-field__input{display:flex;border:none !important;background-color:rgba(0,0,0,0)}.mdc-text-field--disabled .mdc-text-field__input{pointer-events:auto}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input{color:var(--mdc-filled-text-field-input-text-color, var(--mat-sys-on-surface));caret-color:var(--mdc-filled-text-field-caret-color, var(--mat-sys-primary))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::-moz-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::-webkit-input-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__input{caret-color:var(--mdc-filled-text-field-error-caret-color)}.mdc-text-field--filled.mdc-text-field--disabled .mdc-text-field__input{color:var(--mdc-filled-text-field-disabled-input-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input{color:var(--mdc-outlined-text-field-input-text-color, var(--mat-sys-on-surface));caret-color:var(--mdc-outlined-text-field-caret-color, var(--mat-sys-primary))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::-moz-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::-webkit-input-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__input{caret-color:var(--mdc-outlined-text-field-error-caret-color)}.mdc-text-field--outlined.mdc-text-field--disabled .mdc-text-field__input{color:var(--mdc-outlined-text-field-disabled-input-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}@media(forced-colors: active){.mdc-text-field--disabled .mdc-text-field__input{background-color:Window}}.mdc-text-field--filled{height:56px;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:var(--mdc-filled-text-field-container-shape, var(--mat-sys-corner-extra-small));border-top-right-radius:var(--mdc-filled-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:var(--mdc-filled-text-field-container-color, var(--mat-sys-surface-variant))}.mdc-text-field--filled.mdc-text-field--disabled{background-color:var(--mdc-filled-text-field-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 4%, transparent))}.mdc-text-field--outlined{height:56px;overflow:visible;padding-right:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)));padding-left:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)) + 4px)}[dir=rtl] .mdc-text-field--outlined{padding-right:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)) + 4px);padding-left:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))}.mdc-floating-label{position:absolute;left:0;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform}[dir=rtl] .mdc-floating-label{right:0;left:auto;transform-origin:right top;text-align:right}.mdc-text-field .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-text-field--outlined .mdc-floating-label{left:4px;right:auto}[dir=rtl] .mdc-text-field--outlined .mdc-floating-label{left:auto;right:4px}.mdc-text-field--filled .mdc-floating-label{left:16px;right:auto}[dir=rtl] .mdc-text-field--filled .mdc-floating-label{left:auto;right:16px}.mdc-text-field--disabled .mdc-floating-label{cursor:default}@media(forced-colors: active){.mdc-text-field--disabled .mdc-floating-label{z-index:1}}.mdc-text-field--filled.mdc-text-field--no-label .mdc-floating-label{display:none}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-floating-label{color:var(--mdc-filled-text-field-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label{color:var(--mdc-filled-text-field-focus-label-text-color, var(--mat-sys-primary))}.mdc-text-field--filled:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-floating-label{color:var(--mdc-filled-text-field-hover-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled.mdc-text-field--disabled .mdc-floating-label{color:var(--mdc-filled-text-field-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-floating-label{color:var(--mdc-filled-text-field-error-label-text-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mdc-floating-label{color:var(--mdc-filled-text-field-error-focus-label-text-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-floating-label{color:var(--mdc-filled-text-field-error-hover-label-text-color, var(--mat-sys-on-error-container))}.mdc-text-field--filled .mdc-floating-label{font-family:var(--mdc-filled-text-field-label-text-font, var(--mat-sys-body-large-font));font-size:var(--mdc-filled-text-field-label-text-size, var(--mat-sys-body-large-size));font-weight:var(--mdc-filled-text-field-label-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mdc-filled-text-field-label-text-tracking, var(--mat-sys-body-large-tracking))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-floating-label{color:var(--mdc-outlined-text-field-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label{color:var(--mdc-outlined-text-field-focus-label-text-color, var(--mat-sys-primary))}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-floating-label{color:var(--mdc-outlined-text-field-hover-label-text-color, var(--mat-sys-on-surface))}.mdc-text-field--outlined.mdc-text-field--disabled .mdc-floating-label{color:var(--mdc-outlined-text-field-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-floating-label{color:var(--mdc-outlined-text-field-error-label-text-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mdc-floating-label{color:var(--mdc-outlined-text-field-error-focus-label-text-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-floating-label{color:var(--mdc-outlined-text-field-error-hover-label-text-color, var(--mat-sys-on-error-container))}.mdc-text-field--outlined .mdc-floating-label{font-family:var(--mdc-outlined-text-field-label-text-font, var(--mat-sys-body-large-font));font-size:var(--mdc-outlined-text-field-label-text-size, var(--mat-sys-body-large-size));font-weight:var(--mdc-outlined-text-field-label-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mdc-outlined-text-field-label-text-tracking, var(--mat-sys-body-large-tracking))}.mdc-floating-label--float-above{cursor:auto;transform:translateY(-106%) scale(0.75)}.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1);font-size:.75rem}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:133.3333333333%}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-floating-label--required:not(.mdc-floating-label--hide-required-marker)::after{margin-left:1px;margin-right:0;content:"*"}[dir=rtl] .mdc-floating-label--required:not(.mdc-floating-label--hide-required-marker)::after{margin-left:0;margin-right:1px}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline{text-align:right}.mdc-text-field--outlined .mdc-notched-outline{z-index:1}.mat-mdc-notch-piece{box-sizing:border-box;height:100%;pointer-events:none;border-top:1px solid;border-bottom:1px solid}.mdc-text-field--focused .mat-mdc-notch-piece{border-width:2px}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-outline-color, var(--mat-sys-outline));border-width:var(--mdc-outlined-text-field-outline-width, 1px)}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-hover-outline-color, var(--mat-sys-on-surface))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-focus-outline-color, var(--mat-sys-primary))}.mdc-text-field--outlined.mdc-text-field--disabled .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-outline-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--focused):hover .mdc-notched-outline .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-hover-outline-color, var(--mat-sys-on-error-container))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-focus-outline-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline .mat-mdc-notch-piece{border-width:var(--mdc-outlined-text-field-focus-outline-width, 2px)}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))}[dir=rtl] .mdc-notched-outline__leading{border-left:none;border-right:1px solid;border-bottom-left-radius:0;border-top-left-radius:0;border-top-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-notched-outline__trailing{flex-grow:1;border-left:none;border-right:1px solid;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}[dir=rtl] .mdc-notched-outline__trailing{border-left:1px solid;border-right:none;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-notched-outline__notch{flex:0 0 auto;width:auto}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:min(var(--mat-form-field-notch-max-width, 100%),100% - max(12px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))*2)}.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none;--mat-form-field-notch-max-width: 100%}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{z-index:1;border-bottom-width:var(--mdc-filled-text-field-active-indicator-height, 1px)}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-active-indicator-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-hover-active-indicator-color, var(--mat-sys-on-surface))}.mdc-text-field--filled.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-disabled-active-indicator-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-error-active-indicator-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--focused):hover .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-error-hover-active-indicator-color, var(--mat-sys-on-error-container))}.mdc-line-ripple::after{transform:scaleX(0);opacity:0;z-index:2}.mdc-text-field--filled .mdc-line-ripple::after{border-bottom-width:var(--mdc-filled-text-field-focus-active-indicator-height, 2px)}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:var(--mdc-filled-text-field-focus-active-indicator-color, var(--mat-sys-primary))}.mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:var(--mdc-filled-text-field-error-focus-active-indicator-color, var(--mat-sys-error))}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-text-field--disabled{pointer-events:none}.mat-mdc-form-field-textarea-control{vertical-align:middle;resize:vertical;box-sizing:border-box;height:auto;margin:0;padding:0;border:none;overflow:auto}.mat-mdc-form-field-input-control.mat-mdc-form-field-input-control{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font:inherit;letter-spacing:inherit;text-decoration:inherit;text-transform:inherit;border:none}.mat-mdc-form-field .mat-mdc-floating-label.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;line-height:normal;pointer-events:all;will-change:auto}.mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{cursor:inherit}.mdc-text-field--no-label:not(.mdc-text-field--textarea) .mat-mdc-form-field-input-control.mdc-text-field__input,.mat-mdc-text-field-wrapper .mat-mdc-form-field-input-control{height:auto}.mat-mdc-text-field-wrapper .mat-mdc-form-field-input-control.mdc-text-field__input[type=color]{height:23px}.mat-mdc-text-field-wrapper{height:auto;flex:auto;will-change:auto}.mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper{padding-left:0;--mat-mdc-form-field-label-offset-x: -16px}.mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper{padding-right:0}[dir=rtl] .mat-mdc-text-field-wrapper{padding-left:16px;padding-right:16px}[dir=rtl] .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper{padding-left:0}[dir=rtl] .mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper{padding-right:0}.mat-form-field-disabled .mdc-text-field__input::placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input::-moz-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input::-webkit-input-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input:-ms-input-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-label-always-float .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}.mat-mdc-text-field-wrapper .mat-mdc-form-field-infix .mat-mdc-floating-label{left:auto;right:auto}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-text-field__input{display:inline-block}.mat-mdc-form-field .mat-mdc-text-field-wrapper.mdc-text-field .mdc-notched-outline__notch{padding-top:0}.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch{border-left:1px solid rgba(0,0,0,0)}[dir=rtl] .mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch{border-left:none;border-right:1px solid rgba(0,0,0,0)}.mat-mdc-form-field-infix{min-height:var(--mat-form-field-container-height, 56px);padding-top:var(--mat-form-field-filled-with-label-container-padding-top, 24px);padding-bottom:var(--mat-form-field-filled-with-label-container-padding-bottom, 8px)}.mdc-text-field--outlined .mat-mdc-form-field-infix,.mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:var(--mat-form-field-container-vertical-padding, 16px);padding-bottom:var(--mat-form-field-container-vertical-padding, 16px)}.mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:calc(var(--mat-form-field-container-height, 56px)/2)}.mdc-text-field--filled .mat-mdc-floating-label{display:var(--mat-form-field-filled-label-display, block)}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{--mat-mdc-form-field-label-transform: translateY(calc(calc(6.75px + var(--mat-form-field-container-height, 56px) / 2) * -1)) scale(var(--mat-mdc-form-field-floating-label-scale, 0.75));transform:var(--mat-mdc-form-field-label-transform)}@keyframes _mat-form-field-subscript-animation{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.mat-mdc-form-field-subscript-wrapper{box-sizing:border-box;width:100%;position:relative}.mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field-error-wrapper{position:absolute;top:0;left:0;right:0;padding:0 16px;opacity:1;transform:translateY(0);animation:_mat-form-field-subscript-animation 0ms cubic-bezier(0.55, 0, 0.55, 0.2)}.mat-mdc-form-field-subscript-dynamic-size .mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field-subscript-dynamic-size .mat-mdc-form-field-error-wrapper{position:static}.mat-mdc-form-field-bottom-align::before{content:"";display:inline-block;height:16px}.mat-mdc-form-field-bottom-align.mat-mdc-form-field-subscript-dynamic-size::before{content:unset}.mat-mdc-form-field-hint-end{order:1}.mat-mdc-form-field-hint-wrapper{display:flex}.mat-mdc-form-field-hint-spacer{flex:1 0 1em}.mat-mdc-form-field-error{display:block;color:var(--mat-form-field-error-text-color, var(--mat-sys-error))}.mat-mdc-form-field-subscript-wrapper,.mat-mdc-form-field-bottom-align::before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mat-form-field-subscript-text-font, var(--mat-sys-body-small-font));line-height:var(--mat-form-field-subscript-text-line-height, var(--mat-sys-body-small-line-height));font-size:var(--mat-form-field-subscript-text-size, var(--mat-sys-body-small-size));letter-spacing:var(--mat-form-field-subscript-text-tracking, var(--mat-sys-body-small-tracking));font-weight:var(--mat-form-field-subscript-text-weight, var(--mat-sys-body-small-weight))}.mat-mdc-form-field-focus-overlay{top:0;left:0;right:0;bottom:0;position:absolute;opacity:0;pointer-events:none;background-color:var(--mat-form-field-state-layer-color, var(--mat-sys-on-surface))}.mat-mdc-text-field-wrapper:hover .mat-mdc-form-field-focus-overlay{opacity:var(--mat-form-field-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-form-field.mat-focused .mat-mdc-form-field-focus-overlay{opacity:var(--mat-form-field-focus-state-layer-opacity, 0)}select.mat-mdc-form-field-input-control{-moz-appearance:none;-webkit-appearance:none;background-color:rgba(0,0,0,0);display:inline-flex;box-sizing:border-box}select.mat-mdc-form-field-input-control:not(:disabled){cursor:pointer}select.mat-mdc-form-field-input-control:not(.mat-mdc-native-select-inline) option{color:var(--mat-form-field-select-option-text-color, var(--mat-sys-neutral10))}select.mat-mdc-form-field-input-control:not(.mat-mdc-native-select-inline) option:disabled{color:var(--mat-form-field-select-disabled-option-text-color, color-mix(in srgb, var(--mat-sys-neutral10) 38%, transparent))}.mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-infix::after{content:"";width:0;height:0;border-left:5px solid rgba(0,0,0,0);border-right:5px solid rgba(0,0,0,0);border-top:5px solid;position:absolute;right:0;top:50%;margin-top:-2.5px;pointer-events:none;color:var(--mat-form-field-enabled-select-arrow-color, var(--mat-sys-on-surface-variant))}[dir=rtl] .mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-infix::after{right:auto;left:0}.mat-mdc-form-field-type-mat-native-select.mat-focused .mat-mdc-form-field-infix::after{color:var(--mat-form-field-focus-select-arrow-color, var(--mat-sys-primary))}.mat-mdc-form-field-type-mat-native-select.mat-form-field-disabled .mat-mdc-form-field-infix::after{color:var(--mat-form-field-disabled-select-arrow-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-input-control{padding-right:15px}[dir=rtl] .mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-input-control{padding-right:0;padding-left:15px}@media(forced-colors: active){.mat-form-field-appearance-fill .mat-mdc-text-field-wrapper{outline:solid 1px}}@media(forced-colors: active){.mat-form-field-appearance-fill.mat-form-field-disabled .mat-mdc-text-field-wrapper{outline-color:GrayText}}@media(forced-colors: active){.mat-form-field-appearance-fill.mat-focused .mat-mdc-text-field-wrapper{outline:dashed 3px}}@media(forced-colors: active){.mat-mdc-form-field.mat-focused .mdc-notched-outline{border:dashed 3px}}.mat-mdc-form-field-input-control[type=date],.mat-mdc-form-field-input-control[type=datetime],.mat-mdc-form-field-input-control[type=datetime-local],.mat-mdc-form-field-input-control[type=month],.mat-mdc-form-field-input-control[type=week],.mat-mdc-form-field-input-control[type=time]{line-height:1}.mat-mdc-form-field-input-control::-webkit-datetime-edit{line-height:1;padding:0;margin-bottom:-2px}.mat-mdc-form-field{--mat-mdc-form-field-floating-label-scale: 0.75;display:inline-flex;flex-direction:column;min-width:0;text-align:left;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mat-form-field-container-text-font, var(--mat-sys-body-large-font));line-height:var(--mat-form-field-container-text-line-height, var(--mat-sys-body-large-line-height));font-size:var(--mat-form-field-container-text-size, var(--mat-sys-body-large-size));letter-spacing:var(--mat-form-field-container-text-tracking, var(--mat-sys-body-large-tracking));font-weight:var(--mat-form-field-container-text-weight, var(--mat-sys-body-large-weight))}.mat-mdc-form-field .mdc-text-field--outlined .mdc-floating-label--float-above{font-size:calc(var(--mat-form-field-outlined-label-text-populated-size)*var(--mat-mdc-form-field-floating-label-scale))}.mat-mdc-form-field .mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:var(--mat-form-field-outlined-label-text-populated-size)}[dir=rtl] .mat-mdc-form-field{text-align:right}.mat-mdc-form-field-flex{display:inline-flex;align-items:baseline;box-sizing:border-box;width:100%}.mat-mdc-text-field-wrapper{width:100%;z-index:0}.mat-mdc-form-field-icon-prefix,.mat-mdc-form-field-icon-suffix{align-self:center;line-height:0;pointer-events:auto;position:relative;z-index:1}.mat-mdc-form-field-icon-prefix>.mat-icon,.mat-mdc-form-field-icon-suffix>.mat-icon{padding:0 12px;box-sizing:content-box}.mat-mdc-form-field-icon-prefix{color:var(--mat-form-field-leading-icon-color, var(--mat-sys-on-surface-variant))}.mat-form-field-disabled .mat-mdc-form-field-icon-prefix{color:var(--mat-form-field-disabled-leading-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-trailing-icon-color, var(--mat-sys-on-surface-variant))}.mat-form-field-disabled .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-disabled-trailing-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-invalid .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-trailing-icon-color, var(--mat-sys-error))}.mat-form-field-invalid:not(.mat-focused):not(.mat-form-field-disabled) .mat-mdc-text-field-wrapper:hover .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-hover-trailing-icon-color, var(--mat-sys-on-error-container))}.mat-form-field-invalid.mat-focused .mat-mdc-text-field-wrapper .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-focus-trailing-icon-color, var(--mat-sys-error))}.mat-mdc-form-field-icon-prefix,[dir=rtl] .mat-mdc-form-field-icon-suffix{padding:0 4px 0 0}.mat-mdc-form-field-icon-suffix,[dir=rtl] .mat-mdc-form-field-icon-prefix{padding:0 0 0 4px}.mat-mdc-form-field-subscript-wrapper .mat-icon,.mat-mdc-form-field label .mat-icon{width:1em;height:1em;font-size:inherit}.mat-mdc-form-field-infix{flex:auto;min-width:0;width:180px;position:relative;box-sizing:border-box}.mat-mdc-form-field-infix:has(textarea[cols]){width:auto}.mat-mdc-form-field .mdc-notched-outline__notch{margin-left:-1px;-webkit-clip-path:inset(-9em -999em -9em 1px);clip-path:inset(-9em -999em -9em 1px)}[dir=rtl] .mat-mdc-form-field .mdc-notched-outline__notch{margin-left:0;margin-right:-1px;-webkit-clip-path:inset(-9em 1px -9em -999em);clip-path:inset(-9em 1px -9em -999em)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-floating-label{transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::-moz-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::-webkit-input-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input:-ms-input-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::-moz-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::-moz-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::-webkit-input-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::-webkit-input-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before{transition-duration:75ms}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field.mat-form-field-animations-enabled .mat-mdc-form-field-error-wrapper{animation-duration:300ms}.mdc-notched-outline .mdc-floating-label{max-width:calc(100% + 1px)}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(133.3333333333% + 1px)}\n'],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormField, [{
type: Component,
args: [{
selector: "mat-form-field",
exportAs: "matFormField",
host: {
"class": "mat-mdc-form-field",
"[class.mat-mdc-form-field-label-always-float]": "_shouldAlwaysFloat()",
"[class.mat-mdc-form-field-has-icon-prefix]": "_hasIconPrefix",
"[class.mat-mdc-form-field-has-icon-suffix]": "_hasIconSuffix",
// Note that these classes reuse the same names as the non-MDC version, because they can be
// considered a public API since custom form controls may use them to style themselves.
// See https://github.com/angular/components/pull/20502#discussion_r486124901.
"[class.mat-form-field-invalid]": "_control.errorState",
"[class.mat-form-field-disabled]": "_control.disabled",
"[class.mat-form-field-autofilled]": "_control.autofilled",
"[class.mat-form-field-appearance-fill]": 'appearance == "fill"',
"[class.mat-form-field-appearance-outline]": 'appearance == "outline"',
"[class.mat-form-field-hide-placeholder]": "_hasFloatingLabel() && !_shouldLabelFloat()",
"[class.mat-focused]": "_control.focused",
"[class.mat-primary]": 'color !== "accent" && color !== "warn"',
"[class.mat-accent]": 'color === "accent"',
"[class.mat-warn]": 'color === "warn"',
"[class.ng-untouched]": '_shouldForward("untouched")',
"[class.ng-touched]": '_shouldForward("touched")',
"[class.ng-pristine]": '_shouldForward("pristine")',
"[class.ng-dirty]": '_shouldForward("dirty")',
"[class.ng-valid]": '_shouldForward("valid")',
"[class.ng-invalid]": '_shouldForward("invalid")',
"[class.ng-pending]": '_shouldForward("pending")'
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [{
provide: MAT_FORM_FIELD,
useExisting: MatFormField
}, {
provide: FLOATING_LABEL_PARENT,
useExisting: MatFormField
}],
imports: [MatFormFieldFloatingLabel, MatFormFieldNotchedOutline, NgTemplateOutlet, MatFormFieldLineRipple, MatHint],
template: '<ng-template #labelTemplate>\n <!--\n MDC recommends that the text-field is a `<label>` element. This rather complicates the\n setup because it would require every form-field control to explicitly set `aria-labelledby`.\n This is because the `<label>` itself contains more than the actual label (e.g. prefix, suffix\n or other projected content), and screen readers could potentially read out undesired content.\n Excluding elements from being printed out requires them to be marked with `aria-hidden`, or\n the form control is set to a scoped element for the label (using `aria-labelledby`). Both of\n these options seem to complicate the setup because we know exactly what content is rendered\n as part of the label, and we don\'t want to spend resources on walking through projected content\n to set `aria-hidden`. Nor do we want to set `aria-labelledby` on every form control if we could\n simply link the label to the control using the label `for` attribute.\n -->\n @if (_hasFloatingLabel()) {\n <label\n matFormFieldFloatingLabel\n [floating]="_shouldLabelFloat()"\n [monitorResize]="_hasOutline()"\n [id]="_labelId"\n [attr.for]="_control.disableAutomaticLabeling ? null : _control.id"\n >\n <ng-content select="mat-label"></ng-content>\n <!--\n We set the required marker as a separate element, in order to make it easier to target if\n apps want to override it and to be able to set `aria-hidden` so that screen readers don\'t\n pick it up.\n -->\n @if (!hideRequiredMarker && _control.required) {\n <span\n aria-hidden="true"\n class="mat-mdc-form-field-required-marker mdc-floating-label--required"\n ></span>\n }\n </label>\n }\n</ng-template>\n\n<div\n class="mat-mdc-text-field-wrapper mdc-text-field"\n #textField\n [class.mdc-text-field--filled]="!_hasOutline()"\n [class.mdc-text-field--outlined]="_hasOutline()"\n [class.mdc-text-field--no-label]="!_hasFloatingLabel()"\n [class.mdc-text-field--disabled]="_control.disabled"\n [class.mdc-text-field--invalid]="_control.errorState"\n (click)="_control.onContainerClick($event)"\n>\n @if (!_hasOutline() && !_control.disabled) {\n <div class="mat-mdc-form-field-focus-overlay"></div>\n }\n <div class="mat-mdc-form-field-flex">\n @if (_hasOutline()) {\n <div matFormFieldNotchedOutline [matFormFieldNotchedOutlineOpen]="_shouldLabelFloat()">\n @if (!_forceDisplayInfixLabel()) {\n <ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>\n }\n </div>\n }\n\n @if (_hasIconPrefix) {\n <div class="mat-mdc-form-field-icon-prefix" #iconPrefixContainer>\n <ng-content select="[matPrefix], [matIconPrefix]"></ng-content>\n </div>\n }\n\n @if (_hasTextPrefix) {\n <div class="mat-mdc-form-field-text-prefix" #textPrefixContainer>\n <ng-content select="[matTextPrefix]"></ng-content>\n </div>\n }\n\n <div class="mat-mdc-form-field-infix">\n @if (!_hasOutline() || _forceDisplayInfixLabel()) {\n <ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>\n }\n\n <ng-content></ng-content>\n </div>\n\n @if (_hasTextSuffix) {\n <div class="mat-mdc-form-field-text-suffix" #textSuffixContainer>\n <ng-content select="[matTextSuffix]"></ng-content>\n </div>\n }\n\n @if (_hasIconSuffix) {\n <div class="mat-mdc-form-field-icon-suffix" #iconSuffixContainer>\n <ng-content select="[matSuffix], [matIconSuffix]"></ng-content>\n </div>\n }\n </div>\n\n @if (!_hasOutline()) {\n <div matFormFieldLineRipple></div>\n }\n</div>\n\n<div\n class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"\n [class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === \'dynamic\'"\n>\n @let subscriptMessageType = _getSubscriptMessageType();\n\n <!-- \n Use a single permanent wrapper for both hints and errors so aria-live works correctly,\n as having it appear post render will not consistently work. We also do not want to add\n additional divs as it causes styling regressions.\n -->\n <div aria-atomic="true" aria-live="polite" \n [class.mat-mdc-form-field-error-wrapper]="subscriptMessageType === \'error\'"\n [class.mat-mdc-form-field-hint-wrapper]="subscriptMessageType === \'hint\'"\n >\n @switch (subscriptMessageType) {\n @case (\'error\') {\n <ng-content select="mat-error, [matError]"></ng-content>\n }\n\n @case (\'hint\') {\n @if (hintLabel) {\n <mat-hint [id]="_hintLabelId">{{hintLabel}}</mat-hint>\n }\n <ng-content select="mat-hint:not([align=\'end\'])"></ng-content>\n <div class="mat-mdc-form-field-hint-spacer"></div>\n <ng-content select="mat-hint[align=\'end\']"></ng-content>\n }\n }\n </div>\n</div>\n',
styles: ['.mdc-text-field{display:inline-flex;align-items:baseline;padding:0 16px;position:relative;box-sizing:border-box;overflow:hidden;will-change:opacity,transform,color;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.mdc-text-field__input{width:100%;min-width:0;border:none;border-radius:0;background:none;padding:0;-moz-appearance:none;-webkit-appearance:none;height:28px}.mdc-text-field__input::-webkit-calendar-picker-indicator{display:none}.mdc-text-field__input::-ms-clear{display:none}.mdc-text-field__input:focus{outline:none}.mdc-text-field__input:invalid{box-shadow:none}.mdc-text-field__input::placeholder{opacity:0}.mdc-text-field__input::-moz-placeholder{opacity:0}.mdc-text-field__input::-webkit-input-placeholder{opacity:0}.mdc-text-field__input:-ms-input-placeholder{opacity:0}.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mdc-text-field--focused .mdc-text-field__input::placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input::-moz-placeholder,.mdc-text-field--focused .mdc-text-field__input::-moz-placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input::-webkit-input-placeholder,.mdc-text-field--focused .mdc-text-field__input::-webkit-input-placeholder{opacity:1}.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{opacity:1}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::-moz-placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive::-webkit-input-placeholder{opacity:0}.mdc-text-field--disabled:not(.mdc-text-field--no-label) .mdc-text-field__input.mat-mdc-input-disabled-interactive:-ms-input-placeholder{opacity:0}.mdc-text-field--outlined .mdc-text-field__input,.mdc-text-field--filled.mdc-text-field--no-label .mdc-text-field__input{height:100%}.mdc-text-field--outlined .mdc-text-field__input{display:flex;border:none !important;background-color:rgba(0,0,0,0)}.mdc-text-field--disabled .mdc-text-field__input{pointer-events:auto}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input{color:var(--mdc-filled-text-field-input-text-color, var(--mat-sys-on-surface));caret-color:var(--mdc-filled-text-field-caret-color, var(--mat-sys-primary))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::-moz-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input::-webkit-input-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:var(--mdc-filled-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__input{caret-color:var(--mdc-filled-text-field-error-caret-color)}.mdc-text-field--filled.mdc-text-field--disabled .mdc-text-field__input{color:var(--mdc-filled-text-field-disabled-input-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input{color:var(--mdc-outlined-text-field-input-text-color, var(--mat-sys-on-surface));caret-color:var(--mdc-outlined-text-field-caret-color, var(--mat-sys-primary))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::-moz-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input::-webkit-input-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-text-field__input:-ms-input-placeholder{color:var(--mdc-outlined-text-field-input-text-placeholder-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-text-field__input{caret-color:var(--mdc-outlined-text-field-error-caret-color)}.mdc-text-field--outlined.mdc-text-field--disabled .mdc-text-field__input{color:var(--mdc-outlined-text-field-disabled-input-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}@media(forced-colors: active){.mdc-text-field--disabled .mdc-text-field__input{background-color:Window}}.mdc-text-field--filled{height:56px;border-bottom-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:var(--mdc-filled-text-field-container-shape, var(--mat-sys-corner-extra-small));border-top-right-radius:var(--mdc-filled-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-text-field--filled:not(.mdc-text-field--disabled){background-color:var(--mdc-filled-text-field-container-color, var(--mat-sys-surface-variant))}.mdc-text-field--filled.mdc-text-field--disabled{background-color:var(--mdc-filled-text-field-disabled-container-color, color-mix(in srgb, var(--mat-sys-on-surface) 4%, transparent))}.mdc-text-field--outlined{height:56px;overflow:visible;padding-right:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)));padding-left:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)) + 4px)}[dir=rtl] .mdc-text-field--outlined{padding-right:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)) + 4px);padding-left:max(16px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))}.mdc-floating-label{position:absolute;left:0;transform-origin:left top;line-height:1.15rem;text-align:left;text-overflow:ellipsis;white-space:nowrap;cursor:text;overflow:hidden;will-change:transform}[dir=rtl] .mdc-floating-label{right:0;left:auto;transform-origin:right top;text-align:right}.mdc-text-field .mdc-floating-label{top:50%;transform:translateY(-50%);pointer-events:none}.mdc-notched-outline .mdc-floating-label{display:inline-block;position:relative;max-width:100%}.mdc-text-field--outlined .mdc-floating-label{left:4px;right:auto}[dir=rtl] .mdc-text-field--outlined .mdc-floating-label{left:auto;right:4px}.mdc-text-field--filled .mdc-floating-label{left:16px;right:auto}[dir=rtl] .mdc-text-field--filled .mdc-floating-label{left:auto;right:16px}.mdc-text-field--disabled .mdc-floating-label{cursor:default}@media(forced-colors: active){.mdc-text-field--disabled .mdc-floating-label{z-index:1}}.mdc-text-field--filled.mdc-text-field--no-label .mdc-floating-label{display:none}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-floating-label{color:var(--mdc-filled-text-field-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label{color:var(--mdc-filled-text-field-focus-label-text-color, var(--mat-sys-primary))}.mdc-text-field--filled:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-floating-label{color:var(--mdc-filled-text-field-hover-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled.mdc-text-field--disabled .mdc-floating-label{color:var(--mdc-filled-text-field-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-floating-label{color:var(--mdc-filled-text-field-error-label-text-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mdc-floating-label{color:var(--mdc-filled-text-field-error-focus-label-text-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-floating-label{color:var(--mdc-filled-text-field-error-hover-label-text-color, var(--mat-sys-on-error-container))}.mdc-text-field--filled .mdc-floating-label{font-family:var(--mdc-filled-text-field-label-text-font, var(--mat-sys-body-large-font));font-size:var(--mdc-filled-text-field-label-text-size, var(--mat-sys-body-large-size));font-weight:var(--mdc-filled-text-field-label-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mdc-filled-text-field-label-text-tracking, var(--mat-sys-body-large-tracking))}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mdc-floating-label{color:var(--mdc-outlined-text-field-label-text-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-floating-label{color:var(--mdc-outlined-text-field-focus-label-text-color, var(--mat-sys-primary))}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-floating-label{color:var(--mdc-outlined-text-field-hover-label-text-color, var(--mat-sys-on-surface))}.mdc-text-field--outlined.mdc-text-field--disabled .mdc-floating-label{color:var(--mdc-outlined-text-field-disabled-label-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-floating-label{color:var(--mdc-outlined-text-field-error-label-text-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mdc-floating-label{color:var(--mdc-outlined-text-field-error-focus-label-text-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--disabled):hover .mdc-floating-label{color:var(--mdc-outlined-text-field-error-hover-label-text-color, var(--mat-sys-on-error-container))}.mdc-text-field--outlined .mdc-floating-label{font-family:var(--mdc-outlined-text-field-label-text-font, var(--mat-sys-body-large-font));font-size:var(--mdc-outlined-text-field-label-text-size, var(--mat-sys-body-large-size));font-weight:var(--mdc-outlined-text-field-label-text-weight, var(--mat-sys-body-large-weight));letter-spacing:var(--mdc-outlined-text-field-label-text-tracking, var(--mat-sys-body-large-tracking))}.mdc-floating-label--float-above{cursor:auto;transform:translateY(-106%) scale(0.75)}.mdc-text-field--filled .mdc-floating-label--float-above{transform:translateY(-106%) scale(0.75)}.mdc-text-field--outlined .mdc-floating-label--float-above{transform:translateY(-37.25px) scale(1);font-size:.75rem}.mdc-notched-outline .mdc-floating-label--float-above{text-overflow:clip}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:133.3333333333%}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{transform:translateY(-34.75px) scale(0.75)}.mdc-text-field--outlined.mdc-notched-outline--upgraded .mdc-floating-label--float-above,.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:1rem}.mdc-floating-label--required:not(.mdc-floating-label--hide-required-marker)::after{margin-left:1px;margin-right:0;content:"*"}[dir=rtl] .mdc-floating-label--required:not(.mdc-floating-label--hide-required-marker)::after{margin-left:0;margin-right:1px}.mdc-notched-outline{display:flex;position:absolute;top:0;right:0;left:0;box-sizing:border-box;width:100%;max-width:100%;height:100%;text-align:left;pointer-events:none}[dir=rtl] .mdc-notched-outline{text-align:right}.mdc-text-field--outlined .mdc-notched-outline{z-index:1}.mat-mdc-notch-piece{box-sizing:border-box;height:100%;pointer-events:none;border-top:1px solid;border-bottom:1px solid}.mdc-text-field--focused .mat-mdc-notch-piece{border-width:2px}.mdc-text-field--outlined:not(.mdc-text-field--disabled) .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-outline-color, var(--mat-sys-outline));border-width:var(--mdc-outlined-text-field-outline-width, 1px)}.mdc-text-field--outlined:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-hover-outline-color, var(--mat-sys-on-surface))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-focus-outline-color, var(--mat-sys-primary))}.mdc-text-field--outlined.mdc-text-field--disabled .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-disabled-outline-color, color-mix(in srgb, var(--mat-sys-on-surface) 12%, transparent))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-outline-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--focused):hover .mdc-notched-outline .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-hover-outline-color, var(--mat-sys-on-error-container))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--invalid.mdc-text-field--focused .mat-mdc-notch-piece{border-color:var(--mdc-outlined-text-field-error-focus-outline-color, var(--mat-sys-error))}.mdc-text-field--outlined:not(.mdc-text-field--disabled).mdc-text-field--focused .mdc-notched-outline .mat-mdc-notch-piece{border-width:var(--mdc-outlined-text-field-focus-outline-width, 2px)}.mdc-notched-outline__leading{border-left:1px solid;border-right:none;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__leading{width:max(12px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))}[dir=rtl] .mdc-notched-outline__leading{border-left:none;border-right:1px solid;border-bottom-left-radius:0;border-top-left-radius:0;border-top-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-notched-outline__trailing{flex-grow:1;border-left:none;border-right:1px solid;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-right-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}[dir=rtl] .mdc-notched-outline__trailing{border-left:1px solid;border-right:none;border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small));border-bottom-left-radius:var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small))}.mdc-notched-outline__notch{flex:0 0 auto;width:auto}.mdc-text-field--outlined .mdc-notched-outline .mdc-notched-outline__notch{max-width:min(var(--mat-form-field-notch-max-width, 100%),100% - max(12px,var(--mdc-outlined-text-field-container-shape, var(--mat-sys-corner-extra-small)))*2)}.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:1px}.mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-top:2px}.mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:0;padding-right:8px;border-top:none;--mat-form-field-notch-max-width: 100%}[dir=rtl] .mdc-notched-outline--notched .mdc-notched-outline__notch{padding-left:8px;padding-right:0}.mdc-notched-outline--no-label .mdc-notched-outline__notch{display:none}.mdc-line-ripple::before,.mdc-line-ripple::after{position:absolute;bottom:0;left:0;width:100%;border-bottom-style:solid;content:""}.mdc-line-ripple::before{z-index:1;border-bottom-width:var(--mdc-filled-text-field-active-indicator-height, 1px)}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-active-indicator-color, var(--mat-sys-on-surface-variant))}.mdc-text-field--filled:not(.mdc-text-field--disabled):not(.mdc-text-field--focused):hover .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-hover-active-indicator-color, var(--mat-sys-on-surface))}.mdc-text-field--filled.mdc-text-field--disabled .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-disabled-active-indicator-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-error-active-indicator-color, var(--mat-sys-error))}.mdc-text-field--filled:not(.mdc-text-field--disabled).mdc-text-field--invalid:not(.mdc-text-field--focused):hover .mdc-line-ripple::before{border-bottom-color:var(--mdc-filled-text-field-error-hover-active-indicator-color, var(--mat-sys-on-error-container))}.mdc-line-ripple::after{transform:scaleX(0);opacity:0;z-index:2}.mdc-text-field--filled .mdc-line-ripple::after{border-bottom-width:var(--mdc-filled-text-field-focus-active-indicator-height, 2px)}.mdc-text-field--filled:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:var(--mdc-filled-text-field-focus-active-indicator-color, var(--mat-sys-primary))}.mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) .mdc-line-ripple::after{border-bottom-color:var(--mdc-filled-text-field-error-focus-active-indicator-color, var(--mat-sys-error))}.mdc-line-ripple--active::after{transform:scaleX(1);opacity:1}.mdc-line-ripple--deactivating::after{opacity:0}.mdc-text-field--disabled{pointer-events:none}.mat-mdc-form-field-textarea-control{vertical-align:middle;resize:vertical;box-sizing:border-box;height:auto;margin:0;padding:0;border:none;overflow:auto}.mat-mdc-form-field-input-control.mat-mdc-form-field-input-control{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font:inherit;letter-spacing:inherit;text-decoration:inherit;text-transform:inherit;border:none}.mat-mdc-form-field .mat-mdc-floating-label.mdc-floating-label{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;line-height:normal;pointer-events:all;will-change:auto}.mat-mdc-form-field:not(.mat-form-field-disabled) .mat-mdc-floating-label.mdc-floating-label{cursor:inherit}.mdc-text-field--no-label:not(.mdc-text-field--textarea) .mat-mdc-form-field-input-control.mdc-text-field__input,.mat-mdc-text-field-wrapper .mat-mdc-form-field-input-control{height:auto}.mat-mdc-text-field-wrapper .mat-mdc-form-field-input-control.mdc-text-field__input[type=color]{height:23px}.mat-mdc-text-field-wrapper{height:auto;flex:auto;will-change:auto}.mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper{padding-left:0;--mat-mdc-form-field-label-offset-x: -16px}.mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper{padding-right:0}[dir=rtl] .mat-mdc-text-field-wrapper{padding-left:16px;padding-right:16px}[dir=rtl] .mat-mdc-form-field-has-icon-suffix .mat-mdc-text-field-wrapper{padding-left:0}[dir=rtl] .mat-mdc-form-field-has-icon-prefix .mat-mdc-text-field-wrapper{padding-right:0}.mat-form-field-disabled .mdc-text-field__input::placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input::-moz-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input::-webkit-input-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-disabled .mdc-text-field__input:-ms-input-placeholder{color:var(--mat-form-field-disabled-input-text-placeholder-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-label-always-float .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms;opacity:1}.mat-mdc-text-field-wrapper .mat-mdc-form-field-infix .mat-mdc-floating-label{left:auto;right:auto}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-text-field__input{display:inline-block}.mat-mdc-form-field .mat-mdc-text-field-wrapper.mdc-text-field .mdc-notched-outline__notch{padding-top:0}.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch{border-left:1px solid rgba(0,0,0,0)}[dir=rtl] .mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field.mat-mdc-form-field .mdc-notched-outline__notch{border-left:none;border-right:1px solid rgba(0,0,0,0)}.mat-mdc-form-field-infix{min-height:var(--mat-form-field-container-height, 56px);padding-top:var(--mat-form-field-filled-with-label-container-padding-top, 24px);padding-bottom:var(--mat-form-field-filled-with-label-container-padding-bottom, 8px)}.mdc-text-field--outlined .mat-mdc-form-field-infix,.mdc-text-field--no-label .mat-mdc-form-field-infix{padding-top:var(--mat-form-field-container-vertical-padding, 16px);padding-bottom:var(--mat-form-field-container-vertical-padding, 16px)}.mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-floating-label{top:calc(var(--mat-form-field-container-height, 56px)/2)}.mdc-text-field--filled .mat-mdc-floating-label{display:var(--mat-form-field-filled-label-display, block)}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{--mat-mdc-form-field-label-transform: translateY(calc(calc(6.75px + var(--mat-form-field-container-height, 56px) / 2) * -1)) scale(var(--mat-mdc-form-field-floating-label-scale, 0.75));transform:var(--mat-mdc-form-field-label-transform)}@keyframes _mat-form-field-subscript-animation{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.mat-mdc-form-field-subscript-wrapper{box-sizing:border-box;width:100%;position:relative}.mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field-error-wrapper{position:absolute;top:0;left:0;right:0;padding:0 16px;opacity:1;transform:translateY(0);animation:_mat-form-field-subscript-animation 0ms cubic-bezier(0.55, 0, 0.55, 0.2)}.mat-mdc-form-field-subscript-dynamic-size .mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field-subscript-dynamic-size .mat-mdc-form-field-error-wrapper{position:static}.mat-mdc-form-field-bottom-align::before{content:"";display:inline-block;height:16px}.mat-mdc-form-field-bottom-align.mat-mdc-form-field-subscript-dynamic-size::before{content:unset}.mat-mdc-form-field-hint-end{order:1}.mat-mdc-form-field-hint-wrapper{display:flex}.mat-mdc-form-field-hint-spacer{flex:1 0 1em}.mat-mdc-form-field-error{display:block;color:var(--mat-form-field-error-text-color, var(--mat-sys-error))}.mat-mdc-form-field-subscript-wrapper,.mat-mdc-form-field-bottom-align::before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mat-form-field-subscript-text-font, var(--mat-sys-body-small-font));line-height:var(--mat-form-field-subscript-text-line-height, var(--mat-sys-body-small-line-height));font-size:var(--mat-form-field-subscript-text-size, var(--mat-sys-body-small-size));letter-spacing:var(--mat-form-field-subscript-text-tracking, var(--mat-sys-body-small-tracking));font-weight:var(--mat-form-field-subscript-text-weight, var(--mat-sys-body-small-weight))}.mat-mdc-form-field-focus-overlay{top:0;left:0;right:0;bottom:0;position:absolute;opacity:0;pointer-events:none;background-color:var(--mat-form-field-state-layer-color, var(--mat-sys-on-surface))}.mat-mdc-text-field-wrapper:hover .mat-mdc-form-field-focus-overlay{opacity:var(--mat-form-field-hover-state-layer-opacity, var(--mat-sys-hover-state-layer-opacity))}.mat-mdc-form-field.mat-focused .mat-mdc-form-field-focus-overlay{opacity:var(--mat-form-field-focus-state-layer-opacity, 0)}select.mat-mdc-form-field-input-control{-moz-appearance:none;-webkit-appearance:none;background-color:rgba(0,0,0,0);display:inline-flex;box-sizing:border-box}select.mat-mdc-form-field-input-control:not(:disabled){cursor:pointer}select.mat-mdc-form-field-input-control:not(.mat-mdc-native-select-inline) option{color:var(--mat-form-field-select-option-text-color, var(--mat-sys-neutral10))}select.mat-mdc-form-field-input-control:not(.mat-mdc-native-select-inline) option:disabled{color:var(--mat-form-field-select-disabled-option-text-color, color-mix(in srgb, var(--mat-sys-neutral10) 38%, transparent))}.mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-infix::after{content:"";width:0;height:0;border-left:5px solid rgba(0,0,0,0);border-right:5px solid rgba(0,0,0,0);border-top:5px solid;position:absolute;right:0;top:50%;margin-top:-2.5px;pointer-events:none;color:var(--mat-form-field-enabled-select-arrow-color, var(--mat-sys-on-surface-variant))}[dir=rtl] .mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-infix::after{right:auto;left:0}.mat-mdc-form-field-type-mat-native-select.mat-focused .mat-mdc-form-field-infix::after{color:var(--mat-form-field-focus-select-arrow-color, var(--mat-sys-primary))}.mat-mdc-form-field-type-mat-native-select.mat-form-field-disabled .mat-mdc-form-field-infix::after{color:var(--mat-form-field-disabled-select-arrow-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-input-control{padding-right:15px}[dir=rtl] .mat-mdc-form-field-type-mat-native-select .mat-mdc-form-field-input-control{padding-right:0;padding-left:15px}@media(forced-colors: active){.mat-form-field-appearance-fill .mat-mdc-text-field-wrapper{outline:solid 1px}}@media(forced-colors: active){.mat-form-field-appearance-fill.mat-form-field-disabled .mat-mdc-text-field-wrapper{outline-color:GrayText}}@media(forced-colors: active){.mat-form-field-appearance-fill.mat-focused .mat-mdc-text-field-wrapper{outline:dashed 3px}}@media(forced-colors: active){.mat-mdc-form-field.mat-focused .mdc-notched-outline{border:dashed 3px}}.mat-mdc-form-field-input-control[type=date],.mat-mdc-form-field-input-control[type=datetime],.mat-mdc-form-field-input-control[type=datetime-local],.mat-mdc-form-field-input-control[type=month],.mat-mdc-form-field-input-control[type=week],.mat-mdc-form-field-input-control[type=time]{line-height:1}.mat-mdc-form-field-input-control::-webkit-datetime-edit{line-height:1;padding:0;margin-bottom:-2px}.mat-mdc-form-field{--mat-mdc-form-field-floating-label-scale: 0.75;display:inline-flex;flex-direction:column;min-width:0;text-align:left;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--mat-form-field-container-text-font, var(--mat-sys-body-large-font));line-height:var(--mat-form-field-container-text-line-height, var(--mat-sys-body-large-line-height));font-size:var(--mat-form-field-container-text-size, var(--mat-sys-body-large-size));letter-spacing:var(--mat-form-field-container-text-tracking, var(--mat-sys-body-large-tracking));font-weight:var(--mat-form-field-container-text-weight, var(--mat-sys-body-large-weight))}.mat-mdc-form-field .mdc-text-field--outlined .mdc-floating-label--float-above{font-size:calc(var(--mat-form-field-outlined-label-text-populated-size)*var(--mat-mdc-form-field-floating-label-scale))}.mat-mdc-form-field .mdc-text-field--outlined .mdc-notched-outline--upgraded .mdc-floating-label--float-above{font-size:var(--mat-form-field-outlined-label-text-populated-size)}[dir=rtl] .mat-mdc-form-field{text-align:right}.mat-mdc-form-field-flex{display:inline-flex;align-items:baseline;box-sizing:border-box;width:100%}.mat-mdc-text-field-wrapper{width:100%;z-index:0}.mat-mdc-form-field-icon-prefix,.mat-mdc-form-field-icon-suffix{align-self:center;line-height:0;pointer-events:auto;position:relative;z-index:1}.mat-mdc-form-field-icon-prefix>.mat-icon,.mat-mdc-form-field-icon-suffix>.mat-icon{padding:0 12px;box-sizing:content-box}.mat-mdc-form-field-icon-prefix{color:var(--mat-form-field-leading-icon-color, var(--mat-sys-on-surface-variant))}.mat-form-field-disabled .mat-mdc-form-field-icon-prefix{color:var(--mat-form-field-disabled-leading-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-trailing-icon-color, var(--mat-sys-on-surface-variant))}.mat-form-field-disabled .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-disabled-trailing-icon-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-invalid .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-trailing-icon-color, var(--mat-sys-error))}.mat-form-field-invalid:not(.mat-focused):not(.mat-form-field-disabled) .mat-mdc-text-field-wrapper:hover .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-hover-trailing-icon-color, var(--mat-sys-on-error-container))}.mat-form-field-invalid.mat-focused .mat-mdc-text-field-wrapper .mat-mdc-form-field-icon-suffix{color:var(--mat-form-field-error-focus-trailing-icon-color, var(--mat-sys-error))}.mat-mdc-form-field-icon-prefix,[dir=rtl] .mat-mdc-form-field-icon-suffix{padding:0 4px 0 0}.mat-mdc-form-field-icon-suffix,[dir=rtl] .mat-mdc-form-field-icon-prefix{padding:0 0 0 4px}.mat-mdc-form-field-subscript-wrapper .mat-icon,.mat-mdc-form-field label .mat-icon{width:1em;height:1em;font-size:inherit}.mat-mdc-form-field-infix{flex:auto;min-width:0;width:180px;position:relative;box-sizing:border-box}.mat-mdc-form-field-infix:has(textarea[cols]){width:auto}.mat-mdc-form-field .mdc-notched-outline__notch{margin-left:-1px;-webkit-clip-path:inset(-9em -999em -9em 1px);clip-path:inset(-9em -999em -9em 1px)}[dir=rtl] .mat-mdc-form-field .mdc-notched-outline__notch{margin-left:0;margin-right:-1px;-webkit-clip-path:inset(-9em 1px -9em -999em);clip-path:inset(-9em 1px -9em -999em)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-floating-label{transition:transform 150ms cubic-bezier(0.4, 0, 0.2, 1),color 150ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input{transition:opacity 150ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::-moz-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input::-webkit-input-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field__input:-ms-input-placeholder{transition:opacity 67ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::-moz-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::-moz-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input::-webkit-input-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input::-webkit-input-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--no-label .mdc-text-field__input:-ms-input-placeholder,.mat-mdc-form-field.mat-form-field-animations-enabled.mdc-text-field--focused .mdc-text-field__input:-ms-input-placeholder{transition-delay:40ms;transition-duration:110ms}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before{transition-duration:75ms}.mat-mdc-form-field.mat-form-field-animations-enabled .mdc-line-ripple::after{transition:transform 180ms cubic-bezier(0.4, 0, 0.2, 1),opacity 180ms cubic-bezier(0.4, 0, 0.2, 1)}.mat-mdc-form-field.mat-form-field-animations-enabled .mat-mdc-form-field-hint-wrapper,.mat-mdc-form-field.mat-form-field-animations-enabled .mat-mdc-form-field-error-wrapper{animation-duration:300ms}.mdc-notched-outline .mdc-floating-label{max-width:calc(100% + 1px)}.mdc-notched-outline--upgraded .mdc-floating-label--float-above{max-width:calc(133.3333333333% + 1px)}\n']
}]
}], () => [], {
_textField: [{
type: ViewChild,
args: ["textField"]
}],
_iconPrefixContainer: [{
type: ViewChild,
args: ["iconPrefixContainer"]
}],
_textPrefixContainer: [{
type: ViewChild,
args: ["textPrefixContainer"]
}],
_iconSuffixContainer: [{
type: ViewChild,
args: ["iconSuffixContainer"]
}],
_textSuffixContainer: [{
type: ViewChild,
args: ["textSuffixContainer"]
}],
_floatingLabel: [{
type: ViewChild,
args: [MatFormFieldFloatingLabel]
}],
_notchedOutline: [{
type: ViewChild,
args: [MatFormFieldNotchedOutline]
}],
_lineRipple: [{
type: ViewChild,
args: [MatFormFieldLineRipple]
}],
_formFieldControl: [{
type: ContentChild,
args: [MatFormFieldControl]
}],
_prefixChildren: [{
type: ContentChildren,
args: [MAT_PREFIX, {
descendants: true
}]
}],
_suffixChildren: [{
type: ContentChildren,
args: [MAT_SUFFIX, {
descendants: true
}]
}],
_errorChildren: [{
type: ContentChildren,
args: [MAT_ERROR, {
descendants: true
}]
}],
_hintChildren: [{
type: ContentChildren,
args: [MatHint, {
descendants: true
}]
}],
hideRequiredMarker: [{
type: Input
}],
color: [{
type: Input
}],
floatLabel: [{
type: Input
}],
appearance: [{
type: Input
}],
subscriptSizing: [{
type: Input
}],
hintLabel: [{
type: Input
}]
});
})();
// node_modules/@angular/material/fesm2022/module-BXZhw7pQ.mjs
var MatFormFieldModule = class _MatFormFieldModule {
static \u0275fac = function MatFormFieldModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatFormFieldModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatFormFieldModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, ObserversModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatFormFieldModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, ObserversModule, MatFormField, MatLabel, MatError, MatHint, MatPrefix, MatSuffix],
exports: [MatFormField, MatLabel, MatHint, MatError, MatPrefix, MatSuffix, MatCommonModule]
}]
}], null, null);
})();
// node_modules/@angular/cdk/fesm2022/text-field.mjs
var _CdkTextFieldStyleLoader = class __CdkTextFieldStyleLoader {
static \u0275fac = function _CdkTextFieldStyleLoader_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || __CdkTextFieldStyleLoader)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: __CdkTextFieldStyleLoader,
selectors: [["ng-component"]],
hostAttrs: ["cdk-text-field-style-loader", ""],
decls: 0,
vars: 0,
template: function _CdkTextFieldStyleLoader_Template(rf, ctx) {
},
styles: ["textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0 !important;box-sizing:content-box !important;height:auto !important;overflow:hidden !important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0 !important;box-sizing:content-box !important;height:0 !important}@keyframes cdk-text-field-autofill-start{/*!*/}@keyframes cdk-text-field-autofill-end{/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){animation:cdk-text-field-autofill-end 0s 1ms}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(_CdkTextFieldStyleLoader, [{
type: Component,
args: [{
template: "",
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
host: {
"cdk-text-field-style-loader": ""
},
styles: ["textarea.cdk-textarea-autosize{resize:none}textarea.cdk-textarea-autosize-measuring{padding:2px 0 !important;box-sizing:content-box !important;height:auto !important;overflow:hidden !important}textarea.cdk-textarea-autosize-measuring-firefox{padding:2px 0 !important;box-sizing:content-box !important;height:0 !important}@keyframes cdk-text-field-autofill-start{/*!*/}@keyframes cdk-text-field-autofill-end{/*!*/}.cdk-text-field-autofill-monitored:-webkit-autofill{animation:cdk-text-field-autofill-start 0s 1ms}.cdk-text-field-autofill-monitored:not(:-webkit-autofill){animation:cdk-text-field-autofill-end 0s 1ms}\n"]
}]
}], null, null);
})();
var listenerOptions = {
passive: true
};
var AutofillMonitor = class _AutofillMonitor {
_platform = inject(Platform);
_ngZone = inject(NgZone);
_renderer = inject(RendererFactory2).createRenderer(null, null);
_styleLoader = inject(_CdkPrivateStyleLoader);
_monitoredElements = /* @__PURE__ */ new Map();
constructor() {
}
monitor(elementOrRef) {
if (!this._platform.isBrowser) {
return EMPTY;
}
this._styleLoader.load(_CdkTextFieldStyleLoader);
const element = coerceElement(elementOrRef);
const info = this._monitoredElements.get(element);
if (info) {
return info.subject;
}
const subject = new Subject();
const cssClass = "cdk-text-field-autofilled";
const listener = (event) => {
if (event.animationName === "cdk-text-field-autofill-start" && !element.classList.contains(cssClass)) {
element.classList.add(cssClass);
this._ngZone.run(() => subject.next({
target: event.target,
isAutofilled: true
}));
} else if (event.animationName === "cdk-text-field-autofill-end" && element.classList.contains(cssClass)) {
element.classList.remove(cssClass);
this._ngZone.run(() => subject.next({
target: event.target,
isAutofilled: false
}));
}
};
const unlisten = this._ngZone.runOutsideAngular(() => {
element.classList.add("cdk-text-field-autofill-monitored");
return _bindEventWithOptions(this._renderer, element, "animationstart", listener, listenerOptions);
});
this._monitoredElements.set(element, {
subject,
unlisten
});
return subject;
}
stopMonitoring(elementOrRef) {
const element = coerceElement(elementOrRef);
const info = this._monitoredElements.get(element);
if (info) {
info.unlisten();
info.subject.complete();
element.classList.remove("cdk-text-field-autofill-monitored");
element.classList.remove("cdk-text-field-autofilled");
this._monitoredElements.delete(element);
}
}
ngOnDestroy() {
this._monitoredElements.forEach((_info, element) => this.stopMonitoring(element));
}
static \u0275fac = function AutofillMonitor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AutofillMonitor)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _AutofillMonitor,
factory: _AutofillMonitor.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AutofillMonitor, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [], null);
})();
var CdkAutofill = class _CdkAutofill {
_elementRef = inject(ElementRef);
_autofillMonitor = inject(AutofillMonitor);
/** Emits when the autofill state of the element changes. */
cdkAutofill = new EventEmitter();
constructor() {
}
ngOnInit() {
this._autofillMonitor.monitor(this._elementRef).subscribe((event) => this.cdkAutofill.emit(event));
}
ngOnDestroy() {
this._autofillMonitor.stopMonitoring(this._elementRef);
}
static \u0275fac = function CdkAutofill_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkAutofill)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkAutofill,
selectors: [["", "cdkAutofill", ""]],
outputs: {
cdkAutofill: "cdkAutofill"
}
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkAutofill, [{
type: Directive,
args: [{
selector: "[cdkAutofill]"
}]
}], () => [], {
cdkAutofill: [{
type: Output
}]
});
})();
var CdkTextareaAutosize = class _CdkTextareaAutosize {
_elementRef = inject(ElementRef);
_platform = inject(Platform);
_ngZone = inject(NgZone);
_renderer = inject(Renderer2);
_resizeEvents = new Subject();
/** Keep track of the previous textarea value to avoid resizing when the value hasn't changed. */
_previousValue;
_initialHeight;
_destroyed = new Subject();
_listenerCleanups;
_minRows;
_maxRows;
_enabled = true;
/**
* Value of minRows as of last resize. If the minRows has decreased, the
* height of the textarea needs to be recomputed to reflect the new minimum. The maxHeight
* does not have the same problem because it does not affect the textarea's scrollHeight.
*/
_previousMinRows = -1;
_textareaElement;
/** Minimum amount of rows in the textarea. */
get minRows() {
return this._minRows;
}
set minRows(value) {
this._minRows = coerceNumberProperty(value);
this._setMinHeight();
}
/** Maximum amount of rows in the textarea. */
get maxRows() {
return this._maxRows;
}
set maxRows(value) {
this._maxRows = coerceNumberProperty(value);
this._setMaxHeight();
}
/** Whether autosizing is enabled or not */
get enabled() {
return this._enabled;
}
set enabled(value) {
if (this._enabled !== value) {
(this._enabled = value) ? this.resizeToFitContent(true) : this.reset();
}
}
get placeholder() {
return this._textareaElement.placeholder;
}
set placeholder(value) {
this._cachedPlaceholderHeight = void 0;
if (value) {
this._textareaElement.setAttribute("placeholder", value);
} else {
this._textareaElement.removeAttribute("placeholder");
}
this._cacheTextareaPlaceholderHeight();
}
/** Cached height of a textarea with a single row. */
_cachedLineHeight;
/** Cached height of a textarea with only the placeholder. */
_cachedPlaceholderHeight;
/** Cached scroll top of a textarea */
_cachedScrollTop;
/** Used to reference correct document/window */
_document = inject(DOCUMENT, {
optional: true
});
_hasFocus;
_isViewInited = false;
constructor() {
const styleLoader = inject(_CdkPrivateStyleLoader);
styleLoader.load(_CdkTextFieldStyleLoader);
this._textareaElement = this._elementRef.nativeElement;
}
/** Sets the minimum height of the textarea as determined by minRows. */
_setMinHeight() {
const minHeight = this.minRows && this._cachedLineHeight ? `${this.minRows * this._cachedLineHeight}px` : null;
if (minHeight) {
this._textareaElement.style.minHeight = minHeight;
}
}
/** Sets the maximum height of the textarea as determined by maxRows. */
_setMaxHeight() {
const maxHeight = this.maxRows && this._cachedLineHeight ? `${this.maxRows * this._cachedLineHeight}px` : null;
if (maxHeight) {
this._textareaElement.style.maxHeight = maxHeight;
}
}
ngAfterViewInit() {
if (this._platform.isBrowser) {
this._initialHeight = this._textareaElement.style.height;
this.resizeToFitContent();
this._ngZone.runOutsideAngular(() => {
this._listenerCleanups = [this._renderer.listen("window", "resize", () => this._resizeEvents.next()), this._renderer.listen(this._textareaElement, "focus", this._handleFocusEvent), this._renderer.listen(this._textareaElement, "blur", this._handleFocusEvent)];
this._resizeEvents.pipe(auditTime(16)).subscribe(() => {
this._cachedLineHeight = this._cachedPlaceholderHeight = void 0;
this.resizeToFitContent(true);
});
});
this._isViewInited = true;
this.resizeToFitContent(true);
}
}
ngOnDestroy() {
this._listenerCleanups?.forEach((cleanup) => cleanup());
this._resizeEvents.complete();
this._destroyed.next();
this._destroyed.complete();
}
/**
* Cache the height of a single-row textarea if it has not already been cached.
*
* We need to know how large a single "row" of a textarea is in order to apply minRows and
* maxRows. For the initial version, we will assume that the height of a single line in the
* textarea does not ever change.
*/
_cacheTextareaLineHeight() {
if (this._cachedLineHeight) {
return;
}
const textareaClone = this._textareaElement.cloneNode(false);
const cloneStyles = textareaClone.style;
textareaClone.rows = 1;
cloneStyles.position = "absolute";
cloneStyles.visibility = "hidden";
cloneStyles.border = "none";
cloneStyles.padding = "0";
cloneStyles.height = "";
cloneStyles.minHeight = "";
cloneStyles.maxHeight = "";
cloneStyles.top = cloneStyles.bottom = cloneStyles.left = cloneStyles.right = "auto";
cloneStyles.overflow = "hidden";
this._textareaElement.parentNode.appendChild(textareaClone);
this._cachedLineHeight = textareaClone.clientHeight;
textareaClone.remove();
this._setMinHeight();
this._setMaxHeight();
}
_measureScrollHeight() {
const element = this._textareaElement;
const previousMargin = element.style.marginBottom || "";
const isFirefox = this._platform.FIREFOX;
const needsMarginFiller = isFirefox && this._hasFocus;
const measuringClass = isFirefox ? "cdk-textarea-autosize-measuring-firefox" : "cdk-textarea-autosize-measuring";
if (needsMarginFiller) {
element.style.marginBottom = `${element.clientHeight}px`;
}
element.classList.add(measuringClass);
const scrollHeight = element.scrollHeight - 4;
element.classList.remove(measuringClass);
if (needsMarginFiller) {
element.style.marginBottom = previousMargin;
}
return scrollHeight;
}
_cacheTextareaPlaceholderHeight() {
if (!this._isViewInited || this._cachedPlaceholderHeight != void 0) {
return;
}
if (!this.placeholder) {
this._cachedPlaceholderHeight = 0;
return;
}
const value = this._textareaElement.value;
this._textareaElement.value = this._textareaElement.placeholder;
this._cachedPlaceholderHeight = this._measureScrollHeight();
this._textareaElement.value = value;
}
/** Handles `focus` and `blur` events. */
_handleFocusEvent = (event) => {
this._hasFocus = event.type === "focus";
};
ngDoCheck() {
if (this._platform.isBrowser) {
this.resizeToFitContent();
}
}
/**
* Resize the textarea to fit its content.
* @param force Whether to force a height recalculation. By default the height will be
* recalculated only if the value changed since the last call.
*/
resizeToFitContent(force = false) {
if (!this._enabled) {
return;
}
this._cacheTextareaLineHeight();
this._cacheTextareaPlaceholderHeight();
this._cachedScrollTop = this._textareaElement.scrollTop;
if (!this._cachedLineHeight) {
return;
}
const textarea = this._elementRef.nativeElement;
const value = textarea.value;
if (!force && this._minRows === this._previousMinRows && value === this._previousValue) {
return;
}
const scrollHeight = this._measureScrollHeight();
const height = Math.max(scrollHeight, this._cachedPlaceholderHeight || 0);
textarea.style.height = `${height}px`;
this._ngZone.runOutsideAngular(() => {
if (typeof requestAnimationFrame !== "undefined") {
requestAnimationFrame(() => this._scrollToCaretPosition(textarea));
} else {
setTimeout(() => this._scrollToCaretPosition(textarea));
}
});
this._previousValue = value;
this._previousMinRows = this._minRows;
}
/**
* Resets the textarea to its original size
*/
reset() {
if (this._initialHeight !== void 0) {
this._textareaElement.style.height = this._initialHeight;
}
}
_noopInputHandler() {
}
/**
* Scrolls a textarea to the caret position. On Firefox resizing the textarea will
* prevent it from scrolling to the caret position. We need to re-set the selection
* in order for it to scroll to the proper position.
*/
_scrollToCaretPosition(textarea) {
const {
selectionStart,
selectionEnd
} = textarea;
if (!this._destroyed.isStopped && this._hasFocus) {
textarea.setSelectionRange(selectionStart, selectionEnd);
textarea.scrollTop = this._cachedScrollTop;
}
}
static \u0275fac = function CdkTextareaAutosize_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _CdkTextareaAutosize)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _CdkTextareaAutosize,
selectors: [["textarea", "cdkTextareaAutosize", ""]],
hostAttrs: ["rows", "1", 1, "cdk-textarea-autosize"],
hostBindings: function CdkTextareaAutosize_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("input", function CdkTextareaAutosize_input_HostBindingHandler() {
return ctx._noopInputHandler();
});
}
},
inputs: {
minRows: [0, "cdkAutosizeMinRows", "minRows"],
maxRows: [0, "cdkAutosizeMaxRows", "maxRows"],
enabled: [2, "cdkTextareaAutosize", "enabled", booleanAttribute],
placeholder: "placeholder"
},
exportAs: ["cdkTextareaAutosize"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(CdkTextareaAutosize, [{
type: Directive,
args: [{
selector: "textarea[cdkTextareaAutosize]",
exportAs: "cdkTextareaAutosize",
host: {
"class": "cdk-textarea-autosize",
// Textarea elements that have the directive applied should have a single row by default.
// Browsers normally show two rows by default and therefore this limits the minRows binding.
"rows": "1",
"(input)": "_noopInputHandler()"
}
}]
}], () => [], {
minRows: [{
type: Input,
args: ["cdkAutosizeMinRows"]
}],
maxRows: [{
type: Input,
args: ["cdkAutosizeMaxRows"]
}],
enabled: [{
type: Input,
args: [{
alias: "cdkTextareaAutosize",
transform: booleanAttribute
}]
}],
placeholder: [{
type: Input
}]
});
})();
var TextFieldModule = class _TextFieldModule {
static \u0275fac = function TextFieldModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _TextFieldModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _TextFieldModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TextFieldModule, [{
type: NgModule,
args: [{
imports: [CdkAutofill, CdkTextareaAutosize],
exports: [CdkAutofill, CdkTextareaAutosize]
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/input-value-accessor-D1GvPuqO.mjs
var MAT_INPUT_VALUE_ACCESSOR = new InjectionToken("MAT_INPUT_VALUE_ACCESSOR");
// node_modules/@angular/material/fesm2022/error-options-Dm2JJUbF.mjs
var ShowOnDirtyErrorStateMatcher = class _ShowOnDirtyErrorStateMatcher {
isErrorState(control, form) {
return !!(control && control.invalid && (control.dirty || form && form.submitted));
}
static \u0275fac = function ShowOnDirtyErrorStateMatcher_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ShowOnDirtyErrorStateMatcher)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ShowOnDirtyErrorStateMatcher,
factory: _ShowOnDirtyErrorStateMatcher.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ShowOnDirtyErrorStateMatcher, [{
type: Injectable
}], null, null);
})();
var ErrorStateMatcher = class _ErrorStateMatcher {
isErrorState(control, form) {
return !!(control && control.invalid && (control.touched || form && form.submitted));
}
static \u0275fac = function ErrorStateMatcher_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _ErrorStateMatcher)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _ErrorStateMatcher,
factory: _ErrorStateMatcher.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ErrorStateMatcher, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/error-state-Dtb1IHM-.mjs
var _ErrorStateTracker = class {
_defaultMatcher;
ngControl;
_parentFormGroup;
_parentForm;
_stateChanges;
/** Whether the tracker is currently in an error state. */
errorState = false;
/** User-defined matcher for the error state. */
matcher;
constructor(_defaultMatcher, ngControl, _parentFormGroup, _parentForm, _stateChanges) {
this._defaultMatcher = _defaultMatcher;
this.ngControl = ngControl;
this._parentFormGroup = _parentFormGroup;
this._parentForm = _parentForm;
this._stateChanges = _stateChanges;
}
/** Updates the error state based on the provided error state matcher. */
updateErrorState() {
const oldState = this.errorState;
const parent = this._parentFormGroup || this._parentForm;
const matcher = this.matcher || this._defaultMatcher;
const control = this.ngControl ? this.ngControl.control : null;
const newState = matcher?.isErrorState(control, parent) ?? false;
if (newState !== oldState) {
this.errorState = newState;
this._stateChanges.next();
}
}
};
// node_modules/@angular/material/fesm2022/input.mjs
function getMatInputUnsupportedTypeError(type) {
return Error(`Input type "${type}" isn't supported by matInput.`);
}
var MAT_INPUT_INVALID_TYPES = ["button", "checkbox", "file", "hidden", "image", "radio", "range", "reset", "submit"];
var MAT_INPUT_CONFIG = new InjectionToken("MAT_INPUT_CONFIG");
var MatInput = class _MatInput {
_elementRef = inject(ElementRef);
_platform = inject(Platform);
ngControl = inject(NgControl, {
optional: true,
self: true
});
_autofillMonitor = inject(AutofillMonitor);
_ngZone = inject(NgZone);
_formField = inject(MAT_FORM_FIELD, {
optional: true
});
_renderer = inject(Renderer2);
_uid = inject(_IdGenerator).getId("mat-input-");
_previousNativeValue;
_inputValueAccessor;
_signalBasedValueAccessor;
_previousPlaceholder;
_errorStateTracker;
_config = inject(MAT_INPUT_CONFIG, {
optional: true
});
_cleanupIosKeyup;
_cleanupWebkitWheel;
/** `aria-describedby` IDs assigned by the form field. */
_formFieldDescribedBy;
/** Whether the component is being rendered on the server. */
_isServer;
/** Whether the component is a native html select. */
_isNativeSelect;
/** Whether the component is a textarea. */
_isTextarea;
/** Whether the input is inside of a form field. */
_isInFormField;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
focused = false;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
stateChanges = new Subject();
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
controlType = "mat-input";
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
autofilled = false;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get disabled() {
return this._disabled;
}
set disabled(value) {
this._disabled = coerceBooleanProperty(value);
if (this.focused) {
this.focused = false;
this.stateChanges.next();
}
}
_disabled = false;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get id() {
return this._id;
}
set id(value) {
this._id = value || this._uid;
}
_id;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
placeholder;
/**
* Name of the input.
* @docs-private
*/
name;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get required() {
return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
}
set required(value) {
this._required = coerceBooleanProperty(value);
}
_required;
/** Input type of the element. */
get type() {
return this._type;
}
set type(value) {
const prevType = this._type;
this._type = value || "text";
this._validateType();
if (!this._isTextarea && getSupportedInputTypes().has(this._type)) {
this._elementRef.nativeElement.type = this._type;
}
if (this._type !== prevType) {
this._ensureWheelDefaultBehavior();
}
}
_type = "text";
/** An object used to control when error messages are shown. */
get errorStateMatcher() {
return this._errorStateTracker.matcher;
}
set errorStateMatcher(value) {
this._errorStateTracker.matcher = value;
}
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
userAriaDescribedBy;
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get value() {
return this._signalBasedValueAccessor ? this._signalBasedValueAccessor.value() : this._inputValueAccessor.value;
}
set value(value) {
if (value !== this.value) {
if (this._signalBasedValueAccessor) {
this._signalBasedValueAccessor.value.set(value);
} else {
this._inputValueAccessor.value = value;
}
this.stateChanges.next();
}
}
/** Whether the element is readonly. */
get readonly() {
return this._readonly;
}
set readonly(value) {
this._readonly = coerceBooleanProperty(value);
}
_readonly = false;
/** Whether the input should remain interactive when it is disabled. */
disabledInteractive;
/** Whether the input is in an error state. */
get errorState() {
return this._errorStateTracker.errorState;
}
set errorState(value) {
this._errorStateTracker.errorState = value;
}
_neverEmptyInputTypes = ["date", "datetime", "datetime-local", "month", "time", "week"].filter((t) => getSupportedInputTypes().has(t));
constructor() {
const parentForm = inject(NgForm, {
optional: true
});
const parentFormGroup = inject(FormGroupDirective, {
optional: true
});
const defaultErrorStateMatcher = inject(ErrorStateMatcher);
const accessor = inject(MAT_INPUT_VALUE_ACCESSOR, {
optional: true,
self: true
});
const element = this._elementRef.nativeElement;
const nodeName = element.nodeName.toLowerCase();
if (accessor) {
if (isSignal(accessor.value)) {
this._signalBasedValueAccessor = accessor;
} else {
this._inputValueAccessor = accessor;
}
} else {
this._inputValueAccessor = element;
}
this._previousNativeValue = this.value;
this.id = this.id;
if (this._platform.IOS) {
this._ngZone.runOutsideAngular(() => {
this._cleanupIosKeyup = this._renderer.listen(element, "keyup", this._iOSKeyupListener);
});
}
this._errorStateTracker = new _ErrorStateTracker(defaultErrorStateMatcher, this.ngControl, parentFormGroup, parentForm, this.stateChanges);
this._isServer = !this._platform.isBrowser;
this._isNativeSelect = nodeName === "select";
this._isTextarea = nodeName === "textarea";
this._isInFormField = !!this._formField;
this.disabledInteractive = this._config?.disabledInteractive || false;
if (this._isNativeSelect) {
this.controlType = element.multiple ? "mat-native-select-multiple" : "mat-native-select";
}
if (this._signalBasedValueAccessor) {
effect(() => {
this._signalBasedValueAccessor.value();
this.stateChanges.next();
});
}
}
ngAfterViewInit() {
if (this._platform.isBrowser) {
this._autofillMonitor.monitor(this._elementRef.nativeElement).subscribe((event) => {
this.autofilled = event.isAutofilled;
this.stateChanges.next();
});
}
}
ngOnChanges() {
this.stateChanges.next();
}
ngOnDestroy() {
this.stateChanges.complete();
if (this._platform.isBrowser) {
this._autofillMonitor.stopMonitoring(this._elementRef.nativeElement);
}
this._cleanupIosKeyup?.();
this._cleanupWebkitWheel?.();
}
ngDoCheck() {
if (this.ngControl) {
this.updateErrorState();
if (this.ngControl.disabled !== null && this.ngControl.disabled !== this.disabled) {
this.disabled = this.ngControl.disabled;
this.stateChanges.next();
}
}
this._dirtyCheckNativeValue();
this._dirtyCheckPlaceholder();
}
/** Focuses the input. */
focus(options) {
this._elementRef.nativeElement.focus(options);
}
/** Refreshes the error state of the input. */
updateErrorState() {
this._errorStateTracker.updateErrorState();
}
/** Callback for the cases where the focused state of the input changes. */
_focusChanged(isFocused) {
if (isFocused === this.focused) {
return;
}
if (!this._isNativeSelect && isFocused && this.disabled && this.disabledInteractive) {
const element = this._elementRef.nativeElement;
if (element.type === "number") {
element.type = "text";
element.setSelectionRange(0, 0);
element.type = "number";
} else {
element.setSelectionRange(0, 0);
}
}
this.focused = isFocused;
this.stateChanges.next();
}
_onInput() {
}
/** Does some manual dirty checking on the native input `value` property. */
_dirtyCheckNativeValue() {
const newValue = this._elementRef.nativeElement.value;
if (this._previousNativeValue !== newValue) {
this._previousNativeValue = newValue;
this.stateChanges.next();
}
}
/** Does some manual dirty checking on the native input `placeholder` attribute. */
_dirtyCheckPlaceholder() {
const placeholder = this._getPlaceholder();
if (placeholder !== this._previousPlaceholder) {
const element = this._elementRef.nativeElement;
this._previousPlaceholder = placeholder;
placeholder ? element.setAttribute("placeholder", placeholder) : element.removeAttribute("placeholder");
}
}
/** Gets the current placeholder of the form field. */
_getPlaceholder() {
return this.placeholder || null;
}
/** Make sure the input is a supported type. */
_validateType() {
if (MAT_INPUT_INVALID_TYPES.indexOf(this._type) > -1 && (typeof ngDevMode === "undefined" || ngDevMode)) {
throw getMatInputUnsupportedTypeError(this._type);
}
}
/** Checks whether the input type is one of the types that are never empty. */
_isNeverEmpty() {
return this._neverEmptyInputTypes.indexOf(this._type) > -1;
}
/** Checks whether the input is invalid based on the native validation. */
_isBadInput() {
let validity = this._elementRef.nativeElement.validity;
return validity && validity.badInput;
}
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get empty() {
return !this._isNeverEmpty() && !this._elementRef.nativeElement.value && !this._isBadInput() && !this.autofilled;
}
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
get shouldLabelFloat() {
if (this._isNativeSelect) {
const selectElement = this._elementRef.nativeElement;
const firstOption = selectElement.options[0];
return this.focused || selectElement.multiple || !this.empty || !!(selectElement.selectedIndex > -1 && firstOption && firstOption.label);
} else {
return this.focused && !this.disabled || !this.empty;
}
}
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
setDescribedByIds(ids) {
const element = this._elementRef.nativeElement;
const existingDescribedBy = element.getAttribute("aria-describedby");
let toAssign;
if (existingDescribedBy) {
const exclude = this._formFieldDescribedBy || ids;
toAssign = ids.concat(existingDescribedBy.split(" ").filter((id) => id && !exclude.includes(id)));
} else {
toAssign = ids;
}
this._formFieldDescribedBy = ids;
if (toAssign.length) {
element.setAttribute("aria-describedby", toAssign.join(" "));
} else {
element.removeAttribute("aria-describedby");
}
}
/**
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
onContainerClick() {
if (!this.focused) {
this.focus();
}
}
/** Whether the form control is a native select that is displayed inline. */
_isInlineSelect() {
const element = this._elementRef.nativeElement;
return this._isNativeSelect && (element.multiple || element.size > 1);
}
_iOSKeyupListener = (event) => {
const el = event.target;
if (!el.value && el.selectionStart === 0 && el.selectionEnd === 0) {
el.setSelectionRange(1, 1);
el.setSelectionRange(0, 0);
}
};
_webkitBlinkWheelListener = () => {
};
/**
* In blink and webkit browsers a focused number input does not increment or decrement its value
* on mouse wheel interaction unless a wheel event listener is attached to it or one of its
* ancestors or a passive wheel listener is attached somewhere in the DOM. For example: Hitting
* a tooltip once enables the mouse wheel input for all number inputs as long as it exists. In
* order to get reliable and intuitive behavior we apply a wheel event on our own thus making
* sure increment and decrement by mouse wheel works every time.
* @docs-private
*/
_ensureWheelDefaultBehavior() {
this._cleanupWebkitWheel?.();
if (this._type === "number" && (this._platform.BLINK || this._platform.WEBKIT)) {
this._cleanupWebkitWheel = this._renderer.listen(this._elementRef.nativeElement, "wheel", this._webkitBlinkWheelListener);
}
}
/** Gets the value to set on the `readonly` attribute. */
_getReadonlyAttribute() {
if (this._isNativeSelect) {
return null;
}
if (this.readonly || this.disabled && this.disabledInteractive) {
return "true";
}
return null;
}
static \u0275fac = function MatInput_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatInput)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatInput,
selectors: [["input", "matInput", ""], ["textarea", "matInput", ""], ["select", "matNativeControl", ""], ["input", "matNativeControl", ""], ["textarea", "matNativeControl", ""]],
hostAttrs: [1, "mat-mdc-input-element"],
hostVars: 21,
hostBindings: function MatInput_HostBindings(rf, ctx) {
if (rf & 1) {
\u0275\u0275listener("focus", function MatInput_focus_HostBindingHandler() {
return ctx._focusChanged(true);
})("blur", function MatInput_blur_HostBindingHandler() {
return ctx._focusChanged(false);
})("input", function MatInput_input_HostBindingHandler() {
return ctx._onInput();
});
}
if (rf & 2) {
\u0275\u0275hostProperty("id", ctx.id)("disabled", ctx.disabled && !ctx.disabledInteractive)("required", ctx.required);
\u0275\u0275attribute("name", ctx.name || null)("readonly", ctx._getReadonlyAttribute())("aria-disabled", ctx.disabled && ctx.disabledInteractive ? "true" : null)("aria-invalid", ctx.empty && ctx.required ? null : ctx.errorState)("aria-required", ctx.required)("id", ctx.id);
\u0275\u0275classProp("mat-input-server", ctx._isServer)("mat-mdc-form-field-textarea-control", ctx._isInFormField && ctx._isTextarea)("mat-mdc-form-field-input-control", ctx._isInFormField)("mat-mdc-input-disabled-interactive", ctx.disabledInteractive)("mdc-text-field__input", ctx._isInFormField)("mat-mdc-native-select-inline", ctx._isInlineSelect());
}
},
inputs: {
disabled: "disabled",
id: "id",
placeholder: "placeholder",
name: "name",
required: "required",
type: "type",
errorStateMatcher: "errorStateMatcher",
userAriaDescribedBy: [0, "aria-describedby", "userAriaDescribedBy"],
value: "value",
readonly: "readonly",
disabledInteractive: [2, "disabledInteractive", "disabledInteractive", booleanAttribute]
},
exportAs: ["matInput"],
features: [\u0275\u0275ProvidersFeature([{
provide: MatFormFieldControl,
useExisting: _MatInput
}]), \u0275\u0275NgOnChangesFeature]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatInput, [{
type: Directive,
args: [{
selector: `input[matInput], textarea[matInput], select[matNativeControl],
input[matNativeControl], textarea[matNativeControl]`,
exportAs: "matInput",
host: {
"class": "mat-mdc-input-element",
// The BaseMatInput parent class adds `mat-input-element`, `mat-form-field-control` and
// `mat-form-field-autofill-control` to the CSS class list, but this should not be added for
// this MDC equivalent input.
"[class.mat-input-server]": "_isServer",
"[class.mat-mdc-form-field-textarea-control]": "_isInFormField && _isTextarea",
"[class.mat-mdc-form-field-input-control]": "_isInFormField",
"[class.mat-mdc-input-disabled-interactive]": "disabledInteractive",
"[class.mdc-text-field__input]": "_isInFormField",
"[class.mat-mdc-native-select-inline]": "_isInlineSelect()",
// Native input properties that are overwritten by Angular inputs need to be synced with
// the native input element. Otherwise property bindings for those don't work.
"[id]": "id",
"[disabled]": "disabled && !disabledInteractive",
"[required]": "required",
"[attr.name]": "name || null",
"[attr.readonly]": "_getReadonlyAttribute()",
"[attr.aria-disabled]": 'disabled && disabledInteractive ? "true" : null',
// Only mark the input as invalid for assistive technology if it has a value since the
// state usually overlaps with `aria-required` when the input is empty and can be redundant.
"[attr.aria-invalid]": "(empty && required) ? null : errorState",
"[attr.aria-required]": "required",
// Native input properties that are overwritten by Angular inputs need to be synced with
// the native input element. Otherwise property bindings for those don't work.
"[attr.id]": "id",
"(focus)": "_focusChanged(true)",
"(blur)": "_focusChanged(false)",
"(input)": "_onInput()"
},
providers: [{
provide: MatFormFieldControl,
useExisting: MatInput
}]
}]
}], () => [], {
disabled: [{
type: Input
}],
id: [{
type: Input
}],
placeholder: [{
type: Input
}],
name: [{
type: Input
}],
required: [{
type: Input
}],
type: [{
type: Input
}],
errorStateMatcher: [{
type: Input
}],
userAriaDescribedBy: [{
type: Input,
args: ["aria-describedby"]
}],
value: [{
type: Input
}],
readonly: [{
type: Input
}],
disabledInteractive: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}]
});
})();
var MatInputModule = class _MatInputModule {
static \u0275fac = function MatInputModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatInputModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatInputModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, MatFormFieldModule, MatFormFieldModule, TextFieldModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatInputModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, MatFormFieldModule, MatInput],
exports: [MatInput, MatFormFieldModule, TextFieldModule, MatCommonModule]
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/icon-registry-B2IMBfNA.mjs
var policy;
function getPolicy() {
if (policy === void 0) {
policy = null;
if (typeof window !== "undefined") {
const ttWindow = window;
if (ttWindow.trustedTypes !== void 0) {
policy = ttWindow.trustedTypes.createPolicy("angular#components", {
createHTML: (s) => s
});
}
}
}
return policy;
}
function trustedHTMLFromString(html) {
return getPolicy()?.createHTML(html) || html;
}
function getMatIconNameNotFoundError(iconName) {
return Error(`Unable to find icon with the name "${iconName}"`);
}
function getMatIconNoHttpProviderError() {
return Error("Could not find HttpClient for use with Angular Material icons. Please add provideHttpClient() to your providers.");
}
function getMatIconFailedToSanitizeUrlError(url) {
return Error(`The URL provided to MatIconRegistry was not trusted as a resource URL via Angular's DomSanitizer. Attempted URL was "${url}".`);
}
function getMatIconFailedToSanitizeLiteralError(literal) {
return Error(`The literal provided to MatIconRegistry was not trusted as safe HTML by Angular's DomSanitizer. Attempted literal was "${literal}".`);
}
var SvgIconConfig = class {
url;
svgText;
options;
svgElement;
constructor(url, svgText, options) {
this.url = url;
this.svgText = svgText;
this.options = options;
}
};
var MatIconRegistry = class _MatIconRegistry {
_httpClient;
_sanitizer;
_errorHandler;
_document;
/**
* URLs and cached SVG elements for individual icons. Keys are of the format "[namespace]:[icon]".
*/
_svgIconConfigs = /* @__PURE__ */ new Map();
/**
* SvgIconConfig objects and cached SVG elements for icon sets, keyed by namespace.
* Multiple icon sets can be registered under the same namespace.
*/
_iconSetConfigs = /* @__PURE__ */ new Map();
/** Cache for icons loaded by direct URLs. */
_cachedIconsByUrl = /* @__PURE__ */ new Map();
/** In-progress icon fetches. Used to coalesce multiple requests to the same URL. */
_inProgressUrlFetches = /* @__PURE__ */ new Map();
/** Map from font identifiers to their CSS class names. Used for icon fonts. */
_fontCssClassesByAlias = /* @__PURE__ */ new Map();
/** Registered icon resolver functions. */
_resolvers = [];
/**
* The CSS classes to apply when an `<mat-icon>` component has no icon name, url, or font
* specified. The default 'material-icons' value assumes that the material icon font has been
* loaded as described at https://google.github.io/material-design-icons/#icon-font-for-the-web
*/
_defaultFontSetClass = ["material-icons", "mat-ligature-font"];
constructor(_httpClient, _sanitizer, document2, _errorHandler) {
this._httpClient = _httpClient;
this._sanitizer = _sanitizer;
this._errorHandler = _errorHandler;
this._document = document2;
}
/**
* Registers an icon by URL in the default namespace.
* @param iconName Name under which the icon should be registered.
* @param url
*/
addSvgIcon(iconName, url, options) {
return this.addSvgIconInNamespace("", iconName, url, options);
}
/**
* Registers an icon using an HTML string in the default namespace.
* @param iconName Name under which the icon should be registered.
* @param literal SVG source of the icon.
*/
addSvgIconLiteral(iconName, literal, options) {
return this.addSvgIconLiteralInNamespace("", iconName, literal, options);
}
/**
* Registers an icon by URL in the specified namespace.
* @param namespace Namespace in which the icon should be registered.
* @param iconName Name under which the icon should be registered.
* @param url
*/
addSvgIconInNamespace(namespace, iconName, url, options) {
return this._addSvgIconConfig(namespace, iconName, new SvgIconConfig(url, null, options));
}
/**
* Registers an icon resolver function with the registry. The function will be invoked with the
* name and namespace of an icon when the registry tries to resolve the URL from which to fetch
* the icon. The resolver is expected to return a `SafeResourceUrl` that points to the icon,
* an object with the icon URL and icon options, or `null` if the icon is not supported. Resolvers
* will be invoked in the order in which they have been registered.
* @param resolver Resolver function to be registered.
*/
addSvgIconResolver(resolver) {
this._resolvers.push(resolver);
return this;
}
/**
* Registers an icon using an HTML string in the specified namespace.
* @param namespace Namespace in which the icon should be registered.
* @param iconName Name under which the icon should be registered.
* @param literal SVG source of the icon.
*/
addSvgIconLiteralInNamespace(namespace, iconName, literal, options) {
const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);
if (!cleanLiteral) {
throw getMatIconFailedToSanitizeLiteralError(literal);
}
const trustedLiteral = trustedHTMLFromString(cleanLiteral);
return this._addSvgIconConfig(namespace, iconName, new SvgIconConfig("", trustedLiteral, options));
}
/**
* Registers an icon set by URL in the default namespace.
* @param url
*/
addSvgIconSet(url, options) {
return this.addSvgIconSetInNamespace("", url, options);
}
/**
* Registers an icon set using an HTML string in the default namespace.
* @param literal SVG source of the icon set.
*/
addSvgIconSetLiteral(literal, options) {
return this.addSvgIconSetLiteralInNamespace("", literal, options);
}
/**
* Registers an icon set by URL in the specified namespace.
* @param namespace Namespace in which to register the icon set.
* @param url
*/
addSvgIconSetInNamespace(namespace, url, options) {
return this._addSvgIconSetConfig(namespace, new SvgIconConfig(url, null, options));
}
/**
* Registers an icon set using an HTML string in the specified namespace.
* @param namespace Namespace in which to register the icon set.
* @param literal SVG source of the icon set.
*/
addSvgIconSetLiteralInNamespace(namespace, literal, options) {
const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);
if (!cleanLiteral) {
throw getMatIconFailedToSanitizeLiteralError(literal);
}
const trustedLiteral = trustedHTMLFromString(cleanLiteral);
return this._addSvgIconSetConfig(namespace, new SvgIconConfig("", trustedLiteral, options));
}
/**
* Defines an alias for CSS class names to be used for icon fonts. Creating an matIcon
* component with the alias as the fontSet input will cause the class name to be applied
* to the `<mat-icon>` element.
*
* If the registered font is a ligature font, then don't forget to also include the special
* class `mat-ligature-font` to allow the usage via attribute. So register like this:
*
* ```ts
* iconRegistry.registerFontClassAlias('f1', 'font1 mat-ligature-font');
* ```
*
* And use like this:
*
* ```html
* <mat-icon fontSet="f1" fontIcon="home"></mat-icon>
* ```
*
* @param alias Alias for the font.
* @param classNames Class names override to be used instead of the alias.
*/
registerFontClassAlias(alias, classNames = alias) {
this._fontCssClassesByAlias.set(alias, classNames);
return this;
}
/**
* Returns the CSS class name associated with the alias by a previous call to
* registerFontClassAlias. If no CSS class has been associated, returns the alias unmodified.
*/
classNameForFontAlias(alias) {
return this._fontCssClassesByAlias.get(alias) || alias;
}
/**
* Sets the CSS classes to be used for icon fonts when an `<mat-icon>` component does not
* have a fontSet input value, and is not loading an icon by name or URL.
*/
setDefaultFontSetClass(...classNames) {
this._defaultFontSetClass = classNames;
return this;
}
/**
* Returns the CSS classes to be used for icon fonts when an `<mat-icon>` component does not
* have a fontSet input value, and is not loading an icon by name or URL.
*/
getDefaultFontSetClass() {
return this._defaultFontSetClass;
}
/**
* Returns an Observable that produces the icon (as an `<svg>` DOM element) from the given URL.
* The response from the URL may be cached so this will not always cause an HTTP request, but
* the produced element will always be a new copy of the originally fetched icon. (That is,
* it will not contain any modifications made to elements previously returned).
*
* @param safeUrl URL from which to fetch the SVG icon.
*/
getSvgIconFromUrl(safeUrl) {
const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);
if (!url) {
throw getMatIconFailedToSanitizeUrlError(safeUrl);
}
const cachedIcon = this._cachedIconsByUrl.get(url);
if (cachedIcon) {
return of(cloneSvg(cachedIcon));
}
return this._loadSvgIconFromConfig(new SvgIconConfig(safeUrl, null)).pipe(tap((svg) => this._cachedIconsByUrl.set(url, svg)), map((svg) => cloneSvg(svg)));
}
/**
* Returns an Observable that produces the icon (as an `<svg>` DOM element) with the given name
* and namespace. The icon must have been previously registered with addIcon or addIconSet;
* if not, the Observable will throw an error.
*
* @param name Name of the icon to be retrieved.
* @param namespace Namespace in which to look for the icon.
*/
getNamedSvgIcon(name, namespace = "") {
const key = iconKey(namespace, name);
let config = this._svgIconConfigs.get(key);
if (config) {
return this._getSvgFromConfig(config);
}
config = this._getIconConfigFromResolvers(namespace, name);
if (config) {
this._svgIconConfigs.set(key, config);
return this._getSvgFromConfig(config);
}
const iconSetConfigs = this._iconSetConfigs.get(namespace);
if (iconSetConfigs) {
return this._getSvgFromIconSetConfigs(name, iconSetConfigs);
}
return throwError(getMatIconNameNotFoundError(key));
}
ngOnDestroy() {
this._resolvers = [];
this._svgIconConfigs.clear();
this._iconSetConfigs.clear();
this._cachedIconsByUrl.clear();
}
/**
* Returns the cached icon for a SvgIconConfig if available, or fetches it from its URL if not.
*/
_getSvgFromConfig(config) {
if (config.svgText) {
return of(cloneSvg(this._svgElementFromConfig(config)));
} else {
return this._loadSvgIconFromConfig(config).pipe(map((svg) => cloneSvg(svg)));
}
}
/**
* Attempts to find an icon with the specified name in any of the SVG icon sets.
* First searches the available cached icons for a nested element with a matching name, and
* if found copies the element to a new `<svg>` element. If not found, fetches all icon sets
* that have not been cached, and searches again after all fetches are completed.
* The returned Observable produces the SVG element if possible, and throws
* an error if no icon with the specified name can be found.
*/
_getSvgFromIconSetConfigs(name, iconSetConfigs) {
const namedIcon = this._extractIconWithNameFromAnySet(name, iconSetConfigs);
if (namedIcon) {
return of(namedIcon);
}
const iconSetFetchRequests = iconSetConfigs.filter((iconSetConfig) => !iconSetConfig.svgText).map((iconSetConfig) => {
return this._loadSvgIconSetFromConfig(iconSetConfig).pipe(catchError((err) => {
const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, iconSetConfig.url);
const errorMessage = `Loading icon set URL: ${url} failed: ${err.message}`;
this._errorHandler.handleError(new Error(errorMessage));
return of(null);
}));
});
return forkJoin(iconSetFetchRequests).pipe(map(() => {
const foundIcon = this._extractIconWithNameFromAnySet(name, iconSetConfigs);
if (!foundIcon) {
throw getMatIconNameNotFoundError(name);
}
return foundIcon;
}));
}
/**
* Searches the cached SVG elements for the given icon sets for a nested icon element whose "id"
* tag matches the specified name. If found, copies the nested element to a new SVG element and
* returns it. Returns null if no matching element is found.
*/
_extractIconWithNameFromAnySet(iconName, iconSetConfigs) {
for (let i = iconSetConfigs.length - 1; i >= 0; i--) {
const config = iconSetConfigs[i];
if (config.svgText && config.svgText.toString().indexOf(iconName) > -1) {
const svg = this._svgElementFromConfig(config);
const foundIcon = this._extractSvgIconFromSet(svg, iconName, config.options);
if (foundIcon) {
return foundIcon;
}
}
}
return null;
}
/**
* Loads the content of the icon URL specified in the SvgIconConfig and creates an SVG element
* from it.
*/
_loadSvgIconFromConfig(config) {
return this._fetchIcon(config).pipe(tap((svgText) => config.svgText = svgText), map(() => this._svgElementFromConfig(config)));
}
/**
* Loads the content of the icon set URL specified in the
* SvgIconConfig and attaches it to the config.
*/
_loadSvgIconSetFromConfig(config) {
if (config.svgText) {
return of(null);
}
return this._fetchIcon(config).pipe(tap((svgText) => config.svgText = svgText));
}
/**
* Searches the cached element of the given SvgIconConfig for a nested icon element whose "id"
* tag matches the specified name. If found, copies the nested element to a new SVG element and
* returns it. Returns null if no matching element is found.
*/
_extractSvgIconFromSet(iconSet, iconName, options) {
const iconSource = iconSet.querySelector(`[id="${iconName}"]`);
if (!iconSource) {
return null;
}
const iconElement = iconSource.cloneNode(true);
iconElement.removeAttribute("id");
if (iconElement.nodeName.toLowerCase() === "svg") {
return this._setSvgAttributes(iconElement, options);
}
if (iconElement.nodeName.toLowerCase() === "symbol") {
return this._setSvgAttributes(this._toSvgElement(iconElement), options);
}
const svg = this._svgElementFromString(trustedHTMLFromString("<svg></svg>"));
svg.appendChild(iconElement);
return this._setSvgAttributes(svg, options);
}
/**
* Creates a DOM element from the given SVG string.
*/
_svgElementFromString(str) {
const div = this._document.createElement("DIV");
div.innerHTML = str;
const svg = div.querySelector("svg");
if (!svg) {
throw Error("<svg> tag not found");
}
return svg;
}
/**
* Converts an element into an SVG node by cloning all of its children.
*/
_toSvgElement(element) {
const svg = this._svgElementFromString(trustedHTMLFromString("<svg></svg>"));
const attributes = element.attributes;
for (let i = 0; i < attributes.length; i++) {
const {
name,
value
} = attributes[i];
if (name !== "id") {
svg.setAttribute(name, value);
}
}
for (let i = 0; i < element.childNodes.length; i++) {
if (element.childNodes[i].nodeType === this._document.ELEMENT_NODE) {
svg.appendChild(element.childNodes[i].cloneNode(true));
}
}
return svg;
}
/**
* Sets the default attributes for an SVG element to be used as an icon.
*/
_setSvgAttributes(svg, options) {
svg.setAttribute("fit", "");
svg.setAttribute("height", "100%");
svg.setAttribute("width", "100%");
svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
svg.setAttribute("focusable", "false");
if (options && options.viewBox) {
svg.setAttribute("viewBox", options.viewBox);
}
return svg;
}
/**
* Returns an Observable which produces the string contents of the given icon. Results may be
* cached, so future calls with the same URL may not cause another HTTP request.
*/
_fetchIcon(iconConfig) {
const {
url: safeUrl,
options
} = iconConfig;
const withCredentials = options?.withCredentials ?? false;
if (!this._httpClient) {
throw getMatIconNoHttpProviderError();
}
if (safeUrl == null) {
throw Error(`Cannot fetch icon from URL "${safeUrl}".`);
}
const url = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeUrl);
if (!url) {
throw getMatIconFailedToSanitizeUrlError(safeUrl);
}
const inProgressFetch = this._inProgressUrlFetches.get(url);
if (inProgressFetch) {
return inProgressFetch;
}
const req = this._httpClient.get(url, {
responseType: "text",
withCredentials
}).pipe(map((svg) => {
return trustedHTMLFromString(svg);
}), finalize(() => this._inProgressUrlFetches.delete(url)), share());
this._inProgressUrlFetches.set(url, req);
return req;
}
/**
* Registers an icon config by name in the specified namespace.
* @param namespace Namespace in which to register the icon config.
* @param iconName Name under which to register the config.
* @param config Config to be registered.
*/
_addSvgIconConfig(namespace, iconName, config) {
this._svgIconConfigs.set(iconKey(namespace, iconName), config);
return this;
}
/**
* Registers an icon set config in the specified namespace.
* @param namespace Namespace in which to register the icon config.
* @param config Config to be registered.
*/
_addSvgIconSetConfig(namespace, config) {
const configNamespace = this._iconSetConfigs.get(namespace);
if (configNamespace) {
configNamespace.push(config);
} else {
this._iconSetConfigs.set(namespace, [config]);
}
return this;
}
/** Parses a config's text into an SVG element. */
_svgElementFromConfig(config) {
if (!config.svgElement) {
const svg = this._svgElementFromString(config.svgText);
this._setSvgAttributes(svg, config.options);
config.svgElement = svg;
}
return config.svgElement;
}
/** Tries to create an icon config through the registered resolver functions. */
_getIconConfigFromResolvers(namespace, name) {
for (let i = 0; i < this._resolvers.length; i++) {
const result = this._resolvers[i](name, namespace);
if (result) {
return isSafeUrlWithOptions(result) ? new SvgIconConfig(result.url, null, result.options) : new SvgIconConfig(result, null);
}
}
return void 0;
}
static \u0275fac = function MatIconRegistry_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatIconRegistry)(\u0275\u0275inject(HttpClient, 8), \u0275\u0275inject(DomSanitizer), \u0275\u0275inject(DOCUMENT, 8), \u0275\u0275inject(ErrorHandler));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _MatIconRegistry,
factory: _MatIconRegistry.\u0275fac,
providedIn: "root"
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatIconRegistry, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], () => [{
type: HttpClient,
decorators: [{
type: Optional
}]
}, {
type: DomSanitizer
}, {
type: void 0,
decorators: [{
type: Optional
}, {
type: Inject,
args: [DOCUMENT]
}]
}, {
type: ErrorHandler
}], null);
})();
function ICON_REGISTRY_PROVIDER_FACTORY(parentRegistry, httpClient, sanitizer, errorHandler2, document2) {
return parentRegistry || new MatIconRegistry(httpClient, sanitizer, document2, errorHandler2);
}
var ICON_REGISTRY_PROVIDER = {
// If there is already an MatIconRegistry available, use that. Otherwise, provide a new one.
provide: MatIconRegistry,
deps: [[new Optional(), new SkipSelf(), MatIconRegistry], [new Optional(), HttpClient], DomSanitizer, ErrorHandler, [new Optional(), DOCUMENT]],
useFactory: ICON_REGISTRY_PROVIDER_FACTORY
};
function cloneSvg(svg) {
return svg.cloneNode(true);
}
function iconKey(namespace, name) {
return namespace + ":" + name;
}
function isSafeUrlWithOptions(value) {
return !!(value.url && value.options);
}
// node_modules/@angular/material/fesm2022/icon.mjs
var _c06 = ["*"];
var MAT_ICON_DEFAULT_OPTIONS = new InjectionToken("MAT_ICON_DEFAULT_OPTIONS");
var MAT_ICON_LOCATION = new InjectionToken("mat-icon-location", {
providedIn: "root",
factory: MAT_ICON_LOCATION_FACTORY
});
function MAT_ICON_LOCATION_FACTORY() {
const _document2 = inject(DOCUMENT);
const _location = _document2 ? _document2.location : null;
return {
// Note that this needs to be a function, rather than a property, because Angular
// will only resolve it once, but we want the current path on each call.
getPathname: () => _location ? _location.pathname + _location.search : ""
};
}
var funcIriAttributes = ["clip-path", "color-profile", "src", "cursor", "fill", "filter", "marker", "marker-start", "marker-mid", "marker-end", "mask", "stroke"];
var funcIriAttributeSelector = funcIriAttributes.map((attr) => `[${attr}]`).join(", ");
var funcIriPattern = /^url\(['"]?#(.*?)['"]?\)$/;
var MatIcon = class _MatIcon {
_elementRef = inject(ElementRef);
_iconRegistry = inject(MatIconRegistry);
_location = inject(MAT_ICON_LOCATION);
_errorHandler = inject(ErrorHandler);
_defaultColor;
/**
* Theme color of the icon. This API is supported in M2 themes only, it
* has no effect in M3 themes. For color customization in M3, see https://material.angular.dev/components/icon/styling.
*
* For information on applying color variants in M3, see
* https://material.angular.dev/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
*/
get color() {
return this._color || this._defaultColor;
}
set color(value) {
this._color = value;
}
_color;
/**
* Whether the icon should be inlined, automatically sizing the icon to match the font size of
* the element the icon is contained in.
*/
inline = false;
/** Name of the icon in the SVG icon set. */
get svgIcon() {
return this._svgIcon;
}
set svgIcon(value) {
if (value !== this._svgIcon) {
if (value) {
this._updateSvgIcon(value);
} else if (this._svgIcon) {
this._clearSvgElement();
}
this._svgIcon = value;
}
}
_svgIcon;
/** Font set that the icon is a part of. */
get fontSet() {
return this._fontSet;
}
set fontSet(value) {
const newValue = this._cleanupFontValue(value);
if (newValue !== this._fontSet) {
this._fontSet = newValue;
this._updateFontIconClasses();
}
}
_fontSet;
/** Name of an icon within a font set. */
get fontIcon() {
return this._fontIcon;
}
set fontIcon(value) {
const newValue = this._cleanupFontValue(value);
if (newValue !== this._fontIcon) {
this._fontIcon = newValue;
this._updateFontIconClasses();
}
}
_fontIcon;
_previousFontSetClass = [];
_previousFontIconClass;
_svgName;
_svgNamespace;
/** Keeps track of the current page path. */
_previousPath;
/** Keeps track of the elements and attributes that we've prefixed with the current path. */
_elementsWithExternalReferences;
/** Subscription to the current in-progress SVG icon request. */
_currentIconFetch = Subscription.EMPTY;
constructor() {
const ariaHidden = inject(new HostAttributeToken("aria-hidden"), {
optional: true
});
const defaults2 = inject(MAT_ICON_DEFAULT_OPTIONS, {
optional: true
});
if (defaults2) {
if (defaults2.color) {
this.color = this._defaultColor = defaults2.color;
}
if (defaults2.fontSet) {
this.fontSet = defaults2.fontSet;
}
}
if (!ariaHidden) {
this._elementRef.nativeElement.setAttribute("aria-hidden", "true");
}
}
/**
* Splits an svgIcon binding value into its icon set and icon name components.
* Returns a 2-element array of [(icon set), (icon name)].
* The separator for the two fields is ':'. If there is no separator, an empty
* string is returned for the icon set and the entire value is returned for
* the icon name. If the argument is falsy, returns an array of two empty strings.
* Throws an error if the name contains two or more ':' separators.
* Examples:
* `'social:cake' -> ['social', 'cake']
* 'penguin' -> ['', 'penguin']
* null -> ['', '']
* 'a:b:c' -> (throws Error)`
*/
_splitIconName(iconName) {
if (!iconName) {
return ["", ""];
}
const parts = iconName.split(":");
switch (parts.length) {
case 1:
return ["", parts[0]];
// Use default namespace.
case 2:
return parts;
default:
throw Error(`Invalid icon name: "${iconName}"`);
}
}
ngOnInit() {
this._updateFontIconClasses();
}
ngAfterViewChecked() {
const cachedElements = this._elementsWithExternalReferences;
if (cachedElements && cachedElements.size) {
const newPath = this._location.getPathname();
if (newPath !== this._previousPath) {
this._previousPath = newPath;
this._prependPathToReferences(newPath);
}
}
}
ngOnDestroy() {
this._currentIconFetch.unsubscribe();
if (this._elementsWithExternalReferences) {
this._elementsWithExternalReferences.clear();
}
}
_usingFontIcon() {
return !this.svgIcon;
}
_setSvgElement(svg) {
this._clearSvgElement();
const path = this._location.getPathname();
this._previousPath = path;
this._cacheChildrenWithExternalReferences(svg);
this._prependPathToReferences(path);
this._elementRef.nativeElement.appendChild(svg);
}
_clearSvgElement() {
const layoutElement = this._elementRef.nativeElement;
let childCount = layoutElement.childNodes.length;
if (this._elementsWithExternalReferences) {
this._elementsWithExternalReferences.clear();
}
while (childCount--) {
const child = layoutElement.childNodes[childCount];
if (child.nodeType !== 1 || child.nodeName.toLowerCase() === "svg") {
child.remove();
}
}
}
_updateFontIconClasses() {
if (!this._usingFontIcon()) {
return;
}
const elem = this._elementRef.nativeElement;
const fontSetClasses = (this.fontSet ? this._iconRegistry.classNameForFontAlias(this.fontSet).split(/ +/) : this._iconRegistry.getDefaultFontSetClass()).filter((className) => className.length > 0);
this._previousFontSetClass.forEach((className) => elem.classList.remove(className));
fontSetClasses.forEach((className) => elem.classList.add(className));
this._previousFontSetClass = fontSetClasses;
if (this.fontIcon !== this._previousFontIconClass && !fontSetClasses.includes("mat-ligature-font")) {
if (this._previousFontIconClass) {
elem.classList.remove(this._previousFontIconClass);
}
if (this.fontIcon) {
elem.classList.add(this.fontIcon);
}
this._previousFontIconClass = this.fontIcon;
}
}
/**
* Cleans up a value to be used as a fontIcon or fontSet.
* Since the value ends up being assigned as a CSS class, we
* have to trim the value and omit space-separated values.
*/
_cleanupFontValue(value) {
return typeof value === "string" ? value.trim().split(" ")[0] : value;
}
/**
* Prepends the current path to all elements that have an attribute pointing to a `FuncIRI`
* reference. This is required because WebKit browsers require references to be prefixed with
* the current path, if the page has a `base` tag.
*/
_prependPathToReferences(path) {
const elements = this._elementsWithExternalReferences;
if (elements) {
elements.forEach((attrs, element) => {
attrs.forEach((attr) => {
element.setAttribute(attr.name, `url('${path}#${attr.value}')`);
});
});
}
}
/**
* Caches the children of an SVG element that have `url()`
* references that we need to prefix with the current path.
*/
_cacheChildrenWithExternalReferences(element) {
const elementsWithFuncIri = element.querySelectorAll(funcIriAttributeSelector);
const elements = this._elementsWithExternalReferences = this._elementsWithExternalReferences || /* @__PURE__ */ new Map();
for (let i = 0; i < elementsWithFuncIri.length; i++) {
funcIriAttributes.forEach((attr) => {
const elementWithReference = elementsWithFuncIri[i];
const value = elementWithReference.getAttribute(attr);
const match2 = value ? value.match(funcIriPattern) : null;
if (match2) {
let attributes = elements.get(elementWithReference);
if (!attributes) {
attributes = [];
elements.set(elementWithReference, attributes);
}
attributes.push({
name: attr,
value: match2[1]
});
}
});
}
}
/** Sets a new SVG icon with a particular name. */
_updateSvgIcon(rawName) {
this._svgNamespace = null;
this._svgName = null;
this._currentIconFetch.unsubscribe();
if (rawName) {
const [namespace, iconName] = this._splitIconName(rawName);
if (namespace) {
this._svgNamespace = namespace;
}
if (iconName) {
this._svgName = iconName;
}
this._currentIconFetch = this._iconRegistry.getNamedSvgIcon(iconName, namespace).pipe(take(1)).subscribe((svg) => this._setSvgElement(svg), (err) => {
const errorMessage = `Error retrieving icon ${namespace}:${iconName}! ${err.message}`;
this._errorHandler.handleError(new Error(errorMessage));
});
}
}
static \u0275fac = function MatIcon_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatIcon)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatIcon,
selectors: [["mat-icon"]],
hostAttrs: ["role", "img", 1, "mat-icon", "notranslate"],
hostVars: 10,
hostBindings: function MatIcon_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275attribute("data-mat-icon-type", ctx._usingFontIcon() ? "font" : "svg")("data-mat-icon-name", ctx._svgName || ctx.fontIcon)("data-mat-icon-namespace", ctx._svgNamespace || ctx.fontSet)("fontIcon", ctx._usingFontIcon() ? ctx.fontIcon : null);
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-icon-inline", ctx.inline)("mat-icon-no-color", ctx.color !== "primary" && ctx.color !== "accent" && ctx.color !== "warn");
}
},
inputs: {
color: "color",
inline: [2, "inline", "inline", booleanAttribute],
svgIcon: "svgIcon",
fontSet: "fontSet",
fontIcon: "fontIcon"
},
exportAs: ["matIcon"],
ngContentSelectors: _c06,
decls: 1,
vars: 0,
template: function MatIcon_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef();
\u0275\u0275projection(0);
}
},
styles: ["mat-icon,mat-icon.mat-primary,mat-icon.mat-accent,mat-icon.mat-warn{color:var(--mat-icon-color, inherit)}.mat-icon{-webkit-user-select:none;user-select:none;background-repeat:no-repeat;display:inline-block;fill:currentColor;height:24px;width:24px;overflow:hidden}.mat-icon.mat-icon-inline{font-size:inherit;height:inherit;line-height:inherit;width:inherit}.mat-icon.mat-ligature-font[fontIcon]::before{content:attr(fontIcon)}[dir=rtl] .mat-icon-rtl-mirror{transform:scale(-1, 1)}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon{display:block}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button .mat-icon{margin:auto}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatIcon, [{
type: Component,
args: [{
template: "<ng-content></ng-content>",
selector: "mat-icon",
exportAs: "matIcon",
host: {
"role": "img",
"class": "mat-icon notranslate",
"[class]": 'color ? "mat-" + color : ""',
"[attr.data-mat-icon-type]": '_usingFontIcon() ? "font" : "svg"',
"[attr.data-mat-icon-name]": "_svgName || fontIcon",
"[attr.data-mat-icon-namespace]": "_svgNamespace || fontSet",
"[attr.fontIcon]": "_usingFontIcon() ? fontIcon : null",
"[class.mat-icon-inline]": "inline",
"[class.mat-icon-no-color]": 'color !== "primary" && color !== "accent" && color !== "warn"'
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
styles: ["mat-icon,mat-icon.mat-primary,mat-icon.mat-accent,mat-icon.mat-warn{color:var(--mat-icon-color, inherit)}.mat-icon{-webkit-user-select:none;user-select:none;background-repeat:no-repeat;display:inline-block;fill:currentColor;height:24px;width:24px;overflow:hidden}.mat-icon.mat-icon-inline{font-size:inherit;height:inherit;line-height:inherit;width:inherit}.mat-icon.mat-ligature-font[fontIcon]::before{content:attr(fontIcon)}[dir=rtl] .mat-icon-rtl-mirror{transform:scale(-1, 1)}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon{display:block}.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-prefix .mat-icon-button .mat-icon,.mat-form-field:not(.mat-form-field-appearance-legacy) .mat-form-field-suffix .mat-icon-button .mat-icon{margin:auto}\n"]
}]
}], () => [], {
color: [{
type: Input
}],
inline: [{
type: Input,
args: [{
transform: booleanAttribute
}]
}],
svgIcon: [{
type: Input
}],
fontSet: [{
type: Input
}],
fontIcon: [{
type: Input
}]
});
})();
var MatIconModule = class _MatIconModule {
static \u0275fac = function MatIconModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatIconModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatIconModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatIconModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, MatIcon],
exports: [MatIcon, MatCommonModule]
}]
}], null, null);
})();
// src/app/components/dialog/dialog.component.ts
var DialogComponent = class _DialogComponent {
data;
dialogRef = inject(MatDialogRef);
hide = signal(true);
constructor(data) {
this.data = data;
}
onNoClick() {
this.dialogRef.close();
}
clickEvent(event) {
this.hide.set(!this.hide());
event.stopPropagation();
}
static \u0275fac = function DialogComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _DialogComponent)(\u0275\u0275directiveInject(MAT_DIALOG_DATA));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _DialogComponent, selectors: [["app-dialog"]], decls: 21, vars: 7, consts: [["mat-dialog-title", ""], ["mat-dialog-content", ""], [1, "fillField"], ["matInput", "", 3, "ngModelChange", "ngModel"], ["matInput", "", 3, "ngModelChange", "type", "ngModel"], ["mat-icon-button", "", "matSuffix", "", 3, "click"], ["mat-dialog-actions", ""], ["mat-button", "", "mat-dialog-close", "", 3, "click"], ["mat-button", "", "cdkFocusInitial", "", 3, "mat-dialog-close"]], template: function DialogComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "h1", 0);
\u0275\u0275text(1, "Hi ");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(2, "div", 1)(3, "p");
\u0275\u0275text(4, "User name");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(5, "mat-form-field", 2)(6, "input", 3);
\u0275\u0275twoWayListener("ngModelChange", function DialogComponent_Template_input_ngModelChange_6_listener($event) {
\u0275\u0275twoWayBindingSet(ctx.data.username, $event) || (ctx.data.username = $event);
return $event;
});
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(7, "p");
\u0275\u0275text(8, "Password");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(9, "mat-form-field", 2)(10, "mat-label");
\u0275\u0275text(11, "Enter your password");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(12, "input", 4);
\u0275\u0275twoWayListener("ngModelChange", function DialogComponent_Template_input_ngModelChange_12_listener($event) {
\u0275\u0275twoWayBindingSet(ctx.data.password, $event) || (ctx.data.password = $event);
return $event;
});
\u0275\u0275elementEnd();
\u0275\u0275elementStart(13, "button", 5);
\u0275\u0275listener("click", function DialogComponent_Template_button_click_13_listener($event) {
return ctx.clickEvent($event);
});
\u0275\u0275elementStart(14, "mat-icon");
\u0275\u0275text(15);
\u0275\u0275elementEnd()()()();
\u0275\u0275elementStart(16, "div", 6)(17, "button", 7);
\u0275\u0275listener("click", function DialogComponent_Template_button_click_17_listener() {
return ctx.onNoClick();
});
\u0275\u0275text(18, "No Thanks");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(19, "button", 8);
\u0275\u0275text(20, "Ok");
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(6);
\u0275\u0275twoWayProperty("ngModel", ctx.data.username);
\u0275\u0275advance(6);
\u0275\u0275property("type", ctx.hide() ? "password" : "text");
\u0275\u0275twoWayProperty("ngModel", ctx.data.password);
\u0275\u0275advance();
\u0275\u0275attribute("aria-label", "Hide password")("aria-pressed", ctx.hide());
\u0275\u0275advance(2);
\u0275\u0275textInterpolate(ctx.hide() ? "visibility_off" : "visibility");
\u0275\u0275advance(4);
\u0275\u0275property("mat-dialog-close", ctx.data);
}
}, dependencies: [MatButtonModule, MatButton, MatIconButton, MatLabel, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatFormField, MatInput, FormsModule, DefaultValueAccessor, NgControlStatus, NgModel, MatIcon, MatSuffix], styles: ["\n\n.fillField[_ngcontent-%COMP%] {\n width: 100%;\n}\n/*# sourceMappingURL=dialog.component.css.map */"], changeDetection: 0 });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(DialogComponent, [{
type: Component,
args: [{ selector: "app-dialog", imports: [MatButtonModule, MatLabel, MatDialogActions, MatDialogClose, MatDialogTitle, MatDialogContent, MatFormField, MatInput, FormsModule, MatIcon, MatSuffix], changeDetection: ChangeDetectionStrategy.OnPush, template: `<h1 mat-dialog-title>Hi </h1>\r
<div mat-dialog-content>\r
<p>User name</p>\r
<mat-form-field class="fillField">\r
<input matInput [(ngModel)]="data.username">\r
</mat-form-field>\r
<p>Password</p>\r
<mat-form-field class="fillField">\r
<mat-label>Enter your password</mat-label>\r
<input matInput\r
[type]="hide() ? 'password' : 'text'"\r
[(ngModel)]="data.password"\r
/>\r
<button\r
mat-icon-button\r
matSuffix\r
(click)="clickEvent($event)"\r
[attr.aria-label]="'Hide password'"\r
[attr.aria-pressed]="hide()"\r
>\r
<mat-icon>{{hide() ? 'visibility_off' : 'visibility'}}</mat-icon>\r
</button>\r
</mat-form-field>\r
</div>\r
\r
<div mat-dialog-actions>\r
<button mat-button mat-dialog-close (click)="onNoClick()">No Thanks</button>\r
<button mat-button [mat-dialog-close]="data" cdkFocusInitial>Ok</button>\r
</div>\r
`, styles: ["/* src/app/components/dialog/dialog.component.scss */\n.fillField {\n width: 100%;\n}\n/*# sourceMappingURL=dialog.component.css.map */\n"] }]
}], () => [{ type: void 0, decorators: [{
type: Inject,
args: [MAT_DIALOG_DATA]
}] }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(DialogComponent, { className: "DialogComponent", filePath: "src/app/components/dialog/dialog.component.ts", lineNumber: 28 });
})();
// src/app/_shared/event-bus.service.ts
var EventBusService = class _EventBusService {
subject$ = new Subject();
emit(event) {
this.subject$.next(event);
}
on(eventName, action) {
return this.subject$.pipe(filter((e) => e.name === eventName), map((e) => e["value"])).subscribe(action);
}
static \u0275fac = function EventBusService_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _EventBusService)();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _EventBusService, factory: _EventBusService.\u0275fac, providedIn: "root" });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(EventBusService, [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], null, null);
})();
// node_modules/@angular/material/fesm2022/toolbar.mjs
var _c07 = ["*", [["mat-toolbar-row"]]];
var _c15 = ["*", "mat-toolbar-row"];
var MatToolbarRow = class _MatToolbarRow {
static \u0275fac = function MatToolbarRow_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatToolbarRow)();
};
static \u0275dir = /* @__PURE__ */ \u0275\u0275defineDirective({
type: _MatToolbarRow,
selectors: [["mat-toolbar-row"]],
hostAttrs: [1, "mat-toolbar-row"],
exportAs: ["matToolbarRow"]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatToolbarRow, [{
type: Directive,
args: [{
selector: "mat-toolbar-row",
exportAs: "matToolbarRow",
host: {
"class": "mat-toolbar-row"
}
}]
}], null, null);
})();
var MatToolbar = class _MatToolbar {
_elementRef = inject(ElementRef);
_platform = inject(Platform);
_document = inject(DOCUMENT);
// TODO: should be typed as `ThemePalette` but internal apps pass in arbitrary strings.
/**
* Theme color of the toolbar. This API is supported in M2 themes only, it has
* no effect in M3 themes. For color customization in M3, see https://material.angular.dev/components/toolbar/styling.
*
* For information on applying color variants in M3, see
* https://material.angular.dev/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
*/
color;
/** Reference to all toolbar row elements that have been projected. */
_toolbarRows;
constructor() {
}
ngAfterViewInit() {
if (this._platform.isBrowser) {
this._checkToolbarMixedModes();
this._toolbarRows.changes.subscribe(() => this._checkToolbarMixedModes());
}
}
/**
* Throws an exception when developers are attempting to combine the different toolbar row modes.
*/
_checkToolbarMixedModes() {
if (this._toolbarRows.length && (typeof ngDevMode === "undefined" || ngDevMode)) {
const isCombinedUsage = Array.from(this._elementRef.nativeElement.childNodes).filter((node) => !(node.classList && node.classList.contains("mat-toolbar-row"))).filter((node) => node.nodeType !== (this._document ? this._document.COMMENT_NODE : 8)).some((node) => !!(node.textContent && node.textContent.trim()));
if (isCombinedUsage) {
throwToolbarMixedModesError();
}
}
}
static \u0275fac = function MatToolbar_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatToolbar)();
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({
type: _MatToolbar,
selectors: [["mat-toolbar"]],
contentQueries: function MatToolbar_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) {
\u0275\u0275contentQuery(dirIndex, MatToolbarRow, 5);
}
if (rf & 2) {
let _t;
\u0275\u0275queryRefresh(_t = \u0275\u0275loadQuery()) && (ctx._toolbarRows = _t);
}
},
hostAttrs: [1, "mat-toolbar"],
hostVars: 6,
hostBindings: function MatToolbar_HostBindings(rf, ctx) {
if (rf & 2) {
\u0275\u0275classMap(ctx.color ? "mat-" + ctx.color : "");
\u0275\u0275classProp("mat-toolbar-multiple-rows", ctx._toolbarRows.length > 0)("mat-toolbar-single-row", ctx._toolbarRows.length === 0);
}
},
inputs: {
color: "color"
},
exportAs: ["matToolbar"],
ngContentSelectors: _c15,
decls: 2,
vars: 0,
template: function MatToolbar_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275projectionDef(_c07);
\u0275\u0275projection(0);
\u0275\u0275projection(1, 1);
}
},
styles: [".mat-toolbar{background:var(--mat-toolbar-container-background-color, var(--mat-sys-surface));color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface))}.mat-toolbar,.mat-toolbar h1,.mat-toolbar h2,.mat-toolbar h3,.mat-toolbar h4,.mat-toolbar h5,.mat-toolbar h6{font-family:var(--mat-toolbar-title-text-font, var(--mat-sys-title-large-font));font-size:var(--mat-toolbar-title-text-size, var(--mat-sys-title-large-size));line-height:var(--mat-toolbar-title-text-line-height, var(--mat-sys-title-large-line-height));font-weight:var(--mat-toolbar-title-text-weight, var(--mat-sys-title-large-weight));letter-spacing:var(--mat-toolbar-title-text-tracking, var(--mat-sys-title-large-tracking));margin:0}@media(forced-colors: active){.mat-toolbar{outline:solid 1px}}.mat-toolbar .mat-form-field-underline,.mat-toolbar .mat-form-field-ripple,.mat-toolbar .mat-focused .mat-form-field-ripple{background-color:currentColor}.mat-toolbar .mat-form-field-label,.mat-toolbar .mat-focused .mat-form-field-label,.mat-toolbar .mat-select-value,.mat-toolbar .mat-select-arrow,.mat-toolbar .mat-form-field.mat-focused .mat-select-arrow{color:inherit}.mat-toolbar .mat-input-element{caret-color:currentColor}.mat-toolbar .mat-mdc-button-base.mat-mdc-button-base.mat-unthemed{--mdc-text-button-label-text-color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface));--mdc-outlined-button-label-text-color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface))}.mat-toolbar-row,.mat-toolbar-single-row{display:flex;box-sizing:border-box;padding:0 16px;width:100%;flex-direction:row;align-items:center;white-space:nowrap;height:var(--mat-toolbar-standard-height, 64px)}@media(max-width: 599px){.mat-toolbar-row,.mat-toolbar-single-row{height:var(--mat-toolbar-mobile-height, 56px)}}.mat-toolbar-multiple-rows{display:flex;box-sizing:border-box;flex-direction:column;width:100%;min-height:var(--mat-toolbar-standard-height, 64px)}@media(max-width: 599px){.mat-toolbar-multiple-rows{min-height:var(--mat-toolbar-mobile-height, 56px)}}\n"],
encapsulation: 2,
changeDetection: 0
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatToolbar, [{
type: Component,
args: [{
selector: "mat-toolbar",
exportAs: "matToolbar",
host: {
"class": "mat-toolbar",
"[class]": 'color ? "mat-" + color : ""',
"[class.mat-toolbar-multiple-rows]": "_toolbarRows.length > 0",
"[class.mat-toolbar-single-row]": "_toolbarRows.length === 0"
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
template: '<ng-content></ng-content>\n<ng-content select="mat-toolbar-row"></ng-content>\n',
styles: [".mat-toolbar{background:var(--mat-toolbar-container-background-color, var(--mat-sys-surface));color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface))}.mat-toolbar,.mat-toolbar h1,.mat-toolbar h2,.mat-toolbar h3,.mat-toolbar h4,.mat-toolbar h5,.mat-toolbar h6{font-family:var(--mat-toolbar-title-text-font, var(--mat-sys-title-large-font));font-size:var(--mat-toolbar-title-text-size, var(--mat-sys-title-large-size));line-height:var(--mat-toolbar-title-text-line-height, var(--mat-sys-title-large-line-height));font-weight:var(--mat-toolbar-title-text-weight, var(--mat-sys-title-large-weight));letter-spacing:var(--mat-toolbar-title-text-tracking, var(--mat-sys-title-large-tracking));margin:0}@media(forced-colors: active){.mat-toolbar{outline:solid 1px}}.mat-toolbar .mat-form-field-underline,.mat-toolbar .mat-form-field-ripple,.mat-toolbar .mat-focused .mat-form-field-ripple{background-color:currentColor}.mat-toolbar .mat-form-field-label,.mat-toolbar .mat-focused .mat-form-field-label,.mat-toolbar .mat-select-value,.mat-toolbar .mat-select-arrow,.mat-toolbar .mat-form-field.mat-focused .mat-select-arrow{color:inherit}.mat-toolbar .mat-input-element{caret-color:currentColor}.mat-toolbar .mat-mdc-button-base.mat-mdc-button-base.mat-unthemed{--mdc-text-button-label-text-color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface));--mdc-outlined-button-label-text-color:var(--mat-toolbar-container-text-color, var(--mat-sys-on-surface))}.mat-toolbar-row,.mat-toolbar-single-row{display:flex;box-sizing:border-box;padding:0 16px;width:100%;flex-direction:row;align-items:center;white-space:nowrap;height:var(--mat-toolbar-standard-height, 64px)}@media(max-width: 599px){.mat-toolbar-row,.mat-toolbar-single-row{height:var(--mat-toolbar-mobile-height, 56px)}}.mat-toolbar-multiple-rows{display:flex;box-sizing:border-box;flex-direction:column;width:100%;min-height:var(--mat-toolbar-standard-height, 64px)}@media(max-width: 599px){.mat-toolbar-multiple-rows{min-height:var(--mat-toolbar-mobile-height, 56px)}}\n"]
}]
}], () => [], {
color: [{
type: Input
}],
_toolbarRows: [{
type: ContentChildren,
args: [MatToolbarRow, {
descendants: true
}]
}]
});
})();
function throwToolbarMixedModesError() {
throw Error("MatToolbar: Attempting to combine different toolbar modes. Either specify multiple `<mat-toolbar-row>` elements explicitly or just place content inside of a `<mat-toolbar>` for a single row.");
}
var MatToolbarModule = class _MatToolbarModule {
static \u0275fac = function MatToolbarModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _MatToolbarModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({
type: _MatToolbarModule
});
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({
imports: [MatCommonModule, MatCommonModule]
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(MatToolbarModule, [{
type: NgModule,
args: [{
imports: [MatCommonModule, MatToolbar, MatToolbarRow],
exports: [MatToolbar, MatToolbarRow, MatCommonModule]
}]
}], null, null);
})();
// src/app/app.component.ts
function AppComponent_li_11_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "li", 3)(1, "a", 13);
\u0275\u0275text(2, "Admin Board");
\u0275\u0275elementEnd()();
}
}
function AppComponent_li_12_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "li", 3)(1, "a", 14);
\u0275\u0275text(2, "Moderator Board");
\u0275\u0275elementEnd()();
}
}
function AppComponent_a_14_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "a", 15);
\u0275\u0275text(1, "User");
\u0275\u0275elementEnd();
}
}
function AppComponent_ul_15_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "ul", 16)(1, "li", 3)(2, "a", 17);
\u0275\u0275text(3, "Sign Up");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(4, "li", 3)(5, "a", 18);
\u0275\u0275text(6, "Login");
\u0275\u0275elementEnd()()();
}
}
function AppComponent_ul_16_Template(rf, ctx) {
if (rf & 1) {
const _r1 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "ul", 16)(1, "li", 3)(2, "a", 19);
\u0275\u0275text(3);
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(4, "li", 3)(5, "a", 20);
\u0275\u0275listener("click", function AppComponent_ul_16_Template_a_click_5_listener() {
\u0275\u0275restoreView(_r1);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.logout());
});
\u0275\u0275text(6, "LogOut");
\u0275\u0275elementEnd()()();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275advance(3);
\u0275\u0275textInterpolate(ctx_r1.username);
}
}
function AppComponent_button_21_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "button", 21)(1, "mat-icon");
\u0275\u0275text(2, "app_registration");
\u0275\u0275elementEnd();
\u0275\u0275text(3, " Register ");
\u0275\u0275elementEnd();
}
}
function AppComponent_button_22_Template(rf, ctx) {
if (rf & 1) {
const _r3 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 22);
\u0275\u0275listener("click", function AppComponent_button_22_Template_button_click_0_listener() {
\u0275\u0275restoreView(_r3);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.openDialog("100ms", "5ms"));
});
\u0275\u0275elementStart(1, "mat-icon");
\u0275\u0275text(2, "login");
\u0275\u0275elementEnd();
\u0275\u0275text(3, " Login ");
\u0275\u0275elementEnd();
}
}
function AppComponent_button_23_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "button", 21)(1, "mat-icon");
\u0275\u0275text(2, "account_circle");
\u0275\u0275elementEnd();
\u0275\u0275text(3);
\u0275\u0275elementEnd();
}
if (rf & 2) {
const ctx_r1 = \u0275\u0275nextContext();
\u0275\u0275advance(3);
\u0275\u0275textInterpolate1(" ", ctx_r1.username, " ");
}
}
function AppComponent_button_24_Template(rf, ctx) {
if (rf & 1) {
const _r4 = \u0275\u0275getCurrentView();
\u0275\u0275elementStart(0, "button", 22);
\u0275\u0275listener("click", function AppComponent_button_24_Template_button_click_0_listener() {
\u0275\u0275restoreView(_r4);
const ctx_r1 = \u0275\u0275nextContext();
return \u0275\u0275resetView(ctx_r1.logout());
});
\u0275\u0275elementStart(1, "mat-icon");
\u0275\u0275text(2, "logout");
\u0275\u0275elementEnd();
\u0275\u0275text(3, " Logout ");
\u0275\u0275elementEnd();
}
}
var AppComponent = class _AppComponent {
storageService;
authService;
eventBusService;
dialog = inject(MatDialog);
//private authService = new AuthService(provideHttpClient())
dialogData = { password: "", username: "" };
roles = [];
isLoggedIn = false;
showAdminBoard = false;
showModeratorBoard = false;
username;
eventBusSub;
errorMessage;
isLoginFailed = false;
constructor(storageService, authService, eventBusService) {
this.storageService = storageService;
this.authService = authService;
this.eventBusService = eventBusService;
}
ngOnInit() {
this.isLoggedIn = this.storageService.isLoggedIn();
if (this.isLoggedIn) {
const user = this.storageService.getUser();
this.roles = user.roles;
this.showAdminBoard = this.roles.includes("ROLE_ADMIN");
this.showModeratorBoard = this.roles.includes("ROLE_MODERATOR");
this.username = user.username;
}
this.eventBusSub = this.eventBusService.on("logout", () => {
this.logout();
});
}
logout() {
this.authService.logout().subscribe({
next: (res) => {
console.log(res);
this.storageService.clean();
window.location.reload();
},
error: (err) => {
console.log(err);
}
});
}
openDialog(enterAnimationDuration, exitAnimationDuration) {
let dialogRef = this.dialog.open(DialogComponent, {
width: "350px",
enterAnimationDuration,
exitAnimationDuration,
data: { username: this.dialogData.username, password: this.dialogData.password }
});
dialogRef.afterClosed().subscribe((result) => {
console.log("The dialog was closed");
if (result == null) {
return;
}
this.dialogData = result;
this.authService.login(this.dialogData.username, this.dialogData.password).subscribe((data) => {
this.storageService.saveToken(data.accessToken);
this.storageService.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
let user = this.storageService.getUser();
this.roles = user.roles;
this.reloadPage();
}, (err) => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
});
});
}
reloadPage() {
window.location.reload();
}
static \u0275fac = function AppComponent_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AppComponent)(\u0275\u0275directiveInject(TokenStorageService), \u0275\u0275directiveInject(AuthService), \u0275\u0275directiveInject(EventBusService));
};
static \u0275cmp = /* @__PURE__ */ \u0275\u0275defineComponent({ type: _AppComponent, selectors: [["app-root"]], standalone: false, decls: 27, vars: 9, consts: [[1, "navbar", "navbar-expand", "navbar-dark", "bg-dark"], ["href", "#", 1, "navbar-brand"], ["routerLinkActive", "active", 1, "navbar-nav", "mr-auto"], [1, "nav-item"], ["routerLink", "tutorials", 1, "nav-link"], ["routerLink", "add", 1, "nav-link"], ["class", "nav-item", 4, "ngIf"], ["href", "/user", "class", "nav-link", "routerLink", "user", 4, "ngIf"], ["class", "navbar-nav ml-auto", 4, "ngIf"], [1, "example-spacer"], ["mat-raised-button", "", 4, "ngIf"], ["mat-raised-button", "", 3, "click", 4, "ngIf"], [1, "container", "mt-3"], ["href", "/admin", "routerLink", "admin", 1, "nav-link"], ["href", "/mod", "routerLink", "mod", 1, "nav-link"], ["href", "/user", "routerLink", "user", 1, "nav-link"], [1, "navbar-nav", "ml-auto"], ["href", "/register", "routerLink", "register", 1, "nav-link"], ["href", "/login", "routerLink", "login", 1, "nav-link"], ["href", "/profile", "routerLink", "profile", 1, "nav-link"], ["href", "", 1, "nav-link", 3, "click"], ["mat-raised-button", ""], ["mat-raised-button", "", 3, "click"]], template: function AppComponent_Template(rf, ctx) {
if (rf & 1) {
\u0275\u0275elementStart(0, "div")(1, "nav", 0)(2, "a", 1);
\u0275\u0275text(3, "Spring-AngularTS");
\u0275\u0275elementEnd();
\u0275\u0275elementStart(4, "ul", 2)(5, "li", 3)(6, "a", 4);
\u0275\u0275text(7, "Tutorials");
\u0275\u0275elementEnd()();
\u0275\u0275elementStart(8, "li", 3)(9, "a", 5);
\u0275\u0275text(10, "Add");
\u0275\u0275elementEnd()();
\u0275\u0275template(11, AppComponent_li_11_Template, 3, 0, "li", 6)(12, AppComponent_li_12_Template, 3, 0, "li", 6);
\u0275\u0275elementStart(13, "li", 3);
\u0275\u0275template(14, AppComponent_a_14_Template, 2, 0, "a", 7);
\u0275\u0275elementEnd()();
\u0275\u0275template(15, AppComponent_ul_15_Template, 7, 0, "ul", 8)(16, AppComponent_ul_16_Template, 7, 1, "ul", 8);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(17, "mat-toolbar")(18, "span");
\u0275\u0275text(19, "My App");
\u0275\u0275elementEnd();
\u0275\u0275element(20, "span", 9);
\u0275\u0275template(21, AppComponent_button_21_Template, 4, 0, "button", 10)(22, AppComponent_button_22_Template, 4, 0, "button", 11)(23, AppComponent_button_23_Template, 4, 1, "button", 10)(24, AppComponent_button_24_Template, 4, 0, "button", 11);
\u0275\u0275elementEnd();
\u0275\u0275elementStart(25, "div", 12);
\u0275\u0275element(26, "router-outlet");
\u0275\u0275elementEnd()();
}
if (rf & 2) {
\u0275\u0275advance(11);
\u0275\u0275property("ngIf", ctx.showAdminBoard);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.showModeratorBoard);
\u0275\u0275advance(2);
\u0275\u0275property("ngIf", ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", !ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.isLoggedIn);
\u0275\u0275advance(5);
\u0275\u0275property("ngIf", !ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", !ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.isLoggedIn);
\u0275\u0275advance();
\u0275\u0275property("ngIf", ctx.isLoggedIn);
}
}, dependencies: [NgIf, RouterOutlet, RouterLink, RouterLinkActive, MatToolbar, MatButton, MatIcon], styles: ["\n\n.example-spacer[_ngcontent-%COMP%] {\n flex: 1 1 auto;\n}\n/*# sourceMappingURL=app.component.css.map */"] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AppComponent, [{
type: Component,
args: [{ selector: "app-root", standalone: false, template: `<div>\r
<nav class="navbar navbar-expand navbar-dark bg-dark">\r
<a href="#" class="navbar-brand">Spring-AngularTS</a>\r
\r
<ul class="navbar-nav mr-auto" routerLinkActive="active">\r
\r
<li class="nav-item">\r
<a routerLink="tutorials" class="nav-link">Tutorials</a>\r
</li>\r
<li class="nav-item">\r
<a routerLink="add" class="nav-link">Add</a>\r
</li>\r
\r
<li class="nav-item" *ngIf="showAdminBoard">\r
<a href="/admin" class="nav-link" routerLink="admin">Admin Board</a>\r
</li>\r
<li class="nav-item" *ngIf="showModeratorBoard">\r
<a href="/mod" class="nav-link" routerLink="mod">Moderator Board</a>\r
</li>\r
<li class="nav-item">\r
<a href="/user" class="nav-link" *ngIf="isLoggedIn" routerLink="user">User</a>\r
</li>\r
\r
</ul>\r
\r
<ul class="navbar-nav ml-auto" *ngIf="!isLoggedIn">\r
<li class="nav-item">\r
<a href="/register" class="nav-link" routerLink="register">Sign Up</a>\r
</li>\r
<li class="nav-item">\r
<a href="/login" class="nav-link" routerLink="login">Login</a>\r
</li>\r
</ul>\r
\r
<ul class="navbar-nav ml-auto" *ngIf="isLoggedIn">\r
<li class="nav-item">\r
<a href="/profile" class="nav-link" routerLink="profile">{{ username }}</a>\r
</li>\r
<li class="nav-item">\r
<a href class="nav-link" (click)="logout()">LogOut</a>\r
</li>\r
</ul>\r
\r
</nav>\r
<mat-toolbar>\r
\r
\r
<span>My App</span>\r
<span class="example-spacer"></span>\r
<button mat-raised-button *ngIf="!isLoggedIn">\r
<mat-icon>app_registration</mat-icon>\r
Register\r
</button>\r
\r
<button mat-raised-button (click)="openDialog('100ms', '5ms')" *ngIf="!isLoggedIn">\r
<mat-icon>login</mat-icon>\r
Login\r
</button>\r
\r
<button mat-raised-button *ngIf="isLoggedIn">\r
<mat-icon>account_circle</mat-icon>\r
{{ username }}\r
</button>\r
\r
<button mat-raised-button (click)="logout()"*ngIf="isLoggedIn">\r
<mat-icon>logout</mat-icon>\r
Logout\r
</button>\r
\r
</mat-toolbar>\r
\r
\r
<div class="container mt-3">\r
<router-outlet></router-outlet>\r
</div>\r
</div>\r
`, styles: ["/* src/app/app.component.scss */\n.example-spacer {\n flex: 1 1 auto;\n}\n/*# sourceMappingURL=app.component.css.map */\n"] }]
}], () => [{ type: TokenStorageService }, { type: AuthService }, { type: EventBusService }], null);
})();
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && \u0275setClassDebugInfo(AppComponent, { className: "AppComponent", filePath: "src/app/app.component.ts", lineNumber: 15 });
})();
// src/app/helpers/auth.interceptor.ts
var TOKEN_HEADER_KEY = "Authorization";
var AuthInterceptor = class _AuthInterceptor {
token;
constructor(token) {
this.token = token;
}
intercept(req, next) {
let authReq = req;
const token = this.token.getToken();
if (token != null) {
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, "Bearer " + token) });
}
return next.handle(authReq);
}
static \u0275fac = function AuthInterceptor_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AuthInterceptor)(\u0275\u0275inject(TokenStorageService));
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({ token: _AuthInterceptor, factory: _AuthInterceptor.\u0275fac });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AuthInterceptor, [{
type: Injectable
}], () => [{ type: TokenStorageService }], null);
})();
var authInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
];
// node_modules/@angular/platform-browser/fesm2022/animations/async.mjs
var ANIMATION_PREFIX = "@";
var AsyncAnimationRendererFactory = class _AsyncAnimationRendererFactory {
doc;
delegate;
zone;
animationType;
moduleImpl;
_rendererFactoryPromise = null;
scheduler = null;
injector = inject(Injector);
loadingSchedulerFn = inject(\u0275ASYNC_ANIMATION_LOADING_SCHEDULER_FN, {
optional: true
});
_engine;
/**
*
* @param moduleImpl allows to provide a mock implmentation (or will load the animation module)
*/
constructor(doc, delegate, zone, animationType, moduleImpl) {
this.doc = doc;
this.delegate = delegate;
this.zone = zone;
this.animationType = animationType;
this.moduleImpl = moduleImpl;
}
/** @docs-private */
ngOnDestroy() {
this._engine?.flush();
}
/**
* @internal
*/
loadImpl() {
const loadFn = () => this.moduleImpl ?? import("./browser-L6TR647S.js").then((m) => m);
let moduleImplPromise;
if (this.loadingSchedulerFn) {
moduleImplPromise = this.loadingSchedulerFn(loadFn);
} else {
moduleImplPromise = loadFn();
}
return moduleImplPromise.catch((e) => {
throw new RuntimeError(5300, (typeof ngDevMode === "undefined" || ngDevMode) && "Async loading for animations package was enabled, but loading failed. Angular falls back to using regular rendering. No animations will be displayed and their styles won't be applied.");
}).then(({
\u0275createEngine,
\u0275AnimationRendererFactory
}) => {
this._engine = \u0275createEngine(this.animationType, this.doc);
const rendererFactory = new \u0275AnimationRendererFactory(this.delegate, this._engine, this.zone);
this.delegate = rendererFactory;
return rendererFactory;
});
}
/**
* This method is delegating the renderer creation to the factories.
* It uses default factory while the animation factory isn't loaded
* and will rely on the animation factory once it is loaded.
*
* Calling this method will trigger as side effect the loading of the animation module
* if the renderered component uses animations.
*/
createRenderer(hostElement, rendererType) {
const renderer = this.delegate.createRenderer(hostElement, rendererType);
if (renderer.\u0275type === 0) {
return renderer;
}
if (typeof renderer.throwOnSyntheticProps === "boolean") {
renderer.throwOnSyntheticProps = false;
}
const dynamicRenderer = new DynamicDelegationRenderer(renderer);
if (rendererType?.data?.["animation"] && !this._rendererFactoryPromise) {
this._rendererFactoryPromise = this.loadImpl();
}
this._rendererFactoryPromise?.then((animationRendererFactory) => {
const animationRenderer = animationRendererFactory.createRenderer(hostElement, rendererType);
dynamicRenderer.use(animationRenderer);
this.scheduler ??= this.injector.get(ChangeDetectionScheduler, null, {
optional: true
});
this.scheduler?.notify(
10
/* NotificationSource.AsyncAnimationsLoaded */
);
}).catch((e) => {
dynamicRenderer.use(renderer);
});
return dynamicRenderer;
}
begin() {
this.delegate.begin?.();
}
end() {
this.delegate.end?.();
}
whenRenderingDone() {
return this.delegate.whenRenderingDone?.() ?? Promise.resolve();
}
/**
* Used during HMR to clear any cached data about a component.
* @param componentId ID of the component that is being replaced.
*/
componentReplaced(componentId) {
this._engine?.flush();
this.delegate.componentReplaced?.(componentId);
}
static \u0275fac = function AsyncAnimationRendererFactory_Factory(__ngFactoryType__) {
\u0275\u0275invalidFactory();
};
static \u0275prov = /* @__PURE__ */ \u0275\u0275defineInjectable({
token: _AsyncAnimationRendererFactory,
factory: _AsyncAnimationRendererFactory.\u0275fac
});
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AsyncAnimationRendererFactory, [{
type: Injectable
}], () => [{
type: Document
}, {
type: RendererFactory2
}, {
type: NgZone
}, {
type: void 0
}, {
type: Promise
}], null);
})();
var DynamicDelegationRenderer = class {
delegate;
// List of callbacks that need to be replayed on the animation renderer once its loaded
replay = [];
\u0275type = 1;
constructor(delegate) {
this.delegate = delegate;
}
use(impl) {
this.delegate = impl;
if (this.replay !== null) {
for (const fn of this.replay) {
fn(impl);
}
this.replay = null;
}
}
get data() {
return this.delegate.data;
}
destroy() {
this.replay = null;
this.delegate.destroy();
}
createElement(name, namespace) {
return this.delegate.createElement(name, namespace);
}
createComment(value) {
return this.delegate.createComment(value);
}
createText(value) {
return this.delegate.createText(value);
}
get destroyNode() {
return this.delegate.destroyNode;
}
appendChild(parent, newChild) {
this.delegate.appendChild(parent, newChild);
}
insertBefore(parent, newChild, refChild, isMove) {
this.delegate.insertBefore(parent, newChild, refChild, isMove);
}
removeChild(parent, oldChild, isHostElement) {
this.delegate.removeChild(parent, oldChild, isHostElement);
}
selectRootElement(selectorOrNode, preserveContent) {
return this.delegate.selectRootElement(selectorOrNode, preserveContent);
}
parentNode(node) {
return this.delegate.parentNode(node);
}
nextSibling(node) {
return this.delegate.nextSibling(node);
}
setAttribute(el, name, value, namespace) {
this.delegate.setAttribute(el, name, value, namespace);
}
removeAttribute(el, name, namespace) {
this.delegate.removeAttribute(el, name, namespace);
}
addClass(el, name) {
this.delegate.addClass(el, name);
}
removeClass(el, name) {
this.delegate.removeClass(el, name);
}
setStyle(el, style, value, flags) {
this.delegate.setStyle(el, style, value, flags);
}
removeStyle(el, style, flags) {
this.delegate.removeStyle(el, style, flags);
}
setProperty(el, name, value) {
if (this.shouldReplay(name)) {
this.replay.push((renderer) => renderer.setProperty(el, name, value));
}
this.delegate.setProperty(el, name, value);
}
setValue(node, value) {
this.delegate.setValue(node, value);
}
listen(target, eventName, callback, options) {
if (this.shouldReplay(eventName)) {
this.replay.push((renderer) => renderer.listen(target, eventName, callback, options));
}
return this.delegate.listen(target, eventName, callback, options);
}
shouldReplay(propOrEventName) {
return this.replay !== null && propOrEventName.startsWith(ANIMATION_PREFIX);
}
};
var \u0275ASYNC_ANIMATION_LOADING_SCHEDULER_FN = new InjectionToken(ngDevMode ? "async_animation_loading_scheduler_fn" : "");
function provideAnimationsAsync(type = "animations") {
performanceMarkFeature("NgAsyncAnimations");
if (false) {
type = "noop";
}
return makeEnvironmentProviders([{
provide: RendererFactory2,
useFactory: (doc, renderer, zone) => {
return new AsyncAnimationRendererFactory(doc, renderer, zone, type);
},
deps: [DOCUMENT, DomRendererFactory2, NgZone]
}, {
provide: ANIMATION_MODULE_TYPE,
useValue: type === "noop" ? "NoopAnimations" : "BrowserAnimations"
}]);
}
// src/app/app.module.ts
var AppModule = class _AppModule {
static \u0275fac = function AppModule_Factory(__ngFactoryType__) {
return new (__ngFactoryType__ || _AppModule)();
};
static \u0275mod = /* @__PURE__ */ \u0275\u0275defineNgModule({ type: _AppModule, bootstrap: [AppComponent] });
static \u0275inj = /* @__PURE__ */ \u0275\u0275defineInjector({ providers: [authInterceptorProviders, provideHttpClient(withInterceptorsFromDi()), provideAnimationsAsync()], imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
LoginComponent,
MatToolbar,
MatButton,
MatIcon
] });
};
(() => {
(typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(AppModule, [{
type: NgModule,
args: [{
declarations: [
AppComponent,
TutorialsListComponent,
TutorialDetailsComponent,
AddTutorialComponent,
RegisterComponent,
HomeComponent,
ProfileComponent,
BoardAdminComponent,
BoardModeratorComponent,
BoardUserComponent
],
bootstrap: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
LoginComponent,
MatToolbar,
MatButton,
MatIcon
],
providers: [authInterceptorProviders, provideHttpClient(withInterceptorsFromDi()), provideAnimationsAsync()]
}]
}], null, null);
})();
// src/environments/environment.ts
var environment = {
production: false
};
// src/main.ts
if (environment.production) {
enableProdMode();
}
platformBrowser().bootstrapModule(AppModule).catch((err) => console.error(err));
/*! Bundled license information:
@angular/common/fesm2022/dom_tokens-rA0ACyx7.mjs:
@angular/common/fesm2022/location-Dq4mJT-A.mjs:
@angular/common/fesm2022/common_module-Dx7dWex5.mjs:
@angular/common/fesm2022/xhr-BfNfxNDv.mjs:
@angular/common/fesm2022/common.mjs:
@angular/platform-browser/fesm2022/dom_renderer-DGKzginR.mjs:
@angular/platform-browser/fesm2022/browser-X3l5Bmdq.mjs:
@angular/common/fesm2022/module-CYx9OwZ_.mjs:
@angular/common/fesm2022/http.mjs:
@angular/platform-browser/fesm2022/platform-browser.mjs:
@angular/router/fesm2022/router-Dwfin5Au.mjs:
@angular/router/fesm2022/router_module-DTJgGWLd.mjs:
@angular/router/fesm2022/router.mjs:
@angular/forms/fesm2022/forms.mjs:
@angular/platform-browser/fesm2022/animations/async.mjs:
(**
* @license Angular v19.2.11
* (c) 2010-2025 Google LLC. https://angular.io/
* License: MIT
*)
*/
//# sourceMappingURL=main.js.map