UNPKG

@angular-mdc/web

Version:
1,349 lines (1,341 loc) 50.6 kB
/** * @license * Copyright (c) Dominic Carretto * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/trimox/angular-mdc-web/blob/master/LICENSE */ import { Directive, ElementRef, Input, Component, ViewEncapsulation, ChangeDetectionStrategy, NgZone, ContentChild, ContentChildren, Optional, Inject, ViewChild, InjectionToken, TemplateRef, Injectable, Injector, SkipSelf, NgModule } from '@angular/core'; import { Overlay, OverlayModule } from '@angular/cdk/overlay'; import { CdkPortalOutlet, BasePortalOutlet, PortalInjector, ComponentPortal, TemplatePortal, PortalModule } from '@angular/cdk/portal'; import { __extends, __assign } from 'tslib'; import { Platform } from '@angular/cdk/platform'; import { Subject, merge, fromEvent, defer } from 'rxjs'; import { takeUntil, startWith } from 'rxjs/operators'; import { MDCComponent } from '@angular-mdc/web/base'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { MdcButton } from '@angular-mdc/web/button'; import { MdcRipple } from '@angular-mdc/web/ripple'; import { matches, closest } from '@angular-mdc/web/dom'; import { MDCDialogFoundation, util, strings } from '@material/dialog'; import { DOCUMENT } from '@angular/common'; import { FocusTrapFactory } from '@angular/cdk/a11y'; /** * @fileoverview added by tsickle * Generated from: dialog/dialog-directives.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var MdcDialogAction = /** @class */ (function () { function MdcDialogAction(elementRef) { this.elementRef = elementRef; this._action = ''; } Object.defineProperty(MdcDialogAction.prototype, "action", { get: /** * @return {?} */ function () { return this._action; }, set: /** * @param {?} action * @return {?} */ function (action) { // If the directive is set without a name (updated programatically), then this setter will // trigger with an empty string and should not overwrite the programatically set value. if (!action) { return; } this._action = action; this.elementRef.nativeElement.setAttribute('data-mdc-dialog-action', this._action); }, enumerable: true, configurable: true }); MdcDialogAction.decorators = [ { type: Directive, args: [{ selector: '[mdcDialogAction]' },] }, ]; /** @nocollapse */ MdcDialogAction.ctorParameters = function () { return [ { type: ElementRef } ]; }; MdcDialogAction.propDecorators = { action: [{ type: Input, args: ['mdcDialogAction',] }] }; return MdcDialogAction; }()); var MdcDialogScrim = /** @class */ (function () { function MdcDialogScrim(elementRef) { this.elementRef = elementRef; } MdcDialogScrim.decorators = [ { type: Directive, args: [{ selector: 'mdc-dialog-scrim', host: { 'class': 'mdc-dialog__scrim' } },] }, ]; /** @nocollapse */ MdcDialogScrim.ctorParameters = function () { return [ { type: ElementRef } ]; }; return MdcDialogScrim; }()); var MdcDialogContainer = /** @class */ (function () { function MdcDialogContainer(elementRef) { this.elementRef = elementRef; } MdcDialogContainer.decorators = [ { type: Directive, args: [{ selector: '[mdcDialogContainer], mdc-dialog-container', host: { 'class': 'mdc-dialog__container' } },] }, ]; /** @nocollapse */ MdcDialogContainer.ctorParameters = function () { return [ { type: ElementRef } ]; }; return MdcDialogContainer; }()); var MdcDialogSurface = /** @class */ (function () { function MdcDialogSurface(elementRef) { this.elementRef = elementRef; } MdcDialogSurface.decorators = [ { type: Directive, args: [{ selector: '[mdcDialogSurface], mdc-dialog-surface', host: { 'class': 'mdc-dialog__surface' } },] }, ]; /** @nocollapse */ MdcDialogSurface.ctorParameters = function () { return [ { type: ElementRef } ]; }; return MdcDialogSurface; }()); var MdcDialogTitle = /** @class */ (function () { function MdcDialogTitle(elementRef) { this.elementRef = elementRef; } MdcDialogTitle.decorators = [ { type: Directive, args: [{ selector: '[mdcDialogTitle], mdc-dialog-title', host: { 'class': 'mdc-dialog__title' } },] }, ]; /** @nocollapse */ MdcDialogTitle.ctorParameters = function () { return [ { type: ElementRef } ]; }; return MdcDialogTitle; }()); var MdcDialogContent = /** @class */ (function () { function MdcDialogContent(elementRef) { this.elementRef = elementRef; } MdcDialogContent.decorators = [ { type: Directive, args: [{ selector: '[mdcDialogContent], mdc-dialog-content', host: { 'class': 'mdc-dialog__content' } },] }, ]; /** @nocollapse */ MdcDialogContent.ctorParameters = function () { return [ { type: ElementRef } ]; }; return MdcDialogContent; }()); var MdcDialogActions = /** @class */ (function () { function MdcDialogActions(elementRef) { this.elementRef = elementRef; this._stacked = false; } Object.defineProperty(MdcDialogActions.prototype, "stacked", { get: /** * @return {?} */ function () { return this._stacked; }, set: /** * @param {?} value * @return {?} */ function (value) { this._stacked = coerceBooleanProperty(value); }, enumerable: true, configurable: true }); MdcDialogActions.decorators = [ { type: Component, args: [{selector: 'mdc-dialog-actions, [mdcDialogActions]', template: '<ng-content></ng-content>', exportAs: 'mdcDialogActions', host: { 'class': 'mdc-dialog__actions', '[class.mdc-dialog--stacked]': 'stacked' }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush },] }, ]; /** @nocollapse */ MdcDialogActions.ctorParameters = function () { return [ { type: ElementRef } ]; }; MdcDialogActions.propDecorators = { stacked: [{ type: Input }] }; return MdcDialogActions; }()); var MdcDialogButton = /** @class */ (function (_super) { __extends(MdcDialogButton, _super); function MdcDialogButton() { var _this = _super !== null && _super.apply(this, arguments) || this; _this._default = false; return _this; } Object.defineProperty(MdcDialogButton.prototype, "default", { get: /** * @return {?} */ function () { return this._default; }, set: /** * @param {?} value * @return {?} */ function (value) { this._default = coerceBooleanProperty(value); }, enumerable: true, configurable: true }); MdcDialogButton.decorators = [ { type: Component, args: [{selector: '[mdcDialogButton]', exportAs: 'mdcDialogButton', host: { 'class': 'mdc-dialog__button', '[class.mdc-button]': 'true', '[class.mdc-dialog__button--default]': 'default' }, template: "\n <div class=\"mdc-button__ripple\"></div>\n <ng-content></ng-content>", providers: [MdcRipple], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush },] }, ]; MdcDialogButton.propDecorators = { default: [{ type: Input }] }; return MdcDialogButton; }(MdcButton)); /** * @fileoverview added by tsickle * Generated from: dialog/dialog-ref.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Unique id for the created dialog. * @type {?} */ var uniqueId = 0; /** * Reference to a dialog dispatched from the MdcDialog service. * @template T, R */ var /** * Reference to a dialog dispatched from the MdcDialog service. * @template T, R */ MdcDialogRef = /** @class */ (function () { function MdcDialogRef(_overlayRef, _portalInstance, id) { var _this = this; if (id === void 0) { id = "mdc-dialog-" + uniqueId++; } this._overlayRef = _overlayRef; this._portalInstance = _portalInstance; this.id = id; /** * Subject for notifying the user that the dialog has finished opening. */ this._afterOpened = new Subject(); /** * Subject for notifying the user that the dialog has started closing. */ this._beforeClosed = new Subject(); /** * Subject for notifying the user that the dialog has finished closing. */ this._afterClosed = new Subject(); // Pass the id along to the portal. _portalInstance._id = id; _overlayRef.detachments().subscribe((/** * @return {?} */ function () { _this._beforeClosed.next(_this._result); _this._beforeClosed.complete(); _this._afterClosed.next(_this._result); _this._afterClosed.complete(); _this.componentInstance = (/** @type {?} */ (null)); _this._overlayRef.dispose(); })); } /** * Close the dialog. * @param dialogResult Optional result to return to the dialog opener. */ /** * Close the dialog. * @param {?=} dialogResult Optional result to return to the dialog opener. * @return {?} */ MdcDialogRef.prototype.close = /** * Close the dialog. * @param {?=} dialogResult Optional result to return to the dialog opener. * @return {?} */ function (dialogResult) { this._result = dialogResult; this._overlayRef.dispose(); }; /** Marks the dialog as opened. */ /** * Marks the dialog as opened. * @return {?} */ MdcDialogRef.prototype.opened = /** * Marks the dialog as opened. * @return {?} */ function () { if (!this._afterOpened.closed) { this._afterOpened.next(); this._afterOpened.complete(); } }; /** Gets an observable that is notified when the dialog is finished opening. */ /** * Gets an observable that is notified when the dialog is finished opening. * @return {?} */ MdcDialogRef.prototype.afterOpened = /** * Gets an observable that is notified when the dialog is finished opening. * @return {?} */ function () { return this._afterOpened.asObservable(); }; /** Gets an observable that is notified when the dialog has started closing. */ /** * Gets an observable that is notified when the dialog has started closing. * @return {?} */ MdcDialogRef.prototype.beforeClosed = /** * Gets an observable that is notified when the dialog has started closing. * @return {?} */ function () { return this._beforeClosed.asObservable(); }; /** Gets an observable that is notified when the dialog is finished closing. */ /** * Gets an observable that is notified when the dialog is finished closing. * @return {?} */ MdcDialogRef.prototype.afterClosed = /** * Gets an observable that is notified when the dialog is finished closing. * @return {?} */ function () { return this._afterClosed.asObservable(); }; return MdcDialogRef; }()); /** * @fileoverview added by tsickle * Generated from: dialog/dialog.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var LAYOUT_EVENTS = ['resize', 'orientationchange']; var MdcDialogComponent = /** @class */ (function (_super) { __extends(MdcDialogComponent, _super); function MdcDialogComponent(_ngZone, _platform, elementRef, dialogRef) { var _this = _super.call(this, elementRef) || this; _this._ngZone = _ngZone; _this._platform = _platform; _this.elementRef = elementRef; _this.dialogRef = dialogRef; /** * Emits whenever the component is destroyed. */ _this._destroy = new Subject(); _this._scrollable = true; _this._layoutEventSubscription = null; _this.config = dialogRef._portalInstance._config; return _this; } Object.defineProperty(MdcDialogComponent.prototype, "layoutEvents", { /** Combined stream of all of the dialog layout events. */ get: /** * Combined stream of all of the dialog layout events. * @return {?} */ function () { return merge.apply(void 0, LAYOUT_EVENTS.map((/** * @param {?} evt * @return {?} */ function (evt) { return fromEvent(window, evt); }))); }, enumerable: true, configurable: true }); /** * @return {?} */ MdcDialogComponent.prototype.getDefaultFoundation = /** * @return {?} */ function () { var _this = this; /** @type {?} */ var adapter = { addClass: (/** * @param {?} className * @return {?} */ function (className) { return _this._getDialog().classList.add(className); }), removeClass: (/** * @param {?} className * @return {?} */ function (className) { return _this._getDialog().classList.remove(className); }), getInitialFocusEl: (/** * @return {?} */ function () { return _this._platform.isBrowser ? (/** @type {?} */ (document.querySelector("[cdkFocusInitial]"))) : null; }), hasClass: (/** * @param {?} className * @return {?} */ function (className) { return _this._getDialog().classList.contains(className); }), addBodyClass: (/** * @param {?} className * @return {?} */ function (className) { if (_this._platform.isBrowser) { (/** @type {?} */ (document.body)).classList.add(className); } }), removeBodyClass: (/** * @param {?} className * @return {?} */ function (className) { if (_this._platform.isBrowser) { (/** @type {?} */ (document.body)).classList.remove(className); } }), eventTargetMatches: (/** * @param {?} target * @param {?} selector * @return {?} */ function (target, selector) { return matches((/** @type {?} */ (target)), selector); }), trapFocus: (/** * @return {?} */ function () { }), releaseFocus: (/** * @return {?} */ function () { }), isContentScrollable: (/** * @return {?} */ function () { return !!_this._content && _this._scrollable && util.isScrollable(_this._content.elementRef.nativeElement); }), areButtonsStacked: (/** * @return {?} */ function () { return util.areTopsMisaligned((/** @type {?} */ (_this._buttons))); }), getActionFromEvent: (/** * @param {?} event * @return {?} */ function (event) { /** @type {?} */ var element = closest((/** @type {?} */ (event.target)), "[" + strings.ACTION_ATTRIBUTE + "]"); return element && element.getAttribute(strings.ACTION_ATTRIBUTE); }), clickDefaultButton: (/** * @return {?} */ function () { var _a, _b, _c; /** @type {?} */ var defaultBtn = _this._buttons.find((/** * @param {?} _ * @return {?} */ function (_) { return _.default; })); (_c = (_b = (_a = defaultBtn) === null || _a === void 0 ? void 0 : _a.elementRef) === null || _b === void 0 ? void 0 : _b.nativeElement) === null || _c === void 0 ? void 0 : _c.click(); }), reverseButtons: (/** * @return {?} */ function () { _this._buttons.toArray().reverse(); _this._buttons.forEach((/** * @param {?} button * @return {?} */ function (button) { return (/** @type {?} */ (button.getHostElement().parentElement)).appendChild(button.getHostElement()); })); }), notifyOpened: (/** * @return {?} */ function () { return _this.dialogRef.opened(); }), notifyOpening: (/** * @return {?} */ function () { }), notifyClosed: (/** * @param {?} action * @return {?} */ function (action) { return _this._closeDialogByRef(action); }), notifyClosing: (/** * @return {?} */ function () { }) }; return new MDCDialogFoundation(adapter); }; /** * @return {?} */ MdcDialogComponent.prototype.ngAfterViewInit = /** * @return {?} */ function () { this._foundation = this.getDefaultFoundation(); this._initialize(); this._loadListeners(); this._foundation.open(); }; /** * @private * @return {?} */ MdcDialogComponent.prototype._initialize = /** * @private * @return {?} */ function () { this._scrollable = !!this.config.scrollable; if (!this.config.clickOutsideToClose) { this._foundation.setScrimClickAction(''); } if (!this.config.escapeToClose) { this._foundation.setEscapeKeyAction(''); } if (!this.config.buttonsStacked) { this._foundation.setAutoStackButtons(false); } }; /** * @return {?} */ MdcDialogComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { var _a, _b; this._destroy.next(); this._destroy.complete(); (_a = this._layoutEventSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe(); (_b = this._foundation) === null || _b === void 0 ? void 0 : _b.destroy(); }; /** Recalculates layout and automatically adds/removes modifier classes like --scrollable. */ /** * Recalculates layout and automatically adds/removes modifier classes like --scrollable. * @return {?} */ MdcDialogComponent.prototype.layout = /** * Recalculates layout and automatically adds/removes modifier classes like --scrollable. * @return {?} */ function () { this._foundation.layout(); }; /** * @param {?} evt * @return {?} */ MdcDialogComponent.prototype._onKeydown = /** * @param {?} evt * @return {?} */ function (evt) { this._foundation.handleKeydown(evt); }; /** * @param {?} evt * @return {?} */ MdcDialogComponent.prototype._onClick = /** * @param {?} evt * @return {?} */ function (evt) { this._foundation.handleClick(evt); }; /** * @private * @param {?=} action * @return {?} */ MdcDialogComponent.prototype._closeDialogByRef = /** * @private * @param {?=} action * @return {?} */ function (action) { this.dialogRef.close(action); }; /** * @private * @return {?} */ MdcDialogComponent.prototype._loadListeners = /** * @private * @return {?} */ function () { var _this = this; this._layoutEventSubscription = this.layoutEvents.pipe() .subscribe((/** * @return {?} */ function () { return _this.layout(); })); if (this._platform.isBrowser) { this._ngZone.runOutsideAngular((/** * @return {?} */ function () { return fromEvent(document, 'keydown').pipe(takeUntil(_this._destroy)) .subscribe((/** * @param {?} evt * @return {?} */ function (evt) { return _this._ngZone.run((/** * @return {?} */ function () { return _this._foundation.handleDocumentKeydown(evt); })); })); })); } }; /** Retrieves the DOM element of the component host. */ /** * Retrieves the DOM element of the component host. * @private * @return {?} */ MdcDialogComponent.prototype._getDialog = /** * Retrieves the DOM element of the component host. * @private * @return {?} */ function () { return this._elementRef.nativeElement; }; MdcDialogComponent.decorators = [ { type: Component, args: [{selector: 'mdc-dialog', exportAs: 'mdc-dialog', host: { '[attr.id]': 'config?.id', 'role': 'alertdialog', 'class': 'mdc-dialog', '[attr.aria-modal]': 'true', '[attr.aria-labelledby]': 'config?.ariaLabel', '[attr.aria-label]': 'config?.ariaLabel', '[attr.aria-describedby]': 'config?.ariaDescribedBy || null', '(click)': '_onClick($event)', '(keydown)': '_onKeydown($event)' }, template: "\n <mdc-dialog-scrim></mdc-dialog-scrim>\n <ng-content></ng-content>", encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush },] }, ]; /** @nocollapse */ MdcDialogComponent.ctorParameters = function () { return [ { type: NgZone }, { type: Platform }, { type: ElementRef }, { type: MdcDialogRef } ]; }; MdcDialogComponent.propDecorators = { _surface: [{ type: ContentChild, args: [MdcDialogSurface, { static: false },] }], _content: [{ type: ContentChild, args: [MdcDialogContent, { static: false },] }], _buttons: [{ type: ContentChildren, args: [MdcDialogButton, { descendants: true },] }] }; return MdcDialogComponent; }(MDCComponent)); /** * @fileoverview added by tsickle * Generated from: dialog/dialog-config.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @template D */ var /** * @template D */ MdcDialogConfig = /** @class */ (function () { function MdcDialogConfig() { /** * ID of the element that describes the dialog. */ this.ariaDescribedBy = null; /** * Aria label to assign to the dialog element */ this.ariaLabel = null; /** * Whether the user can use escape key to close the dialog */ this.escapeToClose = true; /** * Whether the user can click outside to close the dialog */ this.clickOutsideToClose = true; /** * Applied automatically when the dialog has overflowing content to warrant scrolling. */ this.scrollable = true; /** * Applied automatically when the dialog's action buttons can't fit on a single line and must be stacked. */ this.buttonsStacked = true; /** * 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; /** * Data to be injected into the dialog content. */ this.data = null; } return MdcDialogConfig; }()); /** * @fileoverview added by tsickle * Generated from: dialog/dialog-portal.ts * @suppress {checkTypes,constantProperty,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. * @return {?} */ function throwMdcDialogContentAlreadyAttachedError() { throw Error('Attempting to attach dialog content after content is already attached'); } var MdcDialogPortal = /** @class */ (function (_super) { __extends(MdcDialogPortal, _super); function MdcDialogPortal(_elementRef, _focusTrapFactory, _document, _config) { var _this = _super.call(this) || this; _this._elementRef = _elementRef; _this._focusTrapFactory = _focusTrapFactory; _this._document = _document; _this._config = _config; /** * Element that was focused before the dialog was opened. Save this to restore upon close. */ _this._elementFocusedBeforeDialogWasOpened = null; /** * A subject emitting after the dialog exits the view. */ _this._afterExit = new Subject(); return _this; } /** * Attach a ComponentPortal as content to this dialog container. * @param portal Portal to be attached as the dialog content. */ /** * Attach a ComponentPortal as content to this dialog container. * @template T * @param {?} portal Portal to be attached as the dialog content. * @return {?} */ MdcDialogPortal.prototype.attachComponentPortal = /** * Attach a ComponentPortal as content to this dialog container. * @template T * @param {?} portal Portal to be attached as the dialog content. * @return {?} */ function (portal) { if (this._portalOutlet.hasAttached()) { throwMdcDialogContentAlreadyAttachedError(); } this._savePreviouslyFocusedElement(); return this._portalOutlet.attachComponentPortal(portal); }; /** * Attach a TemplatePortal as content to this dialog container. * @param portal Portal to be attached as the dialog content. */ /** * Attach a TemplatePortal as content to this dialog container. * @template C * @param {?} portal Portal to be attached as the dialog content. * @return {?} */ MdcDialogPortal.prototype.attachTemplatePortal = /** * Attach a TemplatePortal as content to this dialog container. * @template C * @param {?} portal Portal to be attached as the dialog content. * @return {?} */ function (portal) { if (this._portalOutlet.hasAttached()) { throwMdcDialogContentAlreadyAttachedError(); } this._savePreviouslyFocusedElement(); return this._portalOutlet.attachTemplatePortal(portal); }; /** Moves the focus inside the focus trap. */ /** * Moves the focus inside the focus trap. * @return {?} */ MdcDialogPortal.prototype.trapFocus = /** * Moves the focus inside the focus trap. * @return {?} */ function () { /** @type {?} */ var 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 {?} */ var activeElement = this._document.activeElement; // Otherwise ensure that focus is on the dialog container. It's possible that a different // component tried to move focus. 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. */ /** * Restores focus to the element that was focused before the dialog opened. * @return {?} */ MdcDialogPortal.prototype.restoreFocus = /** * Restores focus to the element that was focused before the dialog opened. * @return {?} */ function () { /** @type {?} */ var 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. */ /** * Saves a reference to the element that was focused before the dialog was opened. * @private * @return {?} */ MdcDialogPortal.prototype._savePreviouslyFocusedElement = /** * Saves a reference to the element that was focused before the dialog was opened. * @private * @return {?} */ function () { var _this = this; 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 {?} */ function () { return _this._elementRef.nativeElement.focus(); })); } } }; MdcDialogPortal.decorators = [ { type: Component, args: [{selector: 'mdc-dialog-portal', host: { '[attr.id]': '_id' }, template: '<ng-template cdkPortalOutlet></ng-template>', encapsulation: ViewEncapsulation.None },] }, ]; /** @nocollapse */ MdcDialogPortal.ctorParameters = function () { return [ { type: ElementRef }, { type: FocusTrapFactory }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] }, { type: MdcDialogConfig } ]; }; MdcDialogPortal.propDecorators = { _portalOutlet: [{ type: ViewChild, args: [CdkPortalOutlet, { static: true },] }] }; return MdcDialogPortal; }(BasePortalOutlet)); /** * @fileoverview added by tsickle * Generated from: dialog/dialog.ts * @suppress {checkTypes,constantProperty,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 {?} */ var MDC_DIALOG_DATA = new InjectionToken('MdcDialogData'); /** * Injection token that can be used to specify default dialog options. * @type {?} */ var MDC_DIALOG_DEFAULT_OPTIONS = new InjectionToken('mdc-dialog-default-options'); var MdcDialog = /** @class */ (function () { function MdcDialog(_overlay, _injector, _defaultOptions, _parentDialog) { var _this = this; this._overlay = _overlay; this._injector = _injector; this._defaultOptions = _defaultOptions; this._parentDialog = _parentDialog; this._openDialogsAtThisLevel = []; this._afterAllClosedAtThisLevel = new Subject(); this._afterOpenedAtThisLevel = new Subject(); this._ariaHiddenElements = new Map(); /** * 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 {?} */ function () { return _this.openDialogs.length ? _this._afterAllClosed : _this._afterAllClosed.pipe(startWith(undefined)); })))); } Object.defineProperty(MdcDialog.prototype, "openDialogs", { /** Keeps track of the currently-open dialogs. */ get: /** * Keeps track of the currently-open dialogs. * @return {?} */ function () { return this._parentDialog ? this._parentDialog.openDialogs : this._openDialogsAtThisLevel; }, enumerable: true, configurable: true }); Object.defineProperty(MdcDialog.prototype, "afterOpened", { /** Stream that emits when a dialog has been opened. */ get: /** * Stream that emits when a dialog has been opened. * @return {?} */ function () { return this._parentDialog ? this._parentDialog.afterOpened : this._afterOpenedAtThisLevel; }, enumerable: true, configurable: true }); Object.defineProperty(MdcDialog.prototype, "_afterAllClosed", { get: /** * @return {?} */ function () { /** @type {?} */ var parent = this._parentDialog; return parent ? parent._afterAllClosed : this._afterAllClosedAtThisLevel; }, enumerable: true, configurable: true }); /** * Opens a modal dialog containing the given template. * @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. * @returns Reference to the newly-opened dialog. */ /** * Opens a modal dialog containing the given template. * @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. */ MdcDialog.prototype.open = /** * Opens a modal dialog containing the given template. * @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. */ function (componentOrTemplateRef, config) { var _this = this; config = _applyConfigDefaults(config, this._defaultOptions || new MdcDialogConfig()); if (config.id && this.getDialogById(config.id)) { throw Error("Dialog with id \"" + config.id + "\" exists already. The dialog id must be unique."); } /** @type {?} */ var overlayRef = this._createOverlay(); /** @type {?} */ var dialogContainer = this._attachDialogContainer(overlayRef, config); /** @type {?} */ var dialogRef = this._attachDialogContent(componentOrTemplateRef, dialogContainer, overlayRef, config); this.openDialogs.push(dialogRef); dialogRef.afterClosed().subscribe((/** * @return {?} */ function () { return _this._removeOpenDialog(dialogRef, dialogContainer); })); this.afterOpened.next(dialogRef); return dialogRef; }; /** Closes all of the currently-open dialogs. */ /** * Closes all of the currently-open dialogs. * @return {?} */ MdcDialog.prototype.closeAll = /** * Closes all of the currently-open dialogs. * @return {?} */ function () { this._closeDialogs(this.openDialogs); }; /** * Finds an open dialog by its id. * @param id ID to use when looking up the dialog. */ /** * Finds an open dialog by its id. * @param {?} id ID to use when looking up the dialog. * @return {?} */ MdcDialog.prototype.getDialogById = /** * Finds an open dialog by its id. * @param {?} id ID to use when looking up the dialog. * @return {?} */ function (id) { return this.openDialogs.find((/** * @param {?} dialog * @return {?} */ function (dialog) { return dialog.id === id; })); }; /** * @return {?} */ MdcDialog.prototype.ngOnDestroy = /** * @return {?} */ function () { // 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. * @returns A promise resolving to the OverlayRef for the created overlay. */ /** * Creates the overlay into which the dialog will be loaded. * @private * @return {?} A promise resolving to the OverlayRef for the created overlay. */ MdcDialog.prototype._createOverlay = /** * Creates the overlay into which the dialog will be loaded. * @private * @return {?} A promise resolving to the OverlayRef for the created overlay. */ function () { return this._overlay.create(); }; /** * Attaches an MdcDialogPortal to a dialog's already-created overlay. * @param overlay Reference to the dialog's underlying overlay. * @param config The dialog configuration. * @returns A promise resolving to a ComponentRef for the attached container. */ /** * Attaches an MdcDialogPortal 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. */ MdcDialog.prototype._attachDialogContainer = /** * Attaches an MdcDialogPortal 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. */ function (overlay, config) { /** @type {?} */ var userInjector = config && config.viewContainerRef && config.viewContainerRef.injector; /** @type {?} */ var injector = new PortalInjector(userInjector || this._injector, new WeakMap([ [MdcDialogConfig, config] ])); /** @type {?} */ var containerPortal = new ComponentPortal(MdcDialogPortal, config.viewContainerRef, injector, config.componentFactoryResolver); /** @type {?} */ var containerRef = overlay.attach(containerPortal); return containerRef.instance; }; /** * Attaches the user-provided component to the already-created MdcDialogPortal. * @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 MdcDialogPortal. * @param overlayRef Reference to the overlay in which the dialog resides. * @param config The dialog configuration. * @returns A promise resolving to the MdcDialogRef that should be returned to the user. */ /** * Attaches the user-provided component to the already-created MdcDialogPortal. * @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 MdcDialogPortal. * @param {?} overlayRef Reference to the overlay in which the dialog resides. * @param {?} config The dialog configuration. * @return {?} A promise resolving to the MdcDialogRef that should be returned to the user. */ MdcDialog.prototype._attachDialogContent = /** * Attaches the user-provided component to the already-created MdcDialogPortal. * @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 MdcDialogPortal. * @param {?} overlayRef Reference to the overlay in which the dialog resides. * @param {?} config The dialog configuration. * @return {?} A promise resolving to the MdcDialogRef that should be returned to the user. */ function (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 {?} */ var dialogRef = new MdcDialogRef(overlayRef, dialogContainer, config.id); if (componentOrTemplateRef instanceof TemplateRef) { dialogContainer.attachTemplatePortal(new TemplatePortal(componentOrTemplateRef, (/** @type {?} */ (null)), (/** @type {?} */ ({ $implicit: config.data, dialogRef: dialogRef })))); } else { /** @type {?} */ var injector = this._createInjector(config, dialogRef, dialogContainer); /** @type {?} */ var contentRef = dialogContainer.attachComponentPortal(new ComponentPortal(componentOrTemplateRef, config.viewContainerRef, injector)); dialogRef.componentInstance = contentRef.instance; } 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. * @param config Config object that is used to construct the dialog. * @param dialogRef Reference to the dialog. * @param container Dialog container element that wraps all of the contents. * @returns The custom injector that can be used inside the dialog. */ /** * 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 {?} portalContainer * @return {?} The custom injector that can be used inside the dialog. */ MdcDialog.prototype._createInjector = /** * 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 {?} portalContainer * @return {?} The custom injector that can be used inside the dialog. */ function (config, dialogRef, portalContainer) { /** @type {?} */ var userInjector = config && config.viewContainerRef && config.viewContainerRef.injector; portalContainer.trapFocus(); // The MdcDialogPortal is injected in the portal as the MdcDialogPortal 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 MdcDialogPortal is explicitly // added to the injection tokens. /** @type {?} */ var injectionTokens = new WeakMap([ [MdcDialogPortal, portalContainer], [MDC_DIALOG_DATA, config.data], [MdcDialogRef, dialogRef] ]); return new PortalInjector(userInjector || this._injector, injectionTokens); }; /** * Removes a dialog from the array of open dialogs. * @param dialogRef Dialog to be removed. */ /** * Removes a dialog from the array of open dialogs. * @private * @param {?} dialogRef Dialog to be removed. * @param {?} dialogContainer * @return {?} */ MdcDialog.prototype._removeOpenDialog = /** * Removes a dialog from the array of open dialogs. * @private * @param {?} dialogRef Dialog to be removed. * @param {?} dialogContainer * @return {?} */ function (dialogRef, dialogContainer) { /** @type {?} */ var index = this.openDialogs.indexOf(dialogRef); if (index > -1) { dialogContainer.restoreFocus(); 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 {?} */ function (previousValue, element) { if (previousValue) { element.setAttribute('aria-hidden', previousValue); } else { element.removeAttribute('aria-hidden'); } })); this._ariaHiddenElements.clear(); this._afterAllClosed.next(); } } }; /** Closes all of the dialogs in an array. */ /** * Closes all of the dialogs in an array. * @private * @param {?} dialogs * @return {?} */ MdcDialog.prototype._closeDialogs = /** * Closes all of the dialogs in an array. * @private * @param {?} dialogs * @return {?} */ function (dialogs) { /** @type {?} */ var 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(); } }; MdcDialog.decorators = [ { type: Injectable }, ]; /** @nocollapse */ MdcDialog.ctorParameters = function () { return [ { type: Overlay }, { type: Injector }, { type: MdcDialogConfig, decorators: [{ type: Optional }, { type: Inject, args: [MDC_DIALOG_DEFAULT_OPTIONS,] }] }, { type: MdcDialog, decorators: [{ type: Optional }, { type: SkipSelf }] } ]; }; return MdcDialog; }()); /** * 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 __assign(__assign({}, defaultOptions), config); } /** * @fileoverview added by tsickle * Generated from: dialog/module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var DIALOG_DECLARATIONS = [ MdcDialogAction, MdcDialogActions, MdcDialogButton, MdcDialogComponent, MdcDialogContainer, MdcDialogPortal, MdcDialogContent, MdcDialogScrim, MdcDialogSurface, MdcDialogSurface, MdcDialogTitle ]; var MdcDialogModule = /** @class */ (function () { function MdcDialogModule() { } MdcDialogModule.decorators = [ { type: NgModule, args: [{ imports: [ OverlayModule, PortalModule ], exports: DIALOG_DECLARATIONS, declarations: DIALOG_DECLARATIONS, providers: [MdcDialog],