text: /**
   * @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 { animate, state, style, transition, trigger } from '@angular/animations';
  import { Component, ElementRef, EventEmitter, Inject, Optional, ChangeDetectorRef, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Injectable, InjectionToken, Injector, SkipSelf, TemplateRef, Directive, Input, NgModule } from '@angular/core';
  import { DOCUMENT, Location, CommonModule } from '@angular/common';
  import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, PortalInjector, TemplatePortal, PortalModule } from '@angular/cdk/portal';
  import { FocusTrapFactory } from '@angular/cdk/a11y';
  import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
  import { Subject, defer, of } from 'rxjs';
  import { filter, take, startWith } from 'rxjs/operators';
  import { Directionality } from '@angular/cdk/bidi';
  import { Overlay, OverlayConfig, OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
  import { MatCommonModule } from '@angular/material/core';
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * Configuration for opening a modal dialog with the MatDialog service.
   * @template D
   */
  class MatDialogConfig {
      constructor() {
          /**
           * The ARIA role of the dialog element.
           */
          this.role = 'dialog';
          /**
           * Custom class for the overlay pane.
           */
          this.panelClass = '';
          /**
           * Whether the dialog has a backdrop.
           */
          this.hasBackdrop = true;
          /**
           * Custom class for the backdrop,
           */
          this.backdropClass = '';
          /**
           * Whether the user can use escape or clicking on the backdrop to close the modal.
           */
          this.disableClose = false;
          /**
           * Width of the dialog.
           */
          this.width = '';
          /**
           * Height of the dialog.
           */
          this.height = '';
          /**
           * Max-width of the dialog. If a number is provided, pixel units are assumed. Defaults to 80vw
           */
          this.maxWidth = '80vw';
          /**
           * Data being injected into the child component.
           */
          this.data = null;
          /**
           * ID of the element that describes the dialog.
           */
          this.ariaDescribedBy = null;
          /**
           * ID of the element that labels the dialog.
           */
          this.ariaLabelledBy = null;
          /**
           * Aria label to assign to the dialog element
           */
          this.ariaLabel = null;
          /**
           * Whether the dialog should focus the first focusable element on open.
           */
          this.autoFocus = true;
          /**
           * Whether the dialog should restore focus to the
           * previously-focused element, after it's closed.
           */
          this.restoreFocus = true;
          /**
           * Whether the dialog should close when the user goes backwards/forwards in history.
           * Note that this usually doesn't include clicking on links (unless the user is using
           * the `HashLocationStrategy`).
           */
          this.closeOnNavigation = true;
          // TODO(jelbourn): add configuration for lifecycle hooks, ARIA labelling.
      }
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /** @type {?} */
  const animationBody = [
      // Note: The `enter` animation transitions to `transform: none`, because for some reason
      // specifying the transform explicitly, causes IE both to blur the dialog content and
      // decimate the animation performance. Leaving it as `none` solves both issues.
      state('void, exit', style({ opacity: 0, transform: 'scale(0.7)' })),
      state('enter', style({ transform: 'none' })),
      transition('* => enter', animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({ transform: 'none', opacity: 1 }))),
      transition('* => void, * => exit', animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ opacity: 0 }))),
  ];
  /**
   * Animations used by MatDialog.
   * \@docs-private
   * @type {?}
   */
  const matDialogAnimations = {
      /**
       * Animation that is applied on the dialog container by defalt.
       */
      dialogContainer: trigger('dialogContainer', animationBody),
      /**
       * @deprecated \@breaking-change 8.0.0 Use `matDialogAnimations.dialogContainer` instead.
       */
      slideDialog: trigger('slideDialog', animationBody)
  };
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * Throws an exception for the case when a ComponentPortal is
   * attached to a DomPortalOutlet without an origin.
   * \@docs-private
   * @return {?}
   */
  function throwMatDialogContentAlreadyAttachedError() {
      throw Error('Attempting to attach dialog content after content is already attached');
  }
  /**
   * Internal component that wraps user-provided dialog content.
   * Animation is based on https://material.io/guidelines/motion/choreography.html.
   * \@docs-private
   */
  class MatDialogContainer extends BasePortalOutlet {
      /**
       * @param {?} _elementRef
       * @param {?} _focusTrapFactory
       * @param {?} _changeDetectorRef
       * @param {?} _document
       * @param {?} _config
       */
      constructor(_elementRef, _focusTrapFactory, _changeDetectorRef, _document, _config) {
          super();
          this._elementRef = _elementRef;
          this._focusTrapFactory = _focusTrapFactory;
          this._changeDetectorRef = _changeDetectorRef;
          this._document = _document;
          this._config = _config;
          /**
           * Element that was focused before the dialog was opened. Save this to restore upon close.
           */
          this._elementFocusedBeforeDialogWasOpened = null;
          /**
           * State of the dialog animation.
           */
          this._state = 'enter';
          /**
           * Emits when an animation state changes.
           */
          this._animationStateChanged = new EventEmitter();
          this._ariaLabelledBy = _config.ariaLabelledBy || null;
      }
      /**
       * Attach a ComponentPortal as content to this dialog container.
       * @template T
       * @param {?} portal Portal to be attached as the dialog content.
       * @return {?}
       */
      attachComponentPortal(portal) {
          if (this._portalOutlet.hasAttached()) {
              throwMatDialogContentAlreadyAttachedError();
          }
          this._savePreviouslyFocusedElement();
          return this._portalOutlet.attachComponentPortal(portal);
      }
      /**
       * Attach a TemplatePortal as content to this dialog container.
       * @template C
       * @param {?} portal Portal to be attached as the dialog content.
       * @return {?}
       */
      attachTemplatePortal(portal) {
          if (this._portalOutlet.hasAttached()) {
              throwMatDialogContentAlreadyAttachedError();
          }
          this._savePreviouslyFocusedElement();
          return this._portalOutlet.attachTemplatePortal(portal);
      }
      /**
       * Moves the focus inside the focus trap.
       * @private
       * @return {?}
       */
      _trapFocus() {
          /** @type {?} */
          const element = this._elementRef.nativeElement;
          if (!this._focusTrap) {
              this._focusTrap = this._focusTrapFactory.create(element);
          }
          // If we were to attempt to focus immediately, then the content of the dialog would not yet be
          // ready in instances where change detection has to run first. To deal with this, we simply
          // wait for the microtask queue to be empty.
          if (this._config.autoFocus) {
              this._focusTrap.focusInitialElementWhenReady();
          }
          else {
              /** @type {?} */
              const activeElement = this._document.activeElement;
              // Otherwise ensure that focus is on the dialog container. It's possible that a different
              // component tried to move focus while the open animation was running. See:
              // https://github.com/angular/components/issues/16215. Note that we only want to do this
              // if the focus isn't inside the dialog already, because it's possible that the consumer
              // turned off `autoFocus` in order to move focus themselves.
              if (activeElement !== element && !element.contains(activeElement)) {
                  element.focus();
              }
          }
      }
      /**
       * Restores focus to the element that was focused before the dialog opened.
       * @private
       * @return {?}
       */
      _restoreFocus() {
          /** @type {?} */
          const toFocus = this._elementFocusedBeforeDialogWasOpened;
          // We need the extra check, because IE can set the `activeElement` to null in some cases.
          if (this._config.restoreFocus && toFocus && typeof toFocus.focus === 'function') {
              toFocus.focus();
          }
          if (this._focusTrap) {
              this._focusTrap.destroy();
          }
      }
      /**
       * Saves a reference to the element that was focused before the dialog was opened.
       * @private
       * @return {?}
       */
      _savePreviouslyFocusedElement() {
          if (this._document) {
              this._elementFocusedBeforeDialogWasOpened = (/** @type {?} */ (this._document.activeElement));
              // Note that there is no focus method when rendering on the server.
              if (this._elementRef.nativeElement.focus) {
                  // Move focus onto the dialog immediately in order to prevent the user from accidentally
                  // opening multiple dialogs at the same time. Needs to be async, because the element
                  // may not be focusable immediately.
                  Promise.resolve().then((/**
                   * @return {?}
                   */
                  () => this._elementRef.nativeElement.focus()));
              }
          }
      }
      /**
       * Callback, invoked whenever an animation on the host completes.
       * @param {?} event
       * @return {?}
       */
      _onAnimationDone(event) {
          if (event.toState === 'enter') {
              this._trapFocus();
          }
          else if (event.toState === 'exit') {
              this._restoreFocus();
          }
          this._animationStateChanged.emit(event);
      }
      /**
       * Callback, invoked when an animation on the host starts.
       * @param {?} event
       * @return {?}
       */
      _onAnimationStart(event) {
          this._animationStateChanged.emit(event);
      }
      /**
       * Starts the dialog exit animation.
       * @return {?}
       */
      _startExitAnimation() {
          this._state = 'exit';
          // Mark the container for check so it can react if the
          // view container is using OnPush change detection.
          this._changeDetectorRef.markForCheck();
      }
  }
  MatDialogContainer.decorators = [
      { type: Component, args: [{selector: 'mat-dialog-container',
                  template: "<ng-template cdkPortalOutlet></ng-template>",
                  styles: [".mat-dialog-container{display:block;padding:24px;border-radius:4px;box-sizing:border-box;overflow:auto;outline:0;width:100%;height:100%;min-height:inherit;max-height:inherit}@media (-ms-high-contrast:active){.mat-dialog-container{outline:solid 1px}}.mat-dialog-content{display:block;margin:0 -24px;padding:0 24px;max-height:65vh;overflow:auto;-webkit-overflow-scrolling:touch}.mat-dialog-title{margin:0 0 20px;display:block}.mat-dialog-actions{padding:8px 0;display:flex;flex-wrap:wrap;min-height:52px;align-items:center;margin-bottom:-24px}.mat-dialog-actions[align=end]{justify-content:flex-end}.mat-dialog-actions[align=center]{justify-content:center}.mat-dialog-actions .mat-button-base+.mat-button-base{margin-left:8px}[dir=rtl] .mat-dialog-actions .mat-button-base+.mat-button-base{margin-left:0;margin-right:8px}"],
                  encapsulation: ViewEncapsulation.None,
                  // Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.
                  // tslint:disable-next-line:validate-decorators
                  changeDetection: ChangeDetectionStrategy.Default,
                  animations: [matDialogAnimations.dialogContainer],
                  host: {
                      'class': 'mat-dialog-container',
                      'tabindex': '-1',
                      'aria-modal': 'true',
                      '[attr.id]': '_id',
                      '[attr.role]': '_config.role',
                      '[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',
                      '[attr.aria-label]': '_config.ariaLabel',
                      '[attr.aria-describedby]': '_config.ariaDescribedBy || null',
                      '[@dialogContainer]': '_state',
                      '(@dialogContainer.start)': '_onAnimationStart($event)',
                      '(@dialogContainer.done)': '_onAnimationDone($event)',
                  },
              },] },
  ];
  /** @nocollapse */
  MatDialogContainer.ctorParameters = () => [
      { type: ElementRef },
      { type: FocusTrapFactory },
      { type: ChangeDetectorRef },
      { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] },
      { type: MatDialogConfig }
  ];
  MatDialogContainer.propDecorators = {
      _portalOutlet: [{ type: ViewChild, args: [CdkPortalOutlet, { static: true },] }]
  };
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  // TODO(jelbourn): resizing
  // Counter for unique dialog ids.
  /** @type {?} */
  let uniqueId = 0;
  /**
   * Reference to a dialog opened via the MatDialog service.
   * @template T, R
   */
  class MatDialogRef {
      /**
       * @param {?} _overlayRef
       * @param {?} _containerInstance
       * @param {?=} _location
       * @param {?=} id
       */
      constructor(_overlayRef, _containerInstance, 
      // @breaking-change 8.0.0 `_location` parameter to be removed.
      _location, id = `mat-dialog-${uniqueId++}`) {
          this._overlayRef = _overlayRef;
          this._containerInstance = _containerInstance;
          this.id = id;
          /**
           * Whether the user is allowed to close the dialog.
           */
          this.disableClose = this._containerInstance._config.disableClose;
          /**
           * Subject for notifying the user that the dialog has finished opening.
           */
          this._afterOpened = new Subject();
          /**
           * Subject for notifying the user that the dialog has finished closing.
           */
          this._afterClosed = new Subject();
          /**
           * Subject for notifying the user that the dialog has started closing.
           */
          this._beforeClosed = new Subject();
          // Pass the id along to the container.
          _containerInstance._id = id;
          // Emit when opening animation completes
          _containerInstance._animationStateChanged.pipe(filter((/**
           * @param {?} event
           * @return {?}
           */
          event => event.phaseName === 'done' && event.toState === 'enter')), take(1))
              .subscribe((/**
           * @return {?}
           */
          () => {
              this._afterOpened.next();
              this._afterOpened.complete();
          }));
          // Dispose overlay when closing animation is complete
          _containerInstance._animationStateChanged.pipe(filter((/**
           * @param {?} event
           * @return {?}
           */
          event => event.phaseName === 'done' && event.toState === 'exit')), take(1)).subscribe((/**
           * @return {?}
           */
          () => {
              clearTimeout(this._closeFallbackTimeout);
              this._overlayRef.dispose();
          }));
          _overlayRef.detachments().subscribe((/**
           * @return {?}
           */
          () => {
              this._beforeClosed.next(this._result);
              this._beforeClosed.complete();
              this._afterClosed.next(this._result);
              this._afterClosed.complete();
              this.componentInstance = (/** @type {?} */ (null));
              this._overlayRef.dispose();
          }));
          _overlayRef.keydownEvents()
              .pipe(filter((/**
           * @param {?} event
           * @return {?}
           */
          event => {
              return event.keyCode === ESCAPE && !this.disableClose && !hasModifierKey(event);
          })))
              .subscribe((/**
           * @param {?} event
           * @return {?}
           */
          event => {
              event.preventDefault();
              this.close();
          }));
      }
      /**
       * Close the dialog.
       * @param {?=} dialogResult Optional result to return to the dialog opener.
       * @return {?}
       */
      close(dialogResult) {
          this._result = dialogResult;
          // Transition the backdrop in parallel to the dialog.
          this._containerInstance._animationStateChanged.pipe(filter((/**
           * @param {?} event
           * @return {?}
           */
          event => event.phaseName === 'start')), take(1))
              .subscribe((/**
           * @param {?} event
           * @return {?}
           */
          event => {
              this._beforeClosed.next(dialogResult);
              this._beforeClosed.complete();
              this._overlayRef.detachBackdrop();
              // The logic that disposes of the overlay depends on the exit animation completing, however
              // it isn't guaranteed if the parent view is destroyed while it's running. Add a fallback
              // timeout which will clean everything up if the animation hasn't fired within the specified
              // amount of time plus 100ms. We don't need to run this outside the NgZone, because for the
              // vast majority of cases the timeout will have been cleared before it has the chance to fire.
              this._closeFallbackTimeout = setTimeout((/**
               * @return {?}
               */
              () => {
                  this._overlayRef.dispose();
              }), event.totalTime + 100);
          }));
          this._containerInstance._startExitAnimation();
      }
      /**
       * Gets an observable that is notified when the dialog is finished opening.
       * @return {?}
       */
      afterOpened() {
          return this._afterOpened.asObservable();
      }
      /**
       * Gets an observable that is notified when the dialog is finished closing.
       * @return {?}
       */
      afterClosed() {
          return this._afterClosed.asObservable();
      }
      /**
       * Gets an observable that is notified when the dialog has started closing.
       * @return {?}
       */
      beforeClosed() {
          return this._beforeClosed.asObservable();
      }
      /**
       * Gets an observable that emits when the overlay's backdrop has been clicked.
       * @return {?}
       */
      backdropClick() {
          return this._overlayRef.backdropClick();
      }
      /**
       * Gets an observable that emits when keydown events are targeted on the overlay.
       * @return {?}
       */
      keydownEvents() {
          return this._overlayRef.keydownEvents();
      }
      /**
       * Updates the dialog's position.
       * @template THIS
       * @this {THIS}
       * @param {?=} position New dialog position.
       * @return {THIS}
       */
      updatePosition(position) {
          /** @type {?} */
          let strategy = (/** @type {?} */ (this))._getPositionStrategy();
          if (position && (position.left || position.right)) {
              position.left ? strategy.left(position.left) : strategy.right(position.right);
          }
          else {
              strategy.centerHorizontally();
          }
          if (position && (position.top || position.bottom)) {
              position.top ? strategy.top(position.top) : strategy.bottom(position.bottom);
          }
          else {
              strategy.centerVertically();
          }
          (/** @type {?} */ (this))._overlayRef.updatePosition();
          return (/** @type {?} */ (this));
      }
      /**
       * Updates the dialog's width and height.
       * @template THIS
       * @this {THIS}
       * @param {?=} width New width of the dialog.
       * @param {?=} height New height of the dialog.
       * @return {THIS}
       */
      updateSize(width = '', height = '') {
          (/** @type {?} */ (this))._getPositionStrategy().width(width).height(height);
          (/** @type {?} */ (this))._overlayRef.updatePosition();
          return (/** @type {?} */ (this));
      }
      /**
       * Add a CSS class or an array of classes to the overlay pane.
       * @template THIS
       * @this {THIS}
       * @param {?} classes
       * @return {THIS}
       */
      addPanelClass(classes) {
          (/** @type {?} */ (this))._overlayRef.addPanelClass(classes);
          return (/** @type {?} */ (this));
      }
      /**
       * Remove a CSS class or an array of classes from the overlay pane.
       * @template THIS
       * @this {THIS}
       * @param {?} classes
       * @return {THIS}
       */
      removePanelClass(classes) {
          (/** @type {?} */ (this))._overlayRef.removePanelClass(classes);
          return (/** @type {?} */ (this));
      }
      /**
       * Gets an observable that is notified when the dialog is finished opening.
       * @deprecated Use `afterOpened` instead.
       * \@breaking-change 8.0.0
       * @return {?}
       */
      afterOpen() {
          return this.afterOpened();
      }
      /**
       * Gets an observable that is notified when the dialog has started closing.
       * @deprecated Use `beforeClosed` instead.
       * \@breaking-change 8.0.0
       * @return {?}
       */
      beforeClose() {
          return this.beforeClosed();
      }
      /**
       * Fetches the position strategy object from the overlay ref.
       * @private
       * @return {?}
       */
      _getPositionStrategy() {
          return (/** @type {?} */ (this._overlayRef.getConfig().positionStrategy));
      }
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * Injection token that can be used to access the data that was passed in to a dialog.
   * @type {?}
   */
  const MAT_DIALOG_DATA = new InjectionToken('MatDialogData');
  /**
   * Injection token that can be used to specify default dialog options.
   * @type {?}
   */
  const MAT_DIALOG_DEFAULT_OPTIONS = new InjectionToken('mat-dialog-default-options');
  /**
   * Injection token that determines the scroll handling while the dialog is open.
   * @type {?}
   */
  const MAT_DIALOG_SCROLL_STRATEGY = new InjectionToken('mat-dialog-scroll-strategy');
  /**
   * \@docs-private
   * @param {?} overlay
   * @return {?}
   */
  function MAT_DIALOG_SCROLL_STRATEGY_FACTORY(overlay) {
      return (/**
       * @return {?}
       */
      () => overlay.scrollStrategies.block());
  }
  /**
   * \@docs-private
   * @param {?} overlay
   * @return {?}
   */
  function MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
      return (/**
       * @return {?}
       */
      () => overlay.scrollStrategies.block());
  }
  /**
   * \@docs-private
   * @type {?}
   */
  const MAT_DIALOG_SCROLL_STRATEGY_PROVIDER = {
      provide: MAT_DIALOG_SCROLL_STRATEGY,
      deps: [Overlay],
      useFactory: MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY,
  };
  /**
   * Service to open Material Design modal dialogs.
   */
  class MatDialog {
      /**
       * @param {?} _overlay
       * @param {?} _injector
       * @param {?} _location
       * @param {?} _defaultOptions
       * @param {?} scrollStrategy
       * @param {?} _parentDialog
       * @param {?} _overlayContainer
       */
      constructor(_overlay, _injector, _location, _defaultOptions, scrollStrategy, _parentDialog, _overlayContainer) {
          this._overlay = _overlay;
          this._injector = _injector;
          this._location = _location;
          this._defaultOptions = _defaultOptions;
          this._parentDialog = _parentDialog;
          this._overlayContainer = _overlayContainer;
          this._openDialogsAtThisLevel = [];
          this._afterAllClosedAtThisLevel = new Subject();
          this._afterOpenedAtThisLevel = new Subject();
          this._ariaHiddenElements = new Map();
          // TODO (jelbourn): tighten the typing right-hand side of this expression.
          /**
           * Stream that emits when all open dialog have finished closing.
           * Will emit on subscribe if there are no open dialogs to begin with.
           */
          this.afterAllClosed = (/** @type {?} */ (defer((/**
           * @return {?}
           */
          () => this.openDialogs.length ?
              this._afterAllClosed :
              this._afterAllClosed.pipe(startWith(undefined))))));
          this._scrollStrategy = scrollStrategy;
      }
      /**
       * Keeps track of the currently-open dialogs.
       * @return {?}
       */
      get openDialogs() {
          return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel;
      }
      /**
       * Stream that emits when a dialog has been opened.
       * @return {?}
       */
      get afterOpened() {
          return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel;
      }
      /**
       * Stream that emits when a dialog has been opened.
       * @deprecated Use `afterOpened` instead.
       * \@breaking-change 8.0.0
       * @return {?}
       */
      get afterOpen() {
          return this.afterOpened;
      }
      /**
       * @return {?}
       */
      get _afterAllClosed() {
          /** @type {?} */
          const parent = this._parentDialog;
          return parent ? parent._afterAllClosed : this._afterAllClosedAtThisLevel;
      }
      /**
       * Opens a modal dialog containing the given component.
       * @template T, D, R
       * @param {?} componentOrTemplateRef Type of the component to load into the dialog,
       *     or a TemplateRef to instantiate as the dialog content.
       * @param {?=} config Extra configuration options.
       * @return {?} Reference to the newly-opened dialog.
       */
      open(componentOrTemplateRef, config) {
          config = _applyConfigDefaults(config, this._defaultOptions || new MatDialogConfig());
          if (config.id && this.getDialogById(config.id)) {
              throw Error(`Dialog with id "${config.id}" exists already. The dialog id must be unique.`);
          }
          /** @type {?} */
          const overlayRef = this._createOverlay(config);
          /** @type {?} */
          const dialogContainer = this._attachDialogContainer(overlayRef, config);
          /** @type {?} */
          const dialogRef = this._attachDialogContent(componentOrTemplateRef, dialogContainer, overlayRef, config);
          // If this is the first dialog that we're opening, hide all the non-overlay content.
          if (!this.openDialogs.length) {
              this._hideNonDialogContentFromAssistiveTechnology();
          }
          this.openDialogs.push(dialogRef);
          dialogRef.afterClosed().subscribe((/**
           * @return {?}
           */
          () => this._removeOpenDialog(dialogRef)));
          this.afterOpened.next(dialogRef);
          return dialogRef;
      }
      /**
       * Closes all of the currently-open dialogs.
       * @return {?}
       */
      closeAll() {
          this._closeDialogs(this.openDialogs);
      }
      /**
       * Finds an open dialog by its id.
       * @param {?} id ID to use when looking up the dialog.
       * @return {?}
       */
      getDialogById(id) {
          return this.openDialogs.find((/**
           * @param {?} dialog
           * @return {?}
           */
          dialog => dialog.id === id));
      }
      /**
       * @return {?}
       */
      ngOnDestroy() {
          // Only close the dialogs at this level on destroy
          // since the parent service may still be active.
          this._closeDialogs(this._openDialogsAtThisLevel);
          this._afterAllClosedAtThisLevel.complete();
          this._afterOpenedAtThisLevel.complete();
      }
      /**
       * Creates the overlay into which the dialog will be loaded.
       * @private
       * @param {?} config The dialog configuration.
       * @return {?} A promise resolving to the OverlayRef for the created overlay.
       */
      _createOverlay(config) {
          /** @type {?} */
          const overlayConfig = this._getOverlayConfig(config);
          return this._overlay.create(overlayConfig);
      }
      /**
       * Creates an overlay config from a dialog config.
       * @private
       * @param {?} dialogConfig The dialog configuration.
       * @return {?} The overlay configuration.
       */
      _getOverlayConfig(dialogConfig) {
          /** @type {?} */
          const state$$1 = new OverlayConfig({
              positionStrategy: this._overlay.position().global(),
              scrollStrategy: dialogConfig.scrollStrategy || this._scrollStrategy(),
              panelClass: dialogConfig.panelClass,
              hasBackdrop: dialogConfig.hasBackdrop,
              direction: dialogConfig.direction,
              minWidth: dialogConfig.minWidth,
              minHeight: dialogConfig.minHeight,
              maxWidth: dialogConfig.maxWidth,
              maxHeight: dialogConfig.maxHeight,
              disposeOnNavigation: dialogConfig.closeOnNavigation
          });
          if (dialogConfig.backdropClass) {
              state$$1.backdropClass = dialogConfig.backdropClass;
          }
          return state$$1;
      }
      /**
       * Attaches an MatDialogContainer to a dialog's already-created overlay.
       * @private
       * @param {?} overlay Reference to the dialog's underlying overlay.
       * @param {?} config The dialog configuration.
       * @return {?} A promise resolving to a ComponentRef for the attached container.
       */
      _attachDialogContainer(overlay, config) {
          /** @type {?} */
          const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
          /** @type {?} */
          const injector = new PortalInjector(userInjector || this._injector, new WeakMap([
              [MatDialogConfig, config]
          ]));
          /** @type {?} */
          const containerPortal = new ComponentPortal(MatDialogContainer, config.viewContainerRef, injector);
          /** @type {?} */
          const containerRef = overlay.attach(containerPortal);
          return containerRef.instance;
      }
      /**
       * Attaches the user-provided component to the already-created MatDialogContainer.
       * @private
       * @template T, R
       * @param {?} componentOrTemplateRef The type of component being loaded into the dialog,
       *     or a TemplateRef to instantiate as the content.
       * @param {?} dialogContainer Reference to the wrapping MatDialogContainer.
       * @param {?} overlayRef Reference to the overlay in which the dialog resides.
       * @param {?} config The dialog configuration.
       * @return {?} A promise resolving to the MatDialogRef that should be returned to the user.
       */
      _attachDialogContent(componentOrTemplateRef, dialogContainer, overlayRef, config) {
          // Create a reference to the dialog we're creating in order to give the user a handle
          // to modify and close it.
          /** @type {?} */
          const dialogRef = new MatDialogRef(overlayRef, dialogContainer, this._location, config.id);
          // When the dialog backdrop is clicked, we want to close it.
          if (config.hasBackdrop) {
              overlayRef.backdropClick().subscribe((/**
               * @return {?}
               */
              () => {
                  if (!dialogRef.disableClose) {
                      dialogRef.close();
                  }
              }));
          }
          if (componentOrTemplateRef instanceof TemplateRef) {
              dialogContainer.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, (/** @type {?} */ (null)), (/** @type {?} */ ({ $implicit: config.data, dialogRef }))));
          }
          else {
              /** @type {?} */
              const injector = this._createInjector(config, dialogRef, dialogContainer);
              /** @type {?} */
              const contentRef = dialogContainer.attachComponentPortal(new ComponentPortal(componentOrTemplateRef, undefined, injector));
              dialogRef.componentInstance = contentRef.instance;
          }
          dialogRef
              .updateSize(config.width, config.height)
              .updatePosition(config.position);
          return dialogRef;
      }
      /**
       * Creates a custom injector to be used inside the dialog. This allows a component loaded inside
       * of a dialog to close itself and, optionally, to return a value.
       * @private
       * @template T
       * @param {?} config Config object that is used to construct the dialog.
       * @param {?} dialogRef Reference to the dialog.
       * @param {?} dialogContainer
       * @return {?} The custom injector that can be used inside the dialog.
       */
      _createInjector(config, dialogRef, dialogContainer) {
          /** @type {?} */
          const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
          // The MatDialogContainer is injected in the portal as the MatDialogContainer and the dialog's
          // content are created out of the same ViewContainerRef and as such, are siblings for injector
          // purposes. To allow the hierarchy that is expected, the MatDialogContainer is explicitly
          // added to the injection tokens.
          /** @type {?} */
          const injectionTokens = new WeakMap([
              [MatDialogContainer, dialogContainer],
              [MAT_DIALOG_DATA, config.data],
              [MatDialogRef, dialogRef]
          ]);
          if (config.direction &&
              (!userInjector || !userInjector.get(Directionality, null))) {
              injectionTokens.set(Directionality, {
                  value: config.direction,
                  change: of()
              });
          }
          return new PortalInjector(userInjector || this._injector, injectionTokens);
      }
      /**
       * Removes a dialog from the array of open dialogs.
       * @private
       * @param {?} dialogRef Dialog to be removed.
       * @return {?}
       */
      _removeOpenDialog(dialogRef) {
          /** @type {?} */
          const index = this.openDialogs.indexOf(dialogRef);
          if (index > -1) {
              this.openDialogs.splice(index, 1);
              // If all the dialogs were closed, remove/restore the `aria-hidden`
              // to a the siblings and emit to the `afterAllClosed` stream.
              if (!this.openDialogs.length) {
                  this._ariaHiddenElements.forEach((/**
                   * @param {?} previousValue
                   * @param {?} element
                   * @return {?}
                   */
                  (previousValue, element) => {
                      if (previousValue) {
                          element.setAttribute('aria-hidden', previousValue);
                      }
                      else {
                          element.removeAttribute('aria-hidden');
                      }
                  }));
                  this._ariaHiddenElements.clear();
                  this._afterAllClosed.next();
              }
          }
      }
      /**
       * Hides all of the content that isn't an overlay from assistive technology.
       * @private
       * @return {?}
       */
      _hideNonDialogContentFromAssistiveTechnology() {
          /** @type {?} */
          const overlayContainer = this._overlayContainer.getContainerElement();
          // Ensure that the overlay container is attached to the DOM.
          if (overlayContainer.parentElement) {
              /** @type {?} */
              const siblings = overlayContainer.parentElement.children;
              for (let i = siblings.length - 1; i > -1; i--) {
                  /** @type {?} */
                  let sibling = siblings[i];
                  if (sibling !== overlayContainer &&
                      sibling.nodeName !== 'SCRIPT' &&
                      sibling.nodeName !== 'STYLE' &&
                      !sibling.hasAttribute('aria-live')) {
                      this._ariaHiddenElements.set(sibling, sibling.getAttribute('aria-hidden'));
                      sibling.setAttribute('aria-hidden', 'true');
                  }
              }
          }
      }
      /**
       * Closes all of the dialogs in an array.
       * @private
       * @param {?} dialogs
       * @return {?}
       */
      _closeDialogs(dialogs) {
          /** @type {?} */
          let i = dialogs.length;
          while (i--) {
              // The `_openDialogs` property isn't updated after close until the rxjs subscription
              // runs on the next microtask, in addition to modifying the array as we're going
              // through it. We loop through all of them and call close without assuming that
              // they'll be removed from the list instantaneously.
              dialogs[i].close();
          }
      }
  }
  MatDialog.decorators = [
      { type: Injectable },
  ];
  /** @nocollapse */
  MatDialog.ctorParameters = () => [
      { type: Overlay },
      { type: Injector },
      { type: Location, decorators: [{ type: Optional }] },
      { type: MatDialogConfig, decorators: [{ type: Optional }, { type: Inject, args: [MAT_DIALOG_DEFAULT_OPTIONS,] }] },
      { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_SCROLL_STRATEGY,] }] },
      { type: MatDialog, decorators: [{ type: Optional }, { type: SkipSelf }] },
      { type: OverlayContainer }
  ];
  /**
   * Applies default options to the dialog config.
   * @param {?=} config Config to be modified.
   * @param {?=} defaultOptions Default options provided.
   * @return {?} The new configuration object.
   */
  function _applyConfigDefaults(config, defaultOptions) {
      return Object.assign({}, defaultOptions, config);
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  /**
   * Counter used to generate unique IDs for dialog elements.
   * @type {?}
   */
  let dialogElementUid = 0;
  /**
   * Button that will close the current dialog.
   */
  class MatDialogClose {
      /**
       * @param {?} dialogRef
       * @param {?} _elementRef
       * @param {?} _dialog
       */
      constructor(dialogRef, _elementRef, _dialog) {
          this.dialogRef = dialogRef;
          this._elementRef = _elementRef;
          this._dialog = _dialog;
      }
      /**
       * @return {?}
       */
      ngOnInit() {
          if (!this.dialogRef) {
              // When this directive is included in a dialog via TemplateRef (rather than being
              // in a Component), the DialogRef isn't available via injection because embedded
              // views cannot be given a custom injector. Instead, we look up the DialogRef by
              // ID. This must occur in `onInit`, as the ID binding for the dialog container won't
              // be resolved at constructor time.
              this.dialogRef = (/** @type {?} */ (getClosestDialog(this._elementRef, this._dialog.openDialogs)));
          }
      }
      /**
       * @param {?} changes
       * @return {?}
       */
      ngOnChanges(changes) {
          /** @type {?} */
          const proxiedChange = changes['_matDialogClose'] || changes['_matDialogCloseResult'];
          if (proxiedChange) {
              this.dialogResult = proxiedChange.currentValue;
          }
      }
  }
  MatDialogClose.decorators = [
      { type: Directive, args: [{
                  selector: '[mat-dialog-close], [matDialogClose]',
                  exportAs: 'matDialogClose',
                  host: {
                      '(click)': 'dialogRef.close(dialogResult)',
                      '[attr.aria-label]': 'ariaLabel || null',
                      'type': 'button',
                  }
              },] },
  ];
  /** @nocollapse */
  MatDialogClose.ctorParameters = () => [
      { type: MatDialogRef, decorators: [{ type: Optional }] },
      { type: ElementRef },
      { type: MatDialog }
  ];
  MatDialogClose.propDecorators = {
      ariaLabel: [{ type: Input, args: ['aria-label',] }],
      dialogResult: [{ type: Input, args: ['mat-dialog-close',] }],
      _matDialogClose: [{ type: Input, args: ['matDialogClose',] }]
  };
  /**
   * Title of a dialog element. Stays fixed to the top of the dialog when scrolling.
   */
  class MatDialogTitle {
      /**
       * @param {?} _dialogRef
       * @param {?} _elementRef
       * @param {?} _dialog
       */
      constructor(_dialogRef, _elementRef, _dialog) {
          this._dialogRef = _dialogRef;
          this._elementRef = _elementRef;
          this._dialog = _dialog;
          this.id = `mat-dialog-title-${dialogElementUid++}`;
      }
      /**
       * @return {?}
       */
      ngOnInit() {
          if (!this._dialogRef) {
              this._dialogRef = (/** @type {?} */ (getClosestDialog(this._elementRef, this._dialog.openDialogs)));
          }
          if (this._dialogRef) {
              Promise.resolve().then((/**
               * @return {?}
               */
              () => {
                  /** @type {?} */
                  const container = this._dialogRef._containerInstance;
                  if (container && !container._ariaLabelledBy) {
                      container._ariaLabelledBy = this.id;
                  }
              }));
          }
      }
  }
  MatDialogTitle.decorators = [
      { type: Directive, args: [{
                  selector: '[mat-dialog-title], [matDialogTitle]',
                  exportAs: 'matDialogTitle',
                  host: {
                      'class': 'mat-dialog-title',
                      '[id]': 'id',
                  },
              },] },
  ];
  /** @nocollapse */
  MatDialogTitle.ctorParameters = () => [
      { type: MatDialogRef, decorators: [{ type: Optional }] },
      { type: ElementRef },
      { type: MatDialog }
  ];
  MatDialogTitle.propDecorators = {
      id: [{ type: Input }]
  };
  /**
   * Scrollable content container of a dialog.
   */
  class MatDialogContent {
  }
  MatDialogContent.decorators = [
      { type: Directive, args: [{
                  selector: `[mat-dialog-content], mat-dialog-content, [matDialogContent]`,
                  host: { 'class': 'mat-dialog-content' }
              },] },
  ];
  /**
   * Container for the bottom action buttons in a dialog.
   * Stays fixed to the bottom when scrolling.
   */
  class MatDialogActions {
  }
  MatDialogActions.decorators = [
      { type: Directive, args: [{
                  selector: `[mat-dialog-actions], mat-dialog-actions, [matDialogActions]`,
                  host: { 'class': 'mat-dialog-actions' }
              },] },
  ];
  /**
   * Finds the closest MatDialogRef to an element by looking at the DOM.
   * @param {?} element Element relative to which to look for a dialog.
   * @param {?} openDialogs References to the currently-open dialogs.
   * @return {?}
   */
  function getClosestDialog(element, openDialogs) {
      /** @type {?} */
      let parent = element.nativeElement.parentElement;
      while (parent && !parent.classList.contains('mat-dialog-container')) {
          parent = parent.parentElement;
      }
      return parent ? openDialogs.find((/**
       * @param {?} dialog
       * @return {?}
       */
      dialog => dialog.id === (/** @type {?} */ (parent)).id)) : null;
  }
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  class MatDialogModule {
  }
  MatDialogModule.decorators = [
      { type: NgModule, args: [{
                  imports: [
                      CommonModule,
                      OverlayModule,
                      PortalModule,
                      MatCommonModule,
                  ],
                  exports: [
                      MatDialogContainer,
                      MatDialogClose,
                      MatDialogTitle,
                      MatDialogContent,
                      MatDialogActions,
                      MatCommonModule,
                  ],
                  declarations: [
                      MatDialogContainer,
                      MatDialogClose,
                      MatDialogTitle,
                      MatDialogActions,
                      MatDialogContent,
                  ],
                  providers: [
                      MatDialog,
                      MAT_DIALOG_SCROLL_STRATEGY_PROVIDER,
                  ],
                  entryComponents: [MatDialogContainer],
              },] },
  ];
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  /**
   * @fileoverview added by tsickle
   * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
   */
  
  export { MatDialogModule, MAT_DIALOG_SCROLL_STRATEGY_FACTORY, MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY, MAT_DIALOG_DATA, MAT_DIALOG_DEFAULT_OPTIONS, MAT_DIALOG_SCROLL_STRATEGY, MAT_DIALOG_SCROLL_STRATEGY_PROVIDER, MatDialog, throwMatDialogContentAlreadyAttachedError, MatDialogContainer, MatDialogClose, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogConfig, MatDialogRef, matDialogAnimations };
  //# sourceMappingURL=dialog.js.map
  