UNPKG

@angular/material

Version:
544 lines 87.2 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { Directionality } from '@angular/cdk/bidi'; import { coerceBooleanProperty, coerceStringArray } from '@angular/cdk/coercion'; import { ESCAPE, hasModifierKey, UP_ARROW } from '@angular/cdk/keycodes'; import { Overlay, OverlayConfig, FlexibleConnectedPositionStrategy, } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Inject, InjectionToken, Input, NgZone, Optional, Output, ViewChild, ViewContainerRef, ViewEncapsulation, ChangeDetectorRef, Directive, } from '@angular/core'; import { DateAdapter, mixinColor } from '@angular/material/core'; import { merge, Subject, Subscription } from 'rxjs'; import { filter, take } from 'rxjs/operators'; import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform'; import { MatCalendar } from './calendar'; import { matDatepickerAnimations } from './datepicker-animations'; import { createMissingDateImplError } from './datepicker-errors'; import { MatDateSelectionModel, DateRange, } from './date-selection-model'; import { MAT_DATE_RANGE_SELECTION_STRATEGY, } from './date-range-selection-strategy'; import { MatDatepickerIntl } from './datepicker-intl'; import * as i0 from "@angular/core"; import * as i1 from "./date-selection-model"; import * as i2 from "@angular/material/core"; import * as i3 from "./datepicker-intl"; import * as i4 from "./calendar"; import * as i5 from "@angular/material/button"; import * as i6 from "@angular/cdk/a11y"; import * as i7 from "@angular/common"; import * as i8 from "@angular/cdk/portal"; import * as i9 from "@angular/cdk/overlay"; import * as i10 from "@angular/cdk/bidi"; /** Used to generate a unique ID for each datepicker instance. */ let datepickerUid = 0; /** Injection token that determines the scroll handling while the calendar is open. */ export const MAT_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('mat-datepicker-scroll-strategy'); /** @docs-private */ export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay) { return () => overlay.scrollStrategies.reposition(); } /** @docs-private */ export const MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER = { provide: MAT_DATEPICKER_SCROLL_STRATEGY, deps: [Overlay], useFactory: MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY, }; // Boilerplate for applying mixins to MatDatepickerContent. /** @docs-private */ const _MatDatepickerContentBase = mixinColor(class { constructor(_elementRef) { this._elementRef = _elementRef; } }); /** * Component used as the content for the datepicker overlay. We use this instead of using * MatCalendar directly as the content so we can control the initial focus. This also gives us a * place to put additional features of the overlay that are not part of the calendar itself in the * future. (e.g. confirmation buttons). * @docs-private */ export class MatDatepickerContent extends _MatDatepickerContentBase { constructor(elementRef, _changeDetectorRef, _globalModel, _dateAdapter, _rangeSelectionStrategy, intl) { super(elementRef); this._changeDetectorRef = _changeDetectorRef; this._globalModel = _globalModel; this._dateAdapter = _dateAdapter; this._rangeSelectionStrategy = _rangeSelectionStrategy; this._subscriptions = new Subscription(); /** Emits when an animation has finished. */ this._animationDone = new Subject(); /** Portal with projected action buttons. */ this._actionsPortal = null; this._closeButtonText = intl.closeCalendarLabel; } ngOnInit() { // If we have actions, clone the model so that we have the ability to cancel the selection, // otherwise update the global model directly. Note that we want to assign this as soon as // possible, but `_actionsPortal` isn't available in the constructor so we do it in `ngOnInit`. this._model = this._actionsPortal ? this._globalModel.clone() : this._globalModel; this._animationState = this.datepicker.touchUi ? 'enter-dialog' : 'enter-dropdown'; } ngAfterViewInit() { this._subscriptions.add(this.datepicker.stateChanges.subscribe(() => { this._changeDetectorRef.markForCheck(); })); this._calendar.focusActiveCell(); } ngOnDestroy() { this._subscriptions.unsubscribe(); this._animationDone.complete(); } _handleUserSelection(event) { const selection = this._model.selection; const value = event.value; const isRange = selection instanceof DateRange; // If we're selecting a range and we have a selection strategy, always pass the value through // there. Otherwise don't assign null values to the model, unless we're selecting a range. // A null value when picking a range means that the user cancelled the selection (e.g. by // pressing escape), whereas when selecting a single value it means that the value didn't // change. This isn't very intuitive, but it's here for backwards-compatibility. if (isRange && this._rangeSelectionStrategy) { const newSelection = this._rangeSelectionStrategy.selectionFinished(value, selection, event.event); this._model.updateSelection(newSelection, this); } else if (value && (isRange || !this._dateAdapter.sameDate(value, selection))) { this._model.add(value); } // Delegate closing the overlay to the actions. if ((!this._model || this._model.isComplete()) && !this._actionsPortal) { this.datepicker.close(); } } _startExitAnimation() { this._animationState = 'void'; this._changeDetectorRef.markForCheck(); } _getSelected() { return this._model.selection; } /** Applies the current pending selection to the global model. */ _applyPendingSelection() { if (this._model !== this._globalModel) { this._globalModel.updateSelection(this._model.selection, this); } } } MatDatepickerContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: MatDatepickerContent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1.MatDateSelectionModel }, { token: i2.DateAdapter }, { token: MAT_DATE_RANGE_SELECTION_STRATEGY, optional: true }, { token: i3.MatDatepickerIntl }], target: i0.ɵɵFactoryTarget.Component }); MatDatepickerContent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.0", type: MatDatepickerContent, selector: "mat-datepicker-content", inputs: { color: "color" }, host: { listeners: { "@transformPanel.done": "_animationDone.next()" }, properties: { "@transformPanel": "_animationState", "class.mat-datepicker-content-touch": "datepicker.touchUi" }, classAttribute: "mat-datepicker-content" }, viewQueries: [{ propertyName: "_calendar", first: true, predicate: MatCalendar, descendants: true }], exportAs: ["matDatepickerContent"], usesInheritance: true, ngImport: i0, template: "<div\n cdkTrapFocus\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"_dialogLabelId ?? undefined\"\n class=\"mat-datepicker-content-container\"\n [class.mat-datepicker-content-container-with-custom-header]=\"datepicker.calendarHeaderComponent\"\n [class.mat-datepicker-content-container-with-actions]=\"_actionsPortal\">\n <mat-calendar\n [id]=\"datepicker.id\"\n [ngClass]=\"datepicker.panelClass\"\n [startAt]=\"datepicker.startAt\"\n [startView]=\"datepicker.startView\"\n [minDate]=\"datepicker._getMinDate()\"\n [maxDate]=\"datepicker._getMaxDate()\"\n [dateFilter]=\"datepicker._getDateFilter()\"\n [headerComponent]=\"datepicker.calendarHeaderComponent\"\n [selected]=\"_getSelected()\"\n [dateClass]=\"datepicker.dateClass\"\n [comparisonStart]=\"comparisonStart\"\n [comparisonEnd]=\"comparisonEnd\"\n [@fadeInCalendar]=\"'enter'\"\n (yearSelected)=\"datepicker._selectYear($event)\"\n (monthSelected)=\"datepicker._selectMonth($event)\"\n (viewChanged)=\"datepicker._viewChanged($event)\"\n (_userSelection)=\"_handleUserSelection($event)\"></mat-calendar>\n\n <ng-template [cdkPortalOutlet]=\"_actionsPortal\"></ng-template>\n\n <!-- Invisible close button for screen reader users. -->\n <button\n type=\"button\"\n mat-raised-button\n [color]=\"color || 'primary'\"\n class=\"mat-datepicker-close-button\"\n [class.cdk-visually-hidden]=\"!_closeButtonFocused\"\n (focus)=\"_closeButtonFocused = true\"\n (blur)=\"_closeButtonFocused = false\"\n (click)=\"datepicker.close()\">{{ _closeButtonText }}</button>\n</div>\n", styles: [".mat-datepicker-content{display:block;border-radius:4px}.mat-datepicker-content .mat-calendar{width:296px;height:354px}.mat-datepicker-content .mat-datepicker-content-container-with-custom-header .mat-calendar{height:auto}.mat-datepicker-content .mat-datepicker-close-button{position:absolute;top:100%;left:0;margin-top:8px}.ng-animating .mat-datepicker-content .mat-datepicker-close-button{display:none}.mat-datepicker-content-container{display:flex;flex-direction:column;justify-content:space-between}.mat-datepicker-content-touch{display:block;max-height:80vh;position:relative;overflow:visible}.mat-datepicker-content-touch .mat-datepicker-content-container{min-height:312px;max-height:788px;min-width:250px;max-width:750px}.mat-datepicker-content-touch .mat-calendar{width:100%;height:auto}@media all and (orientation: landscape){.mat-datepicker-content-touch .mat-datepicker-content-container{width:64vh;height:80vh}}@media all and (orientation: portrait){.mat-datepicker-content-touch .mat-datepicker-content-container{width:80vw;height:100vw}.mat-datepicker-content-touch .mat-datepicker-content-container-with-actions{height:115vw}}\n"], components: [{ type: i4.MatCalendar, selector: "mat-calendar", inputs: ["headerComponent", "startAt", "startView", "selected", "minDate", "maxDate", "dateFilter", "dateClass", "comparisonStart", "comparisonEnd"], outputs: ["selectedChange", "yearSelected", "monthSelected", "viewChanged", "_userSelection"], exportAs: ["matCalendar"] }, { type: i5.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i6.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { type: i7.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i8.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], animations: [matDatepickerAnimations.transformPanel, matDatepickerAnimations.fadeInCalendar], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: MatDatepickerContent, decorators: [{ type: Component, args: [{ selector: 'mat-datepicker-content', host: { 'class': 'mat-datepicker-content', '[@transformPanel]': '_animationState', '(@transformPanel.done)': '_animationDone.next()', '[class.mat-datepicker-content-touch]': 'datepicker.touchUi', }, animations: [matDatepickerAnimations.transformPanel, matDatepickerAnimations.fadeInCalendar], exportAs: 'matDatepickerContent', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, inputs: ['color'], template: "<div\n cdkTrapFocus\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"_dialogLabelId ?? undefined\"\n class=\"mat-datepicker-content-container\"\n [class.mat-datepicker-content-container-with-custom-header]=\"datepicker.calendarHeaderComponent\"\n [class.mat-datepicker-content-container-with-actions]=\"_actionsPortal\">\n <mat-calendar\n [id]=\"datepicker.id\"\n [ngClass]=\"datepicker.panelClass\"\n [startAt]=\"datepicker.startAt\"\n [startView]=\"datepicker.startView\"\n [minDate]=\"datepicker._getMinDate()\"\n [maxDate]=\"datepicker._getMaxDate()\"\n [dateFilter]=\"datepicker._getDateFilter()\"\n [headerComponent]=\"datepicker.calendarHeaderComponent\"\n [selected]=\"_getSelected()\"\n [dateClass]=\"datepicker.dateClass\"\n [comparisonStart]=\"comparisonStart\"\n [comparisonEnd]=\"comparisonEnd\"\n [@fadeInCalendar]=\"'enter'\"\n (yearSelected)=\"datepicker._selectYear($event)\"\n (monthSelected)=\"datepicker._selectMonth($event)\"\n (viewChanged)=\"datepicker._viewChanged($event)\"\n (_userSelection)=\"_handleUserSelection($event)\"></mat-calendar>\n\n <ng-template [cdkPortalOutlet]=\"_actionsPortal\"></ng-template>\n\n <!-- Invisible close button for screen reader users. -->\n <button\n type=\"button\"\n mat-raised-button\n [color]=\"color || 'primary'\"\n class=\"mat-datepicker-close-button\"\n [class.cdk-visually-hidden]=\"!_closeButtonFocused\"\n (focus)=\"_closeButtonFocused = true\"\n (blur)=\"_closeButtonFocused = false\"\n (click)=\"datepicker.close()\">{{ _closeButtonText }}</button>\n</div>\n", styles: [".mat-datepicker-content{display:block;border-radius:4px}.mat-datepicker-content .mat-calendar{width:296px;height:354px}.mat-datepicker-content .mat-datepicker-content-container-with-custom-header .mat-calendar{height:auto}.mat-datepicker-content .mat-datepicker-close-button{position:absolute;top:100%;left:0;margin-top:8px}.ng-animating .mat-datepicker-content .mat-datepicker-close-button{display:none}.mat-datepicker-content-container{display:flex;flex-direction:column;justify-content:space-between}.mat-datepicker-content-touch{display:block;max-height:80vh;position:relative;overflow:visible}.mat-datepicker-content-touch .mat-datepicker-content-container{min-height:312px;max-height:788px;min-width:250px;max-width:750px}.mat-datepicker-content-touch .mat-calendar{width:100%;height:auto}@media all and (orientation: landscape){.mat-datepicker-content-touch .mat-datepicker-content-container{width:64vh;height:80vh}}@media all and (orientation: portrait){.mat-datepicker-content-touch .mat-datepicker-content-container{width:80vw;height:100vw}.mat-datepicker-content-touch .mat-datepicker-content-container-with-actions{height:115vw}}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1.MatDateSelectionModel }, { type: i2.DateAdapter }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_DATE_RANGE_SELECTION_STRATEGY] }] }, { type: i3.MatDatepickerIntl }]; }, propDecorators: { _calendar: [{ type: ViewChild, args: [MatCalendar] }] } }); /** Base class for a datepicker. */ export class MatDatepickerBase { constructor(_overlay, _ngZone, _viewContainerRef, scrollStrategy, _dateAdapter, _dir, _model) { this._overlay = _overlay; this._ngZone = _ngZone; this._viewContainerRef = _viewContainerRef; this._dateAdapter = _dateAdapter; this._dir = _dir; this._model = _model; this._inputStateChanges = Subscription.EMPTY; /** The view that the calendar should start in. */ this.startView = 'month'; this._touchUi = false; /** Preferred position of the datepicker in the X axis. */ this.xPosition = 'start'; /** Preferred position of the datepicker in the Y axis. */ this.yPosition = 'below'; this._restoreFocus = true; /** * Emits selected year in multiyear view. * This doesn't imply a change on the selected date. */ this.yearSelected = new EventEmitter(); /** * Emits selected month in year view. * This doesn't imply a change on the selected date. */ this.monthSelected = new EventEmitter(); /** * Emits when the current view changes. */ this.viewChanged = new EventEmitter(true); /** Emits when the datepicker has been opened. */ this.openedStream = new EventEmitter(); /** Emits when the datepicker has been closed. */ this.closedStream = new EventEmitter(); this._opened = false; /** The id for the datepicker calendar. */ this.id = `mat-datepicker-${datepickerUid++}`; /** The element that was focused before the datepicker was opened. */ this._focusedElementBeforeOpen = null; /** Unique class that will be added to the backdrop so that the test harnesses can look it up. */ this._backdropHarnessClass = `${this.id}-backdrop`; /** Emits when the datepicker's state changes. */ this.stateChanges = new Subject(); if (!this._dateAdapter && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw createMissingDateImplError('DateAdapter'); } this._scrollStrategy = scrollStrategy; } /** The date to open the calendar to initially. */ get startAt() { // If an explicit startAt is set we start there, otherwise we start at whatever the currently // selected value is. return this._startAt || (this.datepickerInput ? this.datepickerInput.getStartValue() : null); } set startAt(value) { this._startAt = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** Color palette to use on the datepicker's calendar. */ get color() { return (this._color || (this.datepickerInput ? this.datepickerInput.getThemePalette() : undefined)); } set color(value) { this._color = value; } /** * Whether the calendar UI is in touch mode. In touch mode the calendar opens in a dialog rather * than a dropdown and elements have more padding to allow for bigger touch targets. */ get touchUi() { return this._touchUi; } set touchUi(value) { this._touchUi = coerceBooleanProperty(value); } /** Whether the datepicker pop-up should be disabled. */ get disabled() { return this._disabled === undefined && this.datepickerInput ? this.datepickerInput.disabled : !!this._disabled; } set disabled(value) { const newValue = coerceBooleanProperty(value); if (newValue !== this._disabled) { this._disabled = newValue; this.stateChanges.next(undefined); } } /** * Whether to restore focus to the previously-focused element when the calendar is closed. * Note that automatic focus restoration is an accessibility feature and it is recommended that * you provide your own equivalent, if you decide to turn it off. */ get restoreFocus() { return this._restoreFocus; } set restoreFocus(value) { this._restoreFocus = coerceBooleanProperty(value); } /** * Classes to be passed to the date picker panel. * Supports string and string array values, similar to `ngClass`. */ get panelClass() { return this._panelClass; } set panelClass(value) { this._panelClass = coerceStringArray(value); } /** Whether the calendar is open. */ get opened() { return this._opened; } set opened(value) { coerceBooleanProperty(value) ? this.open() : this.close(); } /** The minimum selectable date. */ _getMinDate() { return this.datepickerInput && this.datepickerInput.min; } /** The maximum selectable date. */ _getMaxDate() { return this.datepickerInput && this.datepickerInput.max; } _getDateFilter() { return this.datepickerInput && this.datepickerInput.dateFilter; } ngOnChanges(changes) { const positionChange = changes['xPosition'] || changes['yPosition']; if (positionChange && !positionChange.firstChange && this._overlayRef) { const positionStrategy = this._overlayRef.getConfig().positionStrategy; if (positionStrategy instanceof FlexibleConnectedPositionStrategy) { this._setConnectedPositions(positionStrategy); if (this.opened) { this._overlayRef.updatePosition(); } } } this.stateChanges.next(undefined); } ngOnDestroy() { this._destroyOverlay(); this.close(); this._inputStateChanges.unsubscribe(); this.stateChanges.complete(); } /** Selects the given date */ select(date) { this._model.add(date); } /** Emits the selected year in multiyear view */ _selectYear(normalizedYear) { this.yearSelected.emit(normalizedYear); } /** Emits selected month in year view */ _selectMonth(normalizedMonth) { this.monthSelected.emit(normalizedMonth); } /** Emits changed view */ _viewChanged(view) { this.viewChanged.emit(view); } /** * Register an input with this datepicker. * @param input The datepicker input to register with this datepicker. * @returns Selection model that the input should hook itself up to. */ registerInput(input) { if (this.datepickerInput && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw Error('A MatDatepicker can only be associated with a single input.'); } this._inputStateChanges.unsubscribe(); this.datepickerInput = input; this._inputStateChanges = input.stateChanges.subscribe(() => this.stateChanges.next(undefined)); return this._model; } /** * Registers a portal containing action buttons with the datepicker. * @param portal Portal to be registered. */ registerActions(portal) { if (this._actionsPortal && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw Error('A MatDatepicker can only be associated with a single actions row.'); } this._actionsPortal = portal; } /** * Removes a portal containing action buttons from the datepicker. * @param portal Portal to be removed. */ removeActions(portal) { if (portal === this._actionsPortal) { this._actionsPortal = null; } } /** Open the calendar. */ open() { if (this._opened || this.disabled) { return; } if (!this.datepickerInput && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw Error('Attempted to open an MatDatepicker with no associated input.'); } this._focusedElementBeforeOpen = _getFocusedElementPierceShadowDom(); this._openOverlay(); this._opened = true; this.openedStream.emit(); } /** Close the calendar. */ close() { if (!this._opened) { return; } if (this._componentRef) { const instance = this._componentRef.instance; instance._startExitAnimation(); instance._animationDone.pipe(take(1)).subscribe(() => this._destroyOverlay()); } const completeClose = () => { // The `_opened` could've been reset already if // we got two events in quick succession. if (this._opened) { this._opened = false; this.closedStream.emit(); this._focusedElementBeforeOpen = null; } }; if (this._restoreFocus && this._focusedElementBeforeOpen && typeof this._focusedElementBeforeOpen.focus === 'function') { // Because IE moves focus asynchronously, we can't count on it being restored before we've // marked the datepicker as closed. If the event fires out of sequence and the element that // we're refocusing opens the datepicker on focus, the user could be stuck with not being // able to close the calendar at all. We work around it by making the logic, that marks // the datepicker as closed, async as well. this._focusedElementBeforeOpen.focus(); setTimeout(completeClose); } else { completeClose(); } } /** Applies the current pending selection on the overlay to the model. */ _applyPendingSelection() { this._componentRef?.instance?._applyPendingSelection(); } /** Forwards relevant values from the datepicker to the datepicker content inside the overlay. */ _forwardContentValues(instance) { instance.datepicker = this; instance.color = this.color; instance._actionsPortal = this._actionsPortal; instance._dialogLabelId = this.datepickerInput.getOverlayLabelId(); } /** Opens the overlay with the calendar. */ _openOverlay() { this._destroyOverlay(); const isDialog = this.touchUi; const portal = new ComponentPortal(MatDatepickerContent, this._viewContainerRef); const overlayRef = (this._overlayRef = this._overlay.create(new OverlayConfig({ positionStrategy: isDialog ? this._getDialogStrategy() : this._getDropdownStrategy(), hasBackdrop: true, backdropClass: [ isDialog ? 'cdk-overlay-dark-backdrop' : 'mat-overlay-transparent-backdrop', this._backdropHarnessClass, ], direction: this._dir, scrollStrategy: isDialog ? this._overlay.scrollStrategies.block() : this._scrollStrategy(), panelClass: `mat-datepicker-${isDialog ? 'dialog' : 'popup'}`, }))); this._getCloseStream(overlayRef).subscribe(event => { if (event) { event.preventDefault(); } this.close(); }); this._componentRef = overlayRef.attach(portal); this._forwardContentValues(this._componentRef.instance); // Update the position once the calendar has rendered. Only relevant in dropdown mode. if (!isDialog) { this._ngZone.onStable.pipe(take(1)).subscribe(() => overlayRef.updatePosition()); } } /** Destroys the current overlay. */ _destroyOverlay() { if (this._overlayRef) { this._overlayRef.dispose(); this._overlayRef = this._componentRef = null; } } /** Gets a position strategy that will open the calendar as a dropdown. */ _getDialogStrategy() { return this._overlay.position().global().centerHorizontally().centerVertically(); } /** Gets a position strategy that will open the calendar as a dropdown. */ _getDropdownStrategy() { const strategy = this._overlay .position() .flexibleConnectedTo(this.datepickerInput.getConnectedOverlayOrigin()) .withTransformOriginOn('.mat-datepicker-content') .withFlexibleDimensions(false) .withViewportMargin(8) .withLockedPosition(); return this._setConnectedPositions(strategy); } /** Sets the positions of the datepicker in dropdown mode based on the current configuration. */ _setConnectedPositions(strategy) { const primaryX = this.xPosition === 'end' ? 'end' : 'start'; const secondaryX = primaryX === 'start' ? 'end' : 'start'; const primaryY = this.yPosition === 'above' ? 'bottom' : 'top'; const secondaryY = primaryY === 'top' ? 'bottom' : 'top'; return strategy.withPositions([ { originX: primaryX, originY: secondaryY, overlayX: primaryX, overlayY: primaryY, }, { originX: primaryX, originY: primaryY, overlayX: primaryX, overlayY: secondaryY, }, { originX: secondaryX, originY: secondaryY, overlayX: secondaryX, overlayY: primaryY, }, { originX: secondaryX, originY: primaryY, overlayX: secondaryX, overlayY: secondaryY, }, ]); } /** Gets an observable that will emit when the overlay is supposed to be closed. */ _getCloseStream(overlayRef) { return merge(overlayRef.backdropClick(), overlayRef.detachments(), overlayRef.keydownEvents().pipe(filter(event => { // Closing on alt + up is only valid when there's an input associated with the datepicker. return ((event.keyCode === ESCAPE && !hasModifierKey(event)) || (this.datepickerInput && hasModifierKey(event, 'altKey') && event.keyCode === UP_ARROW)); }))); } } MatDatepickerBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: MatDatepickerBase, deps: [{ token: i9.Overlay }, { token: i0.NgZone }, { token: i0.ViewContainerRef }, { token: MAT_DATEPICKER_SCROLL_STRATEGY }, { token: i2.DateAdapter, optional: true }, { token: i10.Directionality, optional: true }, { token: i1.MatDateSelectionModel }], target: i0.ɵɵFactoryTarget.Directive }); MatDatepickerBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.0", type: MatDatepickerBase, inputs: { calendarHeaderComponent: "calendarHeaderComponent", startAt: "startAt", startView: "startView", color: "color", touchUi: "touchUi", disabled: "disabled", xPosition: "xPosition", yPosition: "yPosition", restoreFocus: "restoreFocus", dateClass: "dateClass", panelClass: "panelClass", opened: "opened" }, outputs: { yearSelected: "yearSelected", monthSelected: "monthSelected", viewChanged: "viewChanged", openedStream: "opened", closedStream: "closed" }, usesOnChanges: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.0", ngImport: i0, type: MatDatepickerBase, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i9.Overlay }, { type: i0.NgZone }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{ type: Inject, args: [MAT_DATEPICKER_SCROLL_STRATEGY] }] }, { type: i2.DateAdapter, decorators: [{ type: Optional }] }, { type: i10.Directionality, decorators: [{ type: Optional }] }, { type: i1.MatDateSelectionModel }]; }, propDecorators: { calendarHeaderComponent: [{ type: Input }], startAt: [{ type: Input }], startView: [{ type: Input }], color: [{ type: Input }], touchUi: [{ type: Input }], disabled: [{ type: Input }], xPosition: [{ type: Input }], yPosition: [{ type: Input }], restoreFocus: [{ type: Input }], yearSelected: [{ type: Output }], monthSelected: [{ type: Output }], viewChanged: [{ type: Output }], dateClass: [{ type: Input }], openedStream: [{ type: Output, args: ['opened'] }], closedStream: [{ type: Output, args: ['closed'] }], panelClass: [{ type: Input }], opened: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21hdGVyaWFsL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci1iYXNlLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21hdGVyaWFsL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci1jb250ZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBZSxxQkFBcUIsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQzdGLE9BQU8sRUFBQyxNQUFNLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZFLE9BQU8sRUFDTCxPQUFPLEVBQ1AsYUFBYSxFQUdiLGlDQUFpQyxHQUNsQyxNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBQyxlQUFlLEVBQWdDLE1BQU0scUJBQXFCLENBQUM7QUFDbkYsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixTQUFTLEVBRVQsVUFBVSxFQUNWLFlBQVksRUFDWixNQUFNLEVBQ04sY0FBYyxFQUNkLEtBQUssRUFDTCxNQUFNLEVBRU4sUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNqQixpQkFBaUIsRUFDakIsU0FBUyxHQUlWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBVyxXQUFXLEVBQUUsVUFBVSxFQUFlLE1BQU0sd0JBQXdCLENBQUM7QUFDdkYsT0FBTyxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQWMsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQzlELE9BQU8sRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFDLGlDQUFpQyxFQUFDLE1B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