UNPKG

93.2 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { Version, InjectionToken, NgModule, Optional, Inject, inject, LOCALE_ID, Injectable, Directive, Input, Component, ViewEncapsulation, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core';
3import { BidiModule } from '@angular/cdk/bidi';
4import { VERSION as VERSION$1 } from '@angular/cdk';
5import * as i3 from '@angular/common';
6import { DOCUMENT, CommonModule } from '@angular/common';
7import * as i1$1 from '@angular/cdk/platform';
8import { _isTestEnvironment, normalizePassiveListenerOptions } from '@angular/cdk/platform';
9import * as i1 from '@angular/cdk/a11y';
10import { isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader } from '@angular/cdk/a11y';
11import { coerceBooleanProperty, coerceNumberProperty, coerceElement } from '@angular/cdk/coercion';
12import { Observable, Subject } from 'rxjs';
13import { startWith } from 'rxjs/operators';
14import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
15import { ENTER, SPACE, hasModifierKey } from '@angular/cdk/keycodes';
16
17/**
18 * @license
19 * Copyright Google LLC All Rights Reserved.
20 *
21 * Use of this source code is governed by an MIT-style license that can be
22 * found in the LICENSE file at https://angular.io/license
23 */
24/** Current version of Angular Material. */
25const VERSION = new Version('14.0.4');
26
27/**
28 * @license
29 * Copyright Google LLC All Rights Reserved.
30 *
31 * Use of this source code is governed by an MIT-style license that can be
32 * found in the LICENSE file at https://angular.io/license
33 */
34/** @docs-private */
35class AnimationCurves {
36}
37AnimationCurves.STANDARD_CURVE = 'cubic-bezier(0.4,0.0,0.2,1)';
38AnimationCurves.DECELERATION_CURVE = 'cubic-bezier(0.0,0.0,0.2,1)';
39AnimationCurves.ACCELERATION_CURVE = 'cubic-bezier(0.4,0.0,1,1)';
40AnimationCurves.SHARP_CURVE = 'cubic-bezier(0.4,0.0,0.6,1)';
41/** @docs-private */
42class AnimationDurations {
43}
44AnimationDurations.COMPLEX = '375ms';
45AnimationDurations.ENTERING = '225ms';
46AnimationDurations.EXITING = '195ms';
47
48/** @docs-private */
49function MATERIAL_SANITY_CHECKS_FACTORY() {
50 return true;
51}
52/** Injection token that configures whether the Material sanity checks are enabled. */
53const MATERIAL_SANITY_CHECKS = new InjectionToken('mat-sanity-checks', {
54 providedIn: 'root',
55 factory: MATERIAL_SANITY_CHECKS_FACTORY,
56});
57/**
58 * Module that captures anything that should be loaded and/or run for *all* Angular Material
59 * components. This includes Bidi, etc.
60 *
61 * This module should be imported to each top-level component module (e.g., MatTabsModule).
62 */
63class MatCommonModule {
64 constructor(highContrastModeDetector, _sanityChecks, _document) {
65 this._sanityChecks = _sanityChecks;
66 this._document = _document;
67 /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */
68 this._hasDoneGlobalChecks = false;
69 // While A11yModule also does this, we repeat it here to avoid importing A11yModule
70 // in MatCommonModule.
71 highContrastModeDetector._applyBodyHighContrastModeCssClasses();
72 if (!this._hasDoneGlobalChecks) {
73 this._hasDoneGlobalChecks = true;
74 if (typeof ngDevMode === 'undefined' || ngDevMode) {
75 if (this._checkIsEnabled('doctype')) {
76 _checkDoctypeIsDefined(this._document);
77 }
78 if (this._checkIsEnabled('theme')) {
79 _checkThemeIsPresent(this._document);
80 }
81 if (this._checkIsEnabled('version')) {
82 _checkCdkVersionMatch();
83 }
84 }
85 }
86 }
87 /** Gets whether a specific sanity check is enabled. */
88 _checkIsEnabled(name) {
89 if (_isTestEnvironment()) {
90 return false;
91 }
92 if (typeof this._sanityChecks === 'boolean') {
93 return this._sanityChecks;
94 }
95 return !!this._sanityChecks[name];
96 }
97}
98MatCommonModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatCommonModule, deps: [{ token: i1.HighContrastModeDetector }, { token: MATERIAL_SANITY_CHECKS, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.NgModule });
99MatCommonModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatCommonModule, imports: [BidiModule], exports: [BidiModule] });
100MatCommonModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatCommonModule, imports: [BidiModule, BidiModule] });
101i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatCommonModule, decorators: [{
102 type: NgModule,
103 args: [{
104 imports: [BidiModule],
105 exports: [BidiModule],
106 }]
107 }], ctorParameters: function () {
108 return [{ type: i1.HighContrastModeDetector }, { type: undefined, decorators: [{
109 type: Optional
110 }, {
111 type: Inject,
112 args: [MATERIAL_SANITY_CHECKS]
113 }] }, { type: Document, decorators: [{
114 type: Inject,
115 args: [DOCUMENT]
116 }] }];
117 } });
118/** Checks that the page has a doctype. */
119function _checkDoctypeIsDefined(doc) {
120 if (!doc.doctype) {
121 console.warn('Current document does not have a doctype. This may cause ' +
122 'some Angular Material components not to behave as expected.');
123 }
124}
125/** Checks that a theme has been included. */
126function _checkThemeIsPresent(doc) {
127 // We need to assert that the `body` is defined, because these checks run very early
128 // and the `body` won't be defined if the consumer put their scripts in the `head`.
129 if (!doc.body || typeof getComputedStyle !== 'function') {
130 return;
131 }
132 const testElement = doc.createElement('div');
133 testElement.classList.add('mat-theme-loaded-marker');
134 doc.body.appendChild(testElement);
135 const computedStyle = getComputedStyle(testElement);
136 // In some situations the computed style of the test element can be null. For example in
137 // Firefox, the computed style is null if an application is running inside of a hidden iframe.
138 // See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397
139 if (computedStyle && computedStyle.display !== 'none') {
140 console.warn('Could not find Angular Material core theme. Most Material ' +
141 'components may not work as expected. For more info refer ' +
142 'to the theming guide: https://material.angular.io/guide/theming');
143 }
144 testElement.remove();
145}
146/** Checks whether the Material version matches the CDK version. */
147function _checkCdkVersionMatch() {
148 if (VERSION.full !== VERSION$1.full) {
149 console.warn('The Angular Material version (' +
150 VERSION.full +
151 ') does not match ' +
152 'the Angular CDK version (' +
153 VERSION$1.full +
154 ').\n' +
155 'Please ensure the versions of these two packages exactly match.');
156 }
157}
158
159/**
160 * @license
161 * Copyright Google LLC All Rights Reserved.
162 *
163 * Use of this source code is governed by an MIT-style license that can be
164 * found in the LICENSE file at https://angular.io/license
165 */
166function mixinDisabled(base) {
167 return class extends base {
168 constructor(...args) {
169 super(...args);
170 this._disabled = false;
171 }
172 get disabled() {
173 return this._disabled;
174 }
175 set disabled(value) {
176 this._disabled = coerceBooleanProperty(value);
177 }
178 };
179}
180
181/**
182 * @license
183 * Copyright Google LLC All Rights Reserved.
184 *
185 * Use of this source code is governed by an MIT-style license that can be
186 * found in the LICENSE file at https://angular.io/license
187 */
188function mixinColor(base, defaultColor) {
189 return class extends base {
190 constructor(...args) {
191 super(...args);
192 this.defaultColor = defaultColor;
193 // Set the default color that can be specified from the mixin.
194 this.color = defaultColor;
195 }
196 get color() {
197 return this._color;
198 }
199 set color(value) {
200 const colorPalette = value || this.defaultColor;
201 if (colorPalette !== this._color) {
202 if (this._color) {
203 this._elementRef.nativeElement.classList.remove(`mat-${this._color}`);
204 }
205 if (colorPalette) {
206 this._elementRef.nativeElement.classList.add(`mat-${colorPalette}`);
207 }
208 this._color = colorPalette;
209 }
210 }
211 };
212}
213
214/**
215 * @license
216 * Copyright Google LLC All Rights Reserved.
217 *
218 * Use of this source code is governed by an MIT-style license that can be
219 * found in the LICENSE file at https://angular.io/license
220 */
221function mixinDisableRipple(base) {
222 return class extends base {
223 constructor(...args) {
224 super(...args);
225 this._disableRipple = false;
226 }
227 /** Whether the ripple effect is disabled or not. */
228 get disableRipple() {
229 return this._disableRipple;
230 }
231 set disableRipple(value) {
232 this._disableRipple = coerceBooleanProperty(value);
233 }
234 };
235}
236
237/**
238 * @license
239 * Copyright Google LLC All Rights Reserved.
240 *
241 * Use of this source code is governed by an MIT-style license that can be
242 * found in the LICENSE file at https://angular.io/license
243 */
244function mixinTabIndex(base, defaultTabIndex = 0) {
245 return class extends base {
246 constructor(...args) {
247 super(...args);
248 this._tabIndex = defaultTabIndex;
249 this.defaultTabIndex = defaultTabIndex;
250 }
251 get tabIndex() {
252 return this.disabled ? -1 : this._tabIndex;
253 }
254 set tabIndex(value) {
255 // If the specified tabIndex value is null or undefined, fall back to the default value.
256 this._tabIndex = value != null ? coerceNumberProperty(value) : this.defaultTabIndex;
257 }
258 };
259}
260
261/**
262 * @license
263 * Copyright Google LLC All Rights Reserved.
264 *
265 * Use of this source code is governed by an MIT-style license that can be
266 * found in the LICENSE file at https://angular.io/license
267 */
268function mixinErrorState(base) {
269 return class extends base {
270 constructor(...args) {
271 super(...args);
272 /** Whether the component is in an error state. */
273 this.errorState = false;
274 }
275 /** Updates the error state based on the provided error state matcher. */
276 updateErrorState() {
277 const oldState = this.errorState;
278 const parent = this._parentFormGroup || this._parentForm;
279 const matcher = this.errorStateMatcher || this._defaultErrorStateMatcher;
280 const control = this.ngControl ? this.ngControl.control : null;
281 const newState = matcher.isErrorState(control, parent);
282 if (newState !== oldState) {
283 this.errorState = newState;
284 this.stateChanges.next();
285 }
286 }
287 };
288}
289
290/**
291 * @license
292 * Copyright Google LLC All Rights Reserved.
293 *
294 * Use of this source code is governed by an MIT-style license that can be
295 * found in the LICENSE file at https://angular.io/license
296 */
297/** Mixin to augment a directive with an initialized property that will emits when ngOnInit ends. */
298function mixinInitialized(base) {
299 return class extends base {
300 constructor(...args) {
301 super(...args);
302 /** Whether this directive has been marked as initialized. */
303 this._isInitialized = false;
304 /**
305 * List of subscribers that subscribed before the directive was initialized. Should be notified
306 * during _markInitialized. Set to null after pending subscribers are notified, and should
307 * not expect to be populated after.
308 */
309 this._pendingSubscribers = [];
310 /**
311 * Observable stream that emits when the directive initializes. If already initialized, the
312 * subscriber is stored to be notified once _markInitialized is called.
313 */
314 this.initialized = new Observable(subscriber => {
315 // If initialized, immediately notify the subscriber. Otherwise store the subscriber to notify
316 // when _markInitialized is called.
317 if (this._isInitialized) {
318 this._notifySubscriber(subscriber);
319 }
320 else {
321 this._pendingSubscribers.push(subscriber);
322 }
323 });
324 }
325 /**
326 * Marks the state as initialized and notifies pending subscribers. Should be called at the end
327 * of ngOnInit.
328 * @docs-private
329 */
330 _markInitialized() {
331 if (this._isInitialized && (typeof ngDevMode === 'undefined' || ngDevMode)) {
332 throw Error('This directive has already been marked as initialized and ' +
333 'should not be called twice.');
334 }
335 this._isInitialized = true;
336 this._pendingSubscribers.forEach(this._notifySubscriber);
337 this._pendingSubscribers = null;
338 }
339 /** Emits and completes the subscriber stream (should only emit once). */
340 _notifySubscriber(subscriber) {
341 subscriber.next();
342 subscriber.complete();
343 }
344 };
345}
346
347/**
348 * @license
349 * Copyright Google LLC All Rights Reserved.
350 *
351 * Use of this source code is governed by an MIT-style license that can be
352 * found in the LICENSE file at https://angular.io/license
353 */
354
355/**
356 * @license
357 * Copyright Google LLC All Rights Reserved.
358 *
359 * Use of this source code is governed by an MIT-style license that can be
360 * found in the LICENSE file at https://angular.io/license
361 */
362/** InjectionToken for datepicker that can be used to override default locale code. */
363const MAT_DATE_LOCALE = new InjectionToken('MAT_DATE_LOCALE', {
364 providedIn: 'root',
365 factory: MAT_DATE_LOCALE_FACTORY,
366});
367/** @docs-private */
368function MAT_DATE_LOCALE_FACTORY() {
369 return inject(LOCALE_ID);
370}
371/** Adapts type `D` to be usable as a date by cdk-based components that work with dates. */
372class DateAdapter {
373 constructor() {
374 this._localeChanges = new Subject();
375 /** A stream that emits when the locale changes. */
376 this.localeChanges = this._localeChanges;
377 }
378 /**
379 * Given a potential date object, returns that same date object if it is
380 * a valid date, or `null` if it's not a valid date.
381 * @param obj The object to check.
382 * @returns A date or `null`.
383 */
384 getValidDateOrNull(obj) {
385 return this.isDateInstance(obj) && this.isValid(obj) ? obj : null;
386 }
387 /**
388 * Attempts to deserialize a value to a valid date object. This is different from parsing in that
389 * deserialize should only accept non-ambiguous, locale-independent formats (e.g. a ISO 8601
390 * string). The default implementation does not allow any deserialization, it simply checks that
391 * the given value is already a valid date object or null. The `<mat-datepicker>` will call this
392 * method on all of its `@Input()` properties that accept dates. It is therefore possible to
393 * support passing values from your backend directly to these properties by overriding this method
394 * to also deserialize the format used by your backend.
395 * @param value The value to be deserialized into a date object.
396 * @returns The deserialized date object, either a valid date, null if the value can be
397 * deserialized into a null date (e.g. the empty string), or an invalid date.
398 */
399 deserialize(value) {
400 if (value == null || (this.isDateInstance(value) && this.isValid(value))) {
401 return value;
402 }
403 return this.invalid();
404 }
405 /**
406 * Sets the locale used for all dates.
407 * @param locale The new locale.
408 */
409 setLocale(locale) {
410 this.locale = locale;
411 this._localeChanges.next();
412 }
413 /**
414 * Compares two dates.
415 * @param first The first date to compare.
416 * @param second The second date to compare.
417 * @returns 0 if the dates are equal, a number less than 0 if the first date is earlier,
418 * a number greater than 0 if the first date is later.
419 */
420 compareDate(first, second) {
421 return (this.getYear(first) - this.getYear(second) ||
422 this.getMonth(first) - this.getMonth(second) ||
423 this.getDate(first) - this.getDate(second));
424 }
425 /**
426 * Checks if two dates are equal.
427 * @param first The first date to check.
428 * @param second The second date to check.
429 * @returns Whether the two dates are equal.
430 * Null dates are considered equal to other null dates.
431 */
432 sameDate(first, second) {
433 if (first && second) {
434 let firstValid = this.isValid(first);
435 let secondValid = this.isValid(second);
436 if (firstValid && secondValid) {
437 return !this.compareDate(first, second);
438 }
439 return firstValid == secondValid;
440 }
441 return first == second;
442 }
443 /**
444 * Clamp the given date between min and max dates.
445 * @param date The date to clamp.
446 * @param min The minimum value to allow. If null or omitted no min is enforced.
447 * @param max The maximum value to allow. If null or omitted no max is enforced.
448 * @returns `min` if `date` is less than `min`, `max` if date is greater than `max`,
449 * otherwise `date`.
450 */
451 clampDate(date, min, max) {
452 if (min && this.compareDate(date, min) < 0) {
453 return min;
454 }
455 if (max && this.compareDate(date, max) > 0) {
456 return max;
457 }
458 return date;
459 }
460}
461
462/**
463 * @license
464 * Copyright Google LLC All Rights Reserved.
465 *
466 * Use of this source code is governed by an MIT-style license that can be
467 * found in the LICENSE file at https://angular.io/license
468 */
469const MAT_DATE_FORMATS = new InjectionToken('mat-date-formats');
470
471/**
472 * Matches strings that have the form of a valid RFC 3339 string
473 * (https://tools.ietf.org/html/rfc3339). Note that the string may not actually be a valid date
474 * because the regex will match strings an with out of bounds month, date, etc.
475 */
476const ISO_8601_REGEX = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|(?:(?:\+|-)\d{2}:\d{2}))?)?$/;
477/** Creates an array and fills it with values. */
478function range(length, valueFunction) {
479 const valuesArray = Array(length);
480 for (let i = 0; i < length; i++) {
481 valuesArray[i] = valueFunction(i);
482 }
483 return valuesArray;
484}
485/** Adapts the native JS Date for use with cdk-based components that work with dates. */
486class NativeDateAdapter extends DateAdapter {
487 constructor(matDateLocale,
488 /**
489 * @deprecated No longer being used. To be removed.
490 * @breaking-change 14.0.0
491 */
492 _platform) {
493 super();
494 /**
495 * @deprecated No longer being used. To be removed.
496 * @breaking-change 14.0.0
497 */
498 this.useUtcForDisplay = false;
499 super.setLocale(matDateLocale);
500 }
501 getYear(date) {
502 return date.getFullYear();
503 }
504 getMonth(date) {
505 return date.getMonth();
506 }
507 getDate(date) {
508 return date.getDate();
509 }
510 getDayOfWeek(date) {
511 return date.getDay();
512 }
513 getMonthNames(style) {
514 const dtf = new Intl.DateTimeFormat(this.locale, { month: style, timeZone: 'utc' });
515 return range(12, i => this._format(dtf, new Date(2017, i, 1)));
516 }
517 getDateNames() {
518 const dtf = new Intl.DateTimeFormat(this.locale, { day: 'numeric', timeZone: 'utc' });
519 return range(31, i => this._format(dtf, new Date(2017, 0, i + 1)));
520 }
521 getDayOfWeekNames(style) {
522 const dtf = new Intl.DateTimeFormat(this.locale, { weekday: style, timeZone: 'utc' });
523 return range(7, i => this._format(dtf, new Date(2017, 0, i + 1)));
524 }
525 getYearName(date) {
526 const dtf = new Intl.DateTimeFormat(this.locale, { year: 'numeric', timeZone: 'utc' });
527 return this._format(dtf, date);
528 }
529 getFirstDayOfWeek() {
530 // We can't tell using native JS Date what the first day of the week is, we default to Sunday.
531 return 0;
532 }
533 getNumDaysInMonth(date) {
534 return this.getDate(this._createDateWithOverflow(this.getYear(date), this.getMonth(date) + 1, 0));
535 }
536 clone(date) {
537 return new Date(date.getTime());
538 }
539 createDate(year, month, date) {
540 if (typeof ngDevMode === 'undefined' || ngDevMode) {
541 // Check for invalid month and date (except upper bound on date which we have to check after
542 // creating the Date).
543 if (month < 0 || month > 11) {
544 throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
545 }
546 if (date < 1) {
547 throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
548 }
549 }
550 let result = this._createDateWithOverflow(year, month, date);
551 // Check that the date wasn't above the upper bound for the month, causing the month to overflow
552 if (result.getMonth() != month && (typeof ngDevMode === 'undefined' || ngDevMode)) {
553 throw Error(`Invalid date "${date}" for month with index "${month}".`);
554 }
555 return result;
556 }
557 today() {
558 return new Date();
559 }
560 parse(value) {
561 // We have no way using the native JS Date to set the parse format or locale, so we ignore these
562 // parameters.
563 if (typeof value == 'number') {
564 return new Date(value);
565 }
566 return value ? new Date(Date.parse(value)) : null;
567 }
568 format(date, displayFormat) {
569 if (!this.isValid(date)) {
570 throw Error('NativeDateAdapter: Cannot format invalid date.');
571 }
572 const dtf = new Intl.DateTimeFormat(this.locale, Object.assign(Object.assign({}, displayFormat), { timeZone: 'utc' }));
573 return this._format(dtf, date);
574 }
575 addCalendarYears(date, years) {
576 return this.addCalendarMonths(date, years * 12);
577 }
578 addCalendarMonths(date, months) {
579 let newDate = this._createDateWithOverflow(this.getYear(date), this.getMonth(date) + months, this.getDate(date));
580 // It's possible to wind up in the wrong month if the original month has more days than the new
581 // month. In this case we want to go to the last day of the desired month.
582 // Note: the additional + 12 % 12 ensures we end up with a positive number, since JS % doesn't
583 // guarantee this.
584 if (this.getMonth(newDate) != (((this.getMonth(date) + months) % 12) + 12) % 12) {
585 newDate = this._createDateWithOverflow(this.getYear(newDate), this.getMonth(newDate), 0);
586 }
587 return newDate;
588 }
589 addCalendarDays(date, days) {
590 return this._createDateWithOverflow(this.getYear(date), this.getMonth(date), this.getDate(date) + days);
591 }
592 toIso8601(date) {
593 return [
594 date.getUTCFullYear(),
595 this._2digit(date.getUTCMonth() + 1),
596 this._2digit(date.getUTCDate()),
597 ].join('-');
598 }
599 /**
600 * Returns the given value if given a valid Date or null. Deserializes valid ISO 8601 strings
601 * (https://www.ietf.org/rfc/rfc3339.txt) into valid Dates and empty string into null. Returns an
602 * invalid date for all other values.
603 */
604 deserialize(value) {
605 if (typeof value === 'string') {
606 if (!value) {
607 return null;
608 }
609 // The `Date` constructor accepts formats other than ISO 8601, so we need to make sure the
610 // string is the right format first.
611 if (ISO_8601_REGEX.test(value)) {
612 let date = new Date(value);
613 if (this.isValid(date)) {
614 return date;
615 }
616 }
617 }
618 return super.deserialize(value);
619 }
620 isDateInstance(obj) {
621 return obj instanceof Date;
622 }
623 isValid(date) {
624 return !isNaN(date.getTime());
625 }
626 invalid() {
627 return new Date(NaN);
628 }
629 /** Creates a date but allows the month and date to overflow. */
630 _createDateWithOverflow(year, month, date) {
631 // Passing the year to the constructor causes year numbers <100 to be converted to 19xx.
632 // To work around this we use `setFullYear` and `setHours` instead.
633 const d = new Date();
634 d.setFullYear(year, month, date);
635 d.setHours(0, 0, 0, 0);
636 return d;
637 }
638 /**
639 * Pads a number to make it two digits.
640 * @param n The number to pad.
641 * @returns The padded number.
642 */
643 _2digit(n) {
644 return ('00' + n).slice(-2);
645 }
646 /**
647 * When converting Date object to string, javascript built-in functions may return wrong
648 * results because it applies its internal DST rules. The DST rules around the world change
649 * very frequently, and the current valid rule is not always valid in previous years though.
650 * We work around this problem building a new Date object which has its internal UTC
651 * representation with the local date and time.
652 * @param dtf Intl.DateTimeFormat object, containg the desired string format. It must have
653 * timeZone set to 'utc' to work fine.
654 * @param date Date from which we want to get the string representation according to dtf
655 * @returns A Date object with its UTC representation based on the passed in date info
656 */
657 _format(dtf, date) {
658 // Passing the year to the constructor causes year numbers <100 to be converted to 19xx.
659 // To work around this we use `setUTCFullYear` and `setUTCHours` instead.
660 const d = new Date();
661 d.setUTCFullYear(date.getFullYear(), date.getMonth(), date.getDate());
662 d.setUTCHours(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
663 return dtf.format(d);
664 }
665}
666NativeDateAdapter.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateAdapter, deps: [{ token: MAT_DATE_LOCALE, optional: true }, { token: i1$1.Platform }], target: i0.ɵɵFactoryTarget.Injectable });
667NativeDateAdapter.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateAdapter });
668i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateAdapter, decorators: [{
669 type: Injectable
670 }], ctorParameters: function () {
671 return [{ type: undefined, decorators: [{
672 type: Optional
673 }, {
674 type: Inject,
675 args: [MAT_DATE_LOCALE]
676 }] }, { type: i1$1.Platform }];
677 } });
678
679/**
680 * @license
681 * Copyright Google LLC All Rights Reserved.
682 *
683 * Use of this source code is governed by an MIT-style license that can be
684 * found in the LICENSE file at https://angular.io/license
685 */
686const MAT_NATIVE_DATE_FORMATS = {
687 parse: {
688 dateInput: null,
689 },
690 display: {
691 dateInput: { year: 'numeric', month: 'numeric', day: 'numeric' },
692 monthYearLabel: { year: 'numeric', month: 'short' },
693 dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
694 monthYearA11yLabel: { year: 'numeric', month: 'long' },
695 },
696};
697
698/**
699 * @license
700 * Copyright Google LLC All Rights Reserved.
701 *
702 * Use of this source code is governed by an MIT-style license that can be
703 * found in the LICENSE file at https://angular.io/license
704 */
705class NativeDateModule {
706}
707NativeDateModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
708NativeDateModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: NativeDateModule });
709NativeDateModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateModule, providers: [{ provide: DateAdapter, useClass: NativeDateAdapter }] });
710i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: NativeDateModule, decorators: [{
711 type: NgModule,
712 args: [{
713 providers: [{ provide: DateAdapter, useClass: NativeDateAdapter }],
714 }]
715 }] });
716class MatNativeDateModule {
717}
718MatNativeDateModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatNativeDateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
719MatNativeDateModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatNativeDateModule, imports: [NativeDateModule] });
720MatNativeDateModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatNativeDateModule, providers: [{ provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS }], imports: [NativeDateModule] });
721i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatNativeDateModule, decorators: [{
722 type: NgModule,
723 args: [{
724 imports: [NativeDateModule],
725 providers: [{ provide: MAT_DATE_FORMATS, useValue: MAT_NATIVE_DATE_FORMATS }],
726 }]
727 }] });
728
729/**
730 * @license
731 * Copyright Google LLC All Rights Reserved.
732 *
733 * Use of this source code is governed by an MIT-style license that can be
734 * found in the LICENSE file at https://angular.io/license
735 */
736/** Error state matcher that matches when a control is invalid and dirty. */
737class ShowOnDirtyErrorStateMatcher {
738 isErrorState(control, form) {
739 return !!(control && control.invalid && (control.dirty || (form && form.submitted)));
740 }
741}
742ShowOnDirtyErrorStateMatcher.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ShowOnDirtyErrorStateMatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
743ShowOnDirtyErrorStateMatcher.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ShowOnDirtyErrorStateMatcher });
744i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ShowOnDirtyErrorStateMatcher, decorators: [{
745 type: Injectable
746 }] });
747/** Provider that defines how form controls behave with regards to displaying error messages. */
748class ErrorStateMatcher {
749 isErrorState(control, form) {
750 return !!(control && control.invalid && (control.touched || (form && form.submitted)));
751 }
752}
753ErrorStateMatcher.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ErrorStateMatcher, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
754ErrorStateMatcher.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ErrorStateMatcher, providedIn: 'root' });
755i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: ErrorStateMatcher, decorators: [{
756 type: Injectable,
757 args: [{ providedIn: 'root' }]
758 }] });
759
760/**
761 * @license
762 * Copyright Google LLC All Rights Reserved.
763 *
764 * Use of this source code is governed by an MIT-style license that can be
765 * found in the LICENSE file at https://angular.io/license
766 */
767/**
768 * Shared directive to count lines inside a text area, such as a list item.
769 * Line elements can be extracted with a @ContentChildren(MatLine) query, then
770 * counted by checking the query list's length.
771 */
772class MatLine {
773}
774MatLine.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatLine, deps: [], target: i0.ɵɵFactoryTarget.Directive });
775MatLine.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: MatLine, selector: "[mat-line], [matLine]", host: { classAttribute: "mat-line" }, ngImport: i0 });
776i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatLine, decorators: [{
777 type: Directive,
778 args: [{
779 selector: '[mat-line], [matLine]',
780 host: { 'class': 'mat-line' },
781 }]
782 }] });
783/**
784 * Helper that takes a query list of lines and sets the correct class on the host.
785 * @docs-private
786 */
787function setLines(lines, element, prefix = 'mat') {
788 // Note: doesn't need to unsubscribe, because `changes`
789 // gets completed by Angular when the view is destroyed.
790 lines.changes.pipe(startWith(lines)).subscribe(({ length }) => {
791 setClass(element, `${prefix}-2-line`, false);
792 setClass(element, `${prefix}-3-line`, false);
793 setClass(element, `${prefix}-multi-line`, false);
794 if (length === 2 || length === 3) {
795 setClass(element, `${prefix}-${length}-line`, true);
796 }
797 else if (length > 3) {
798 setClass(element, `${prefix}-multi-line`, true);
799 }
800 });
801}
802/** Adds or removes a class from an element. */
803function setClass(element, className, isAdd) {
804 element.nativeElement.classList.toggle(className, isAdd);
805}
806class MatLineModule {
807}
808MatLineModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatLineModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
809MatLineModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatLineModule, declarations: [MatLine], imports: [MatCommonModule], exports: [MatLine, MatCommonModule] });
810MatLineModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatLineModule, imports: [MatCommonModule, MatCommonModule] });
811i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatLineModule, decorators: [{
812 type: NgModule,
813 args: [{
814 imports: [MatCommonModule],
815 exports: [MatLine, MatCommonModule],
816 declarations: [MatLine],
817 }]
818 }] });
819
820/**
821 * @license
822 * Copyright Google LLC All Rights Reserved.
823 *
824 * Use of this source code is governed by an MIT-style license that can be
825 * found in the LICENSE file at https://angular.io/license
826 */
827/**
828 * Reference to a previously launched ripple element.
829 */
830class RippleRef {
831 constructor(_renderer,
832 /** Reference to the ripple HTML element. */
833 element,
834 /** Ripple configuration used for the ripple. */
835 config,
836 /* Whether animations are forcibly disabled for ripples through CSS. */
837 _animationForciblyDisabledThroughCss = false) {
838 this._renderer = _renderer;
839 this.element = element;
840 this.config = config;
841 this._animationForciblyDisabledThroughCss = _animationForciblyDisabledThroughCss;
842 /** Current state of the ripple. */
843 this.state = 3 /* RippleState.HIDDEN */;
844 }
845 /** Fades out the ripple element. */
846 fadeOut() {
847 this._renderer.fadeOutRipple(this);
848 }
849}
850
851// TODO: import these values from `@material/ripple` eventually.
852/**
853 * Default ripple animation configuration for ripples without an explicit
854 * animation config specified.
855 */
856const defaultRippleAnimationConfig = {
857 enterDuration: 225,
858 exitDuration: 150,
859};
860/**
861 * Timeout for ignoring mouse events. Mouse events will be temporary ignored after touch
862 * events to avoid synthetic mouse events.
863 */
864const ignoreMouseEventsTimeout = 800;
865/** Options that apply to all the event listeners that are bound by the ripple renderer. */
866const passiveEventOptions = normalizePassiveListenerOptions({ passive: true });
867/** Events that signal that the pointer is down. */
868const pointerDownEvents = ['mousedown', 'touchstart'];
869/** Events that signal that the pointer is up. */
870const pointerUpEvents = ['mouseup', 'mouseleave', 'touchend', 'touchcancel'];
871/**
872 * Helper service that performs DOM manipulations. Not intended to be used outside this module.
873 * The constructor takes a reference to the ripple directive's host element and a map of DOM
874 * event handlers to be installed on the element that triggers ripple animations.
875 * This will eventually become a custom renderer once Angular support exists.
876 * @docs-private
877 */
878class RippleRenderer {
879 constructor(_target, _ngZone, elementOrElementRef, platform) {
880 this._target = _target;
881 this._ngZone = _ngZone;
882 /** Whether the pointer is currently down or not. */
883 this._isPointerDown = false;
884 /**
885 * Map of currently active ripple references.
886 * The ripple reference is mapped to its element event listeners.
887 * The reason why `| null` is used is that event listeners are added only
888 * when the condition is truthy (see the `_startFadeOutTransition` method).
889 */
890 this._activeRipples = new Map();
891 /** Whether pointer-up event listeners have been registered. */
892 this._pointerUpEventsRegistered = false;
893 // Only do anything if we're on the browser.
894 if (platform.isBrowser) {
895 this._containerElement = coerceElement(elementOrElementRef);
896 }
897 }
898 /**
899 * Fades in a ripple at the given coordinates.
900 * @param x Coordinate within the element, along the X axis at which to start the ripple.
901 * @param y Coordinate within the element, along the Y axis at which to start the ripple.
902 * @param config Extra ripple options.
903 */
904 fadeInRipple(x, y, config = {}) {
905 const containerRect = (this._containerRect =
906 this._containerRect || this._containerElement.getBoundingClientRect());
907 const animationConfig = Object.assign(Object.assign({}, defaultRippleAnimationConfig), config.animation);
908 if (config.centered) {
909 x = containerRect.left + containerRect.width / 2;
910 y = containerRect.top + containerRect.height / 2;
911 }
912 const radius = config.radius || distanceToFurthestCorner(x, y, containerRect);
913 const offsetX = x - containerRect.left;
914 const offsetY = y - containerRect.top;
915 const enterDuration = animationConfig.enterDuration;
916 const ripple = document.createElement('div');
917 ripple.classList.add('mat-ripple-element');
918 ripple.style.left = `${offsetX - radius}px`;
919 ripple.style.top = `${offsetY - radius}px`;
920 ripple.style.height = `${radius * 2}px`;
921 ripple.style.width = `${radius * 2}px`;
922 // If a custom color has been specified, set it as inline style. If no color is
923 // set, the default color will be applied through the ripple theme styles.
924 if (config.color != null) {
925 ripple.style.backgroundColor = config.color;
926 }
927 ripple.style.transitionDuration = `${enterDuration}ms`;
928 this._containerElement.appendChild(ripple);
929 // By default the browser does not recalculate the styles of dynamically created
930 // ripple elements. This is critical to ensure that the `scale` animates properly.
931 // We enforce a style recalculation by calling `getComputedStyle` and *accessing* a property.
932 // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
933 const computedStyles = window.getComputedStyle(ripple);
934 const userTransitionProperty = computedStyles.transitionProperty;
935 const userTransitionDuration = computedStyles.transitionDuration;
936 // Note: We detect whether animation is forcibly disabled through CSS by the use of
937 // `transition: none`. This is technically unexpected since animations are controlled
938 // through the animation config, but this exists for backwards compatibility. This logic does
939 // not need to be super accurate since it covers some edge cases which can be easily avoided by users.
940 const animationForciblyDisabledThroughCss = userTransitionProperty === 'none' ||
941 // Note: The canonical unit for serialized CSS `<time>` properties is seconds. Additionally
942 // some browsers expand the duration for every property (in our case `opacity` and `transform`).
943 userTransitionDuration === '0s' ||
944 userTransitionDuration === '0s, 0s';
945 // Exposed reference to the ripple that will be returned.
946 const rippleRef = new RippleRef(this, ripple, config, animationForciblyDisabledThroughCss);
947 // Start the enter animation by setting the transform/scale to 100%. The animation will
948 // execute as part of this statement because we forced a style recalculation before.
949 // Note: We use a 3d transform here in order to avoid an issue in Safari where
950 // the ripples aren't clipped when inside the shadow DOM (see #24028).
951 ripple.style.transform = 'scale3d(1, 1, 1)';
952 rippleRef.state = 0 /* RippleState.FADING_IN */;
953 if (!config.persistent) {
954 this._mostRecentTransientRipple = rippleRef;
955 }
956 let eventListeners = null;
957 // Do not register the `transition` event listener if fade-in and fade-out duration
958 // are set to zero. The events won't fire anyway and we can save resources here.
959 if (!animationForciblyDisabledThroughCss && (enterDuration || animationConfig.exitDuration)) {
960 this._ngZone.runOutsideAngular(() => {
961 const onTransitionEnd = () => this._finishRippleTransition(rippleRef);
962 const onTransitionCancel = () => this._destroyRipple(rippleRef);
963 ripple.addEventListener('transitionend', onTransitionEnd);
964 // If the transition is cancelled (e.g. due to DOM removal), we destroy the ripple
965 // directly as otherwise we would keep it part of the ripple container forever.
966 // https://www.w3.org/TR/css-transitions-1/#:~:text=no%20longer%20in%20the%20document.
967 ripple.addEventListener('transitioncancel', onTransitionCancel);
968 eventListeners = { onTransitionEnd, onTransitionCancel };
969 });
970 }
971 // Add the ripple reference to the list of all active ripples.
972 this._activeRipples.set(rippleRef, eventListeners);
973 // In case there is no fade-in transition duration, we need to manually call the transition
974 // end listener because `transitionend` doesn't fire if there is no transition.
975 if (animationForciblyDisabledThroughCss || !enterDuration) {
976 this._finishRippleTransition(rippleRef);
977 }
978 return rippleRef;
979 }
980 /** Fades out a ripple reference. */
981 fadeOutRipple(rippleRef) {
982 // For ripples already fading out or hidden, this should be a noop.
983 if (rippleRef.state === 2 /* RippleState.FADING_OUT */ || rippleRef.state === 3 /* RippleState.HIDDEN */) {
984 return;
985 }
986 const rippleEl = rippleRef.element;
987 const animationConfig = Object.assign(Object.assign({}, defaultRippleAnimationConfig), rippleRef.config.animation);
988 // This starts the fade-out transition and will fire the transition end listener that
989 // removes the ripple element from the DOM.
990 rippleEl.style.transitionDuration = `${animationConfig.exitDuration}ms`;
991 rippleEl.style.opacity = '0';
992 rippleRef.state = 2 /* RippleState.FADING_OUT */;
993 // In case there is no fade-out transition duration, we need to manually call the
994 // transition end listener because `transitionend` doesn't fire if there is no transition.
995 if (rippleRef._animationForciblyDisabledThroughCss || !animationConfig.exitDuration) {
996 this._finishRippleTransition(rippleRef);
997 }
998 }
999 /** Fades out all currently active ripples. */
1000 fadeOutAll() {
1001 this._getActiveRipples().forEach(ripple => ripple.fadeOut());
1002 }
1003 /** Fades out all currently active non-persistent ripples. */
1004 fadeOutAllNonPersistent() {
1005 this._getActiveRipples().forEach(ripple => {
1006 if (!ripple.config.persistent) {
1007 ripple.fadeOut();
1008 }
1009 });
1010 }
1011 /** Sets up the trigger event listeners */
1012 setupTriggerEvents(elementOrElementRef) {
1013 const element = coerceElement(elementOrElementRef);
1014 if (!element || element === this._triggerElement) {
1015 return;
1016 }
1017 // Remove all previously registered event listeners from the trigger element.
1018 this._removeTriggerEvents();
1019 this._triggerElement = element;
1020 this._registerEvents(pointerDownEvents);
1021 }
1022 /**
1023 * Handles all registered events.
1024 * @docs-private
1025 */
1026 handleEvent(event) {
1027 if (event.type === 'mousedown') {
1028 this._onMousedown(event);
1029 }
1030 else if (event.type === 'touchstart') {
1031 this._onTouchStart(event);
1032 }
1033 else {
1034 this._onPointerUp();
1035 }
1036 // If pointer-up events haven't been registered yet, do so now.
1037 // We do this on-demand in order to reduce the total number of event listeners
1038 // registered by the ripples, which speeds up the rendering time for large UIs.
1039 if (!this._pointerUpEventsRegistered) {
1040 this._registerEvents(pointerUpEvents);
1041 this._pointerUpEventsRegistered = true;
1042 }
1043 }
1044 /** Method that will be called if the fade-in or fade-in transition completed. */
1045 _finishRippleTransition(rippleRef) {
1046 if (rippleRef.state === 0 /* RippleState.FADING_IN */) {
1047 this._startFadeOutTransition(rippleRef);
1048 }
1049 else if (rippleRef.state === 2 /* RippleState.FADING_OUT */) {
1050 this._destroyRipple(rippleRef);
1051 }
1052 }
1053 /**
1054 * Starts the fade-out transition of the given ripple if it's not persistent and the pointer
1055 * is not held down anymore.
1056 */
1057 _startFadeOutTransition(rippleRef) {
1058 const isMostRecentTransientRipple = rippleRef === this._mostRecentTransientRipple;
1059 const { persistent } = rippleRef.config;
1060 rippleRef.state = 1 /* RippleState.VISIBLE */;
1061 // When the timer runs out while the user has kept their pointer down, we want to
1062 // keep only the persistent ripples and the latest transient ripple. We do this,
1063 // because we don't want stacked transient ripples to appear after their enter
1064 // animation has finished.
1065 if (!persistent && (!isMostRecentTransientRipple || !this._isPointerDown)) {
1066 rippleRef.fadeOut();
1067 }
1068 }
1069 /** Destroys the given ripple by removing it from the DOM and updating its state. */
1070 _destroyRipple(rippleRef) {
1071 var _a;
1072 const eventListeners = (_a = this._activeRipples.get(rippleRef)) !== null && _a !== void 0 ? _a : null;
1073 this._activeRipples.delete(rippleRef);
1074 // Clear out the cached bounding rect if we have no more ripples.
1075 if (!this._activeRipples.size) {
1076 this._containerRect = null;
1077 }
1078 // If the current ref is the most recent transient ripple, unset it
1079 // avoid memory leaks.
1080 if (rippleRef === this._mostRecentTransientRipple) {
1081 this._mostRecentTransientRipple = null;
1082 }
1083 rippleRef.state = 3 /* RippleState.HIDDEN */;
1084 if (eventListeners !== null) {
1085 rippleRef.element.removeEventListener('transitionend', eventListeners.onTransitionEnd);
1086 rippleRef.element.removeEventListener('transitioncancel', eventListeners.onTransitionCancel);
1087 }
1088 rippleRef.element.remove();
1089 }
1090 /** Function being called whenever the trigger is being pressed using mouse. */
1091 _onMousedown(event) {
1092 // Screen readers will fire fake mouse events for space/enter. Skip launching a
1093 // ripple in this case for consistency with the non-screen-reader experience.
1094 const isFakeMousedown = isFakeMousedownFromScreenReader(event);
1095 const isSyntheticEvent = this._lastTouchStartEvent &&
1096 Date.now() < this._lastTouchStartEvent + ignoreMouseEventsTimeout;
1097 if (!this._target.rippleDisabled && !isFakeMousedown && !isSyntheticEvent) {
1098 this._isPointerDown = true;
1099 this.fadeInRipple(event.clientX, event.clientY, this._target.rippleConfig);
1100 }
1101 }
1102 /** Function being called whenever the trigger is being pressed using touch. */
1103 _onTouchStart(event) {
1104 if (!this._target.rippleDisabled && !isFakeTouchstartFromScreenReader(event)) {
1105 // Some browsers fire mouse events after a `touchstart` event. Those synthetic mouse
1106 // events will launch a second ripple if we don't ignore mouse events for a specific
1107 // time after a touchstart event.
1108 this._lastTouchStartEvent = Date.now();
1109 this._isPointerDown = true;
1110 // Use `changedTouches` so we skip any touches where the user put
1111 // their finger down, but used another finger to tap the element again.
1112 const touches = event.changedTouches;
1113 for (let i = 0; i < touches.length; i++) {
1114 this.fadeInRipple(touches[i].clientX, touches[i].clientY, this._target.rippleConfig);
1115 }
1116 }
1117 }
1118 /** Function being called whenever the trigger is being released. */
1119 _onPointerUp() {
1120 if (!this._isPointerDown) {
1121 return;
1122 }
1123 this._isPointerDown = false;
1124 // Fade-out all ripples that are visible and not persistent.
1125 this._getActiveRipples().forEach(ripple => {
1126 // By default, only ripples that are completely visible will fade out on pointer release.
1127 // If the `terminateOnPointerUp` option is set, ripples that still fade in will also fade out.
1128 const isVisible = ripple.state === 1 /* RippleState.VISIBLE */ ||
1129 (ripple.config.terminateOnPointerUp && ripple.state === 0 /* RippleState.FADING_IN */);
1130 if (!ripple.config.persistent && isVisible) {
1131 ripple.fadeOut();
1132 }
1133 });
1134 }
1135 /** Registers event listeners for a given list of events. */
1136 _registerEvents(eventTypes) {
1137 this._ngZone.runOutsideAngular(() => {
1138 eventTypes.forEach(type => {
1139 this._triggerElement.addEventListener(type, this, passiveEventOptions);
1140 });
1141 });
1142 }
1143 _getActiveRipples() {
1144 return Array.from(this._activeRipples.keys());
1145 }
1146 /** Removes previously registered event listeners from the trigger element. */
1147 _removeTriggerEvents() {
1148 if (this._triggerElement) {
1149 pointerDownEvents.forEach(type => {
1150 this._triggerElement.removeEventListener(type, this, passiveEventOptions);
1151 });
1152 if (this._pointerUpEventsRegistered) {
1153 pointerUpEvents.forEach(type => {
1154 this._triggerElement.removeEventListener(type, this, passiveEventOptions);
1155 });
1156 }
1157 }
1158 }
1159}
1160/**
1161 * Returns the distance from the point (x, y) to the furthest corner of a rectangle.
1162 */
1163function distanceToFurthestCorner(x, y, rect) {
1164 const distX = Math.max(Math.abs(x - rect.left), Math.abs(x - rect.right));
1165 const distY = Math.max(Math.abs(y - rect.top), Math.abs(y - rect.bottom));
1166 return Math.sqrt(distX * distX + distY * distY);
1167}
1168
1169/** Injection token that can be used to specify the global ripple options. */
1170const MAT_RIPPLE_GLOBAL_OPTIONS = new InjectionToken('mat-ripple-global-options');
1171class MatRipple {
1172 constructor(_elementRef, ngZone, platform, globalOptions, _animationMode) {
1173 this._elementRef = _elementRef;
1174 this._animationMode = _animationMode;
1175 /**
1176 * If set, the radius in pixels of foreground ripples when fully expanded. If unset, the radius
1177 * will be the distance from the center of the ripple to the furthest corner of the host element's
1178 * bounding rectangle.
1179 */
1180 this.radius = 0;
1181 this._disabled = false;
1182 /** Whether ripple directive is initialized and the input bindings are set. */
1183 this._isInitialized = false;
1184 this._globalOptions = globalOptions || {};
1185 this._rippleRenderer = new RippleRenderer(this, ngZone, _elementRef, platform);
1186 }
1187 /**
1188 * Whether click events will not trigger the ripple. Ripples can be still launched manually
1189 * by using the `launch()` method.
1190 */
1191 get disabled() {
1192 return this._disabled;
1193 }
1194 set disabled(value) {
1195 if (value) {
1196 this.fadeOutAllNonPersistent();
1197 }
1198 this._disabled = value;
1199 this._setupTriggerEventsIfEnabled();
1200 }
1201 /**
1202 * The element that triggers the ripple when click events are received.
1203 * Defaults to the directive's host element.
1204 */
1205 get trigger() {
1206 return this._trigger || this._elementRef.nativeElement;
1207 }
1208 set trigger(trigger) {
1209 this._trigger = trigger;
1210 this._setupTriggerEventsIfEnabled();
1211 }
1212 ngOnInit() {
1213 this._isInitialized = true;
1214 this._setupTriggerEventsIfEnabled();
1215 }
1216 ngOnDestroy() {
1217 this._rippleRenderer._removeTriggerEvents();
1218 }
1219 /** Fades out all currently showing ripple elements. */
1220 fadeOutAll() {
1221 this._rippleRenderer.fadeOutAll();
1222 }
1223 /** Fades out all currently showing non-persistent ripple elements. */
1224 fadeOutAllNonPersistent() {
1225 this._rippleRenderer.fadeOutAllNonPersistent();
1226 }
1227 /**
1228 * Ripple configuration from the directive's input values.
1229 * @docs-private Implemented as part of RippleTarget
1230 */
1231 get rippleConfig() {
1232 return {
1233 centered: this.centered,
1234 radius: this.radius,
1235 color: this.color,
1236 animation: Object.assign(Object.assign(Object.assign({}, this._globalOptions.animation), (this._animationMode === 'NoopAnimations' ? { enterDuration: 0, exitDuration: 0 } : {})), this.animation),
1237 terminateOnPointerUp: this._globalOptions.terminateOnPointerUp,
1238 };
1239 }
1240 /**
1241 * Whether ripples on pointer-down are disabled or not.
1242 * @docs-private Implemented as part of RippleTarget
1243 */
1244 get rippleDisabled() {
1245 return this.disabled || !!this._globalOptions.disabled;
1246 }
1247 /** Sets up the trigger event listeners if ripples are enabled. */
1248 _setupTriggerEventsIfEnabled() {
1249 if (!this.disabled && this._isInitialized) {
1250 this._rippleRenderer.setupTriggerEvents(this.trigger);
1251 }
1252 }
1253 /** Launches a manual ripple at the specified coordinated or just by the ripple config. */
1254 launch(configOrX, y = 0, config) {
1255 if (typeof configOrX === 'number') {
1256 return this._rippleRenderer.fadeInRipple(configOrX, y, Object.assign(Object.assign({}, this.rippleConfig), config));
1257 }
1258 else {
1259 return this._rippleRenderer.fadeInRipple(0, 0, Object.assign(Object.assign({}, this.rippleConfig), configOrX));
1260 }
1261 }
1262}
1263MatRipple.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatRipple, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i1$1.Platform }, { token: MAT_RIPPLE_GLOBAL_OPTIONS, optional: true }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1264MatRipple.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: MatRipple, selector: "[mat-ripple], [matRipple]", inputs: { color: ["matRippleColor", "color"], unbounded: ["matRippleUnbounded", "unbounded"], centered: ["matRippleCentered", "centered"], radius: ["matRippleRadius", "radius"], animation: ["matRippleAnimation", "animation"], disabled: ["matRippleDisabled", "disabled"], trigger: ["matRippleTrigger", "trigger"] }, host: { properties: { "class.mat-ripple-unbounded": "unbounded" }, classAttribute: "mat-ripple" }, exportAs: ["matRipple"], ngImport: i0 });
1265i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatRipple, decorators: [{
1266 type: Directive,
1267 args: [{
1268 selector: '[mat-ripple], [matRipple]',
1269 exportAs: 'matRipple',
1270 host: {
1271 'class': 'mat-ripple',
1272 '[class.mat-ripple-unbounded]': 'unbounded',
1273 },
1274 }]
1275 }], ctorParameters: function () {
1276 return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i1$1.Platform }, { type: undefined, decorators: [{
1277 type: Optional
1278 }, {
1279 type: Inject,
1280 args: [MAT_RIPPLE_GLOBAL_OPTIONS]
1281 }] }, { type: undefined, decorators: [{
1282 type: Optional
1283 }, {
1284 type: Inject,
1285 args: [ANIMATION_MODULE_TYPE]
1286 }] }];
1287 }, propDecorators: { color: [{
1288 type: Input,
1289 args: ['matRippleColor']
1290 }], unbounded: [{
1291 type: Input,
1292 args: ['matRippleUnbounded']
1293 }], centered: [{
1294 type: Input,
1295 args: ['matRippleCentered']
1296 }], radius: [{
1297 type: Input,
1298 args: ['matRippleRadius']
1299 }], animation: [{
1300 type: Input,
1301 args: ['matRippleAnimation']
1302 }], disabled: [{
1303 type: Input,
1304 args: ['matRippleDisabled']
1305 }], trigger: [{
1306 type: Input,
1307 args: ['matRippleTrigger']
1308 }] } });
1309
1310/**
1311 * @license
1312 * Copyright Google LLC All Rights Reserved.
1313 *
1314 * Use of this source code is governed by an MIT-style license that can be
1315 * found in the LICENSE file at https://angular.io/license
1316 */
1317class MatRippleModule {
1318}
1319MatRippleModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatRippleModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1320MatRippleModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatRippleModule, declarations: [MatRipple], imports: [MatCommonModule], exports: [MatRipple, MatCommonModule] });
1321MatRippleModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatRippleModule, imports: [MatCommonModule, MatCommonModule] });
1322i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatRippleModule, decorators: [{
1323 type: NgModule,
1324 args: [{
1325 imports: [MatCommonModule],
1326 exports: [MatRipple, MatCommonModule],
1327 declarations: [MatRipple],
1328 }]
1329 }] });
1330
1331/**
1332 * @license
1333 * Copyright Google LLC All Rights Reserved.
1334 *
1335 * Use of this source code is governed by an MIT-style license that can be
1336 * found in the LICENSE file at https://angular.io/license
1337 */
1338/**
1339 * Component that shows a simplified checkbox without including any kind of "real" checkbox.
1340 * Meant to be used when the checkbox is purely decorative and a large number of them will be
1341 * included, such as for the options in a multi-select. Uses no SVGs or complex animations.
1342 * Note that theming is meant to be handled by the parent element, e.g.
1343 * `mat-primary .mat-pseudo-checkbox`.
1344 *
1345 * Note that this component will be completely invisible to screen-reader users. This is *not*
1346 * interchangeable with `<mat-checkbox>` and should *not* be used if the user would directly
1347 * interact with the checkbox. The pseudo-checkbox should only be used as an implementation detail
1348 * of more complex components that appropriately handle selected / checked state.
1349 * @docs-private
1350 */
1351class MatPseudoCheckbox {
1352 constructor(_animationMode) {
1353 this._animationMode = _animationMode;
1354 /** Display state of the checkbox. */
1355 this.state = 'unchecked';
1356 /** Whether the checkbox is disabled. */
1357 this.disabled = false;
1358 }
1359}
1360MatPseudoCheckbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckbox, deps: [{ token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1361MatPseudoCheckbox.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatPseudoCheckbox, selector: "mat-pseudo-checkbox", inputs: { state: "state", disabled: "disabled" }, host: { properties: { "class.mat-pseudo-checkbox-indeterminate": "state === \"indeterminate\"", "class.mat-pseudo-checkbox-checked": "state === \"checked\"", "class.mat-pseudo-checkbox-disabled": "disabled", "class._mat-animation-noopable": "_animationMode === \"NoopAnimations\"" }, classAttribute: "mat-pseudo-checkbox" }, ngImport: i0, template: '', isInline: true, styles: [".mat-pseudo-checkbox{width:16px;height:16px;border:2px solid;border-radius:2px;cursor:pointer;display:inline-block;vertical-align:middle;box-sizing:border-box;position:relative;flex-shrink:0;transition:border-color 90ms cubic-bezier(0, 0, 0.2, 0.1),background-color 90ms cubic-bezier(0, 0, 0.2, 0.1)}.mat-pseudo-checkbox::after{position:absolute;opacity:0;content:\"\";border-bottom:2px solid currentColor;transition:opacity 90ms cubic-bezier(0, 0, 0.2, 0.1)}.mat-pseudo-checkbox.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox.mat-pseudo-checkbox-indeterminate{border-color:rgba(0,0,0,0)}.mat-pseudo-checkbox._mat-animation-noopable{transition:none !important;animation:none !important}.mat-pseudo-checkbox._mat-animation-noopable::after{transition:none}.mat-pseudo-checkbox-disabled{cursor:default}.mat-pseudo-checkbox-indeterminate::after{top:5px;left:1px;width:10px;opacity:1;border-radius:2px}.mat-pseudo-checkbox-checked::after{top:2.4px;left:1px;width:8px;height:3px;border-left:2px solid currentColor;transform:rotate(-45deg);opacity:1;box-sizing:content-box}"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1362i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckbox, decorators: [{
1363 type: Component,
1364 args: [{ encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, selector: 'mat-pseudo-checkbox', template: '', host: {
1365 'class': 'mat-pseudo-checkbox',
1366 '[class.mat-pseudo-checkbox-indeterminate]': 'state === "indeterminate"',
1367 '[class.mat-pseudo-checkbox-checked]': 'state === "checked"',
1368 '[class.mat-pseudo-checkbox-disabled]': 'disabled',
1369 '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
1370 }, styles: [".mat-pseudo-checkbox{width:16px;height:16px;border:2px solid;border-radius:2px;cursor:pointer;display:inline-block;vertical-align:middle;box-sizing:border-box;position:relative;flex-shrink:0;transition:border-color 90ms cubic-bezier(0, 0, 0.2, 0.1),background-color 90ms cubic-bezier(0, 0, 0.2, 0.1)}.mat-pseudo-checkbox::after{position:absolute;opacity:0;content:\"\";border-bottom:2px solid currentColor;transition:opacity 90ms cubic-bezier(0, 0, 0.2, 0.1)}.mat-pseudo-checkbox.mat-pseudo-checkbox-checked,.mat-pseudo-checkbox.mat-pseudo-checkbox-indeterminate{border-color:rgba(0,0,0,0)}.mat-pseudo-checkbox._mat-animation-noopable{transition:none !important;animation:none !important}.mat-pseudo-checkbox._mat-animation-noopable::after{transition:none}.mat-pseudo-checkbox-disabled{cursor:default}.mat-pseudo-checkbox-indeterminate::after{top:5px;left:1px;width:10px;opacity:1;border-radius:2px}.mat-pseudo-checkbox-checked::after{top:2.4px;left:1px;width:8px;height:3px;border-left:2px solid currentColor;transform:rotate(-45deg);opacity:1;box-sizing:content-box}"] }]
1371 }], ctorParameters: function () {
1372 return [{ type: undefined, decorators: [{
1373 type: Optional
1374 }, {
1375 type: Inject,
1376 args: [ANIMATION_MODULE_TYPE]
1377 }] }];
1378 }, propDecorators: { state: [{
1379 type: Input
1380 }], disabled: [{
1381 type: Input
1382 }] } });
1383
1384/**
1385 * @license
1386 * Copyright Google LLC All Rights Reserved.
1387 *
1388 * Use of this source code is governed by an MIT-style license that can be
1389 * found in the LICENSE file at https://angular.io/license
1390 */
1391class MatPseudoCheckboxModule {
1392}
1393MatPseudoCheckboxModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckboxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1394MatPseudoCheckboxModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckboxModule, declarations: [MatPseudoCheckbox], imports: [MatCommonModule], exports: [MatPseudoCheckbox] });
1395MatPseudoCheckboxModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckboxModule, imports: [MatCommonModule] });
1396i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatPseudoCheckboxModule, decorators: [{
1397 type: NgModule,
1398 args: [{
1399 imports: [MatCommonModule],
1400 exports: [MatPseudoCheckbox],
1401 declarations: [MatPseudoCheckbox],
1402 }]
1403 }] });
1404
1405/**
1406 * @license
1407 * Copyright Google LLC All Rights Reserved.
1408 *
1409 * Use of this source code is governed by an MIT-style license that can be
1410 * found in the LICENSE file at https://angular.io/license
1411 */
1412
1413/**
1414 * @license
1415 * Copyright Google LLC All Rights Reserved.
1416 *
1417 * Use of this source code is governed by an MIT-style license that can be
1418 * found in the LICENSE file at https://angular.io/license
1419 */
1420/**
1421 * Injection token used to provide the parent component to options.
1422 */
1423const MAT_OPTION_PARENT_COMPONENT = new InjectionToken('MAT_OPTION_PARENT_COMPONENT');
1424
1425/**
1426 * @license
1427 * Copyright Google LLC All Rights Reserved.
1428 *
1429 * Use of this source code is governed by an MIT-style license that can be
1430 * found in the LICENSE file at https://angular.io/license
1431 */
1432// Notes on the accessibility pattern used for `mat-optgroup`.
1433// The option group has two different "modes": regular and inert. The regular mode uses the
1434// recommended a11y pattern which has `role="group"` on the group element with `aria-labelledby`
1435// pointing to the label. This works for `mat-select`, but it seems to hit a bug for autocomplete
1436// under VoiceOver where the group doesn't get read out at all. The bug appears to be that if
1437// there's __any__ a11y-related attribute on the group (e.g. `role` or `aria-labelledby`),
1438// VoiceOver on Safari won't read it out.
1439// We've introduced the `inert` mode as a workaround. Under this mode, all a11y attributes are
1440// removed from the group, and we get the screen reader to read out the group label by mirroring it
1441// inside an invisible element in the option. This is sub-optimal, because the screen reader will
1442// repeat the group label on each navigation, whereas the default pattern only reads the group when
1443// the user enters a new group. The following alternate approaches were considered:
1444// 1. Reading out the group label using the `LiveAnnouncer` solves the problem, but we can't control
1445// when the text will be read out so sometimes it comes in too late or never if the user
1446// navigates quickly.
1447// 2. `<mat-option aria-describedby="groupLabel"` - This works on Safari, but VoiceOver in Chrome
1448// won't read out the description at all.
1449// 3. `<mat-option aria-labelledby="optionLabel groupLabel"` - This works on Chrome, but Safari
1450// doesn't read out the text at all. Furthermore, on
1451// Boilerplate for applying mixins to MatOptgroup.
1452/** @docs-private */
1453const _MatOptgroupMixinBase = mixinDisabled(class {
1454});
1455// Counter for unique group ids.
1456let _uniqueOptgroupIdCounter = 0;
1457class _MatOptgroupBase extends _MatOptgroupMixinBase {
1458 constructor(parent) {
1459 var _a;
1460 super();
1461 /** Unique id for the underlying label. */
1462 this._labelId = `mat-optgroup-label-${_uniqueOptgroupIdCounter++}`;
1463 this._inert = (_a = parent === null || parent === void 0 ? void 0 : parent.inertGroups) !== null && _a !== void 0 ? _a : false;
1464 }
1465}
1466_MatOptgroupBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: _MatOptgroupBase, deps: [{ token: MAT_OPTION_PARENT_COMPONENT, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1467_MatOptgroupBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: _MatOptgroupBase, inputs: { label: "label" }, usesInheritance: true, ngImport: i0 });
1468i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: _MatOptgroupBase, decorators: [{
1469 type: Directive
1470 }], ctorParameters: function () {
1471 return [{ type: undefined, decorators: [{
1472 type: Inject,
1473 args: [MAT_OPTION_PARENT_COMPONENT]
1474 }, {
1475 type: Optional
1476 }] }];
1477 }, propDecorators: { label: [{
1478 type: Input
1479 }] } });
1480/**
1481 * Injection token that can be used to reference instances of `MatOptgroup`. It serves as
1482 * alternative token to the actual `MatOptgroup` class which could cause unnecessary
1483 * retention of the class and its component metadata.
1484 */
1485const MAT_OPTGROUP = new InjectionToken('MatOptgroup');
1486/**
1487 * Component that is used to group instances of `mat-option`.
1488 */
1489class MatOptgroup extends _MatOptgroupBase {
1490}
1491MatOptgroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOptgroup, deps: null, target: i0.ɵɵFactoryTarget.Component });
1492MatOptgroup.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatOptgroup, selector: "mat-optgroup", inputs: { disabled: "disabled" }, host: { properties: { "attr.role": "_inert ? null : \"group\"", "attr.aria-disabled": "_inert ? null : disabled.toString()", "attr.aria-labelledby": "_inert ? null : _labelId", "class.mat-optgroup-disabled": "disabled" }, classAttribute: "mat-optgroup" }, providers: [{ provide: MAT_OPTGROUP, useExisting: MatOptgroup }], exportAs: ["matOptgroup"], usesInheritance: true, ngImport: i0, template: "<span class=\"mat-optgroup-label\" aria-hidden=\"true\" [id]=\"_labelId\">{{ label }} <ng-content></ng-content></span>\n<ng-content select=\"mat-option, ng-container\"></ng-content>\n", styles: [".mat-optgroup-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;max-width:100%;-webkit-user-select:none;user-select:none;cursor:default}.mat-optgroup-label[disabled]{cursor:default}[dir=rtl] .mat-optgroup-label{text-align:right}.mat-optgroup-label .mat-icon{margin-right:16px;vertical-align:middle}.mat-optgroup-label .mat-icon svg{vertical-align:top}[dir=rtl] .mat-optgroup-label .mat-icon{margin-left:16px;margin-right:0}"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1493i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOptgroup, decorators: [{
1494 type: Component,
1495 args: [{ selector: 'mat-optgroup', exportAs: 'matOptgroup', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, inputs: ['disabled'], host: {
1496 'class': 'mat-optgroup',
1497 '[attr.role]': '_inert ? null : "group"',
1498 '[attr.aria-disabled]': '_inert ? null : disabled.toString()',
1499 '[attr.aria-labelledby]': '_inert ? null : _labelId',
1500 '[class.mat-optgroup-disabled]': 'disabled',
1501 }, providers: [{ provide: MAT_OPTGROUP, useExisting: MatOptgroup }], template: "<span class=\"mat-optgroup-label\" aria-hidden=\"true\" [id]=\"_labelId\">{{ label }} <ng-content></ng-content></span>\n<ng-content select=\"mat-option, ng-container\"></ng-content>\n", styles: [".mat-optgroup-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;max-width:100%;-webkit-user-select:none;user-select:none;cursor:default}.mat-optgroup-label[disabled]{cursor:default}[dir=rtl] .mat-optgroup-label{text-align:right}.mat-optgroup-label .mat-icon{margin-right:16px;vertical-align:middle}.mat-optgroup-label .mat-icon svg{vertical-align:top}[dir=rtl] .mat-optgroup-label .mat-icon{margin-left:16px;margin-right:0}"] }]
1502 }] });
1503
1504/**
1505 * @license
1506 * Copyright Google LLC All Rights Reserved.
1507 *
1508 * Use of this source code is governed by an MIT-style license that can be
1509 * found in the LICENSE file at https://angular.io/license
1510 */
1511/**
1512 * Option IDs need to be unique across components, so this counter exists outside of
1513 * the component definition.
1514 */
1515let _uniqueIdCounter = 0;
1516/** Event object emitted by MatOption when selected or deselected. */
1517class MatOptionSelectionChange {
1518 constructor(
1519 /** Reference to the option that emitted the event. */
1520 source,
1521 /** Whether the change in the option's value was a result of a user action. */
1522 isUserInput = false) {
1523 this.source = source;
1524 this.isUserInput = isUserInput;
1525 }
1526}
1527class _MatOptionBase {
1528 constructor(_element, _changeDetectorRef, _parent, group) {
1529 this._element = _element;
1530 this._changeDetectorRef = _changeDetectorRef;
1531 this._parent = _parent;
1532 this.group = group;
1533 this._selected = false;
1534 this._active = false;
1535 this._disabled = false;
1536 this._mostRecentViewValue = '';
1537 /** The unique ID of the option. */
1538 this.id = `mat-option-${_uniqueIdCounter++}`;
1539 /** Event emitted when the option is selected or deselected. */
1540 // tslint:disable-next-line:no-output-on-prefix
1541 this.onSelectionChange = new EventEmitter();
1542 /** Emits when the state of the option changes and any parents have to be notified. */
1543 this._stateChanges = new Subject();
1544 }
1545 /** Whether the wrapping component is in multiple selection mode. */
1546 get multiple() {
1547 return this._parent && this._parent.multiple;
1548 }
1549 /** Whether or not the option is currently selected. */
1550 get selected() {
1551 return this._selected;
1552 }
1553 /** Whether the option is disabled. */
1554 get disabled() {
1555 return (this.group && this.group.disabled) || this._disabled;
1556 }
1557 set disabled(value) {
1558 this._disabled = coerceBooleanProperty(value);
1559 }
1560 /** Whether ripples for the option are disabled. */
1561 get disableRipple() {
1562 return !!(this._parent && this._parent.disableRipple);
1563 }
1564 /**
1565 * Whether or not the option is currently active and ready to be selected.
1566 * An active option displays styles as if it is focused, but the
1567 * focus is actually retained somewhere else. This comes in handy
1568 * for components like autocomplete where focus must remain on the input.
1569 */
1570 get active() {
1571 return this._active;
1572 }
1573 /**
1574 * The displayed value of the option. It is necessary to show the selected option in the
1575 * select's trigger.
1576 */
1577 get viewValue() {
1578 // TODO(kara): Add input property alternative for node envs.
1579 return (this._getHostElement().textContent || '').trim();
1580 }
1581 /** Selects the option. */
1582 select() {
1583 if (!this._selected) {
1584 this._selected = true;
1585 this._changeDetectorRef.markForCheck();
1586 this._emitSelectionChangeEvent();
1587 }
1588 }
1589 /** Deselects the option. */
1590 deselect() {
1591 if (this._selected) {
1592 this._selected = false;
1593 this._changeDetectorRef.markForCheck();
1594 this._emitSelectionChangeEvent();
1595 }
1596 }
1597 /** Sets focus onto this option. */
1598 focus(_origin, options) {
1599 // Note that we aren't using `_origin`, but we need to keep it because some internal consumers
1600 // use `MatOption` in a `FocusKeyManager` and we need it to match `FocusableOption`.
1601 const element = this._getHostElement();
1602 if (typeof element.focus === 'function') {
1603 element.focus(options);
1604 }
1605 }
1606 /**
1607 * This method sets display styles on the option to make it appear
1608 * active. This is used by the ActiveDescendantKeyManager so key
1609 * events will display the proper options as active on arrow key events.
1610 */
1611 setActiveStyles() {
1612 if (!this._active) {
1613 this._active = true;
1614 this._changeDetectorRef.markForCheck();
1615 }
1616 }
1617 /**
1618 * This method removes display styles on the option that made it appear
1619 * active. This is used by the ActiveDescendantKeyManager so key
1620 * events will display the proper options as active on arrow key events.
1621 */
1622 setInactiveStyles() {
1623 if (this._active) {
1624 this._active = false;
1625 this._changeDetectorRef.markForCheck();
1626 }
1627 }
1628 /** Gets the label to be used when determining whether the option should be focused. */
1629 getLabel() {
1630 return this.viewValue;
1631 }
1632 /** Ensures the option is selected when activated from the keyboard. */
1633 _handleKeydown(event) {
1634 if ((event.keyCode === ENTER || event.keyCode === SPACE) && !hasModifierKey(event)) {
1635 this._selectViaInteraction();
1636 // Prevent the page from scrolling down and form submits.
1637 event.preventDefault();
1638 }
1639 }
1640 /**
1641 * `Selects the option while indicating the selection came from the user. Used to
1642 * determine if the select's view -> model callback should be invoked.`
1643 */
1644 _selectViaInteraction() {
1645 if (!this.disabled) {
1646 this._selected = this.multiple ? !this._selected : true;
1647 this._changeDetectorRef.markForCheck();
1648 this._emitSelectionChangeEvent(true);
1649 }
1650 }
1651 /**
1652 * Gets the `aria-selected` value for the option. We explicitly omit the `aria-selected`
1653 * attribute from single-selection, unselected options. Including the `aria-selected="false"`
1654 * attributes adds a significant amount of noise to screen-reader users without providing useful
1655 * information.
1656 */
1657 _getAriaSelected() {
1658 return this.selected || (this.multiple ? false : null);
1659 }
1660 /** Returns the correct tabindex for the option depending on disabled state. */
1661 _getTabIndex() {
1662 return this.disabled ? '-1' : '0';
1663 }
1664 /** Gets the host DOM element. */
1665 _getHostElement() {
1666 return this._element.nativeElement;
1667 }
1668 ngAfterViewChecked() {
1669 // Since parent components could be using the option's label to display the selected values
1670 // (e.g. `mat-select`) and they don't have a way of knowing if the option's label has changed
1671 // we have to check for changes in the DOM ourselves and dispatch an event. These checks are
1672 // relatively cheap, however we still limit them only to selected options in order to avoid
1673 // hitting the DOM too often.
1674 if (this._selected) {
1675 const viewValue = this.viewValue;
1676 if (viewValue !== this._mostRecentViewValue) {
1677 this._mostRecentViewValue = viewValue;
1678 this._stateChanges.next();
1679 }
1680 }
1681 }
1682 ngOnDestroy() {
1683 this._stateChanges.complete();
1684 }
1685 /** Emits the selection change event. */
1686 _emitSelectionChangeEvent(isUserInput = false) {
1687 this.onSelectionChange.emit(new MatOptionSelectionChange(this, isUserInput));
1688 }
1689}
1690_MatOptionBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: _MatOptionBase, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
1691_MatOptionBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.0.1", type: _MatOptionBase, inputs: { value: "value", id: "id", disabled: "disabled" }, outputs: { onSelectionChange: "onSelectionChange" }, ngImport: i0 });
1692i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: _MatOptionBase, decorators: [{
1693 type: Directive
1694 }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined }, { type: _MatOptgroupBase }]; }, propDecorators: { value: [{
1695 type: Input
1696 }], id: [{
1697 type: Input
1698 }], disabled: [{
1699 type: Input
1700 }], onSelectionChange: [{
1701 type: Output
1702 }] } });
1703/**
1704 * Single option inside of a `<mat-select>` element.
1705 */
1706class MatOption extends _MatOptionBase {
1707 constructor(element, changeDetectorRef, parent, group) {
1708 super(element, changeDetectorRef, parent, group);
1709 }
1710}
1711MatOption.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOption, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: MAT_OPTION_PARENT_COMPONENT, optional: true }, { token: MAT_OPTGROUP, optional: true }], target: i0.ɵɵFactoryTarget.Component });
1712MatOption.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.1", type: MatOption, selector: "mat-option", host: { attributes: { "role": "option" }, listeners: { "click": "_selectViaInteraction()", "keydown": "_handleKeydown($event)" }, properties: { "attr.tabindex": "_getTabIndex()", "class.mat-selected": "selected", "class.mat-option-multiple": "multiple", "class.mat-active": "active", "id": "id", "attr.aria-selected": "_getAriaSelected()", "attr.aria-disabled": "disabled.toString()", "class.mat-option-disabled": "disabled" }, classAttribute: "mat-option mat-focus-indicator" }, exportAs: ["matOption"], usesInheritance: true, ngImport: i0, template: "<mat-pseudo-checkbox *ngIf=\"multiple\" class=\"mat-option-pseudo-checkbox\"\n [state]=\"selected ? 'checked' : 'unchecked'\" [disabled]=\"disabled\"></mat-pseudo-checkbox>\n\n<span class=\"mat-option-text\"><ng-content></ng-content></span>\n\n<!-- See a11y notes inside optgroup.ts for context behind this element. -->\n<span class=\"cdk-visually-hidden\" *ngIf=\"group && group._inert\">({{ group.label }})</span>\n\n<div class=\"mat-option-ripple\" mat-ripple\n [matRippleTrigger]=\"_getHostElement()\"\n [matRippleDisabled]=\"disabled || disableRipple\">\n</div>\n", styles: [".mat-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;max-width:100%;position:relative;cursor:pointer;outline:none;display:flex;flex-direction:row;max-width:100%;box-sizing:border-box;align-items:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-option[disabled]{cursor:default}[dir=rtl] .mat-option{text-align:right}.mat-option .mat-icon{margin-right:16px;vertical-align:middle}.mat-option .mat-icon svg{vertical-align:top}[dir=rtl] .mat-option .mat-icon{margin-left:16px;margin-right:0}.mat-option[aria-disabled=true]{-webkit-user-select:none;user-select:none;cursor:default}.mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:32px}[dir=rtl] .mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:16px;padding-right:32px}.cdk-high-contrast-active .mat-option{margin:0 1px}.cdk-high-contrast-active .mat-option.mat-active{border:solid 1px currentColor;margin:0}.cdk-high-contrast-active .mat-option[aria-disabled=true]{opacity:.5}.mat-option-text{display:inline-block;flex-grow:1;overflow:hidden;text-overflow:ellipsis}.mat-option .mat-option-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}.mat-option-pseudo-checkbox{margin-right:8px}[dir=rtl] .mat-option-pseudo-checkbox{margin-left:8px;margin-right:0}"], dependencies: [{ kind: "directive", type: MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MatPseudoCheckbox, selector: "mat-pseudo-checkbox", inputs: ["state", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1713i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOption, decorators: [{
1714 type: Component,
1715 args: [{ selector: 'mat-option', exportAs: 'matOption', host: {
1716 'role': 'option',
1717 '[attr.tabindex]': '_getTabIndex()',
1718 '[class.mat-selected]': 'selected',
1719 '[class.mat-option-multiple]': 'multiple',
1720 '[class.mat-active]': 'active',
1721 '[id]': 'id',
1722 '[attr.aria-selected]': '_getAriaSelected()',
1723 '[attr.aria-disabled]': 'disabled.toString()',
1724 '[class.mat-option-disabled]': 'disabled',
1725 '(click)': '_selectViaInteraction()',
1726 '(keydown)': '_handleKeydown($event)',
1727 'class': 'mat-option mat-focus-indicator',
1728 }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-pseudo-checkbox *ngIf=\"multiple\" class=\"mat-option-pseudo-checkbox\"\n [state]=\"selected ? 'checked' : 'unchecked'\" [disabled]=\"disabled\"></mat-pseudo-checkbox>\n\n<span class=\"mat-option-text\"><ng-content></ng-content></span>\n\n<!-- See a11y notes inside optgroup.ts for context behind this element. -->\n<span class=\"cdk-visually-hidden\" *ngIf=\"group && group._inert\">({{ group.label }})</span>\n\n<div class=\"mat-option-ripple\" mat-ripple\n [matRippleTrigger]=\"_getHostElement()\"\n [matRippleDisabled]=\"disabled || disableRipple\">\n</div>\n", styles: [".mat-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;line-height:48px;height:48px;padding:0 16px;text-align:left;text-decoration:none;max-width:100%;position:relative;cursor:pointer;outline:none;display:flex;flex-direction:row;max-width:100%;box-sizing:border-box;align-items:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-option[disabled]{cursor:default}[dir=rtl] .mat-option{text-align:right}.mat-option .mat-icon{margin-right:16px;vertical-align:middle}.mat-option .mat-icon svg{vertical-align:top}[dir=rtl] .mat-option .mat-icon{margin-left:16px;margin-right:0}.mat-option[aria-disabled=true]{-webkit-user-select:none;user-select:none;cursor:default}.mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:32px}[dir=rtl] .mat-optgroup .mat-option:not(.mat-option-multiple){padding-left:16px;padding-right:32px}.cdk-high-contrast-active .mat-option{margin:0 1px}.cdk-high-contrast-active .mat-option.mat-active{border:solid 1px currentColor;margin:0}.cdk-high-contrast-active .mat-option[aria-disabled=true]{opacity:.5}.mat-option-text{display:inline-block;flex-grow:1;overflow:hidden;text-overflow:ellipsis}.mat-option .mat-option-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}.mat-option-pseudo-checkbox{margin-right:8px}[dir=rtl] .mat-option-pseudo-checkbox{margin-left:8px;margin-right:0}"] }]
1729 }], ctorParameters: function () {
1730 return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
1731 type: Optional
1732 }, {
1733 type: Inject,
1734 args: [MAT_OPTION_PARENT_COMPONENT]
1735 }] }, { type: MatOptgroup, decorators: [{
1736 type: Optional
1737 }, {
1738 type: Inject,
1739 args: [MAT_OPTGROUP]
1740 }] }];
1741 } });
1742/**
1743 * Counts the amount of option group labels that precede the specified option.
1744 * @param optionIndex Index of the option at which to start counting.
1745 * @param options Flat list of all of the options.
1746 * @param optionGroups Flat list of all of the option groups.
1747 * @docs-private
1748 */
1749function _countGroupLabelsBeforeOption(optionIndex, options, optionGroups) {
1750 if (optionGroups.length) {
1751 let optionsArray = options.toArray();
1752 let groups = optionGroups.toArray();
1753 let groupCounter = 0;
1754 for (let i = 0; i < optionIndex + 1; i++) {
1755 if (optionsArray[i].group && optionsArray[i].group === groups[groupCounter]) {
1756 groupCounter++;
1757 }
1758 }
1759 return groupCounter;
1760 }
1761 return 0;
1762}
1763/**
1764 * Determines the position to which to scroll a panel in order for an option to be into view.
1765 * @param optionOffset Offset of the option from the top of the panel.
1766 * @param optionHeight Height of the options.
1767 * @param currentScrollPosition Current scroll position of the panel.
1768 * @param panelHeight Height of the panel.
1769 * @docs-private
1770 */
1771function _getOptionScrollPosition(optionOffset, optionHeight, currentScrollPosition, panelHeight) {
1772 if (optionOffset < currentScrollPosition) {
1773 return optionOffset;
1774 }
1775 if (optionOffset + optionHeight > currentScrollPosition + panelHeight) {
1776 return Math.max(0, optionOffset - panelHeight + optionHeight);
1777 }
1778 return currentScrollPosition;
1779}
1780
1781/**
1782 * @license
1783 * Copyright Google LLC All Rights Reserved.
1784 *
1785 * Use of this source code is governed by an MIT-style license that can be
1786 * found in the LICENSE file at https://angular.io/license
1787 */
1788class MatOptionModule {
1789}
1790MatOptionModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOptionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1791MatOptionModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.1", ngImport: i0, type: MatOptionModule, declarations: [MatOption, MatOptgroup], imports: [MatRippleModule, CommonModule, MatCommonModule, MatPseudoCheckboxModule], exports: [MatOption, MatOptgroup] });
1792MatOptionModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOptionModule, imports: [MatRippleModule, CommonModule, MatCommonModule, MatPseudoCheckboxModule] });
1793i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.1", ngImport: i0, type: MatOptionModule, decorators: [{
1794 type: NgModule,
1795 args: [{
1796 imports: [MatRippleModule, CommonModule, MatCommonModule, MatPseudoCheckboxModule],
1797 exports: [MatOption, MatOptgroup],
1798 declarations: [MatOption, MatOptgroup],
1799 }]
1800 }] });
1801
1802/**
1803 * @license
1804 * Copyright Google LLC All Rights Reserved.
1805 *
1806 * Use of this source code is governed by an MIT-style license that can be
1807 * found in the LICENSE file at https://angular.io/license
1808 */
1809
1810/**
1811 * @license
1812 * Copyright Google LLC All Rights Reserved.
1813 *
1814 * Use of this source code is governed by an MIT-style license that can be
1815 * found in the LICENSE file at https://angular.io/license
1816 */
1817
1818/**
1819 * Generated bundle index. Do not edit.
1820 */
1821
1822export { AnimationCurves, AnimationDurations, DateAdapter, ErrorStateMatcher, MATERIAL_SANITY_CHECKS, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MAT_DATE_LOCALE_FACTORY, MAT_NATIVE_DATE_FORMATS, MAT_OPTGROUP, MAT_OPTION_PARENT_COMPONENT, MAT_RIPPLE_GLOBAL_OPTIONS, MatCommonModule, MatLine, MatLineModule, MatNativeDateModule, MatOptgroup, MatOption, MatOptionModule, MatOptionSelectionChange, MatPseudoCheckbox, MatPseudoCheckboxModule, MatRipple, MatRippleModule, NativeDateAdapter, NativeDateModule, RippleRef, RippleRenderer, ShowOnDirtyErrorStateMatcher, VERSION, _MatOptgroupBase, _MatOptionBase, _countGroupLabelsBeforeOption, _getOptionScrollPosition, defaultRippleAnimationConfig, mixinColor, mixinDisableRipple, mixinDisabled, mixinErrorState, mixinInitialized, mixinTabIndex, setLines };
1823//# sourceMappingURL=core.mjs.map