text: /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * @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 } from '@angular/cdk/coercion';
  import { ESCAPE, UP_ARROW } from '@angular/cdk/keycodes';
  import { Overlay, OverlayConfig, } from '@angular/cdk/overlay';
  import { ComponentPortal } from '@angular/cdk/portal';
  import { DOCUMENT } from '@angular/common';
  import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Inject, InjectionToken, Input, NgZone, Optional, Output, ViewChild, ViewContainerRef, ViewEncapsulation, } from '@angular/core';
  import { DateAdapter, mixinColor, } from '@angular/material/core';
  import { MatDialog } from '@angular/material/dialog';
  import { merge, Subject, Subscription } from 'rxjs';
  import { filter, take } from 'rxjs/operators';
  import { MatCalendar } from './calendar';
  import { matDatepickerAnimations } from './datepicker-animations';
  import { createMissingDateImplError } from './datepicker-errors';
  /**
   * Used to generate a unique ID for each datepicker instance.
   * @type {?}
   */
  let datepickerUid = 0;
  /**
   * Injection token that determines the scroll handling while the calendar is open.
   * @type {?}
   */
  export const MAT_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('mat-datepicker-scroll-strategy');
  /**
   * \@docs-private
   * @param {?} overlay
   * @return {?}
   */
  export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay) {
      return (/**
       * @return {?}
       */
      () => overlay.scrollStrategies.reposition());
  }
  /**
   * \@docs-private
   * @type {?}
   */
  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
   */
  class MatDatepickerContentBase {
      /**
       * @param {?} _elementRef
       */
      constructor(_elementRef) {
          this._elementRef = _elementRef;
      }
  }
  if (false) {
      /** @type {?} */
      MatDatepickerContentBase.prototype._elementRef;
  }
  /** @type {?} */
  const _MatDatepickerContentMixinBase = mixinColor(MatDatepickerContentBase);
  /**
   * Component used as the content for the datepicker dialog and popup. 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 popup that are not part of the calendar itself in the
   * future. (e.g. confirmation buttons).
   * \@docs-private
   * @template D
   */
  export class MatDatepickerContent extends _MatDatepickerContentMixinBase {
      /**
       * @param {?} elementRef
       */
      constructor(elementRef) {
          super(elementRef);
      }
      /**
       * @return {?}
       */
      ngAfterViewInit() {
          this._calendar.focusActiveCell();
      }
  }
  MatDatepickerContent.decorators = [
      { type: Component, args: [{selector: 'mat-datepicker-content',
                  template: "<mat-calendar cdkTrapFocus [id]=\"datepicker.id\" [ngClass]=\"datepicker.panelClass\" [startAt]=\"datepicker.startAt\" [startView]=\"datepicker.startView\" [minDate]=\"datepicker._minDate\" [maxDate]=\"datepicker._maxDate\" [dateFilter]=\"datepicker._dateFilter\" [headerComponent]=\"datepicker.calendarHeaderComponent\" [selected]=\"datepicker._selected\" [dateClass]=\"datepicker.dateClass\" [@fadeInCalendar]=\"'enter'\" (selectedChange)=\"datepicker.select($event)\" (yearSelected)=\"datepicker._selectYear($event)\" (monthSelected)=\"datepicker._selectMonth($event)\" (_userSelection)=\"datepicker.close()\"></mat-calendar>",
                  styles: [".mat-datepicker-content{display:block;border-radius:4px}.mat-datepicker-content .mat-calendar{width:296px;height:354px}.mat-datepicker-content-touch{display:block;max-height:80vh;overflow:auto;margin:-24px}.mat-datepicker-content-touch .mat-calendar{min-width:250px;min-height:312px;max-width:750px;max-height:788px}@media all and (orientation:landscape){.mat-datepicker-content-touch .mat-calendar{width:64vh;height:80vh}}@media all and (orientation:portrait){.mat-datepicker-content-touch .mat-calendar{width:80vw;height:100vw}}"],
                  host: {
                      'class': 'mat-datepicker-content',
                      '[@transformPanel]': '"enter"',
                      '[class.mat-datepicker-content-touch]': 'datepicker.touchUi',
                  },
                  animations: [
                      matDatepickerAnimations.transformPanel,
                      matDatepickerAnimations.fadeInCalendar,
                  ],
                  exportAs: 'matDatepickerContent',
                  encapsulation: ViewEncapsulation.None,
                  changeDetection: ChangeDetectionStrategy.OnPush,
                  inputs: ['color'],
              },] },
  ];
  /** @nocollapse */
  MatDatepickerContent.ctorParameters = () => [
      { type: ElementRef }
  ];
  MatDatepickerContent.propDecorators = {
      _calendar: [{ type: ViewChild, args: [MatCalendar, { static: false },] }]
  };
  if (false) {
      /**
       * Reference to the internal calendar component.
       * @type {?}
       */
      MatDatepickerContent.prototype._calendar;
      /**
       * Reference to the datepicker that created the overlay.
       * @type {?}
       */
      MatDatepickerContent.prototype.datepicker;
      /**
       * Whether the datepicker is above or below the input.
       * @type {?}
       */
      MatDatepickerContent.prototype._isAbove;
  }
  // TODO(mmalerba): We use a component instead of a directive here so the user can use implicit
  // template reference variables (e.g. #d vs #d="matDatepicker"). We can change this to a directive
  // if angular adds support for `exportAs: '$implicit'` on directives.
  /**
   * Component responsible for managing the datepicker popup/dialog.
   * @template D
   */
  export class MatDatepicker {
      /**
       * @param {?} _dialog
       * @param {?} _overlay
       * @param {?} _ngZone
       * @param {?} _viewContainerRef
       * @param {?} scrollStrategy
       * @param {?} _dateAdapter
       * @param {?} _dir
       * @param {?} _document
       */
      constructor(_dialog, _overlay, _ngZone, _viewContainerRef, scrollStrategy, _dateAdapter, _dir, _document) {
          this._dialog = _dialog;
          this._overlay = _overlay;
          this._ngZone = _ngZone;
          this._viewContainerRef = _viewContainerRef;
          this._dateAdapter = _dateAdapter;
          this._dir = _dir;
          this._document = _document;
          /**
           * The view that the calendar should start in.
           */
          this.startView = 'month';
          this._touchUi = false;
          /**
           * 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 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++}`;
          this._validSelected = null;
          /**
           * The element that was focused before the datepicker was opened.
           */
          this._focusedElementBeforeOpen = null;
          /**
           * Subscription to value changes in the associated input element.
           */
          this._inputSubscription = Subscription.EMPTY;
          /**
           * Emits when the datepicker is disabled.
           */
          this._disabledChange = new Subject();
          /**
           * Emits new selected date when selected date changes.
           */
          this._selectedChanged = new Subject();
          if (!this._dateAdapter) {
              throw createMissingDateImplError('DateAdapter');
          }
          this._scrollStrategy = scrollStrategy;
      }
      /**
       * The date to open the calendar to initially.
       * @return {?}
       */
      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.value : null);
      }
      /**
       * @param {?} value
       * @return {?}
       */
      set startAt(value) {
          this._startAt = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
      }
      /**
       * Color palette to use on the datepicker's calendar.
       * @return {?}
       */
      get color() {
          return this._color ||
              (this._datepickerInput ? this._datepickerInput._getThemePalette() : undefined);
      }
      /**
       * @param {?} value
       * @return {?}
       */
      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 popup and elements have more padding to allow for bigger touch targets.
       * @return {?}
       */
      get touchUi() { return this._touchUi; }
      /**
       * @param {?} value
       * @return {?}
       */
      set touchUi(value) {
          this._touchUi = coerceBooleanProperty(value);
      }
      /**
       * Whether the datepicker pop-up should be disabled.
       * @return {?}
       */
      get disabled() {
          return this._disabled === undefined && this._datepickerInput ?
              this._datepickerInput.disabled : !!this._disabled;
      }
      /**
       * @param {?} value
       * @return {?}
       */
      set disabled(value) {
          /** @type {?} */
          const newValue = coerceBooleanProperty(value);
          if (newValue !== this._disabled) {
              this._disabled = newValue;
              this._disabledChange.next(newValue);
          }
      }
      /**
       * Whether the calendar is open.
       * @return {?}
       */
      get opened() { return this._opened; }
      /**
       * @param {?} value
       * @return {?}
       */
      set opened(value) { value ? this.open() : this.close(); }
      /**
       * The currently selected date.
       * @return {?}
       */
      get _selected() { return this._validSelected; }
      /**
       * @param {?} value
       * @return {?}
       */
      set _selected(value) { this._validSelected = value; }
      /**
       * The minimum selectable date.
       * @return {?}
       */
      get _minDate() {
          return this._datepickerInput && this._datepickerInput.min;
      }
      /**
       * The maximum selectable date.
       * @return {?}
       */
      get _maxDate() {
          return this._datepickerInput && this._datepickerInput.max;
      }
      /**
       * @return {?}
       */
      get _dateFilter() {
          return this._datepickerInput && this._datepickerInput._dateFilter;
      }
      /**
       * @return {?}
       */
      ngOnDestroy() {
          this.close();
          this._inputSubscription.unsubscribe();
          this._disabledChange.complete();
          if (this._popupRef) {
              this._popupRef.dispose();
              this._popupComponentRef = null;
          }
      }
      /**
       * Selects the given date
       * @param {?} date
       * @return {?}
       */
      select(date) {
          /** @type {?} */
          let oldValue = this._selected;
          this._selected = date;
          if (!this._dateAdapter.sameDate(oldValue, this._selected)) {
              this._selectedChanged.next(date);
          }
      }
      /**
       * Emits the selected year in multiyear view
       * @param {?} normalizedYear
       * @return {?}
       */
      _selectYear(normalizedYear) {
          this.yearSelected.emit(normalizedYear);
      }
      /**
       * Emits selected month in year view
       * @param {?} normalizedMonth
       * @return {?}
       */
      _selectMonth(normalizedMonth) {
          this.monthSelected.emit(normalizedMonth);
      }
      /**
       * Register an input with this datepicker.
       * @param {?} input The datepicker input to register with this datepicker.
       * @return {?}
       */
      _registerInput(input) {
          if (this._datepickerInput) {
              throw Error('A MatDatepicker can only be associated with a single input.');
          }
          this._datepickerInput = input;
          this._inputSubscription =
              this._datepickerInput._valueChange.subscribe((/**
               * @param {?} value
               * @return {?}
               */
              (value) => this._selected = value));
      }
      /**
       * Open the calendar.
       * @return {?}
       */
      open() {
          if (this._opened || this.disabled) {
              return;
          }
          if (!this._datepickerInput) {
              throw Error('Attempted to open an MatDatepicker with no associated input.');
          }
          if (this._document) {
              this._focusedElementBeforeOpen = this._document.activeElement;
          }
          this.touchUi ? this._openAsDialog() : this._openAsPopup();
          this._opened = true;
          this.openedStream.emit();
      }
      /**
       * Close the calendar.
       * @return {?}
       */
      close() {
          if (!this._opened) {
              return;
          }
          if (this._popupRef && this._popupRef.hasAttached()) {
              this._popupRef.detach();
          }
          if (this._dialogRef) {
              this._dialogRef.close();
              this._dialogRef = null;
          }
          if (this._calendarPortal && this._calendarPortal.isAttached) {
              this._calendarPortal.detach();
          }
          /** @type {?} */
          const completeClose = (/**
           * @return {?}
           */
          () => {
              // 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._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();
          }
      }
      /**
       * Open the calendar as a dialog.
       * @private
       * @return {?}
       */
      _openAsDialog() {
          // Usually this would be handled by `open` which ensures that we can only have one overlay
          // open at a time, however since we reset the variables in async handlers some overlays
          // may slip through if the user opens and closes multiple times in quick succession (e.g.
          // by holding down the enter key).
          if (this._dialogRef) {
              this._dialogRef.close();
          }
          this._dialogRef = this._dialog.open(MatDatepickerContent, {
              direction: this._dir ? this._dir.value : 'ltr',
              viewContainerRef: this._viewContainerRef,
              panelClass: 'mat-datepicker-dialog',
          });
          this._dialogRef.afterClosed().subscribe((/**
           * @return {?}
           */
          () => this.close()));
          this._dialogRef.componentInstance.datepicker = this;
          this._setColor();
      }
      /**
       * Open the calendar as a popup.
       * @private
       * @return {?}
       */
      _openAsPopup() {
          if (!this._calendarPortal) {
              this._calendarPortal = new ComponentPortal(MatDatepickerContent, this._viewContainerRef);
          }
          if (!this._popupRef) {
              this._createPopup();
          }
          if (!this._popupRef.hasAttached()) {
              this._popupComponentRef = this._popupRef.attach(this._calendarPortal);
              this._popupComponentRef.instance.datepicker = this;
              this._setColor();
              // Update the position once the calendar has rendered.
              this._ngZone.onStable.asObservable().pipe(take(1)).subscribe((/**
               * @return {?}
               */
              () => {
                  this._popupRef.updatePosition();
              }));
          }
      }
      /**
       * Create the popup.
       * @private
       * @return {?}
       */
      _createPopup() {
          /** @type {?} */
          const overlayConfig = new OverlayConfig({
              positionStrategy: this._createPopupPositionStrategy(),
              hasBackdrop: true,
              backdropClass: 'mat-overlay-transparent-backdrop',
              direction: this._dir,
              scrollStrategy: this._scrollStrategy(),
              panelClass: 'mat-datepicker-popup',
          });
          this._popupRef = this._overlay.create(overlayConfig);
          this._popupRef.overlayElement.setAttribute('role', 'dialog');
          merge(this._popupRef.backdropClick(), this._popupRef.detachments(), this._popupRef.keydownEvents().pipe(filter((/**
           * @param {?} event
           * @return {?}
           */
          event => {
              // Closing on alt + up is only valid when there's an input associated with the datepicker.
              return event.keyCode === ESCAPE ||
                  (this._datepickerInput && event.altKey && event.keyCode === UP_ARROW);
          })))).subscribe((/**
           * @param {?} event
           * @return {?}
           */
          event => {
              if (event) {
                  event.preventDefault();
              }
              this.close();
          }));
      }
      /**
       * Create the popup PositionStrategy.
       * @private
       * @return {?}
       */
      _createPopupPositionStrategy() {
          return this._overlay.position()
              .flexibleConnectedTo(this._datepickerInput.getConnectedOverlayOrigin())
              .withTransformOriginOn('.mat-datepicker-content')
              .withFlexibleDimensions(false)
              .withViewportMargin(8)
              .withLockedPosition()
              .withPositions([
              {
                  originX: 'start',
                  originY: 'bottom',
                  overlayX: 'start',
                  overlayY: 'top'
              },
              {
                  originX: 'start',
                  originY: 'top',
                  overlayX: 'start',
                  overlayY: 'bottom'
              },
              {
                  originX: 'end',
                  originY: 'bottom',
                  overlayX: 'end',
                  overlayY: 'top'
              },
              {
                  originX: 'end',
                  originY: 'top',
                  overlayX: 'end',
                  overlayY: 'bottom'
              }
          ]);
      }
      /**
       * @private
       * @param {?} obj The object to check.
       * @return {?} The given object if it is both a date instance and valid, otherwise null.
       */
      _getValidDateOrNull(obj) {
          return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
      }
      /**
       * Passes the current theme color along to the calendar overlay.
       * @private
       * @return {?}
       */
      _setColor() {
          /** @type {?} */
          const color = this.color;
          if (this._popupComponentRef) {
              this._popupComponentRef.instance.color = color;
          }
          if (this._dialogRef) {
              this._dialogRef.componentInstance.color = color;
          }
      }
  }
  MatDatepicker.decorators = [
      { type: Component, args: [{selector: 'mat-datepicker',
                  template: '',
                  exportAs: 'matDatepicker',
                  changeDetection: ChangeDetectionStrategy.OnPush,
                  encapsulation: ViewEncapsulation.None,
              },] },
  ];
  /** @nocollapse */
  MatDatepicker.ctorParameters = () => [
      { type: MatDialog },
      { type: Overlay },
      { type: NgZone },
      { type: ViewContainerRef },
      { type: undefined, decorators: [{ type: Inject, args: [MAT_DATEPICKER_SCROLL_STRATEGY,] }] },
      { type: DateAdapter, decorators: [{ type: Optional }] },
      { type: Directionality, decorators: [{ type: Optional }] },
      { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] }
  ];
  MatDatepicker.propDecorators = {
      calendarHeaderComponent: [{ type: Input }],
      startAt: [{ type: Input }],
      startView: [{ type: Input }],
      color: [{ type: Input }],
      touchUi: [{ type: Input }],
      disabled: [{ type: Input }],
      yearSelected: [{ type: Output }],
      monthSelected: [{ type: Output }],
      panelClass: [{ type: Input }],
      dateClass: [{ type: Input }],
      openedStream: [{ type: Output, args: ['opened',] }],
      closedStream: [{ type: Output, args: ['closed',] }],
      opened: [{ type: Input }]
  };
  if (false) {
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._scrollStrategy;
      /**
       * An input indicating the type of the custom header component for the calendar, if set.
       * @type {?}
       */
      MatDatepicker.prototype.calendarHeaderComponent;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._startAt;
      /**
       * The view that the calendar should start in.
       * @type {?}
       */
      MatDatepicker.prototype.startView;
      /** @type {?} */
      MatDatepicker.prototype._color;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._touchUi;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._disabled;
      /**
       * Emits selected year in multiyear view.
       * This doesn't imply a change on the selected date.
       * @type {?}
       */
      MatDatepicker.prototype.yearSelected;
      /**
       * Emits selected month in year view.
       * This doesn't imply a change on the selected date.
       * @type {?}
       */
      MatDatepicker.prototype.monthSelected;
      /**
       * Classes to be passed to the date picker panel. Supports the same syntax as `ngClass`.
       * @type {?}
       */
      MatDatepicker.prototype.panelClass;
      /**
       * Function that can be used to add custom CSS classes to dates.
       * @type {?}
       */
      MatDatepicker.prototype.dateClass;
      /**
       * Emits when the datepicker has been opened.
       * @type {?}
       */
      MatDatepicker.prototype.openedStream;
      /**
       * Emits when the datepicker has been closed.
       * @type {?}
       */
      MatDatepicker.prototype.closedStream;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._opened;
      /**
       * The id for the datepicker calendar.
       * @type {?}
       */
      MatDatepicker.prototype.id;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._validSelected;
      /**
       * A reference to the overlay when the calendar is opened as a popup.
       * @type {?}
       */
      MatDatepicker.prototype._popupRef;
      /**
       * A reference to the dialog when the calendar is opened as a dialog.
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._dialogRef;
      /**
       * A portal containing the calendar for this datepicker.
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._calendarPortal;
      /**
       * Reference to the component instantiated in popup mode.
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._popupComponentRef;
      /**
       * The element that was focused before the datepicker was opened.
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._focusedElementBeforeOpen;
      /**
       * Subscription to value changes in the associated input element.
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._inputSubscription;
      /**
       * The input element this datepicker is associated with.
       * @type {?}
       */
      MatDatepicker.prototype._datepickerInput;
      /**
       * Emits when the datepicker is disabled.
       * @type {?}
       */
      MatDatepicker.prototype._disabledChange;
      /**
       * Emits new selected date when selected date changes.
       * @type {?}
       */
      MatDatepicker.prototype._selectedChanged;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._dialog;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._overlay;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._ngZone;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._viewContainerRef;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._dateAdapter;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._dir;
      /**
       * @type {?}
       * @private
       */
      MatDatepicker.prototype._document;
  }
  //# sourceMappingURL=datepicker.js.map