| /** |
| * @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 { coerceCssPixelValue, coerceArray, coerceBooleanProperty } from '@angular/cdk/coercion'; |
| import { ScrollDispatcher, ViewportRuler, ScrollingModule, VIEWPORT_RULER_PROVIDER } from '@angular/cdk/scrolling'; |
| export { ViewportRuler, VIEWPORT_RULER_PROVIDER, CdkScrollable, ScrollDispatcher } from '@angular/cdk/scrolling'; |
| import { DOCUMENT, Location } from '@angular/common'; |
| import { Inject, Injectable, NgZone, Optional, NgModule, SkipSelf, ApplicationRef, ComponentFactoryResolver, Injector, ElementRef, Directive, EventEmitter, InjectionToken, Input, Output, TemplateRef, ViewContainerRef, ɵɵdefineInjectable, ɵɵinject } from '@angular/core'; |
| import { __assign, __extends } from 'tslib'; |
| import { Observable, Subject, merge, Subscription } from 'rxjs'; |
| import { take, takeUntil } from 'rxjs/operators'; |
| import { Platform } from '@angular/cdk/platform'; |
| import { Directionality, BidiModule } from '@angular/cdk/bidi'; |
| import { DomPortalOutlet, TemplatePortal, PortalModule } from '@angular/cdk/portal'; |
| import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes'; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Strategy that will prevent the user from scrolling while the overlay is visible. |
| */ |
| var /** |
| * Strategy that will prevent the user from scrolling while the overlay is visible. |
| */ |
| BlockScrollStrategy = /** @class */ (function () { |
| function BlockScrollStrategy(_viewportRuler, document) { |
| this._viewportRuler = _viewportRuler; |
| this._previousHTMLStyles = { top: '', left: '' }; |
| this._isEnabled = false; |
| this._document = document; |
| } |
| /** Attaches this scroll strategy to an overlay. */ |
| /** |
| * Attaches this scroll strategy to an overlay. |
| * @return {?} |
| */ |
| BlockScrollStrategy.prototype.attach = /** |
| * Attaches this scroll strategy to an overlay. |
| * @return {?} |
| */ |
| function () { }; |
| /** Blocks page-level scroll while the attached overlay is open. */ |
| /** |
| * Blocks page-level scroll while the attached overlay is open. |
| * @return {?} |
| */ |
| BlockScrollStrategy.prototype.enable = /** |
| * Blocks page-level scroll while the attached overlay is open. |
| * @return {?} |
| */ |
| function () { |
| if (this._canBeEnabled()) { |
| /** @type {?} */ |
| var root = (/** @type {?} */ (this._document.documentElement)); |
| this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition(); |
| // Cache the previous inline styles in case the user had set them. |
| this._previousHTMLStyles.left = root.style.left || ''; |
| this._previousHTMLStyles.top = root.style.top || ''; |
| // Note: we're using the `html` node, instead of the `body`, because the `body` may |
| // have the user agent margin, whereas the `html` is guaranteed not to have one. |
| root.style.left = coerceCssPixelValue(-this._previousScrollPosition.left); |
| root.style.top = coerceCssPixelValue(-this._previousScrollPosition.top); |
| root.classList.add('cdk-global-scrollblock'); |
| this._isEnabled = true; |
| } |
| }; |
| /** Unblocks page-level scroll while the attached overlay is open. */ |
| /** |
| * Unblocks page-level scroll while the attached overlay is open. |
| * @return {?} |
| */ |
| BlockScrollStrategy.prototype.disable = /** |
| * Unblocks page-level scroll while the attached overlay is open. |
| * @return {?} |
| */ |
| function () { |
| if (this._isEnabled) { |
| /** @type {?} */ |
| var html = (/** @type {?} */ (this._document.documentElement)); |
| /** @type {?} */ |
| var body = (/** @type {?} */ (this._document.body)); |
| /** @type {?} */ |
| var htmlStyle = (/** @type {?} */ (html.style)); |
| /** @type {?} */ |
| var bodyStyle = (/** @type {?} */ (body.style)); |
| /** @type {?} */ |
| var previousHtmlScrollBehavior = htmlStyle.scrollBehavior || ''; |
| /** @type {?} */ |
| var previousBodyScrollBehavior = bodyStyle.scrollBehavior || ''; |
| this._isEnabled = false; |
| htmlStyle.left = this._previousHTMLStyles.left; |
| htmlStyle.top = this._previousHTMLStyles.top; |
| html.classList.remove('cdk-global-scrollblock'); |
| // Disable user-defined smooth scrolling temporarily while we restore the scroll position. |
| // See https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior |
| htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto'; |
| window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top); |
| htmlStyle.scrollBehavior = previousHtmlScrollBehavior; |
| bodyStyle.scrollBehavior = previousBodyScrollBehavior; |
| } |
| }; |
| /** |
| * @private |
| * @return {?} |
| */ |
| BlockScrollStrategy.prototype._canBeEnabled = /** |
| * @private |
| * @return {?} |
| */ |
| function () { |
| // Since the scroll strategies can't be singletons, we have to use a global CSS class |
| // (`cdk-global-scrollblock`) to make sure that we don't try to disable global |
| // scrolling multiple times. |
| /** @type {?} */ |
| var html = (/** @type {?} */ (this._document.documentElement)); |
| if (html.classList.contains('cdk-global-scrollblock') || this._isEnabled) { |
| return false; |
| } |
| /** @type {?} */ |
| var body = this._document.body; |
| /** @type {?} */ |
| var viewport = this._viewportRuler.getViewportSize(); |
| return body.scrollHeight > viewport.height || body.scrollWidth > viewport.width; |
| }; |
| return BlockScrollStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Returns an error to be thrown when attempting to attach an already-attached scroll strategy. |
| * @return {?} |
| */ |
| function getMatScrollStrategyAlreadyAttachedError() { |
| return Error("Scroll strategy has already been attached."); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Strategy that will close the overlay as soon as the user starts scrolling. |
| */ |
| var /** |
| * Strategy that will close the overlay as soon as the user starts scrolling. |
| */ |
| CloseScrollStrategy = /** @class */ (function () { |
| function CloseScrollStrategy(_scrollDispatcher, _ngZone, _viewportRuler, _config) { |
| var _this = this; |
| this._scrollDispatcher = _scrollDispatcher; |
| this._ngZone = _ngZone; |
| this._viewportRuler = _viewportRuler; |
| this._config = _config; |
| this._scrollSubscription = null; |
| /** |
| * Detaches the overlay ref and disables the scroll strategy. |
| */ |
| this._detach = (/** |
| * @return {?} |
| */ |
| function () { |
| _this.disable(); |
| if (_this._overlayRef.hasAttached()) { |
| _this._ngZone.run((/** |
| * @return {?} |
| */ |
| function () { return _this._overlayRef.detach(); })); |
| } |
| }); |
| } |
| /** Attaches this scroll strategy to an overlay. */ |
| /** |
| * Attaches this scroll strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| CloseScrollStrategy.prototype.attach = /** |
| * Attaches this scroll strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| if (this._overlayRef) { |
| throw getMatScrollStrategyAlreadyAttachedError(); |
| } |
| this._overlayRef = overlayRef; |
| }; |
| /** Enables the closing of the attached overlay on scroll. */ |
| /** |
| * Enables the closing of the attached overlay on scroll. |
| * @return {?} |
| */ |
| CloseScrollStrategy.prototype.enable = /** |
| * Enables the closing of the attached overlay on scroll. |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (this._scrollSubscription) { |
| return; |
| } |
| /** @type {?} */ |
| var stream = this._scrollDispatcher.scrolled(0); |
| if (this._config && this._config.threshold && this._config.threshold > 1) { |
| this._initialScrollPosition = this._viewportRuler.getViewportScrollPosition().top; |
| this._scrollSubscription = stream.subscribe((/** |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var scrollPosition = _this._viewportRuler.getViewportScrollPosition().top; |
| if (Math.abs(scrollPosition - _this._initialScrollPosition) > (/** @type {?} */ ((/** @type {?} */ (_this._config)).threshold))) { |
| _this._detach(); |
| } |
| else { |
| _this._overlayRef.updatePosition(); |
| } |
| })); |
| } |
| else { |
| this._scrollSubscription = stream.subscribe(this._detach); |
| } |
| }; |
| /** Disables the closing the attached overlay on scroll. */ |
| /** |
| * Disables the closing the attached overlay on scroll. |
| * @return {?} |
| */ |
| CloseScrollStrategy.prototype.disable = /** |
| * Disables the closing the attached overlay on scroll. |
| * @return {?} |
| */ |
| function () { |
| if (this._scrollSubscription) { |
| this._scrollSubscription.unsubscribe(); |
| this._scrollSubscription = null; |
| } |
| }; |
| /** |
| * @return {?} |
| */ |
| CloseScrollStrategy.prototype.detach = /** |
| * @return {?} |
| */ |
| function () { |
| this.disable(); |
| this._overlayRef = (/** @type {?} */ (null)); |
| }; |
| return CloseScrollStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * Scroll strategy that doesn't do anything. |
| */ |
| var /** |
| * Scroll strategy that doesn't do anything. |
| */ |
| NoopScrollStrategy = /** @class */ (function () { |
| function NoopScrollStrategy() { |
| } |
| /** Does nothing, as this scroll strategy is a no-op. */ |
| /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| NoopScrollStrategy.prototype.enable = /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| function () { }; |
| /** Does nothing, as this scroll strategy is a no-op. */ |
| /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| NoopScrollStrategy.prototype.disable = /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| function () { }; |
| /** Does nothing, as this scroll strategy is a no-op. */ |
| /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| NoopScrollStrategy.prototype.attach = /** |
| * Does nothing, as this scroll strategy is a no-op. |
| * @return {?} |
| */ |
| function () { }; |
| return NoopScrollStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| // TODO(jelbourn): move this to live with the rest of the scrolling code |
| // TODO(jelbourn): someday replace this with IntersectionObservers |
| /** |
| * Gets whether an element is scrolled outside of view by any of its parent scrolling containers. |
| * \@docs-private |
| * @param {?} element Dimensions of the element (from getBoundingClientRect) |
| * @param {?} scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect) |
| * @return {?} Whether the element is scrolled out of view |
| */ |
| function isElementScrolledOutsideView(element, scrollContainers) { |
| return scrollContainers.some((/** |
| * @param {?} containerBounds |
| * @return {?} |
| */ |
| function (containerBounds) { |
| /** @type {?} */ |
| var outsideAbove = element.bottom < containerBounds.top; |
| /** @type {?} */ |
| var outsideBelow = element.top > containerBounds.bottom; |
| /** @type {?} */ |
| var outsideLeft = element.right < containerBounds.left; |
| /** @type {?} */ |
| var outsideRight = element.left > containerBounds.right; |
| return outsideAbove || outsideBelow || outsideLeft || outsideRight; |
| })); |
| } |
| /** |
| * Gets whether an element is clipped by any of its scrolling containers. |
| * \@docs-private |
| * @param {?} element Dimensions of the element (from getBoundingClientRect) |
| * @param {?} scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect) |
| * @return {?} Whether the element is clipped |
| */ |
| function isElementClippedByScrolling(element, scrollContainers) { |
| return scrollContainers.some((/** |
| * @param {?} scrollContainerRect |
| * @return {?} |
| */ |
| function (scrollContainerRect) { |
| /** @type {?} */ |
| var clippedAbove = element.top < scrollContainerRect.top; |
| /** @type {?} */ |
| var clippedBelow = element.bottom > scrollContainerRect.bottom; |
| /** @type {?} */ |
| var clippedLeft = element.left < scrollContainerRect.left; |
| /** @type {?} */ |
| var clippedRight = element.right > scrollContainerRect.right; |
| return clippedAbove || clippedBelow || clippedLeft || clippedRight; |
| })); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Strategy that will update the element position as the user is scrolling. |
| */ |
| var /** |
| * Strategy that will update the element position as the user is scrolling. |
| */ |
| RepositionScrollStrategy = /** @class */ (function () { |
| function RepositionScrollStrategy(_scrollDispatcher, _viewportRuler, _ngZone, _config) { |
| this._scrollDispatcher = _scrollDispatcher; |
| this._viewportRuler = _viewportRuler; |
| this._ngZone = _ngZone; |
| this._config = _config; |
| this._scrollSubscription = null; |
| } |
| /** Attaches this scroll strategy to an overlay. */ |
| /** |
| * Attaches this scroll strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| RepositionScrollStrategy.prototype.attach = /** |
| * Attaches this scroll strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| if (this._overlayRef) { |
| throw getMatScrollStrategyAlreadyAttachedError(); |
| } |
| this._overlayRef = overlayRef; |
| }; |
| /** Enables repositioning of the attached overlay on scroll. */ |
| /** |
| * Enables repositioning of the attached overlay on scroll. |
| * @return {?} |
| */ |
| RepositionScrollStrategy.prototype.enable = /** |
| * Enables repositioning of the attached overlay on scroll. |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (!this._scrollSubscription) { |
| /** @type {?} */ |
| var throttle = this._config ? this._config.scrollThrottle : 0; |
| this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe((/** |
| * @return {?} |
| */ |
| function () { |
| _this._overlayRef.updatePosition(); |
| // TODO(crisbeto): make `close` on by default once all components can handle it. |
| if (_this._config && _this._config.autoClose) { |
| /** @type {?} */ |
| var overlayRect = _this._overlayRef.overlayElement.getBoundingClientRect(); |
| var _a = _this._viewportRuler.getViewportSize(), width = _a.width, height = _a.height; |
| // TODO(crisbeto): include all ancestor scroll containers here once |
| // we have a way of exposing the trigger element to the scroll strategy. |
| /** @type {?} */ |
| var parentRects = [{ width: width, height: height, bottom: height, right: width, top: 0, left: 0 }]; |
| if (isElementScrolledOutsideView(overlayRect, parentRects)) { |
| _this.disable(); |
| _this._ngZone.run((/** |
| * @return {?} |
| */ |
| function () { return _this._overlayRef.detach(); })); |
| } |
| } |
| })); |
| } |
| }; |
| /** Disables repositioning of the attached overlay on scroll. */ |
| /** |
| * Disables repositioning of the attached overlay on scroll. |
| * @return {?} |
| */ |
| RepositionScrollStrategy.prototype.disable = /** |
| * Disables repositioning of the attached overlay on scroll. |
| * @return {?} |
| */ |
| function () { |
| if (this._scrollSubscription) { |
| this._scrollSubscription.unsubscribe(); |
| this._scrollSubscription = null; |
| } |
| }; |
| /** |
| * @return {?} |
| */ |
| RepositionScrollStrategy.prototype.detach = /** |
| * @return {?} |
| */ |
| function () { |
| this.disable(); |
| this._overlayRef = (/** @type {?} */ (null)); |
| }; |
| return RepositionScrollStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Options for how an overlay will handle scrolling. |
| * |
| * Users can provide a custom value for `ScrollStrategyOptions` to replace the default |
| * behaviors. This class primarily acts as a factory for ScrollStrategy instances. |
| */ |
| var ScrollStrategyOptions = /** @class */ (function () { |
| function ScrollStrategyOptions(_scrollDispatcher, _viewportRuler, _ngZone, document) { |
| var _this = this; |
| this._scrollDispatcher = _scrollDispatcher; |
| this._viewportRuler = _viewportRuler; |
| this._ngZone = _ngZone; |
| /** |
| * Do nothing on scroll. |
| */ |
| this.noop = (/** |
| * @return {?} |
| */ |
| function () { return new NoopScrollStrategy(); }); |
| /** |
| * Close the overlay as soon as the user scrolls. |
| * @param config Configuration to be used inside the scroll strategy. |
| */ |
| this.close = (/** |
| * @param {?=} config |
| * @return {?} |
| */ |
| function (config) { return new CloseScrollStrategy(_this._scrollDispatcher, _this._ngZone, _this._viewportRuler, config); }); |
| /** |
| * Block scrolling. |
| */ |
| this.block = (/** |
| * @return {?} |
| */ |
| function () { return new BlockScrollStrategy(_this._viewportRuler, _this._document); }); |
| /** |
| * Update the overlay's position on scroll. |
| * @param config Configuration to be used inside the scroll strategy. |
| * Allows debouncing the reposition calls. |
| */ |
| this.reposition = (/** |
| * @param {?=} config |
| * @return {?} |
| */ |
| function (config) { return new RepositionScrollStrategy(_this._scrollDispatcher, _this._viewportRuler, _this._ngZone, config); }); |
| this._document = document; |
| } |
| ScrollStrategyOptions.decorators = [ |
| { type: Injectable, args: [{ providedIn: 'root' },] }, |
| ]; |
| /** @nocollapse */ |
| ScrollStrategyOptions.ctorParameters = function () { return [ |
| { type: ScrollDispatcher }, |
| { type: ViewportRuler }, |
| { type: NgZone }, |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } |
| ]; }; |
| /** @nocollapse */ ScrollStrategyOptions.ngInjectableDef = ɵɵdefineInjectable({ factory: function ScrollStrategyOptions_Factory() { return new ScrollStrategyOptions(ɵɵinject(ScrollDispatcher), ɵɵinject(ViewportRuler), ɵɵinject(NgZone), ɵɵinject(DOCUMENT)); }, token: ScrollStrategyOptions, providedIn: "root" }); |
| return ScrollStrategyOptions; |
| }()); |
| |
| /** |
| * @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 |
| */ |
| /** |
| * Initial configuration used when creating an overlay. |
| */ |
| var /** |
| * Initial configuration used when creating an overlay. |
| */ |
| OverlayConfig = /** @class */ (function () { |
| function OverlayConfig(config) { |
| /** |
| * Strategy to be used when handling scroll events while the overlay is open. |
| */ |
| this.scrollStrategy = new NoopScrollStrategy(); |
| /** |
| * Custom class to add to the overlay pane. |
| */ |
| this.panelClass = ''; |
| /** |
| * Whether the overlay has a backdrop. |
| */ |
| this.hasBackdrop = false; |
| /** |
| * Custom class to add to the backdrop |
| */ |
| this.backdropClass = 'cdk-overlay-dark-backdrop'; |
| /** |
| * Whether the overlay should be disposed of 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.disposeOnNavigation = false; |
| if (config) { |
| /** @type {?} */ |
| var configKeys = (/** @type {?} */ (Object.keys(config))); |
| for (var _i = 0, configKeys_1 = configKeys; _i < configKeys_1.length; _i++) { |
| var key = configKeys_1[_i]; |
| if (config[key] !== undefined) { |
| // TypeScript, as of version 3.5, sees the left-hand-side of this expression |
| // as "I don't know *which* key this is, so the only valid value is the intersection |
| // of all the posible values." In this case, that happens to be `undefined`. TypeScript |
| // is not smart enough to see that the right-hand-side is actually an access of the same |
| // exact type with the same exact key, meaning that the value type must be identical. |
| // So we use `any` to work around this. |
| this[key] = (/** @type {?} */ (config[key])); |
| } |
| } |
| } |
| } |
| return OverlayConfig; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * The points of the origin element and the overlay element to connect. |
| */ |
| var /** |
| * The points of the origin element and the overlay element to connect. |
| */ |
| ConnectionPositionPair = /** @class */ (function () { |
| function ConnectionPositionPair(origin, overlay, offsetX, offsetY, panelClass) { |
| this.offsetX = offsetX; |
| this.offsetY = offsetY; |
| this.panelClass = panelClass; |
| this.originX = origin.originX; |
| this.originY = origin.originY; |
| this.overlayX = overlay.overlayX; |
| this.overlayY = overlay.overlayY; |
| } |
| return ConnectionPositionPair; |
| }()); |
| /** |
| * Set of properties regarding the position of the origin and overlay relative to the viewport |
| * with respect to the containing Scrollable elements. |
| * |
| * The overlay and origin are clipped if any part of their bounding client rectangle exceeds the |
| * bounds of any one of the strategy's Scrollable's bounding client rectangle. |
| * |
| * The overlay and origin are outside view if there is no overlap between their bounding client |
| * rectangle and any one of the strategy's Scrollable's bounding client rectangle. |
| * |
| * ----------- ----------- |
| * | outside | | clipped | |
| * | view | -------------------------- |
| * | | | | | | |
| * ---------- | ----------- | |
| * -------------------------- | | |
| * | | | Scrollable | |
| * | | | | |
| * | | -------------------------- |
| * | Scrollable | |
| * | | |
| * -------------------------- |
| * |
| * \@docs-private |
| */ |
| var /** |
| * Set of properties regarding the position of the origin and overlay relative to the viewport |
| * with respect to the containing Scrollable elements. |
| * |
| * The overlay and origin are clipped if any part of their bounding client rectangle exceeds the |
| * bounds of any one of the strategy's Scrollable's bounding client rectangle. |
| * |
| * The overlay and origin are outside view if there is no overlap between their bounding client |
| * rectangle and any one of the strategy's Scrollable's bounding client rectangle. |
| * |
| * ----------- ----------- |
| * | outside | | clipped | |
| * | view | -------------------------- |
| * | | | | | | |
| * ---------- | ----------- | |
| * -------------------------- | | |
| * | | | Scrollable | |
| * | | | | |
| * | | -------------------------- |
| * | Scrollable | |
| * | | |
| * -------------------------- |
| * |
| * \@docs-private |
| */ |
| ScrollingVisibility = /** @class */ (function () { |
| function ScrollingVisibility() { |
| } |
| return ScrollingVisibility; |
| }()); |
| /** |
| * The change event emitted by the strategy when a fallback position is used. |
| */ |
| var ConnectedOverlayPositionChange = /** @class */ (function () { |
| function ConnectedOverlayPositionChange(connectionPair, scrollableViewProperties) { |
| this.connectionPair = connectionPair; |
| this.scrollableViewProperties = scrollableViewProperties; |
| } |
| /** @nocollapse */ |
| ConnectedOverlayPositionChange.ctorParameters = function () { return [ |
| { type: ConnectionPositionPair }, |
| { type: ScrollingVisibility, decorators: [{ type: Optional }] } |
| ]; }; |
| return ConnectedOverlayPositionChange; |
| }()); |
| /** |
| * Validates whether a vertical position property matches the expected values. |
| * \@docs-private |
| * @param {?} property Name of the property being validated. |
| * @param {?} value Value of the property being validated. |
| * @return {?} |
| */ |
| function validateVerticalPosition(property, value) { |
| if (value !== 'top' && value !== 'bottom' && value !== 'center') { |
| throw Error("ConnectedPosition: Invalid " + property + " \"" + value + "\". " + |
| "Expected \"top\", \"bottom\" or \"center\"."); |
| } |
| } |
| /** |
| * Validates whether a horizontal position property matches the expected values. |
| * \@docs-private |
| * @param {?} property Name of the property being validated. |
| * @param {?} value Value of the property being validated. |
| * @return {?} |
| */ |
| function validateHorizontalPosition(property, value) { |
| if (value !== 'start' && value !== 'end' && value !== 'center') { |
| throw Error("ConnectedPosition: Invalid " + property + " \"" + value + "\". " + |
| "Expected \"start\", \"end\" or \"center\"."); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Service for dispatching keyboard events that land on the body to appropriate overlay ref, |
| * if any. It maintains a list of attached overlays to determine best suited overlay based |
| * on event target and order of overlay opens. |
| */ |
| var OverlayKeyboardDispatcher = /** @class */ (function () { |
| function OverlayKeyboardDispatcher(document) { |
| var _this = this; |
| /** |
| * Currently attached overlays in the order they were attached. |
| */ |
| this._attachedOverlays = []; |
| /** |
| * Keyboard event listener that will be attached to the body. |
| */ |
| this._keydownListener = (/** |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| /** @type {?} */ |
| var overlays = _this._attachedOverlays; |
| for (var i = overlays.length - 1; i > -1; i--) { |
| // Dispatch the keydown event to the top overlay which has subscribers to its keydown events. |
| // We want to target the most recent overlay, rather than trying to match where the event came |
| // from, because some components might open an overlay, but keep focus on a trigger element |
| // (e.g. for select and autocomplete). We skip overlays without keydown event subscriptions, |
| // because we don't want overlays that don't handle keyboard events to block the ones below |
| // them that do. |
| if (overlays[i]._keydownEventSubscriptions > 0) { |
| overlays[i]._keydownEvents.next(event); |
| break; |
| } |
| } |
| }); |
| this._document = document; |
| } |
| /** |
| * @return {?} |
| */ |
| OverlayKeyboardDispatcher.prototype.ngOnDestroy = /** |
| * @return {?} |
| */ |
| function () { |
| this._detach(); |
| }; |
| /** Add a new overlay to the list of attached overlay refs. */ |
| /** |
| * Add a new overlay to the list of attached overlay refs. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| OverlayKeyboardDispatcher.prototype.add = /** |
| * Add a new overlay to the list of attached overlay refs. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| // Ensure that we don't get the same overlay multiple times. |
| this.remove(overlayRef); |
| // Lazily start dispatcher once first overlay is added |
| if (!this._isAttached) { |
| this._document.body.addEventListener('keydown', this._keydownListener); |
| this._isAttached = true; |
| } |
| this._attachedOverlays.push(overlayRef); |
| }; |
| /** Remove an overlay from the list of attached overlay refs. */ |
| /** |
| * Remove an overlay from the list of attached overlay refs. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| OverlayKeyboardDispatcher.prototype.remove = /** |
| * Remove an overlay from the list of attached overlay refs. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| /** @type {?} */ |
| var index = this._attachedOverlays.indexOf(overlayRef); |
| if (index > -1) { |
| this._attachedOverlays.splice(index, 1); |
| } |
| // Remove the global listener once there are no more overlays. |
| if (this._attachedOverlays.length === 0) { |
| this._detach(); |
| } |
| }; |
| /** Detaches the global keyboard event listener. */ |
| /** |
| * Detaches the global keyboard event listener. |
| * @private |
| * @return {?} |
| */ |
| OverlayKeyboardDispatcher.prototype._detach = /** |
| * Detaches the global keyboard event listener. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (this._isAttached) { |
| this._document.body.removeEventListener('keydown', this._keydownListener); |
| this._isAttached = false; |
| } |
| }; |
| OverlayKeyboardDispatcher.decorators = [ |
| { type: Injectable, args: [{ providedIn: 'root' },] }, |
| ]; |
| /** @nocollapse */ |
| OverlayKeyboardDispatcher.ctorParameters = function () { return [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } |
| ]; }; |
| /** @nocollapse */ OverlayKeyboardDispatcher.ngInjectableDef = ɵɵdefineInjectable({ factory: function OverlayKeyboardDispatcher_Factory() { return new OverlayKeyboardDispatcher(ɵɵinject(DOCUMENT)); }, token: OverlayKeyboardDispatcher, providedIn: "root" }); |
| return OverlayKeyboardDispatcher; |
| }()); |
| /** |
| * \@docs-private \@deprecated \@breaking-change 8.0.0 |
| * @param {?} dispatcher |
| * @param {?} _document |
| * @return {?} |
| */ |
| function OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY(dispatcher, _document) { |
| return dispatcher || new OverlayKeyboardDispatcher(_document); |
| } |
| /** |
| * \@docs-private \@deprecated \@breaking-change 8.0.0 |
| * @type {?} |
| */ |
| var OVERLAY_KEYBOARD_DISPATCHER_PROVIDER = { |
| // If there is already an OverlayKeyboardDispatcher available, use that. |
| // Otherwise, provide a new one. |
| provide: OverlayKeyboardDispatcher, |
| deps: [ |
| [new Optional(), new SkipSelf(), OverlayKeyboardDispatcher], |
| (/** @type {?} */ ( |
| // Coerce to `InjectionToken` so that the `deps` match the "shape" |
| // of the type expected by Angular |
| DOCUMENT)) |
| ], |
| useFactory: OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Container inside which all overlays will render. |
| */ |
| var OverlayContainer = /** @class */ (function () { |
| function OverlayContainer(_document) { |
| this._document = _document; |
| } |
| /** |
| * @return {?} |
| */ |
| OverlayContainer.prototype.ngOnDestroy = /** |
| * @return {?} |
| */ |
| function () { |
| if (this._containerElement && this._containerElement.parentNode) { |
| this._containerElement.parentNode.removeChild(this._containerElement); |
| } |
| }; |
| /** |
| * This method returns the overlay container element. It will lazily |
| * create the element the first time it is called to facilitate using |
| * the container in non-browser environments. |
| * @returns the container element |
| */ |
| /** |
| * This method returns the overlay container element. It will lazily |
| * create the element the first time it is called to facilitate using |
| * the container in non-browser environments. |
| * @return {?} the container element |
| */ |
| OverlayContainer.prototype.getContainerElement = /** |
| * This method returns the overlay container element. It will lazily |
| * create the element the first time it is called to facilitate using |
| * the container in non-browser environments. |
| * @return {?} the container element |
| */ |
| function () { |
| if (!this._containerElement) { |
| this._createContainer(); |
| } |
| return this._containerElement; |
| }; |
| /** |
| * Create the overlay container element, which is simply a div |
| * with the 'cdk-overlay-container' class on the document body. |
| */ |
| /** |
| * Create the overlay container element, which is simply a div |
| * with the 'cdk-overlay-container' class on the document body. |
| * @protected |
| * @return {?} |
| */ |
| OverlayContainer.prototype._createContainer = /** |
| * Create the overlay container element, which is simply a div |
| * with the 'cdk-overlay-container' class on the document body. |
| * @protected |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var container = this._document.createElement('div'); |
| container.classList.add('cdk-overlay-container'); |
| this._document.body.appendChild(container); |
| this._containerElement = container; |
| }; |
| OverlayContainer.decorators = [ |
| { type: Injectable, args: [{ providedIn: 'root' },] }, |
| ]; |
| /** @nocollapse */ |
| OverlayContainer.ctorParameters = function () { return [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } |
| ]; }; |
| /** @nocollapse */ OverlayContainer.ngInjectableDef = ɵɵdefineInjectable({ factory: function OverlayContainer_Factory() { return new OverlayContainer(ɵɵinject(DOCUMENT)); }, token: OverlayContainer, providedIn: "root" }); |
| return OverlayContainer; |
| }()); |
| /** |
| * \@docs-private \@deprecated \@breaking-change 8.0.0 |
| * @param {?} parentContainer |
| * @param {?} _document |
| * @return {?} |
| */ |
| function OVERLAY_CONTAINER_PROVIDER_FACTORY(parentContainer, _document) { |
| return parentContainer || new OverlayContainer(_document); |
| } |
| /** |
| * \@docs-private \@deprecated \@breaking-change 8.0.0 |
| * @type {?} |
| */ |
| var OVERLAY_CONTAINER_PROVIDER = { |
| // If there is already an OverlayContainer available, use that. Otherwise, provide a new one. |
| provide: OverlayContainer, |
| deps: [ |
| [new Optional(), new SkipSelf(), OverlayContainer], |
| (/** @type {?} */ (DOCUMENT)) |
| ], |
| useFactory: OVERLAY_CONTAINER_PROVIDER_FACTORY |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Reference to an overlay that has been created with the Overlay service. |
| * Used to manipulate or dispose of said overlay. |
| */ |
| var /** |
| * Reference to an overlay that has been created with the Overlay service. |
| * Used to manipulate or dispose of said overlay. |
| */ |
| OverlayRef = /** @class */ (function () { |
| function OverlayRef(_portalOutlet, _host, _pane, _config, _ngZone, _keyboardDispatcher, _document, _location) { |
| var _this = this; |
| this._portalOutlet = _portalOutlet; |
| this._host = _host; |
| this._pane = _pane; |
| this._config = _config; |
| this._ngZone = _ngZone; |
| this._keyboardDispatcher = _keyboardDispatcher; |
| this._document = _document; |
| this._location = _location; |
| this._backdropElement = null; |
| this._backdropClick = new Subject(); |
| this._attachments = new Subject(); |
| this._detachments = new Subject(); |
| this._locationChanges = Subscription.EMPTY; |
| this._backdropClickHandler = (/** |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { return _this._backdropClick.next(event); }); |
| this._keydownEventsObservable = new Observable((/** |
| * @param {?} observer |
| * @return {?} |
| */ |
| function (observer) { |
| /** @type {?} */ |
| var subscription = _this._keydownEvents.subscribe(observer); |
| _this._keydownEventSubscriptions++; |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| subscription.unsubscribe(); |
| _this._keydownEventSubscriptions--; |
| }); |
| })); |
| /** |
| * Stream of keydown events dispatched to this overlay. |
| */ |
| this._keydownEvents = new Subject(); |
| /** |
| * Amount of subscriptions to the keydown events. |
| */ |
| this._keydownEventSubscriptions = 0; |
| if (_config.scrollStrategy) { |
| this._scrollStrategy = _config.scrollStrategy; |
| this._scrollStrategy.attach(this); |
| } |
| this._positionStrategy = _config.positionStrategy; |
| } |
| Object.defineProperty(OverlayRef.prototype, "overlayElement", { |
| /** The overlay's HTML element */ |
| get: /** |
| * The overlay's HTML element |
| * @return {?} |
| */ |
| function () { |
| return this._pane; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(OverlayRef.prototype, "backdropElement", { |
| /** The overlay's backdrop HTML element. */ |
| get: /** |
| * The overlay's backdrop HTML element. |
| * @return {?} |
| */ |
| function () { |
| return this._backdropElement; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(OverlayRef.prototype, "hostElement", { |
| /** |
| * Wrapper around the panel element. Can be used for advanced |
| * positioning where a wrapper with specific styling is |
| * required around the overlay pane. |
| */ |
| get: /** |
| * Wrapper around the panel element. Can be used for advanced |
| * positioning where a wrapper with specific styling is |
| * required around the overlay pane. |
| * @return {?} |
| */ |
| function () { |
| return this._host; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| /** |
| * Attaches content, given via a Portal, to the overlay. |
| * If the overlay is configured to have a backdrop, it will be created. |
| * |
| * @param portal Portal instance to which to attach the overlay. |
| * @returns The portal attachment result. |
| */ |
| /** |
| * Attaches content, given via a Portal, to the overlay. |
| * If the overlay is configured to have a backdrop, it will be created. |
| * |
| * @param {?} portal Portal instance to which to attach the overlay. |
| * @return {?} The portal attachment result. |
| */ |
| OverlayRef.prototype.attach = /** |
| * Attaches content, given via a Portal, to the overlay. |
| * If the overlay is configured to have a backdrop, it will be created. |
| * |
| * @param {?} portal Portal instance to which to attach the overlay. |
| * @return {?} The portal attachment result. |
| */ |
| function (portal) { |
| var _this = this; |
| /** @type {?} */ |
| var attachResult = this._portalOutlet.attach(portal); |
| if (this._positionStrategy) { |
| this._positionStrategy.attach(this); |
| } |
| // Update the pane element with the given configuration. |
| if (!this._host.parentElement && this._previousHostParent) { |
| this._previousHostParent.appendChild(this._host); |
| } |
| this._updateStackingOrder(); |
| this._updateElementSize(); |
| this._updateElementDirection(); |
| if (this._scrollStrategy) { |
| this._scrollStrategy.enable(); |
| } |
| // Update the position once the zone is stable so that the overlay will be fully rendered |
| // before attempting to position it, as the position may depend on the size of the rendered |
| // content. |
| this._ngZone.onStable |
| .asObservable() |
| .pipe(take(1)) |
| .subscribe((/** |
| * @return {?} |
| */ |
| function () { |
| // The overlay could've been detached before the zone has stabilized. |
| if (_this.hasAttached()) { |
| _this.updatePosition(); |
| } |
| })); |
| // Enable pointer events for the overlay pane element. |
| this._togglePointerEvents(true); |
| if (this._config.hasBackdrop) { |
| this._attachBackdrop(); |
| } |
| if (this._config.panelClass) { |
| this._toggleClasses(this._pane, this._config.panelClass, true); |
| } |
| // Only emit the `attachments` event once all other setup is done. |
| this._attachments.next(); |
| // Track this overlay by the keyboard dispatcher |
| this._keyboardDispatcher.add(this); |
| // @breaking-change 8.0.0 remove the null check for `_location` |
| // once the constructor parameter is made required. |
| if (this._config.disposeOnNavigation && this._location) { |
| this._locationChanges = this._location.subscribe((/** |
| * @return {?} |
| */ |
| function () { return _this.dispose(); })); |
| } |
| return attachResult; |
| }; |
| /** |
| * Detaches an overlay from a portal. |
| * @returns The portal detachment result. |
| */ |
| /** |
| * Detaches an overlay from a portal. |
| * @return {?} The portal detachment result. |
| */ |
| OverlayRef.prototype.detach = /** |
| * Detaches an overlay from a portal. |
| * @return {?} The portal detachment result. |
| */ |
| function () { |
| if (!this.hasAttached()) { |
| return; |
| } |
| this.detachBackdrop(); |
| // When the overlay is detached, the pane element should disable pointer events. |
| // This is necessary because otherwise the pane element will cover the page and disable |
| // pointer events therefore. Depends on the position strategy and the applied pane boundaries. |
| this._togglePointerEvents(false); |
| if (this._positionStrategy && this._positionStrategy.detach) { |
| this._positionStrategy.detach(); |
| } |
| if (this._scrollStrategy) { |
| this._scrollStrategy.disable(); |
| } |
| /** @type {?} */ |
| var detachmentResult = this._portalOutlet.detach(); |
| // Only emit after everything is detached. |
| this._detachments.next(); |
| // Remove this overlay from keyboard dispatcher tracking. |
| this._keyboardDispatcher.remove(this); |
| // Keeping the host element in DOM the can cause scroll jank, because it still gets |
| // rendered, even though it's transparent and unclickable which is why we remove it. |
| this._detachContentWhenStable(); |
| // Stop listening for location changes. |
| this._locationChanges.unsubscribe(); |
| return detachmentResult; |
| }; |
| /** Cleans up the overlay from the DOM. */ |
| /** |
| * Cleans up the overlay from the DOM. |
| * @return {?} |
| */ |
| OverlayRef.prototype.dispose = /** |
| * Cleans up the overlay from the DOM. |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var isAttached = this.hasAttached(); |
| if (this._positionStrategy) { |
| this._positionStrategy.dispose(); |
| } |
| this._disposeScrollStrategy(); |
| this.detachBackdrop(); |
| this._locationChanges.unsubscribe(); |
| this._keyboardDispatcher.remove(this); |
| this._portalOutlet.dispose(); |
| this._attachments.complete(); |
| this._backdropClick.complete(); |
| this._keydownEvents.complete(); |
| if (this._host && this._host.parentNode) { |
| this._host.parentNode.removeChild(this._host); |
| this._host = (/** @type {?} */ (null)); |
| } |
| this._previousHostParent = this._pane = (/** @type {?} */ (null)); |
| if (isAttached) { |
| this._detachments.next(); |
| } |
| this._detachments.complete(); |
| }; |
| /** Whether the overlay has attached content. */ |
| /** |
| * Whether the overlay has attached content. |
| * @return {?} |
| */ |
| OverlayRef.prototype.hasAttached = /** |
| * Whether the overlay has attached content. |
| * @return {?} |
| */ |
| function () { |
| return this._portalOutlet.hasAttached(); |
| }; |
| /** Gets an observable that emits when the backdrop has been clicked. */ |
| /** |
| * Gets an observable that emits when the backdrop has been clicked. |
| * @return {?} |
| */ |
| OverlayRef.prototype.backdropClick = /** |
| * Gets an observable that emits when the backdrop has been clicked. |
| * @return {?} |
| */ |
| function () { |
| return this._backdropClick.asObservable(); |
| }; |
| /** Gets an observable that emits when the overlay has been attached. */ |
| /** |
| * Gets an observable that emits when the overlay has been attached. |
| * @return {?} |
| */ |
| OverlayRef.prototype.attachments = /** |
| * Gets an observable that emits when the overlay has been attached. |
| * @return {?} |
| */ |
| function () { |
| return this._attachments.asObservable(); |
| }; |
| /** Gets an observable that emits when the overlay has been detached. */ |
| /** |
| * Gets an observable that emits when the overlay has been detached. |
| * @return {?} |
| */ |
| OverlayRef.prototype.detachments = /** |
| * Gets an observable that emits when the overlay has been detached. |
| * @return {?} |
| */ |
| function () { |
| return this._detachments.asObservable(); |
| }; |
| /** Gets an observable of keydown events targeted to this overlay. */ |
| /** |
| * Gets an observable of keydown events targeted to this overlay. |
| * @return {?} |
| */ |
| OverlayRef.prototype.keydownEvents = /** |
| * Gets an observable of keydown events targeted to this overlay. |
| * @return {?} |
| */ |
| function () { |
| return this._keydownEventsObservable; |
| }; |
| /** Gets the current overlay configuration, which is immutable. */ |
| /** |
| * Gets the current overlay configuration, which is immutable. |
| * @return {?} |
| */ |
| OverlayRef.prototype.getConfig = /** |
| * Gets the current overlay configuration, which is immutable. |
| * @return {?} |
| */ |
| function () { |
| return this._config; |
| }; |
| /** Updates the position of the overlay based on the position strategy. */ |
| /** |
| * Updates the position of the overlay based on the position strategy. |
| * @return {?} |
| */ |
| OverlayRef.prototype.updatePosition = /** |
| * Updates the position of the overlay based on the position strategy. |
| * @return {?} |
| */ |
| function () { |
| if (this._positionStrategy) { |
| this._positionStrategy.apply(); |
| } |
| }; |
| /** Switches to a new position strategy and updates the overlay position. */ |
| /** |
| * Switches to a new position strategy and updates the overlay position. |
| * @param {?} strategy |
| * @return {?} |
| */ |
| OverlayRef.prototype.updatePositionStrategy = /** |
| * Switches to a new position strategy and updates the overlay position. |
| * @param {?} strategy |
| * @return {?} |
| */ |
| function (strategy) { |
| if (strategy === this._positionStrategy) { |
| return; |
| } |
| if (this._positionStrategy) { |
| this._positionStrategy.dispose(); |
| } |
| this._positionStrategy = strategy; |
| if (this.hasAttached()) { |
| strategy.attach(this); |
| this.updatePosition(); |
| } |
| }; |
| /** Update the size properties of the overlay. */ |
| /** |
| * Update the size properties of the overlay. |
| * @param {?} sizeConfig |
| * @return {?} |
| */ |
| OverlayRef.prototype.updateSize = /** |
| * Update the size properties of the overlay. |
| * @param {?} sizeConfig |
| * @return {?} |
| */ |
| function (sizeConfig) { |
| this._config = __assign({}, this._config, sizeConfig); |
| this._updateElementSize(); |
| }; |
| /** Sets the LTR/RTL direction for the overlay. */ |
| /** |
| * Sets the LTR/RTL direction for the overlay. |
| * @param {?} dir |
| * @return {?} |
| */ |
| OverlayRef.prototype.setDirection = /** |
| * Sets the LTR/RTL direction for the overlay. |
| * @param {?} dir |
| * @return {?} |
| */ |
| function (dir) { |
| this._config = __assign({}, this._config, { direction: dir }); |
| this._updateElementDirection(); |
| }; |
| /** Add a CSS class or an array of classes to the overlay pane. */ |
| /** |
| * Add a CSS class or an array of classes to the overlay pane. |
| * @param {?} classes |
| * @return {?} |
| */ |
| OverlayRef.prototype.addPanelClass = /** |
| * Add a CSS class or an array of classes to the overlay pane. |
| * @param {?} classes |
| * @return {?} |
| */ |
| function (classes) { |
| if (this._pane) { |
| this._toggleClasses(this._pane, classes, true); |
| } |
| }; |
| /** Remove a CSS class or an array of classes from the overlay pane. */ |
| /** |
| * Remove a CSS class or an array of classes from the overlay pane. |
| * @param {?} classes |
| * @return {?} |
| */ |
| OverlayRef.prototype.removePanelClass = /** |
| * Remove a CSS class or an array of classes from the overlay pane. |
| * @param {?} classes |
| * @return {?} |
| */ |
| function (classes) { |
| if (this._pane) { |
| this._toggleClasses(this._pane, classes, false); |
| } |
| }; |
| /** |
| * Returns the layout direction of the overlay panel. |
| */ |
| /** |
| * Returns the layout direction of the overlay panel. |
| * @return {?} |
| */ |
| OverlayRef.prototype.getDirection = /** |
| * Returns the layout direction of the overlay panel. |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var direction = this._config.direction; |
| if (!direction) { |
| return 'ltr'; |
| } |
| return typeof direction === 'string' ? direction : direction.value; |
| }; |
| /** Switches to a new scroll strategy. */ |
| /** |
| * Switches to a new scroll strategy. |
| * @param {?} strategy |
| * @return {?} |
| */ |
| OverlayRef.prototype.updateScrollStrategy = /** |
| * Switches to a new scroll strategy. |
| * @param {?} strategy |
| * @return {?} |
| */ |
| function (strategy) { |
| if (strategy === this._scrollStrategy) { |
| return; |
| } |
| this._disposeScrollStrategy(); |
| this._scrollStrategy = strategy; |
| if (this.hasAttached()) { |
| strategy.attach(this); |
| strategy.enable(); |
| } |
| }; |
| /** Updates the text direction of the overlay panel. */ |
| /** |
| * Updates the text direction of the overlay panel. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._updateElementDirection = /** |
| * Updates the text direction of the overlay panel. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| this._host.setAttribute('dir', this.getDirection()); |
| }; |
| /** Updates the size of the overlay element based on the overlay config. */ |
| /** |
| * Updates the size of the overlay element based on the overlay config. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._updateElementSize = /** |
| * Updates the size of the overlay element based on the overlay config. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var style = this._pane.style; |
| style.width = coerceCssPixelValue(this._config.width); |
| style.height = coerceCssPixelValue(this._config.height); |
| style.minWidth = coerceCssPixelValue(this._config.minWidth); |
| style.minHeight = coerceCssPixelValue(this._config.minHeight); |
| style.maxWidth = coerceCssPixelValue(this._config.maxWidth); |
| style.maxHeight = coerceCssPixelValue(this._config.maxHeight); |
| }; |
| /** Toggles the pointer events for the overlay pane element. */ |
| /** |
| * Toggles the pointer events for the overlay pane element. |
| * @private |
| * @param {?} enablePointer |
| * @return {?} |
| */ |
| OverlayRef.prototype._togglePointerEvents = /** |
| * Toggles the pointer events for the overlay pane element. |
| * @private |
| * @param {?} enablePointer |
| * @return {?} |
| */ |
| function (enablePointer) { |
| this._pane.style.pointerEvents = enablePointer ? 'auto' : 'none'; |
| }; |
| /** Attaches a backdrop for this overlay. */ |
| /** |
| * Attaches a backdrop for this overlay. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._attachBackdrop = /** |
| * Attaches a backdrop for this overlay. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| /** @type {?} */ |
| var showingClass = 'cdk-overlay-backdrop-showing'; |
| this._backdropElement = this._document.createElement('div'); |
| this._backdropElement.classList.add('cdk-overlay-backdrop'); |
| if (this._config.backdropClass) { |
| this._toggleClasses(this._backdropElement, this._config.backdropClass, true); |
| } |
| // Insert the backdrop before the pane in the DOM order, |
| // in order to handle stacked overlays properly. |
| (/** @type {?} */ (this._host.parentElement)).insertBefore(this._backdropElement, this._host); |
| // Forward backdrop clicks such that the consumer of the overlay can perform whatever |
| // action desired when such a click occurs (usually closing the overlay). |
| this._backdropElement.addEventListener('click', this._backdropClickHandler); |
| // Add class to fade-in the backdrop after one frame. |
| if (typeof requestAnimationFrame !== 'undefined') { |
| this._ngZone.runOutsideAngular((/** |
| * @return {?} |
| */ |
| function () { |
| requestAnimationFrame((/** |
| * @return {?} |
| */ |
| function () { |
| if (_this._backdropElement) { |
| _this._backdropElement.classList.add(showingClass); |
| } |
| })); |
| })); |
| } |
| else { |
| this._backdropElement.classList.add(showingClass); |
| } |
| }; |
| /** |
| * Updates the stacking order of the element, moving it to the top if necessary. |
| * This is required in cases where one overlay was detached, while another one, |
| * that should be behind it, was destroyed. The next time both of them are opened, |
| * the stacking will be wrong, because the detached element's pane will still be |
| * in its original DOM position. |
| */ |
| /** |
| * Updates the stacking order of the element, moving it to the top if necessary. |
| * This is required in cases where one overlay was detached, while another one, |
| * that should be behind it, was destroyed. The next time both of them are opened, |
| * the stacking will be wrong, because the detached element's pane will still be |
| * in its original DOM position. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._updateStackingOrder = /** |
| * Updates the stacking order of the element, moving it to the top if necessary. |
| * This is required in cases where one overlay was detached, while another one, |
| * that should be behind it, was destroyed. The next time both of them are opened, |
| * the stacking will be wrong, because the detached element's pane will still be |
| * in its original DOM position. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (this._host.nextSibling) { |
| (/** @type {?} */ (this._host.parentNode)).appendChild(this._host); |
| } |
| }; |
| /** Detaches the backdrop (if any) associated with the overlay. */ |
| /** |
| * Detaches the backdrop (if any) associated with the overlay. |
| * @return {?} |
| */ |
| OverlayRef.prototype.detachBackdrop = /** |
| * Detaches the backdrop (if any) associated with the overlay. |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| /** @type {?} */ |
| var backdropToDetach = this._backdropElement; |
| if (!backdropToDetach) { |
| return; |
| } |
| /** @type {?} */ |
| var timeoutId; |
| /** @type {?} */ |
| var finishDetach = (/** |
| * @return {?} |
| */ |
| function () { |
| // It may not be attached to anything in certain cases (e.g. unit tests). |
| if (backdropToDetach) { |
| backdropToDetach.removeEventListener('click', _this._backdropClickHandler); |
| backdropToDetach.removeEventListener('transitionend', finishDetach); |
| if (backdropToDetach.parentNode) { |
| backdropToDetach.parentNode.removeChild(backdropToDetach); |
| } |
| } |
| // It is possible that a new portal has been attached to this overlay since we started |
| // removing the backdrop. If that is the case, only clear the backdrop reference if it |
| // is still the same instance that we started to remove. |
| if (_this._backdropElement == backdropToDetach) { |
| _this._backdropElement = null; |
| } |
| if (_this._config.backdropClass) { |
| _this._toggleClasses((/** @type {?} */ (backdropToDetach)), _this._config.backdropClass, false); |
| } |
| clearTimeout(timeoutId); |
| }); |
| backdropToDetach.classList.remove('cdk-overlay-backdrop-showing'); |
| this._ngZone.runOutsideAngular((/** |
| * @return {?} |
| */ |
| function () { |
| (/** @type {?} */ (backdropToDetach)).addEventListener('transitionend', finishDetach); |
| })); |
| // If the backdrop doesn't have a transition, the `transitionend` event won't fire. |
| // In this case we make it unclickable and we try to remove it after a delay. |
| backdropToDetach.style.pointerEvents = 'none'; |
| // Run this outside the Angular zone because there's nothing that Angular cares about. |
| // If it were to run inside the Angular zone, every test that used Overlay would have to be |
| // either async or fakeAsync. |
| timeoutId = this._ngZone.runOutsideAngular((/** |
| * @return {?} |
| */ |
| function () { return setTimeout(finishDetach, 500); })); |
| }; |
| /** Toggles a single CSS class or an array of classes on an element. */ |
| /** |
| * Toggles a single CSS class or an array of classes on an element. |
| * @private |
| * @param {?} element |
| * @param {?} cssClasses |
| * @param {?} isAdd |
| * @return {?} |
| */ |
| OverlayRef.prototype._toggleClasses = /** |
| * Toggles a single CSS class or an array of classes on an element. |
| * @private |
| * @param {?} element |
| * @param {?} cssClasses |
| * @param {?} isAdd |
| * @return {?} |
| */ |
| function (element, cssClasses, isAdd) { |
| /** @type {?} */ |
| var classList = element.classList; |
| coerceArray(cssClasses).forEach((/** |
| * @param {?} cssClass |
| * @return {?} |
| */ |
| function (cssClass) { |
| // We can't do a spread here, because IE doesn't support setting multiple classes. |
| isAdd ? classList.add(cssClass) : classList.remove(cssClass); |
| })); |
| }; |
| /** Detaches the overlay content next time the zone stabilizes. */ |
| /** |
| * Detaches the overlay content next time the zone stabilizes. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._detachContentWhenStable = /** |
| * Detaches the overlay content next time the zone stabilizes. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| // Normally we wouldn't have to explicitly run this outside the `NgZone`, however |
| // if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will |
| // be patched to run inside the zone, which will throw us into an infinite loop. |
| this._ngZone.runOutsideAngular((/** |
| * @return {?} |
| */ |
| function () { |
| // We can't remove the host here immediately, because the overlay pane's content |
| // might still be animating. This stream helps us avoid interrupting the animation |
| // by waiting for the pane to become empty. |
| /** @type {?} */ |
| var subscription = _this._ngZone.onStable |
| .asObservable() |
| .pipe(takeUntil(merge(_this._attachments, _this._detachments))) |
| .subscribe((/** |
| * @return {?} |
| */ |
| function () { |
| // Needs a couple of checks for the pane and host, because |
| // they may have been removed by the time the zone stabilizes. |
| if (!_this._pane || !_this._host || _this._pane.children.length === 0) { |
| if (_this._pane && _this._config.panelClass) { |
| _this._toggleClasses(_this._pane, _this._config.panelClass, false); |
| } |
| if (_this._host && _this._host.parentElement) { |
| _this._previousHostParent = _this._host.parentElement; |
| _this._previousHostParent.removeChild(_this._host); |
| } |
| subscription.unsubscribe(); |
| } |
| })); |
| })); |
| }; |
| /** Disposes of a scroll strategy. */ |
| /** |
| * Disposes of a scroll strategy. |
| * @private |
| * @return {?} |
| */ |
| OverlayRef.prototype._disposeScrollStrategy = /** |
| * Disposes of a scroll strategy. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var scrollStrategy = this._scrollStrategy; |
| if (scrollStrategy) { |
| scrollStrategy.disable(); |
| if (scrollStrategy.detach) { |
| scrollStrategy.detach(); |
| } |
| } |
| }; |
| return OverlayRef; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| // TODO: refactor clipping detection into a separate thing (part of scrolling module) |
| // TODO: doesn't handle both flexible width and height when it has to scroll along both axis. |
| /** |
| * Class to be added to the overlay bounding box. |
| * @type {?} |
| */ |
| var boundingBoxClass = 'cdk-overlay-connected-position-bounding-box'; |
| /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * implicit position relative some origin element. The relative position is defined in terms of |
| * a point on the origin element that is connected to a point on the overlay element. For example, |
| * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner |
| * of the overlay. |
| */ |
| var /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * implicit position relative some origin element. The relative position is defined in terms of |
| * a point on the origin element that is connected to a point on the overlay element. For example, |
| * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner |
| * of the overlay. |
| */ |
| FlexibleConnectedPositionStrategy = /** @class */ (function () { |
| function FlexibleConnectedPositionStrategy(connectedTo, _viewportRuler, _document, _platform, _overlayContainer) { |
| this._viewportRuler = _viewportRuler; |
| this._document = _document; |
| this._platform = _platform; |
| this._overlayContainer = _overlayContainer; |
| /** |
| * Last size used for the bounding box. Used to avoid resizing the overlay after open. |
| */ |
| this._lastBoundingBoxSize = { width: 0, height: 0 }; |
| /** |
| * Whether the overlay was pushed in a previous positioning. |
| */ |
| this._isPushed = false; |
| /** |
| * Whether the overlay can be pushed on-screen on the initial open. |
| */ |
| this._canPush = true; |
| /** |
| * Whether the overlay can grow via flexible width/height after the initial open. |
| */ |
| this._growAfterOpen = false; |
| /** |
| * Whether the overlay's width and height can be constrained to fit within the viewport. |
| */ |
| this._hasFlexibleDimensions = true; |
| /** |
| * Whether the overlay position is locked. |
| */ |
| this._positionLocked = false; |
| /** |
| * Amount of space that must be maintained between the overlay and the edge of the viewport. |
| */ |
| this._viewportMargin = 0; |
| /** |
| * The Scrollable containers used to check scrollable view properties on position change. |
| */ |
| this._scrollables = []; |
| /** |
| * Ordered list of preferred positions, from most to least desirable. |
| */ |
| this._preferredPositions = []; |
| /** |
| * Subject that emits whenever the position changes. |
| */ |
| this._positionChanges = new Subject(); |
| /** |
| * Subscription to viewport size changes. |
| */ |
| this._resizeSubscription = Subscription.EMPTY; |
| /** |
| * Default offset for the overlay along the x axis. |
| */ |
| this._offsetX = 0; |
| /** |
| * Default offset for the overlay along the y axis. |
| */ |
| this._offsetY = 0; |
| /** |
| * Keeps track of the CSS classes that the position strategy has applied on the overlay panel. |
| */ |
| this._appliedPanelClasses = []; |
| /** |
| * Observable sequence of position changes. |
| */ |
| this.positionChanges = this._positionChanges.asObservable(); |
| this.setOrigin(connectedTo); |
| } |
| Object.defineProperty(FlexibleConnectedPositionStrategy.prototype, "positions", { |
| /** Ordered list of preferred positions, from most to least desirable. */ |
| get: /** |
| * Ordered list of preferred positions, from most to least desirable. |
| * @return {?} |
| */ |
| function () { |
| return this._preferredPositions; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| /** Attaches this position strategy to an overlay. */ |
| /** |
| * Attaches this position strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.attach = /** |
| * Attaches this position strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| var _this = this; |
| if (this._overlayRef && overlayRef !== this._overlayRef) { |
| throw Error('This position strategy is already attached to an overlay'); |
| } |
| this._validatePositions(); |
| overlayRef.hostElement.classList.add(boundingBoxClass); |
| this._overlayRef = overlayRef; |
| this._boundingBox = overlayRef.hostElement; |
| this._pane = overlayRef.overlayElement; |
| this._isDisposed = false; |
| this._isInitialRender = true; |
| this._lastPosition = null; |
| this._resizeSubscription.unsubscribe(); |
| this._resizeSubscription = this._viewportRuler.change().subscribe((/** |
| * @return {?} |
| */ |
| function () { |
| // When the window is resized, we want to trigger the next reposition as if it |
| // was an initial render, in order for the strategy to pick a new optimal position, |
| // otherwise position locking will cause it to stay at the old one. |
| _this._isInitialRender = true; |
| _this.apply(); |
| })); |
| }; |
| /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin best fits on-screen. |
| * |
| * The selection of a position goes as follows: |
| * - If any positions fit completely within the viewport as-is, |
| * choose the first position that does so. |
| * - If flexible dimensions are enabled and at least one satifies the given minimum width/height, |
| * choose the position with the greatest available size modified by the positions' weight. |
| * - If pushing is enabled, take the position that went off-screen the least and push it |
| * on-screen. |
| * - If none of the previous criteria were met, use the position that goes off-screen the least. |
| * @docs-private |
| */ |
| /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin best fits on-screen. |
| * |
| * The selection of a position goes as follows: |
| * - If any positions fit completely within the viewport as-is, |
| * choose the first position that does so. |
| * - If flexible dimensions are enabled and at least one satifies the given minimum width/height, |
| * choose the position with the greatest available size modified by the positions' weight. |
| * - If pushing is enabled, take the position that went off-screen the least and push it |
| * on-screen. |
| * - If none of the previous criteria were met, use the position that goes off-screen the least. |
| * \@docs-private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.apply = /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin best fits on-screen. |
| * |
| * The selection of a position goes as follows: |
| * - If any positions fit completely within the viewport as-is, |
| * choose the first position that does so. |
| * - If flexible dimensions are enabled and at least one satifies the given minimum width/height, |
| * choose the position with the greatest available size modified by the positions' weight. |
| * - If pushing is enabled, take the position that went off-screen the least and push it |
| * on-screen. |
| * - If none of the previous criteria were met, use the position that goes off-screen the least. |
| * \@docs-private |
| * @return {?} |
| */ |
| function () { |
| // We shouldn't do anything if the strategy was disposed or we're on the server. |
| if (this._isDisposed || !this._platform.isBrowser) { |
| return; |
| } |
| // If the position has been applied already (e.g. when the overlay was opened) and the |
| // consumer opted into locking in the position, re-use the old position, in order to |
| // prevent the overlay from jumping around. |
| if (!this._isInitialRender && this._positionLocked && this._lastPosition) { |
| this.reapplyLastPosition(); |
| return; |
| } |
| this._clearPanelClasses(); |
| this._resetOverlayElementStyles(); |
| this._resetBoundingBoxStyles(); |
| // We need the bounding rects for the origin and the overlay to determine how to position |
| // the overlay relative to the origin. |
| // We use the viewport rect to determine whether a position would go off-screen. |
| this._viewportRect = this._getNarrowedViewportRect(); |
| this._originRect = this._getOriginRect(); |
| this._overlayRect = this._pane.getBoundingClientRect(); |
| /** @type {?} */ |
| var originRect = this._originRect; |
| /** @type {?} */ |
| var overlayRect = this._overlayRect; |
| /** @type {?} */ |
| var viewportRect = this._viewportRect; |
| // Positions where the overlay will fit with flexible dimensions. |
| /** @type {?} */ |
| var flexibleFits = []; |
| // Fallback if none of the preferred positions fit within the viewport. |
| /** @type {?} */ |
| var fallback; |
| // Go through each of the preferred positions looking for a good fit. |
| // If a good fit is found, it will be applied immediately. |
| for (var _i = 0, _a = this._preferredPositions; _i < _a.length; _i++) { |
| var pos = _a[_i]; |
| // Get the exact (x, y) coordinate for the point-of-origin on the origin element. |
| /** @type {?} */ |
| var originPoint = this._getOriginPoint(originRect, pos); |
| // From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the |
| // overlay in this position. We use the top-left corner for calculations and later translate |
| // this into an appropriate (top, left, bottom, right) style. |
| /** @type {?} */ |
| var overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos); |
| // Calculate how well the overlay would fit into the viewport with this point. |
| /** @type {?} */ |
| var overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos); |
| // If the overlay, without any further work, fits into the viewport, use this position. |
| if (overlayFit.isCompletelyWithinViewport) { |
| this._isPushed = false; |
| this._applyPosition(pos, originPoint); |
| return; |
| } |
| // If the overlay has flexible dimensions, we can use this position |
| // so long as there's enough space for the minimum dimensions. |
| if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) { |
| // Save positions where the overlay will fit with flexible dimensions. We will use these |
| // if none of the positions fit *without* flexible dimensions. |
| flexibleFits.push({ |
| position: pos, |
| origin: originPoint, |
| overlayRect: overlayRect, |
| boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos) |
| }); |
| continue; |
| } |
| // If the current preferred position does not fit on the screen, remember the position |
| // if it has more visible area on-screen than we've seen and move onto the next preferred |
| // position. |
| if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) { |
| fallback = { overlayFit: overlayFit, overlayPoint: overlayPoint, originPoint: originPoint, position: pos, overlayRect: overlayRect }; |
| } |
| } |
| // If there are any positions where the overlay would fit with flexible dimensions, choose the |
| // one that has the greatest area available modified by the position's weight |
| if (flexibleFits.length) { |
| /** @type {?} */ |
| var bestFit = null; |
| /** @type {?} */ |
| var bestScore = -1; |
| for (var _b = 0, flexibleFits_1 = flexibleFits; _b < flexibleFits_1.length; _b++) { |
| var fit = flexibleFits_1[_b]; |
| /** @type {?} */ |
| var score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1); |
| if (score > bestScore) { |
| bestScore = score; |
| bestFit = fit; |
| } |
| } |
| this._isPushed = false; |
| this._applyPosition((/** @type {?} */ (bestFit)).position, (/** @type {?} */ (bestFit)).origin); |
| return; |
| } |
| // When none of the preferred positions fit within the viewport, take the position |
| // that went off-screen the least and attempt to push it on-screen. |
| if (this._canPush) { |
| // TODO(jelbourn): after pushing, the opening "direction" of the overlay might not make sense. |
| this._isPushed = true; |
| this._applyPosition((/** @type {?} */ (fallback)).position, (/** @type {?} */ (fallback)).originPoint); |
| return; |
| } |
| // All options for getting the overlay within the viewport have been exhausted, so go with the |
| // position that went off-screen the least. |
| this._applyPosition((/** @type {?} */ (fallback)).position, (/** @type {?} */ (fallback)).originPoint); |
| }; |
| /** |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.detach = /** |
| * @return {?} |
| */ |
| function () { |
| this._clearPanelClasses(); |
| this._lastPosition = null; |
| this._previousPushAmount = null; |
| this._resizeSubscription.unsubscribe(); |
| }; |
| /** Cleanup after the element gets destroyed. */ |
| /** |
| * Cleanup after the element gets destroyed. |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.dispose = /** |
| * Cleanup after the element gets destroyed. |
| * @return {?} |
| */ |
| function () { |
| if (this._isDisposed) { |
| return; |
| } |
| // We can't use `_resetBoundingBoxStyles` here, because it resets |
| // some properties to zero, rather than removing them. |
| if (this._boundingBox) { |
| extendStyles(this._boundingBox.style, (/** @type {?} */ ({ |
| top: '', |
| left: '', |
| right: '', |
| bottom: '', |
| height: '', |
| width: '', |
| alignItems: '', |
| justifyContent: '', |
| }))); |
| } |
| if (this._pane) { |
| this._resetOverlayElementStyles(); |
| } |
| if (this._overlayRef) { |
| this._overlayRef.hostElement.classList.remove(boundingBoxClass); |
| } |
| this.detach(); |
| this._positionChanges.complete(); |
| this._overlayRef = this._boundingBox = (/** @type {?} */ (null)); |
| this._isDisposed = true; |
| }; |
| /** |
| * This re-aligns the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| */ |
| /** |
| * This re-aligns the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.reapplyLastPosition = /** |
| * This re-aligns the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| * @return {?} |
| */ |
| function () { |
| if (!this._isDisposed && (!this._platform || this._platform.isBrowser)) { |
| this._originRect = this._getOriginRect(); |
| this._overlayRect = this._pane.getBoundingClientRect(); |
| this._viewportRect = this._getNarrowedViewportRect(); |
| /** @type {?} */ |
| var lastPosition = this._lastPosition || this._preferredPositions[0]; |
| /** @type {?} */ |
| var originPoint = this._getOriginPoint(this._originRect, lastPosition); |
| this._applyPosition(lastPosition, originPoint); |
| } |
| }; |
| /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| */ |
| /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} scrollables |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withScrollableContainers = /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} scrollables |
| * @return {THIS} |
| */ |
| function (scrollables) { |
| (/** @type {?} */ (this))._scrollables = scrollables; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Adds new preferred positions. |
| * @param positions List of positions options for this overlay. |
| */ |
| /** |
| * Adds new preferred positions. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} positions List of positions options for this overlay. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withPositions = /** |
| * Adds new preferred positions. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} positions List of positions options for this overlay. |
| * @return {THIS} |
| */ |
| function (positions) { |
| (/** @type {?} */ (this))._preferredPositions = positions; |
| // If the last calculated position object isn't part of the positions anymore, clear |
| // it in order to avoid it being picked up if the consumer tries to re-apply. |
| if (positions.indexOf((/** @type {?} */ ((/** @type {?} */ (this))._lastPosition))) === -1) { |
| (/** @type {?} */ (this))._lastPosition = null; |
| } |
| (/** @type {?} */ (this))._validatePositions(); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets a minimum distance the overlay may be positioned to the edge of the viewport. |
| * @param margin Required margin between the overlay and the viewport edge in pixels. |
| */ |
| /** |
| * Sets a minimum distance the overlay may be positioned to the edge of the viewport. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} margin Required margin between the overlay and the viewport edge in pixels. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withViewportMargin = /** |
| * Sets a minimum distance the overlay may be positioned to the edge of the viewport. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} margin Required margin between the overlay and the viewport edge in pixels. |
| * @return {THIS} |
| */ |
| function (margin) { |
| (/** @type {?} */ (this))._viewportMargin = margin; |
| return (/** @type {?} */ (this)); |
| }; |
| /** Sets whether the overlay's width and height can be constrained to fit within the viewport. */ |
| /** |
| * Sets whether the overlay's width and height can be constrained to fit within the viewport. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} flexibleDimensions |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withFlexibleDimensions = /** |
| * Sets whether the overlay's width and height can be constrained to fit within the viewport. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} flexibleDimensions |
| * @return {THIS} |
| */ |
| function (flexibleDimensions) { |
| if (flexibleDimensions === void 0) { flexibleDimensions = true; } |
| (/** @type {?} */ (this))._hasFlexibleDimensions = flexibleDimensions; |
| return (/** @type {?} */ (this)); |
| }; |
| /** Sets whether the overlay can grow after the initial open via flexible width/height. */ |
| /** |
| * Sets whether the overlay can grow after the initial open via flexible width/height. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} growAfterOpen |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withGrowAfterOpen = /** |
| * Sets whether the overlay can grow after the initial open via flexible width/height. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} growAfterOpen |
| * @return {THIS} |
| */ |
| function (growAfterOpen) { |
| if (growAfterOpen === void 0) { growAfterOpen = true; } |
| (/** @type {?} */ (this))._growAfterOpen = growAfterOpen; |
| return (/** @type {?} */ (this)); |
| }; |
| /** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */ |
| /** |
| * Sets whether the overlay can be pushed on-screen if none of the provided positions fit. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} canPush |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withPush = /** |
| * Sets whether the overlay can be pushed on-screen if none of the provided positions fit. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} canPush |
| * @return {THIS} |
| */ |
| function (canPush) { |
| if (canPush === void 0) { canPush = true; } |
| (/** @type {?} */ (this))._canPush = canPush; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @param isLocked Whether the overlay should locked in. |
| */ |
| /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} isLocked Whether the overlay should locked in. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withLockedPosition = /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} isLocked Whether the overlay should locked in. |
| * @return {THIS} |
| */ |
| function (isLocked) { |
| if (isLocked === void 0) { isLocked = true; } |
| (/** @type {?} */ (this))._positionLocked = isLocked; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the origin, relative to which to position the overlay. |
| * Using an element origin is useful for building components that need to be positioned |
| * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be |
| * used for cases like contextual menus which open relative to the user's pointer. |
| * @param origin Reference to the new origin. |
| */ |
| /** |
| * Sets the origin, relative to which to position the overlay. |
| * Using an element origin is useful for building components that need to be positioned |
| * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be |
| * used for cases like contextual menus which open relative to the user's pointer. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} origin Reference to the new origin. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.setOrigin = /** |
| * Sets the origin, relative to which to position the overlay. |
| * Using an element origin is useful for building components that need to be positioned |
| * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be |
| * used for cases like contextual menus which open relative to the user's pointer. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} origin Reference to the new origin. |
| * @return {THIS} |
| */ |
| function (origin) { |
| (/** @type {?} */ (this))._origin = origin; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the default offset for the overlay's connection point on the x-axis. |
| * @param offset New offset in the X axis. |
| */ |
| /** |
| * Sets the default offset for the overlay's connection point on the x-axis. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the X axis. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withDefaultOffsetX = /** |
| * Sets the default offset for the overlay's connection point on the x-axis. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the X axis. |
| * @return {THIS} |
| */ |
| function (offset) { |
| (/** @type {?} */ (this))._offsetX = offset; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the default offset for the overlay's connection point on the y-axis. |
| * @param offset New offset in the Y axis. |
| */ |
| /** |
| * Sets the default offset for the overlay's connection point on the y-axis. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the Y axis. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withDefaultOffsetY = /** |
| * Sets the default offset for the overlay's connection point on the y-axis. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the Y axis. |
| * @return {THIS} |
| */ |
| function (offset) { |
| (/** @type {?} */ (this))._offsetY = offset; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Configures that the position strategy should set a `transform-origin` on some elements |
| * inside the overlay, depending on the current position that is being applied. This is |
| * useful for the cases where the origin of an animation can change depending on the |
| * alignment of the overlay. |
| * @param selector CSS selector that will be used to find the target |
| * elements onto which to set the transform origin. |
| */ |
| /** |
| * Configures that the position strategy should set a `transform-origin` on some elements |
| * inside the overlay, depending on the current position that is being applied. This is |
| * useful for the cases where the origin of an animation can change depending on the |
| * alignment of the overlay. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} selector CSS selector that will be used to find the target |
| * elements onto which to set the transform origin. |
| * @return {THIS} |
| */ |
| FlexibleConnectedPositionStrategy.prototype.withTransformOriginOn = /** |
| * Configures that the position strategy should set a `transform-origin` on some elements |
| * inside the overlay, depending on the current position that is being applied. This is |
| * useful for the cases where the origin of an animation can change depending on the |
| * alignment of the overlay. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} selector CSS selector that will be used to find the target |
| * elements onto which to set the transform origin. |
| * @return {THIS} |
| */ |
| function (selector) { |
| (/** @type {?} */ (this))._transformOriginSelector = selector; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Gets the (x, y) coordinate of a connection point on the origin based on a relative position. |
| */ |
| /** |
| * Gets the (x, y) coordinate of a connection point on the origin based on a relative position. |
| * @private |
| * @param {?} originRect |
| * @param {?} pos |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getOriginPoint = /** |
| * Gets the (x, y) coordinate of a connection point on the origin based on a relative position. |
| * @private |
| * @param {?} originRect |
| * @param {?} pos |
| * @return {?} |
| */ |
| function (originRect, pos) { |
| /** @type {?} */ |
| var x; |
| if (pos.originX == 'center') { |
| // Note: when centering we should always use the `left` |
| // offset, otherwise the position will be wrong in RTL. |
| x = originRect.left + (originRect.width / 2); |
| } |
| else { |
| /** @type {?} */ |
| var startX = this._isRtl() ? originRect.right : originRect.left; |
| /** @type {?} */ |
| var endX = this._isRtl() ? originRect.left : originRect.right; |
| x = pos.originX == 'start' ? startX : endX; |
| } |
| /** @type {?} */ |
| var y; |
| if (pos.originY == 'center') { |
| y = originRect.top + (originRect.height / 2); |
| } |
| else { |
| y = pos.originY == 'top' ? originRect.top : originRect.bottom; |
| } |
| return { x: x, y: y }; |
| }; |
| /** |
| * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and |
| * origin point to which the overlay should be connected. |
| */ |
| /** |
| * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and |
| * origin point to which the overlay should be connected. |
| * @private |
| * @param {?} originPoint |
| * @param {?} overlayRect |
| * @param {?} pos |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getOverlayPoint = /** |
| * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and |
| * origin point to which the overlay should be connected. |
| * @private |
| * @param {?} originPoint |
| * @param {?} overlayRect |
| * @param {?} pos |
| * @return {?} |
| */ |
| function (originPoint, overlayRect, pos) { |
| // Calculate the (overlayStartX, overlayStartY), the start of the |
| // potential overlay position relative to the origin point. |
| /** @type {?} */ |
| var overlayStartX; |
| if (pos.overlayX == 'center') { |
| overlayStartX = -overlayRect.width / 2; |
| } |
| else if (pos.overlayX === 'start') { |
| overlayStartX = this._isRtl() ? -overlayRect.width : 0; |
| } |
| else { |
| overlayStartX = this._isRtl() ? 0 : -overlayRect.width; |
| } |
| /** @type {?} */ |
| var overlayStartY; |
| if (pos.overlayY == 'center') { |
| overlayStartY = -overlayRect.height / 2; |
| } |
| else { |
| overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height; |
| } |
| // The (x, y) coordinates of the overlay. |
| return { |
| x: originPoint.x + overlayStartX, |
| y: originPoint.y + overlayStartY, |
| }; |
| }; |
| /** Gets how well an overlay at the given point will fit within the viewport. */ |
| /** |
| * Gets how well an overlay at the given point will fit within the viewport. |
| * @private |
| * @param {?} point |
| * @param {?} overlay |
| * @param {?} viewport |
| * @param {?} position |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getOverlayFit = /** |
| * Gets how well an overlay at the given point will fit within the viewport. |
| * @private |
| * @param {?} point |
| * @param {?} overlay |
| * @param {?} viewport |
| * @param {?} position |
| * @return {?} |
| */ |
| function (point, overlay, viewport, position) { |
| var x = point.x, y = point.y; |
| /** @type {?} */ |
| var offsetX = this._getOffset(position, 'x'); |
| /** @type {?} */ |
| var offsetY = this._getOffset(position, 'y'); |
| // Account for the offsets since they could push the overlay out of the viewport. |
| if (offsetX) { |
| x += offsetX; |
| } |
| if (offsetY) { |
| y += offsetY; |
| } |
| // How much the overlay would overflow at this position, on each side. |
| /** @type {?} */ |
| var leftOverflow = 0 - x; |
| /** @type {?} */ |
| var rightOverflow = (x + overlay.width) - viewport.width; |
| /** @type {?} */ |
| var topOverflow = 0 - y; |
| /** @type {?} */ |
| var bottomOverflow = (y + overlay.height) - viewport.height; |
| // Visible parts of the element on each axis. |
| /** @type {?} */ |
| var visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow); |
| /** @type {?} */ |
| var visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow); |
| /** @type {?} */ |
| var visibleArea = visibleWidth * visibleHeight; |
| return { |
| visibleArea: visibleArea, |
| isCompletelyWithinViewport: (overlay.width * overlay.height) === visibleArea, |
| fitsInViewportVertically: visibleHeight === overlay.height, |
| fitsInViewportHorizontally: visibleWidth == overlay.width, |
| }; |
| }; |
| /** |
| * Whether the overlay can fit within the viewport when it may resize either its width or height. |
| * @param fit How well the overlay fits in the viewport at some position. |
| * @param point The (x, y) coordinates of the overlat at some position. |
| * @param viewport The geometry of the viewport. |
| */ |
| /** |
| * Whether the overlay can fit within the viewport when it may resize either its width or height. |
| * @private |
| * @param {?} fit How well the overlay fits in the viewport at some position. |
| * @param {?} point The (x, y) coordinates of the overlat at some position. |
| * @param {?} viewport The geometry of the viewport. |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._canFitWithFlexibleDimensions = /** |
| * Whether the overlay can fit within the viewport when it may resize either its width or height. |
| * @private |
| * @param {?} fit How well the overlay fits in the viewport at some position. |
| * @param {?} point The (x, y) coordinates of the overlat at some position. |
| * @param {?} viewport The geometry of the viewport. |
| * @return {?} |
| */ |
| function (fit, point, viewport) { |
| if (this._hasFlexibleDimensions) { |
| /** @type {?} */ |
| var availableHeight = viewport.bottom - point.y; |
| /** @type {?} */ |
| var availableWidth = viewport.right - point.x; |
| /** @type {?} */ |
| var minHeight = this._overlayRef.getConfig().minHeight; |
| /** @type {?} */ |
| var minWidth = this._overlayRef.getConfig().minWidth; |
| /** @type {?} */ |
| var verticalFit = fit.fitsInViewportVertically || |
| (minHeight != null && minHeight <= availableHeight); |
| /** @type {?} */ |
| var horizontalFit = fit.fitsInViewportHorizontally || |
| (minWidth != null && minWidth <= availableWidth); |
| return verticalFit && horizontalFit; |
| } |
| }; |
| /** |
| * Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than |
| * the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the |
| * right and bottom). |
| * |
| * @param start Starting point from which the overlay is pushed. |
| * @param overlay Dimensions of the overlay. |
| * @param scrollPosition Current viewport scroll position. |
| * @returns The point at which to position the overlay after pushing. This is effectively a new |
| * originPoint. |
| */ |
| /** |
| * Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than |
| * the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the |
| * right and bottom). |
| * |
| * @private |
| * @param {?} start Starting point from which the overlay is pushed. |
| * @param {?} overlay Dimensions of the overlay. |
| * @param {?} scrollPosition Current viewport scroll position. |
| * @return {?} The point at which to position the overlay after pushing. This is effectively a new |
| * originPoint. |
| */ |
| FlexibleConnectedPositionStrategy.prototype._pushOverlayOnScreen = /** |
| * Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than |
| * the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the |
| * right and bottom). |
| * |
| * @private |
| * @param {?} start Starting point from which the overlay is pushed. |
| * @param {?} overlay Dimensions of the overlay. |
| * @param {?} scrollPosition Current viewport scroll position. |
| * @return {?} The point at which to position the overlay after pushing. This is effectively a new |
| * originPoint. |
| */ |
| function (start, overlay, scrollPosition) { |
| // If the position is locked and we've pushed the overlay already, reuse the previous push |
| // amount, rather than pushing it again. If we were to continue pushing, the element would |
| // remain in the viewport, which goes against the expectations when position locking is enabled. |
| if (this._previousPushAmount && this._positionLocked) { |
| return { |
| x: start.x + this._previousPushAmount.x, |
| y: start.y + this._previousPushAmount.y |
| }; |
| } |
| /** @type {?} */ |
| var viewport = this._viewportRect; |
| // Determine how much the overlay goes outside the viewport on each |
| // side, which we'll use to decide which direction to push it. |
| /** @type {?} */ |
| var overflowRight = Math.max(start.x + overlay.width - viewport.right, 0); |
| /** @type {?} */ |
| var overflowBottom = Math.max(start.y + overlay.height - viewport.bottom, 0); |
| /** @type {?} */ |
| var overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0); |
| /** @type {?} */ |
| var overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0); |
| // Amount by which to push the overlay in each axis such that it remains on-screen. |
| /** @type {?} */ |
| var pushX = 0; |
| /** @type {?} */ |
| var pushY = 0; |
| // If the overlay fits completely within the bounds of the viewport, push it from whichever |
| // direction is goes off-screen. Otherwise, push the top-left corner such that its in the |
| // viewport and allow for the trailing end of the overlay to go out of bounds. |
| if (overlay.width <= viewport.width) { |
| pushX = overflowLeft || -overflowRight; |
| } |
| else { |
| pushX = start.x < this._viewportMargin ? (viewport.left - scrollPosition.left) - start.x : 0; |
| } |
| if (overlay.height <= viewport.height) { |
| pushY = overflowTop || -overflowBottom; |
| } |
| else { |
| pushY = start.y < this._viewportMargin ? (viewport.top - scrollPosition.top) - start.y : 0; |
| } |
| this._previousPushAmount = { x: pushX, y: pushY }; |
| return { |
| x: start.x + pushX, |
| y: start.y + pushY, |
| }; |
| }; |
| /** |
| * Applies a computed position to the overlay and emits a position change. |
| * @param position The position preference |
| * @param originPoint The point on the origin element where the overlay is connected. |
| */ |
| /** |
| * Applies a computed position to the overlay and emits a position change. |
| * @private |
| * @param {?} position The position preference |
| * @param {?} originPoint The point on the origin element where the overlay is connected. |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._applyPosition = /** |
| * Applies a computed position to the overlay and emits a position change. |
| * @private |
| * @param {?} position The position preference |
| * @param {?} originPoint The point on the origin element where the overlay is connected. |
| * @return {?} |
| */ |
| function (position, originPoint) { |
| this._setTransformOrigin(position); |
| this._setOverlayElementStyles(originPoint, position); |
| this._setBoundingBoxStyles(originPoint, position); |
| if (position.panelClass) { |
| this._addPanelClasses(position.panelClass); |
| } |
| // Save the last connected position in case the position needs to be re-calculated. |
| this._lastPosition = position; |
| // Notify that the position has been changed along with its change properties. |
| // We only emit if we've got any subscriptions, because the scroll visibility |
| // calculcations can be somewhat expensive. |
| if (this._positionChanges.observers.length) { |
| /** @type {?} */ |
| var scrollableViewProperties = this._getScrollVisibility(); |
| /** @type {?} */ |
| var changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties); |
| this._positionChanges.next(changeEvent); |
| } |
| this._isInitialRender = false; |
| }; |
| /** Sets the transform origin based on the configured selector and the passed-in position. */ |
| /** |
| * Sets the transform origin based on the configured selector and the passed-in position. |
| * @private |
| * @param {?} position |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._setTransformOrigin = /** |
| * Sets the transform origin based on the configured selector and the passed-in position. |
| * @private |
| * @param {?} position |
| * @return {?} |
| */ |
| function (position) { |
| if (!this._transformOriginSelector) { |
| return; |
| } |
| /** @type {?} */ |
| var elements = (/** @type {?} */ (this._boundingBox)).querySelectorAll(this._transformOriginSelector); |
| /** @type {?} */ |
| var xOrigin; |
| /** @type {?} */ |
| var yOrigin = position.overlayY; |
| if (position.overlayX === 'center') { |
| xOrigin = 'center'; |
| } |
| else if (this._isRtl()) { |
| xOrigin = position.overlayX === 'start' ? 'right' : 'left'; |
| } |
| else { |
| xOrigin = position.overlayX === 'start' ? 'left' : 'right'; |
| } |
| for (var i = 0; i < elements.length; i++) { |
| elements[i].style.transformOrigin = xOrigin + " " + yOrigin; |
| } |
| }; |
| /** |
| * Gets the position and size of the overlay's sizing container. |
| * |
| * This method does no measuring and applies no styles so that we can cheaply compute the |
| * bounds for all positions and choose the best fit based on these results. |
| */ |
| /** |
| * Gets the position and size of the overlay's sizing container. |
| * |
| * This method does no measuring and applies no styles so that we can cheaply compute the |
| * bounds for all positions and choose the best fit based on these results. |
| * @private |
| * @param {?} origin |
| * @param {?} position |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._calculateBoundingBoxRect = /** |
| * Gets the position and size of the overlay's sizing container. |
| * |
| * This method does no measuring and applies no styles so that we can cheaply compute the |
| * bounds for all positions and choose the best fit based on these results. |
| * @private |
| * @param {?} origin |
| * @param {?} position |
| * @return {?} |
| */ |
| function (origin, position) { |
| /** @type {?} */ |
| var viewport = this._viewportRect; |
| /** @type {?} */ |
| var isRtl = this._isRtl(); |
| /** @type {?} */ |
| var height; |
| /** @type {?} */ |
| var top; |
| /** @type {?} */ |
| var bottom; |
| if (position.overlayY === 'top') { |
| // Overlay is opening "downward" and thus is bound by the bottom viewport edge. |
| top = origin.y; |
| height = viewport.height - top + this._viewportMargin; |
| } |
| else if (position.overlayY === 'bottom') { |
| // Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add |
| // the viewport margin back in, because the viewport rect is narrowed down to remove the |
| // margin, whereas the `origin` position is calculated based on its `ClientRect`. |
| bottom = viewport.height - origin.y + this._viewportMargin * 2; |
| height = viewport.height - bottom + this._viewportMargin; |
| } |
| else { |
| // If neither top nor bottom, it means that the overlay is vertically centered on the |
| // origin point. Note that we want the position relative to the viewport, rather than |
| // the page, which is why we don't use something like `viewport.bottom - origin.y` and |
| // `origin.y - viewport.top`. |
| /** @type {?} */ |
| var smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y); |
| /** @type {?} */ |
| var previousHeight = this._lastBoundingBoxSize.height; |
| height = smallestDistanceToViewportEdge * 2; |
| top = origin.y - smallestDistanceToViewportEdge; |
| if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) { |
| top = origin.y - (previousHeight / 2); |
| } |
| } |
| // The overlay is opening 'right-ward' (the content flows to the right). |
| /** @type {?} */ |
| var isBoundedByRightViewportEdge = (position.overlayX === 'start' && !isRtl) || |
| (position.overlayX === 'end' && isRtl); |
| // The overlay is opening 'left-ward' (the content flows to the left). |
| /** @type {?} */ |
| var isBoundedByLeftViewportEdge = (position.overlayX === 'end' && !isRtl) || |
| (position.overlayX === 'start' && isRtl); |
| /** @type {?} */ |
| var width; |
| /** @type {?} */ |
| var left; |
| /** @type {?} */ |
| var right; |
| if (isBoundedByLeftViewportEdge) { |
| right = viewport.width - origin.x + this._viewportMargin; |
| width = origin.x - this._viewportMargin; |
| } |
| else if (isBoundedByRightViewportEdge) { |
| left = origin.x; |
| width = viewport.right - origin.x; |
| } |
| else { |
| // If neither start nor end, it means that the overlay is horizontally centered on the |
| // origin point. Note that we want the position relative to the viewport, rather than |
| // the page, which is why we don't use something like `viewport.right - origin.x` and |
| // `origin.x - viewport.left`. |
| /** @type {?} */ |
| var smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x); |
| /** @type {?} */ |
| var previousWidth = this._lastBoundingBoxSize.width; |
| width = smallestDistanceToViewportEdge * 2; |
| left = origin.x - smallestDistanceToViewportEdge; |
| if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) { |
| left = origin.x - (previousWidth / 2); |
| } |
| } |
| return { top: (/** @type {?} */ (top)), left: (/** @type {?} */ (left)), bottom: (/** @type {?} */ (bottom)), right: (/** @type {?} */ (right)), width: width, height: height }; |
| }; |
| /** |
| * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the |
| * origin's connection point and stetches to the bounds of the viewport. |
| * |
| * @param origin The point on the origin element where the overlay is connected. |
| * @param position The position preference |
| */ |
| /** |
| * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the |
| * origin's connection point and stetches to the bounds of the viewport. |
| * |
| * @private |
| * @param {?} origin The point on the origin element where the overlay is connected. |
| * @param {?} position The position preference |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._setBoundingBoxStyles = /** |
| * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the |
| * origin's connection point and stetches to the bounds of the viewport. |
| * |
| * @private |
| * @param {?} origin The point on the origin element where the overlay is connected. |
| * @param {?} position The position preference |
| * @return {?} |
| */ |
| function (origin, position) { |
| /** @type {?} */ |
| var boundingBoxRect = this._calculateBoundingBoxRect(origin, position); |
| // It's weird if the overlay *grows* while scrolling, so we take the last size into account |
| // when applying a new size. |
| if (!this._isInitialRender && !this._growAfterOpen) { |
| boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height); |
| boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width); |
| } |
| /** @type {?} */ |
| var styles = (/** @type {?} */ ({})); |
| if (this._hasExactPosition()) { |
| styles.top = styles.left = '0'; |
| styles.bottom = styles.right = ''; |
| styles.width = styles.height = '100%'; |
| } |
| else { |
| /** @type {?} */ |
| var maxHeight = this._overlayRef.getConfig().maxHeight; |
| /** @type {?} */ |
| var maxWidth = this._overlayRef.getConfig().maxWidth; |
| styles.height = coerceCssPixelValue(boundingBoxRect.height); |
| styles.top = coerceCssPixelValue(boundingBoxRect.top); |
| styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom); |
| styles.width = coerceCssPixelValue(boundingBoxRect.width); |
| styles.left = coerceCssPixelValue(boundingBoxRect.left); |
| styles.right = coerceCssPixelValue(boundingBoxRect.right); |
| // Push the pane content towards the proper direction. |
| if (position.overlayX === 'center') { |
| styles.alignItems = 'center'; |
| } |
| else { |
| styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start'; |
| } |
| if (position.overlayY === 'center') { |
| styles.justifyContent = 'center'; |
| } |
| else { |
| styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start'; |
| } |
| if (maxHeight) { |
| styles.maxHeight = coerceCssPixelValue(maxHeight); |
| } |
| if (maxWidth) { |
| styles.maxWidth = coerceCssPixelValue(maxWidth); |
| } |
| } |
| this._lastBoundingBoxSize = boundingBoxRect; |
| extendStyles((/** @type {?} */ (this._boundingBox)).style, styles); |
| }; |
| /** Resets the styles for the bounding box so that a new positioning can be computed. */ |
| /** |
| * Resets the styles for the bounding box so that a new positioning can be computed. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._resetBoundingBoxStyles = /** |
| * Resets the styles for the bounding box so that a new positioning can be computed. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| extendStyles((/** @type {?} */ (this._boundingBox)).style, (/** @type {?} */ ({ |
| top: '0', |
| left: '0', |
| right: '0', |
| bottom: '0', |
| height: '', |
| width: '', |
| alignItems: '', |
| justifyContent: '', |
| }))); |
| }; |
| /** Resets the styles for the overlay pane so that a new positioning can be computed. */ |
| /** |
| * Resets the styles for the overlay pane so that a new positioning can be computed. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._resetOverlayElementStyles = /** |
| * Resets the styles for the overlay pane so that a new positioning can be computed. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| extendStyles(this._pane.style, (/** @type {?} */ ({ |
| top: '', |
| left: '', |
| bottom: '', |
| right: '', |
| position: '', |
| transform: '', |
| }))); |
| }; |
| /** Sets positioning styles to the overlay element. */ |
| /** |
| * Sets positioning styles to the overlay element. |
| * @private |
| * @param {?} originPoint |
| * @param {?} position |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._setOverlayElementStyles = /** |
| * Sets positioning styles to the overlay element. |
| * @private |
| * @param {?} originPoint |
| * @param {?} position |
| * @return {?} |
| */ |
| function (originPoint, position) { |
| /** @type {?} */ |
| var styles = (/** @type {?} */ ({})); |
| if (this._hasExactPosition()) { |
| /** @type {?} */ |
| var scrollPosition = this._viewportRuler.getViewportScrollPosition(); |
| extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition)); |
| extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition)); |
| } |
| else { |
| styles.position = 'static'; |
| } |
| // Use a transform to apply the offsets. We do this because the `center` positions rely on |
| // being in the normal flex flow and setting a `top` / `left` at all will completely throw |
| // off the position. We also can't use margins, because they won't have an effect in some |
| // cases where the element doesn't have anything to "push off of". Finally, this works |
| // better both with flexible and non-flexible positioning. |
| /** @type {?} */ |
| var transformString = ''; |
| /** @type {?} */ |
| var offsetX = this._getOffset(position, 'x'); |
| /** @type {?} */ |
| var offsetY = this._getOffset(position, 'y'); |
| if (offsetX) { |
| transformString += "translateX(" + offsetX + "px) "; |
| } |
| if (offsetY) { |
| transformString += "translateY(" + offsetY + "px)"; |
| } |
| styles.transform = transformString.trim(); |
| // If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because |
| // we need these values to both be set to "100%" for the automatic flexible sizing to work. |
| // The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint. |
| if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxHeight) { |
| styles.maxHeight = ''; |
| } |
| if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxWidth) { |
| styles.maxWidth = ''; |
| } |
| extendStyles(this._pane.style, styles); |
| }; |
| /** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */ |
| /** |
| * Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. |
| * @private |
| * @param {?} position |
| * @param {?} originPoint |
| * @param {?} scrollPosition |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getExactOverlayY = /** |
| * Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. |
| * @private |
| * @param {?} position |
| * @param {?} originPoint |
| * @param {?} scrollPosition |
| * @return {?} |
| */ |
| function (position, originPoint, scrollPosition) { |
| // Reset any existing styles. This is necessary in case the |
| // preferred position has changed since the last `apply`. |
| /** @type {?} */ |
| var styles = (/** @type {?} */ ({ top: null, bottom: null })); |
| /** @type {?} */ |
| var overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position); |
| if (this._isPushed) { |
| overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition); |
| } |
| /** @type {?} */ |
| var virtualKeyboardOffset = this._overlayContainer.getContainerElement().getBoundingClientRect().top; |
| // Normally this would be zero, however when the overlay is attached to an input (e.g. in an |
| // autocomplete), mobile browsers will shift everything in order to put the input in the middle |
| // of the screen and to make space for the virtual keyboard. We need to account for this offset, |
| // otherwise our positioning will be thrown off. |
| overlayPoint.y -= virtualKeyboardOffset; |
| // We want to set either `top` or `bottom` based on whether the overlay wants to appear |
| // above or below the origin and the direction in which the element will expand. |
| if (position.overlayY === 'bottom') { |
| // When using `bottom`, we adjust the y position such that it is the distance |
| // from the bottom of the viewport rather than the top. |
| /** @type {?} */ |
| var documentHeight = (/** @type {?} */ (this._document.documentElement)).clientHeight; |
| styles.bottom = documentHeight - (overlayPoint.y + this._overlayRect.height) + "px"; |
| } |
| else { |
| styles.top = coerceCssPixelValue(overlayPoint.y); |
| } |
| return styles; |
| }; |
| /** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */ |
| /** |
| * Gets the exact left/right for the overlay when not using flexible sizing or when pushing. |
| * @private |
| * @param {?} position |
| * @param {?} originPoint |
| * @param {?} scrollPosition |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getExactOverlayX = /** |
| * Gets the exact left/right for the overlay when not using flexible sizing or when pushing. |
| * @private |
| * @param {?} position |
| * @param {?} originPoint |
| * @param {?} scrollPosition |
| * @return {?} |
| */ |
| function (position, originPoint, scrollPosition) { |
| // Reset any existing styles. This is necessary in case the preferred position has |
| // changed since the last `apply`. |
| /** @type {?} */ |
| var styles = (/** @type {?} */ ({ left: null, right: null })); |
| /** @type {?} */ |
| var overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position); |
| if (this._isPushed) { |
| overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition); |
| } |
| // We want to set either `left` or `right` based on whether the overlay wants to appear "before" |
| // or "after" the origin, which determines the direction in which the element will expand. |
| // For the horizontal axis, the meaning of "before" and "after" change based on whether the |
| // page is in RTL or LTR. |
| /** @type {?} */ |
| var horizontalStyleProperty; |
| if (this._isRtl()) { |
| horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right'; |
| } |
| else { |
| horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left'; |
| } |
| // When we're setting `right`, we adjust the x position such that it is the distance |
| // from the right edge of the viewport rather than the left edge. |
| if (horizontalStyleProperty === 'right') { |
| /** @type {?} */ |
| var documentWidth = (/** @type {?} */ (this._document.documentElement)).clientWidth; |
| styles.right = documentWidth - (overlayPoint.x + this._overlayRect.width) + "px"; |
| } |
| else { |
| styles.left = coerceCssPixelValue(overlayPoint.x); |
| } |
| return styles; |
| }; |
| /** |
| * Gets the view properties of the trigger and overlay, including whether they are clipped |
| * or completely outside the view of any of the strategy's scrollables. |
| */ |
| /** |
| * Gets the view properties of the trigger and overlay, including whether they are clipped |
| * or completely outside the view of any of the strategy's scrollables. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getScrollVisibility = /** |
| * Gets the view properties of the trigger and overlay, including whether they are clipped |
| * or completely outside the view of any of the strategy's scrollables. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| // Note: needs fresh rects since the position could've changed. |
| /** @type {?} */ |
| var originBounds = this._getOriginRect(); |
| /** @type {?} */ |
| var overlayBounds = this._pane.getBoundingClientRect(); |
| // TODO(jelbourn): instead of needing all of the client rects for these scrolling containers |
| // every time, we should be able to use the scrollTop of the containers if the size of those |
| // containers hasn't changed. |
| /** @type {?} */ |
| var scrollContainerBounds = this._scrollables.map((/** |
| * @param {?} scrollable |
| * @return {?} |
| */ |
| function (scrollable) { |
| return scrollable.getElementRef().nativeElement.getBoundingClientRect(); |
| })); |
| return { |
| isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds), |
| isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds), |
| isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds), |
| isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds), |
| }; |
| }; |
| /** Subtracts the amount that an element is overflowing on an axis from it's length. */ |
| /** |
| * Subtracts the amount that an element is overflowing on an axis from it's length. |
| * @private |
| * @param {?} length |
| * @param {...?} overflows |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._subtractOverflows = /** |
| * Subtracts the amount that an element is overflowing on an axis from it's length. |
| * @private |
| * @param {?} length |
| * @param {...?} overflows |
| * @return {?} |
| */ |
| function (length) { |
| var overflows = []; |
| for (var _i = 1; _i < arguments.length; _i++) { |
| overflows[_i - 1] = arguments[_i]; |
| } |
| return overflows.reduce((/** |
| * @param {?} currentValue |
| * @param {?} currentOverflow |
| * @return {?} |
| */ |
| function (currentValue, currentOverflow) { |
| return currentValue - Math.max(currentOverflow, 0); |
| }), length); |
| }; |
| /** Narrows the given viewport rect by the current _viewportMargin. */ |
| /** |
| * Narrows the given viewport rect by the current _viewportMargin. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getNarrowedViewportRect = /** |
| * Narrows the given viewport rect by the current _viewportMargin. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| // We recalculate the viewport rect here ourselves, rather than using the ViewportRuler, |
| // because we want to use the `clientWidth` and `clientHeight` as the base. The difference |
| // being that the client properties don't include the scrollbar, as opposed to `innerWidth` |
| // and `innerHeight` that do. This is necessary, because the overlay container uses |
| // 100% `width` and `height` which don't include the scrollbar either. |
| /** @type {?} */ |
| var width = (/** @type {?} */ (this._document.documentElement)).clientWidth; |
| /** @type {?} */ |
| var height = (/** @type {?} */ (this._document.documentElement)).clientHeight; |
| /** @type {?} */ |
| var scrollPosition = this._viewportRuler.getViewportScrollPosition(); |
| return { |
| top: scrollPosition.top + this._viewportMargin, |
| left: scrollPosition.left + this._viewportMargin, |
| right: scrollPosition.left + width - this._viewportMargin, |
| bottom: scrollPosition.top + height - this._viewportMargin, |
| width: width - (2 * this._viewportMargin), |
| height: height - (2 * this._viewportMargin), |
| }; |
| }; |
| /** Whether the we're dealing with an RTL context */ |
| /** |
| * Whether the we're dealing with an RTL context |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._isRtl = /** |
| * Whether the we're dealing with an RTL context |
| * @private |
| * @return {?} |
| */ |
| function () { |
| return this._overlayRef.getDirection() === 'rtl'; |
| }; |
| /** Determines whether the overlay uses exact or flexible positioning. */ |
| /** |
| * Determines whether the overlay uses exact or flexible positioning. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._hasExactPosition = /** |
| * Determines whether the overlay uses exact or flexible positioning. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| return !this._hasFlexibleDimensions || this._isPushed; |
| }; |
| /** Retrieves the offset of a position along the x or y axis. */ |
| /** |
| * Retrieves the offset of a position along the x or y axis. |
| * @private |
| * @param {?} position |
| * @param {?} axis |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getOffset = /** |
| * Retrieves the offset of a position along the x or y axis. |
| * @private |
| * @param {?} position |
| * @param {?} axis |
| * @return {?} |
| */ |
| function (position, axis) { |
| if (axis === 'x') { |
| // We don't do something like `position['offset' + axis]` in |
| // order to avoid breking minifiers that rename properties. |
| return position.offsetX == null ? this._offsetX : position.offsetX; |
| } |
| return position.offsetY == null ? this._offsetY : position.offsetY; |
| }; |
| /** Validates that the current position match the expected values. */ |
| /** |
| * Validates that the current position match the expected values. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._validatePositions = /** |
| * Validates that the current position match the expected values. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (!this._preferredPositions.length) { |
| throw Error('FlexibleConnectedPositionStrategy: At least one position is required.'); |
| } |
| // TODO(crisbeto): remove these once Angular's template type |
| // checking is advanced enough to catch these cases. |
| this._preferredPositions.forEach((/** |
| * @param {?} pair |
| * @return {?} |
| */ |
| function (pair) { |
| validateHorizontalPosition('originX', pair.originX); |
| validateVerticalPosition('originY', pair.originY); |
| validateHorizontalPosition('overlayX', pair.overlayX); |
| validateVerticalPosition('overlayY', pair.overlayY); |
| })); |
| }; |
| /** Adds a single CSS class or an array of classes on the overlay panel. */ |
| /** |
| * Adds a single CSS class or an array of classes on the overlay panel. |
| * @private |
| * @param {?} cssClasses |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._addPanelClasses = /** |
| * Adds a single CSS class or an array of classes on the overlay panel. |
| * @private |
| * @param {?} cssClasses |
| * @return {?} |
| */ |
| function (cssClasses) { |
| var _this = this; |
| if (this._pane) { |
| coerceArray(cssClasses).forEach((/** |
| * @param {?} cssClass |
| * @return {?} |
| */ |
| function (cssClass) { |
| if (cssClass !== '' && _this._appliedPanelClasses.indexOf(cssClass) === -1) { |
| _this._appliedPanelClasses.push(cssClass); |
| _this._pane.classList.add(cssClass); |
| } |
| })); |
| } |
| }; |
| /** Clears the classes that the position strategy has applied from the overlay panel. */ |
| /** |
| * Clears the classes that the position strategy has applied from the overlay panel. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._clearPanelClasses = /** |
| * Clears the classes that the position strategy has applied from the overlay panel. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (this._pane) { |
| this._appliedPanelClasses.forEach((/** |
| * @param {?} cssClass |
| * @return {?} |
| */ |
| function (cssClass) { |
| _this._pane.classList.remove(cssClass); |
| })); |
| this._appliedPanelClasses = []; |
| } |
| }; |
| /** Returns the ClientRect of the current origin. */ |
| /** |
| * Returns the ClientRect of the current origin. |
| * @private |
| * @return {?} |
| */ |
| FlexibleConnectedPositionStrategy.prototype._getOriginRect = /** |
| * Returns the ClientRect of the current origin. |
| * @private |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var origin = this._origin; |
| if (origin instanceof ElementRef) { |
| return origin.nativeElement.getBoundingClientRect(); |
| } |
| if (origin instanceof HTMLElement) { |
| return origin.getBoundingClientRect(); |
| } |
| // If the origin is a point, return a client rect as if it was a 0x0 element at the point. |
| return { |
| top: origin.y, |
| bottom: origin.y, |
| left: origin.x, |
| right: origin.x, |
| height: 0, |
| width: 0 |
| }; |
| }; |
| return FlexibleConnectedPositionStrategy; |
| }()); |
| /** |
| * Shallow-extends a stylesheet object with another stylesheet object. |
| * @param {?} dest |
| * @param {?} source |
| * @return {?} |
| */ |
| function extendStyles(dest, source) { |
| for (var key in source) { |
| if (source.hasOwnProperty(key)) { |
| dest[key] = source[key]; |
| } |
| } |
| return dest; |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * implicit position relative to some origin element. The relative position is defined in terms of |
| * a point on the origin element that is connected to a point on the overlay element. For example, |
| * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner |
| * of the overlay. |
| * @deprecated Use `FlexibleConnectedPositionStrategy` instead. |
| * \@breaking-change 8.0.0 |
| */ |
| var /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * implicit position relative to some origin element. The relative position is defined in terms of |
| * a point on the origin element that is connected to a point on the overlay element. For example, |
| * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner |
| * of the overlay. |
| * @deprecated Use `FlexibleConnectedPositionStrategy` instead. |
| * \@breaking-change 8.0.0 |
| */ |
| ConnectedPositionStrategy = /** @class */ (function () { |
| function ConnectedPositionStrategy(originPos, overlayPos, connectedTo, viewportRuler, document, platform, overlayContainer) { |
| /** |
| * Ordered list of preferred positions, from most to least desirable. |
| */ |
| this._preferredPositions = []; |
| // Since the `ConnectedPositionStrategy` is deprecated and we don't want to maintain |
| // the extra logic, we create an instance of the positioning strategy that has some |
| // defaults that make it behave as the old position strategy and to which we'll |
| // proxy all of the API calls. |
| this._positionStrategy = new FlexibleConnectedPositionStrategy(connectedTo, viewportRuler, document, platform, overlayContainer) |
| .withFlexibleDimensions(false) |
| .withPush(false) |
| .withViewportMargin(0); |
| this.withFallbackPosition(originPos, overlayPos); |
| } |
| Object.defineProperty(ConnectedPositionStrategy.prototype, "_isRtl", { |
| /** Whether the we're dealing with an RTL context */ |
| get: /** |
| * Whether the we're dealing with an RTL context |
| * @return {?} |
| */ |
| function () { |
| return this._overlayRef.getDirection() === 'rtl'; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(ConnectedPositionStrategy.prototype, "onPositionChange", { |
| /** Emits an event when the connection point changes. */ |
| get: /** |
| * Emits an event when the connection point changes. |
| * @return {?} |
| */ |
| function () { |
| return this._positionStrategy.positionChanges; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(ConnectedPositionStrategy.prototype, "positions", { |
| /** Ordered list of preferred positions, from most to least desirable. */ |
| get: /** |
| * Ordered list of preferred positions, from most to least desirable. |
| * @return {?} |
| */ |
| function () { |
| return this._preferredPositions; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| /** Attach this position strategy to an overlay. */ |
| /** |
| * Attach this position strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.attach = /** |
| * Attach this position strategy to an overlay. |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| this._overlayRef = overlayRef; |
| this._positionStrategy.attach(overlayRef); |
| if (this._direction) { |
| overlayRef.setDirection(this._direction); |
| this._direction = null; |
| } |
| }; |
| /** Disposes all resources used by the position strategy. */ |
| /** |
| * Disposes all resources used by the position strategy. |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.dispose = /** |
| * Disposes all resources used by the position strategy. |
| * @return {?} |
| */ |
| function () { |
| this._positionStrategy.dispose(); |
| }; |
| /** @docs-private */ |
| /** |
| * \@docs-private |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.detach = /** |
| * \@docs-private |
| * @return {?} |
| */ |
| function () { |
| this._positionStrategy.detach(); |
| }; |
| /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin fits on-screen. |
| * @docs-private |
| */ |
| /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin fits on-screen. |
| * \@docs-private |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.apply = /** |
| * Updates the position of the overlay element, using whichever preferred position relative |
| * to the origin fits on-screen. |
| * \@docs-private |
| * @return {?} |
| */ |
| function () { |
| this._positionStrategy.apply(); |
| }; |
| /** |
| * Re-positions the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| */ |
| /** |
| * Re-positions the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.recalculateLastPosition = /** |
| * Re-positions the overlay element with the trigger in its last calculated position, |
| * even if a position higher in the "preferred positions" list would now fit. This |
| * allows one to re-align the panel without changing the orientation of the panel. |
| * @return {?} |
| */ |
| function () { |
| this._positionStrategy.reapplyLastPosition(); |
| }; |
| /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| */ |
| /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| * @param {?} scrollables |
| * @return {?} |
| */ |
| ConnectedPositionStrategy.prototype.withScrollableContainers = /** |
| * Sets the list of Scrollable containers that host the origin element so that |
| * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every |
| * Scrollable must be an ancestor element of the strategy's origin element. |
| * @param {?} scrollables |
| * @return {?} |
| */ |
| function (scrollables) { |
| this._positionStrategy.withScrollableContainers(scrollables); |
| }; |
| /** |
| * Adds a new preferred fallback position. |
| * @param originPos |
| * @param overlayPos |
| */ |
| /** |
| * Adds a new preferred fallback position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} originPos |
| * @param {?} overlayPos |
| * @param {?=} offsetX |
| * @param {?=} offsetY |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withFallbackPosition = /** |
| * Adds a new preferred fallback position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} originPos |
| * @param {?} overlayPos |
| * @param {?=} offsetX |
| * @param {?=} offsetY |
| * @return {THIS} |
| */ |
| function (originPos, overlayPos, offsetX, offsetY) { |
| /** @type {?} */ |
| var position = new ConnectionPositionPair(originPos, overlayPos, offsetX, offsetY); |
| (/** @type {?} */ (this))._preferredPositions.push(position); |
| (/** @type {?} */ (this))._positionStrategy.withPositions((/** @type {?} */ (this))._preferredPositions); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the layout direction so the overlay's position can be adjusted to match. |
| * @param dir New layout direction. |
| */ |
| /** |
| * Sets the layout direction so the overlay's position can be adjusted to match. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} dir New layout direction. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withDirection = /** |
| * Sets the layout direction so the overlay's position can be adjusted to match. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} dir New layout direction. |
| * @return {THIS} |
| */ |
| function (dir) { |
| // Since the direction might be declared before the strategy is attached, |
| // we save the value in a temporary property and we'll transfer it to the |
| // overlay ref on attachment. |
| if ((/** @type {?} */ (this))._overlayRef) { |
| (/** @type {?} */ (this))._overlayRef.setDirection(dir); |
| } |
| else { |
| (/** @type {?} */ (this))._direction = dir; |
| } |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets an offset for the overlay's connection point on the x-axis |
| * @param offset New offset in the X axis. |
| */ |
| /** |
| * Sets an offset for the overlay's connection point on the x-axis |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the X axis. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withOffsetX = /** |
| * Sets an offset for the overlay's connection point on the x-axis |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the X axis. |
| * @return {THIS} |
| */ |
| function (offset) { |
| (/** @type {?} */ (this))._positionStrategy.withDefaultOffsetX(offset); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets an offset for the overlay's connection point on the y-axis |
| * @param offset New offset in the Y axis. |
| */ |
| /** |
| * Sets an offset for the overlay's connection point on the y-axis |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the Y axis. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withOffsetY = /** |
| * Sets an offset for the overlay's connection point on the y-axis |
| * @template THIS |
| * @this {THIS} |
| * @param {?} offset New offset in the Y axis. |
| * @return {THIS} |
| */ |
| function (offset) { |
| (/** @type {?} */ (this))._positionStrategy.withDefaultOffsetY(offset); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @param isLocked Whether the overlay should locked in. |
| */ |
| /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @template THIS |
| * @this {THIS} |
| * @param {?} isLocked Whether the overlay should locked in. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withLockedPosition = /** |
| * Sets whether the overlay's position should be locked in after it is positioned |
| * initially. When an overlay is locked in, it won't attempt to reposition itself |
| * when the position is re-applied (e.g. when the user scrolls away). |
| * @template THIS |
| * @this {THIS} |
| * @param {?} isLocked Whether the overlay should locked in. |
| * @return {THIS} |
| */ |
| function (isLocked) { |
| (/** @type {?} */ (this))._positionStrategy.withLockedPosition(isLocked); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Overwrites the current set of positions with an array of new ones. |
| * @param positions Position pairs to be set on the strategy. |
| */ |
| /** |
| * Overwrites the current set of positions with an array of new ones. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} positions Position pairs to be set on the strategy. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.withPositions = /** |
| * Overwrites the current set of positions with an array of new ones. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} positions Position pairs to be set on the strategy. |
| * @return {THIS} |
| */ |
| function (positions) { |
| (/** @type {?} */ (this))._preferredPositions = positions.slice(); |
| (/** @type {?} */ (this))._positionStrategy.withPositions((/** @type {?} */ (this))._preferredPositions); |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the origin element, relative to which to position the overlay. |
| * @param origin Reference to the new origin element. |
| */ |
| /** |
| * Sets the origin element, relative to which to position the overlay. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} origin Reference to the new origin element. |
| * @return {THIS} |
| */ |
| ConnectedPositionStrategy.prototype.setOrigin = /** |
| * Sets the origin element, relative to which to position the overlay. |
| * @template THIS |
| * @this {THIS} |
| * @param {?} origin Reference to the new origin element. |
| * @return {THIS} |
| */ |
| function (origin) { |
| (/** @type {?} */ (this))._positionStrategy.setOrigin(origin); |
| return (/** @type {?} */ (this)); |
| }; |
| return ConnectedPositionStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * Class to be added to the overlay pane wrapper. |
| * @type {?} |
| */ |
| var wrapperClass = 'cdk-global-overlay-wrapper'; |
| /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * explicit position relative to the browser's viewport. We use flexbox, instead of |
| * transforms, in order to avoid issues with subpixel rendering which can cause the |
| * element to become blurry. |
| */ |
| var /** |
| * A strategy for positioning overlays. Using this strategy, an overlay is given an |
| * explicit position relative to the browser's viewport. We use flexbox, instead of |
| * transforms, in order to avoid issues with subpixel rendering which can cause the |
| * element to become blurry. |
| */ |
| GlobalPositionStrategy = /** @class */ (function () { |
| function GlobalPositionStrategy() { |
| this._cssPosition = 'static'; |
| this._topOffset = ''; |
| this._bottomOffset = ''; |
| this._leftOffset = ''; |
| this._rightOffset = ''; |
| this._alignItems = ''; |
| this._justifyContent = ''; |
| this._width = ''; |
| this._height = ''; |
| } |
| /** |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| GlobalPositionStrategy.prototype.attach = /** |
| * @param {?} overlayRef |
| * @return {?} |
| */ |
| function (overlayRef) { |
| /** @type {?} */ |
| var config = overlayRef.getConfig(); |
| this._overlayRef = overlayRef; |
| if (this._width && !config.width) { |
| overlayRef.updateSize({ width: this._width }); |
| } |
| if (this._height && !config.height) { |
| overlayRef.updateSize({ height: this._height }); |
| } |
| overlayRef.hostElement.classList.add(wrapperClass); |
| this._isDisposed = false; |
| }; |
| /** |
| * Sets the top position of the overlay. Clears any previously set vertical position. |
| * @param value New top offset. |
| */ |
| /** |
| * Sets the top position of the overlay. Clears any previously set vertical position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New top offset. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.top = /** |
| * Sets the top position of the overlay. Clears any previously set vertical position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New top offset. |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| (/** @type {?} */ (this))._bottomOffset = ''; |
| (/** @type {?} */ (this))._topOffset = value; |
| (/** @type {?} */ (this))._alignItems = 'flex-start'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the left position of the overlay. Clears any previously set horizontal position. |
| * @param value New left offset. |
| */ |
| /** |
| * Sets the left position of the overlay. Clears any previously set horizontal position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New left offset. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.left = /** |
| * Sets the left position of the overlay. Clears any previously set horizontal position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New left offset. |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| (/** @type {?} */ (this))._rightOffset = ''; |
| (/** @type {?} */ (this))._leftOffset = value; |
| (/** @type {?} */ (this))._justifyContent = 'flex-start'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the bottom position of the overlay. Clears any previously set vertical position. |
| * @param value New bottom offset. |
| */ |
| /** |
| * Sets the bottom position of the overlay. Clears any previously set vertical position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New bottom offset. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.bottom = /** |
| * Sets the bottom position of the overlay. Clears any previously set vertical position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New bottom offset. |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| (/** @type {?} */ (this))._topOffset = ''; |
| (/** @type {?} */ (this))._bottomOffset = value; |
| (/** @type {?} */ (this))._alignItems = 'flex-end'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the right position of the overlay. Clears any previously set horizontal position. |
| * @param value New right offset. |
| */ |
| /** |
| * Sets the right position of the overlay. Clears any previously set horizontal position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New right offset. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.right = /** |
| * Sets the right position of the overlay. Clears any previously set horizontal position. |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New right offset. |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| (/** @type {?} */ (this))._leftOffset = ''; |
| (/** @type {?} */ (this))._rightOffset = value; |
| (/** @type {?} */ (this))._justifyContent = 'flex-end'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the overlay width and clears any previously set width. |
| * @param value New width for the overlay |
| * @deprecated Pass the `width` through the `OverlayConfig`. |
| * @breaking-change 8.0.0 |
| */ |
| /** |
| * Sets the overlay width and clears any previously set width. |
| * @deprecated Pass the `width` through the `OverlayConfig`. |
| * \@breaking-change 8.0.0 |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New width for the overlay |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.width = /** |
| * Sets the overlay width and clears any previously set width. |
| * @deprecated Pass the `width` through the `OverlayConfig`. |
| * \@breaking-change 8.0.0 |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New width for the overlay |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| if ((/** @type {?} */ (this))._overlayRef) { |
| (/** @type {?} */ (this))._overlayRef.updateSize({ width: value }); |
| } |
| else { |
| (/** @type {?} */ (this))._width = value; |
| } |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Sets the overlay height and clears any previously set height. |
| * @param value New height for the overlay |
| * @deprecated Pass the `height` through the `OverlayConfig`. |
| * @breaking-change 8.0.0 |
| */ |
| /** |
| * Sets the overlay height and clears any previously set height. |
| * @deprecated Pass the `height` through the `OverlayConfig`. |
| * \@breaking-change 8.0.0 |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New height for the overlay |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.height = /** |
| * Sets the overlay height and clears any previously set height. |
| * @deprecated Pass the `height` through the `OverlayConfig`. |
| * \@breaking-change 8.0.0 |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} value New height for the overlay |
| * @return {THIS} |
| */ |
| function (value) { |
| if (value === void 0) { value = ''; } |
| if ((/** @type {?} */ (this))._overlayRef) { |
| (/** @type {?} */ (this))._overlayRef.updateSize({ height: value }); |
| } |
| else { |
| (/** @type {?} */ (this))._height = value; |
| } |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Centers the overlay horizontally with an optional offset. |
| * Clears any previously set horizontal position. |
| * |
| * @param offset Overlay offset from the horizontal center. |
| */ |
| /** |
| * Centers the overlay horizontally with an optional offset. |
| * Clears any previously set horizontal position. |
| * |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} offset Overlay offset from the horizontal center. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.centerHorizontally = /** |
| * Centers the overlay horizontally with an optional offset. |
| * Clears any previously set horizontal position. |
| * |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} offset Overlay offset from the horizontal center. |
| * @return {THIS} |
| */ |
| function (offset) { |
| if (offset === void 0) { offset = ''; } |
| (/** @type {?} */ (this)).left(offset); |
| (/** @type {?} */ (this))._justifyContent = 'center'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Centers the overlay vertically with an optional offset. |
| * Clears any previously set vertical position. |
| * |
| * @param offset Overlay offset from the vertical center. |
| */ |
| /** |
| * Centers the overlay vertically with an optional offset. |
| * Clears any previously set vertical position. |
| * |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} offset Overlay offset from the vertical center. |
| * @return {THIS} |
| */ |
| GlobalPositionStrategy.prototype.centerVertically = /** |
| * Centers the overlay vertically with an optional offset. |
| * Clears any previously set vertical position. |
| * |
| * @template THIS |
| * @this {THIS} |
| * @param {?=} offset Overlay offset from the vertical center. |
| * @return {THIS} |
| */ |
| function (offset) { |
| if (offset === void 0) { offset = ''; } |
| (/** @type {?} */ (this)).top(offset); |
| (/** @type {?} */ (this))._alignItems = 'center'; |
| return (/** @type {?} */ (this)); |
| }; |
| /** |
| * Apply the position to the element. |
| * @docs-private |
| */ |
| /** |
| * Apply the position to the element. |
| * \@docs-private |
| * @return {?} |
| */ |
| GlobalPositionStrategy.prototype.apply = /** |
| * Apply the position to the element. |
| * \@docs-private |
| * @return {?} |
| */ |
| function () { |
| // Since the overlay ref applies the strategy asynchronously, it could |
| // have been disposed before it ends up being applied. If that is the |
| // case, we shouldn't do anything. |
| if (!this._overlayRef || !this._overlayRef.hasAttached()) { |
| return; |
| } |
| /** @type {?} */ |
| var styles = this._overlayRef.overlayElement.style; |
| /** @type {?} */ |
| var parentStyles = this._overlayRef.hostElement.style; |
| /** @type {?} */ |
| var config = this._overlayRef.getConfig(); |
| styles.position = this._cssPosition; |
| styles.marginLeft = config.width === '100%' ? '0' : this._leftOffset; |
| styles.marginTop = config.height === '100%' ? '0' : this._topOffset; |
| styles.marginBottom = this._bottomOffset; |
| styles.marginRight = this._rightOffset; |
| if (config.width === '100%') { |
| parentStyles.justifyContent = 'flex-start'; |
| } |
| else if (this._justifyContent === 'center') { |
| parentStyles.justifyContent = 'center'; |
| } |
| else if (this._overlayRef.getConfig().direction === 'rtl') { |
| // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we |
| // don't want that because our positioning is explicitly `left` and `right`, hence |
| // why we do another inversion to ensure that the overlay stays in the same position. |
| // TODO: reconsider this if we add `start` and `end` methods. |
| if (this._justifyContent === 'flex-start') { |
| parentStyles.justifyContent = 'flex-end'; |
| } |
| else if (this._justifyContent === 'flex-end') { |
| parentStyles.justifyContent = 'flex-start'; |
| } |
| } |
| else { |
| parentStyles.justifyContent = this._justifyContent; |
| } |
| parentStyles.alignItems = config.height === '100%' ? 'flex-start' : this._alignItems; |
| }; |
| /** |
| * Cleans up the DOM changes from the position strategy. |
| * @docs-private |
| */ |
| /** |
| * Cleans up the DOM changes from the position strategy. |
| * \@docs-private |
| * @return {?} |
| */ |
| GlobalPositionStrategy.prototype.dispose = /** |
| * Cleans up the DOM changes from the position strategy. |
| * \@docs-private |
| * @return {?} |
| */ |
| function () { |
| if (this._isDisposed || !this._overlayRef) { |
| return; |
| } |
| /** @type {?} */ |
| var styles = this._overlayRef.overlayElement.style; |
| /** @type {?} */ |
| var parent = this._overlayRef.hostElement; |
| /** @type {?} */ |
| var parentStyles = parent.style; |
| parent.classList.remove(wrapperClass); |
| parentStyles.justifyContent = parentStyles.alignItems = styles.marginTop = |
| styles.marginBottom = styles.marginLeft = styles.marginRight = styles.position = ''; |
| this._overlayRef = (/** @type {?} */ (null)); |
| this._isDisposed = true; |
| }; |
| return GlobalPositionStrategy; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Builder for overlay position strategy. |
| */ |
| var OverlayPositionBuilder = /** @class */ (function () { |
| function OverlayPositionBuilder(_viewportRuler, _document, _platform, _overlayContainer) { |
| this._viewportRuler = _viewportRuler; |
| this._document = _document; |
| this._platform = _platform; |
| this._overlayContainer = _overlayContainer; |
| } |
| /** |
| * Creates a global position strategy. |
| */ |
| /** |
| * Creates a global position strategy. |
| * @return {?} |
| */ |
| OverlayPositionBuilder.prototype.global = /** |
| * Creates a global position strategy. |
| * @return {?} |
| */ |
| function () { |
| return new GlobalPositionStrategy(); |
| }; |
| /** |
| * Creates a relative position strategy. |
| * @param elementRef |
| * @param originPos |
| * @param overlayPos |
| * @deprecated Use `flexibleConnectedTo` instead. |
| * @breaking-change 8.0.0 |
| */ |
| /** |
| * Creates a relative position strategy. |
| * @deprecated Use `flexibleConnectedTo` instead. |
| * \@breaking-change 8.0.0 |
| * @param {?} elementRef |
| * @param {?} originPos |
| * @param {?} overlayPos |
| * @return {?} |
| */ |
| OverlayPositionBuilder.prototype.connectedTo = /** |
| * Creates a relative position strategy. |
| * @deprecated Use `flexibleConnectedTo` instead. |
| * \@breaking-change 8.0.0 |
| * @param {?} elementRef |
| * @param {?} originPos |
| * @param {?} overlayPos |
| * @return {?} |
| */ |
| function (elementRef, originPos, overlayPos) { |
| return new ConnectedPositionStrategy(originPos, overlayPos, elementRef, this._viewportRuler, this._document, this._platform, this._overlayContainer); |
| }; |
| /** |
| * Creates a flexible position strategy. |
| * @param origin Origin relative to which to position the overlay. |
| */ |
| /** |
| * Creates a flexible position strategy. |
| * @param {?} origin Origin relative to which to position the overlay. |
| * @return {?} |
| */ |
| OverlayPositionBuilder.prototype.flexibleConnectedTo = /** |
| * Creates a flexible position strategy. |
| * @param {?} origin Origin relative to which to position the overlay. |
| * @return {?} |
| */ |
| function (origin) { |
| return new FlexibleConnectedPositionStrategy(origin, this._viewportRuler, this._document, this._platform, this._overlayContainer); |
| }; |
| OverlayPositionBuilder.decorators = [ |
| { type: Injectable, args: [{ providedIn: 'root' },] }, |
| ]; |
| /** @nocollapse */ |
| OverlayPositionBuilder.ctorParameters = function () { return [ |
| { type: ViewportRuler }, |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, |
| { type: Platform }, |
| { type: OverlayContainer } |
| ]; }; |
| /** @nocollapse */ OverlayPositionBuilder.ngInjectableDef = ɵɵdefineInjectable({ factory: function OverlayPositionBuilder_Factory() { return new OverlayPositionBuilder(ɵɵinject(ViewportRuler), ɵɵinject(DOCUMENT), ɵɵinject(Platform), ɵɵinject(OverlayContainer)); }, token: OverlayPositionBuilder, providedIn: "root" }); |
| return OverlayPositionBuilder; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Next overlay unique ID. |
| * @type {?} |
| */ |
| var nextUniqueId = 0; |
| // Note that Overlay is *not* scoped to the app root because the ComponentFactoryResolver |
| // it needs is different based on where OverlayModule is imported. |
| /** |
| * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be |
| * used as a low-level building block for other components. Dialogs, tooltips, menus, |
| * selects, etc. can all be built using overlays. The service should primarily be used by authors |
| * of re-usable components rather than developers building end-user applications. |
| * |
| * An overlay *is* a PortalOutlet, so any kind of Portal can be loaded into one. |
| */ |
| var Overlay = /** @class */ (function () { |
| function Overlay(scrollStrategies, _overlayContainer, _componentFactoryResolver, _positionBuilder, _keyboardDispatcher, _injector, _ngZone, _document, _directionality, _location) { |
| this.scrollStrategies = scrollStrategies; |
| this._overlayContainer = _overlayContainer; |
| this._componentFactoryResolver = _componentFactoryResolver; |
| this._positionBuilder = _positionBuilder; |
| this._keyboardDispatcher = _keyboardDispatcher; |
| this._injector = _injector; |
| this._ngZone = _ngZone; |
| this._document = _document; |
| this._directionality = _directionality; |
| this._location = _location; |
| } |
| /** |
| * Creates an overlay. |
| * @param config Configuration applied to the overlay. |
| * @returns Reference to the created overlay. |
| */ |
| /** |
| * Creates an overlay. |
| * @param {?=} config Configuration applied to the overlay. |
| * @return {?} Reference to the created overlay. |
| */ |
| Overlay.prototype.create = /** |
| * Creates an overlay. |
| * @param {?=} config Configuration applied to the overlay. |
| * @return {?} Reference to the created overlay. |
| */ |
| function (config) { |
| /** @type {?} */ |
| var host = this._createHostElement(); |
| /** @type {?} */ |
| var pane = this._createPaneElement(host); |
| /** @type {?} */ |
| var portalOutlet = this._createPortalOutlet(pane); |
| /** @type {?} */ |
| var overlayConfig = new OverlayConfig(config); |
| overlayConfig.direction = overlayConfig.direction || this._directionality.value; |
| return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location); |
| }; |
| /** |
| * Gets a position builder that can be used, via fluent API, |
| * to construct and configure a position strategy. |
| * @returns An overlay position builder. |
| */ |
| /** |
| * Gets a position builder that can be used, via fluent API, |
| * to construct and configure a position strategy. |
| * @return {?} An overlay position builder. |
| */ |
| Overlay.prototype.position = /** |
| * Gets a position builder that can be used, via fluent API, |
| * to construct and configure a position strategy. |
| * @return {?} An overlay position builder. |
| */ |
| function () { |
| return this._positionBuilder; |
| }; |
| /** |
| * Creates the DOM element for an overlay and appends it to the overlay container. |
| * @returns Newly-created pane element |
| */ |
| /** |
| * Creates the DOM element for an overlay and appends it to the overlay container. |
| * @private |
| * @param {?} host |
| * @return {?} Newly-created pane element |
| */ |
| Overlay.prototype._createPaneElement = /** |
| * Creates the DOM element for an overlay and appends it to the overlay container. |
| * @private |
| * @param {?} host |
| * @return {?} Newly-created pane element |
| */ |
| function (host) { |
| /** @type {?} */ |
| var pane = this._document.createElement('div'); |
| pane.id = "cdk-overlay-" + nextUniqueId++; |
| pane.classList.add('cdk-overlay-pane'); |
| host.appendChild(pane); |
| return pane; |
| }; |
| /** |
| * Creates the host element that wraps around an overlay |
| * and can be used for advanced positioning. |
| * @returns Newly-create host element. |
| */ |
| /** |
| * Creates the host element that wraps around an overlay |
| * and can be used for advanced positioning. |
| * @private |
| * @return {?} Newly-create host element. |
| */ |
| Overlay.prototype._createHostElement = /** |
| * Creates the host element that wraps around an overlay |
| * and can be used for advanced positioning. |
| * @private |
| * @return {?} Newly-create host element. |
| */ |
| function () { |
| /** @type {?} */ |
| var host = this._document.createElement('div'); |
| this._overlayContainer.getContainerElement().appendChild(host); |
| return host; |
| }; |
| /** |
| * Create a DomPortalOutlet into which the overlay content can be loaded. |
| * @param pane The DOM element to turn into a portal outlet. |
| * @returns A portal outlet for the given DOM element. |
| */ |
| /** |
| * Create a DomPortalOutlet into which the overlay content can be loaded. |
| * @private |
| * @param {?} pane The DOM element to turn into a portal outlet. |
| * @return {?} A portal outlet for the given DOM element. |
| */ |
| Overlay.prototype._createPortalOutlet = /** |
| * Create a DomPortalOutlet into which the overlay content can be loaded. |
| * @private |
| * @param {?} pane The DOM element to turn into a portal outlet. |
| * @return {?} A portal outlet for the given DOM element. |
| */ |
| function (pane) { |
| // We have to resolve the ApplicationRef later in order to allow people |
| // to use overlay-based providers during app initialization. |
| if (!this._appRef) { |
| this._appRef = this._injector.get(ApplicationRef); |
| } |
| return new DomPortalOutlet(pane, this._componentFactoryResolver, this._appRef, this._injector); |
| }; |
| Overlay.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| Overlay.ctorParameters = function () { return [ |
| { type: ScrollStrategyOptions }, |
| { type: OverlayContainer }, |
| { type: ComponentFactoryResolver }, |
| { type: OverlayPositionBuilder }, |
| { type: OverlayKeyboardDispatcher }, |
| { type: Injector }, |
| { type: NgZone }, |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }, |
| { type: Directionality }, |
| { type: Location, decorators: [{ type: Optional }] } |
| ]; }; |
| return Overlay; |
| }()); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Default set of positions for the overlay. Follows the behavior of a dropdown. |
| * @type {?} |
| */ |
| var defaultPositionList = [ |
| { |
| originX: 'start', |
| originY: 'bottom', |
| overlayX: 'start', |
| overlayY: 'top' |
| }, |
| { |
| originX: 'start', |
| originY: 'top', |
| overlayX: 'start', |
| overlayY: 'bottom' |
| }, |
| { |
| originX: 'end', |
| originY: 'top', |
| overlayX: 'end', |
| overlayY: 'bottom' |
| }, |
| { |
| originX: 'end', |
| originY: 'bottom', |
| overlayX: 'end', |
| overlayY: 'top' |
| } |
| ]; |
| /** |
| * Injection token that determines the scroll handling while the connected overlay is open. |
| * @type {?} |
| */ |
| var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = new InjectionToken('cdk-connected-overlay-scroll-strategy'); |
| /** |
| * Directive applied to an element to make it usable as an origin for an Overlay using a |
| * ConnectedPositionStrategy. |
| */ |
| var CdkOverlayOrigin = /** @class */ (function () { |
| function CdkOverlayOrigin(elementRef) { |
| this.elementRef = elementRef; |
| } |
| CdkOverlayOrigin.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]', |
| exportAs: 'cdkOverlayOrigin', |
| },] }, |
| ]; |
| /** @nocollapse */ |
| CdkOverlayOrigin.ctorParameters = function () { return [ |
| { type: ElementRef } |
| ]; }; |
| return CdkOverlayOrigin; |
| }()); |
| /** |
| * Directive to facilitate declarative creation of an |
| * Overlay using a FlexibleConnectedPositionStrategy. |
| */ |
| var CdkConnectedOverlay = /** @class */ (function () { |
| // TODO(jelbourn): inputs for size, scroll behavior, animation, etc. |
| function CdkConnectedOverlay(_overlay, templateRef, viewContainerRef, scrollStrategyFactory, _dir) { |
| this._overlay = _overlay; |
| this._dir = _dir; |
| this._hasBackdrop = false; |
| this._lockPosition = false; |
| this._growAfterOpen = false; |
| this._flexibleDimensions = false; |
| this._push = false; |
| this._backdropSubscription = Subscription.EMPTY; |
| /** |
| * Margin between the overlay and the viewport edges. |
| */ |
| this.viewportMargin = 0; |
| /** |
| * Whether the overlay is open. |
| */ |
| this.open = false; |
| /** |
| * Event emitted when the backdrop is clicked. |
| */ |
| this.backdropClick = new EventEmitter(); |
| /** |
| * Event emitted when the position has changed. |
| */ |
| this.positionChange = new EventEmitter(); |
| /** |
| * Event emitted when the overlay has been attached. |
| */ |
| this.attach = new EventEmitter(); |
| /** |
| * Event emitted when the overlay has been detached. |
| */ |
| this.detach = new EventEmitter(); |
| /** |
| * Emits when there are keyboard events that are targeted at the overlay. |
| */ |
| this.overlayKeydown = new EventEmitter(); |
| this._templatePortal = new TemplatePortal(templateRef, viewContainerRef); |
| this._scrollStrategyFactory = scrollStrategyFactory; |
| this.scrollStrategy = this._scrollStrategyFactory(); |
| } |
| Object.defineProperty(CdkConnectedOverlay.prototype, "offsetX", { |
| /** The offset in pixels for the overlay connection point on the x-axis */ |
| get: /** |
| * The offset in pixels for the overlay connection point on the x-axis |
| * @return {?} |
| */ |
| function () { return this._offsetX; }, |
| set: /** |
| * @param {?} offsetX |
| * @return {?} |
| */ |
| function (offsetX) { |
| this._offsetX = offsetX; |
| if (this._position) { |
| this._updatePositionStrategy(this._position); |
| } |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "offsetY", { |
| /** The offset in pixels for the overlay connection point on the y-axis */ |
| get: /** |
| * The offset in pixels for the overlay connection point on the y-axis |
| * @return {?} |
| */ |
| function () { return this._offsetY; }, |
| set: /** |
| * @param {?} offsetY |
| * @return {?} |
| */ |
| function (offsetY) { |
| this._offsetY = offsetY; |
| if (this._position) { |
| this._updatePositionStrategy(this._position); |
| } |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "hasBackdrop", { |
| /** Whether or not the overlay should attach a backdrop. */ |
| get: /** |
| * Whether or not the overlay should attach a backdrop. |
| * @return {?} |
| */ |
| function () { return this._hasBackdrop; }, |
| set: /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function (value) { this._hasBackdrop = coerceBooleanProperty(value); }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "lockPosition", { |
| /** Whether or not the overlay should be locked when scrolling. */ |
| get: /** |
| * Whether or not the overlay should be locked when scrolling. |
| * @return {?} |
| */ |
| function () { return this._lockPosition; }, |
| set: /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function (value) { this._lockPosition = coerceBooleanProperty(value); }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "flexibleDimensions", { |
| /** Whether the overlay's width and height can be constrained to fit within the viewport. */ |
| get: /** |
| * Whether the overlay's width and height can be constrained to fit within the viewport. |
| * @return {?} |
| */ |
| function () { return this._flexibleDimensions; }, |
| set: /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function (value) { |
| this._flexibleDimensions = coerceBooleanProperty(value); |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "growAfterOpen", { |
| /** Whether the overlay can grow after the initial open when flexible positioning is turned on. */ |
| get: /** |
| * Whether the overlay can grow after the initial open when flexible positioning is turned on. |
| * @return {?} |
| */ |
| function () { return this._growAfterOpen; }, |
| set: /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function (value) { this._growAfterOpen = coerceBooleanProperty(value); }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "push", { |
| /** Whether the overlay can be pushed on-screen if none of the provided positions fit. */ |
| get: /** |
| * Whether the overlay can be pushed on-screen if none of the provided positions fit. |
| * @return {?} |
| */ |
| function () { return this._push; }, |
| set: /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function (value) { this._push = coerceBooleanProperty(value); }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "overlayRef", { |
| /** The associated overlay reference. */ |
| get: /** |
| * The associated overlay reference. |
| * @return {?} |
| */ |
| function () { |
| return this._overlayRef; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| Object.defineProperty(CdkConnectedOverlay.prototype, "dir", { |
| /** The element's layout direction. */ |
| get: /** |
| * The element's layout direction. |
| * @return {?} |
| */ |
| function () { |
| return this._dir ? this._dir.value : 'ltr'; |
| }, |
| enumerable: true, |
| configurable: true |
| }); |
| /** |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype.ngOnDestroy = /** |
| * @return {?} |
| */ |
| function () { |
| if (this._overlayRef) { |
| this._overlayRef.dispose(); |
| } |
| this._backdropSubscription.unsubscribe(); |
| }; |
| /** |
| * @param {?} changes |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype.ngOnChanges = /** |
| * @param {?} changes |
| * @return {?} |
| */ |
| function (changes) { |
| if (this._position) { |
| this._updatePositionStrategy(this._position); |
| this._overlayRef.updateSize({ |
| width: this.width, |
| minWidth: this.minWidth, |
| height: this.height, |
| minHeight: this.minHeight, |
| }); |
| if (changes['origin'] && this.open) { |
| this._position.apply(); |
| } |
| } |
| if (changes['open']) { |
| this.open ? this._attachOverlay() : this._detachOverlay(); |
| } |
| }; |
| /** Creates an overlay */ |
| /** |
| * Creates an overlay |
| * @private |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._createOverlay = /** |
| * Creates an overlay |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (!this.positions || !this.positions.length) { |
| this.positions = defaultPositionList; |
| } |
| this._overlayRef = this._overlay.create(this._buildConfig()); |
| this._overlayRef.keydownEvents().subscribe((/** |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| _this.overlayKeydown.next(event); |
| if (event.keyCode === ESCAPE && !hasModifierKey(event)) { |
| event.preventDefault(); |
| _this._detachOverlay(); |
| } |
| })); |
| }; |
| /** Builds the overlay config based on the directive's inputs */ |
| /** |
| * Builds the overlay config based on the directive's inputs |
| * @private |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._buildConfig = /** |
| * Builds the overlay config based on the directive's inputs |
| * @private |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| var positionStrategy = this._position = this._createPositionStrategy(); |
| /** @type {?} */ |
| var overlayConfig = new OverlayConfig({ |
| direction: this._dir, |
| positionStrategy: positionStrategy, |
| scrollStrategy: this.scrollStrategy, |
| hasBackdrop: this.hasBackdrop |
| }); |
| if (this.width || this.width === 0) { |
| overlayConfig.width = this.width; |
| } |
| if (this.height || this.height === 0) { |
| overlayConfig.height = this.height; |
| } |
| if (this.minWidth || this.minWidth === 0) { |
| overlayConfig.minWidth = this.minWidth; |
| } |
| if (this.minHeight || this.minHeight === 0) { |
| overlayConfig.minHeight = this.minHeight; |
| } |
| if (this.backdropClass) { |
| overlayConfig.backdropClass = this.backdropClass; |
| } |
| if (this.panelClass) { |
| overlayConfig.panelClass = this.panelClass; |
| } |
| return overlayConfig; |
| }; |
| /** Updates the state of a position strategy, based on the values of the directive inputs. */ |
| /** |
| * Updates the state of a position strategy, based on the values of the directive inputs. |
| * @private |
| * @param {?} positionStrategy |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._updatePositionStrategy = /** |
| * Updates the state of a position strategy, based on the values of the directive inputs. |
| * @private |
| * @param {?} positionStrategy |
| * @return {?} |
| */ |
| function (positionStrategy) { |
| var _this = this; |
| /** @type {?} */ |
| var positions = this.positions.map((/** |
| * @param {?} currentPosition |
| * @return {?} |
| */ |
| function (currentPosition) { return ({ |
| originX: currentPosition.originX, |
| originY: currentPosition.originY, |
| overlayX: currentPosition.overlayX, |
| overlayY: currentPosition.overlayY, |
| offsetX: currentPosition.offsetX || _this.offsetX, |
| offsetY: currentPosition.offsetY || _this.offsetY, |
| panelClass: currentPosition.panelClass || undefined, |
| }); })); |
| return positionStrategy |
| .setOrigin(this.origin.elementRef) |
| .withPositions(positions) |
| .withFlexibleDimensions(this.flexibleDimensions) |
| .withPush(this.push) |
| .withGrowAfterOpen(this.growAfterOpen) |
| .withViewportMargin(this.viewportMargin) |
| .withLockedPosition(this.lockPosition); |
| }; |
| /** Returns the position strategy of the overlay to be set on the overlay config */ |
| /** |
| * Returns the position strategy of the overlay to be set on the overlay config |
| * @private |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._createPositionStrategy = /** |
| * Returns the position strategy of the overlay to be set on the overlay config |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| /** @type {?} */ |
| var strategy = this._overlay.position().flexibleConnectedTo(this.origin.elementRef); |
| this._updatePositionStrategy(strategy); |
| strategy.positionChanges.subscribe((/** |
| * @param {?} p |
| * @return {?} |
| */ |
| function (p) { return _this.positionChange.emit(p); })); |
| return strategy; |
| }; |
| /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */ |
| /** |
| * Attaches the overlay and subscribes to backdrop clicks if backdrop exists |
| * @private |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._attachOverlay = /** |
| * Attaches the overlay and subscribes to backdrop clicks if backdrop exists |
| * @private |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| if (!this._overlayRef) { |
| this._createOverlay(); |
| } |
| else { |
| // Update the overlay size, in case the directive's inputs have changed |
| this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop; |
| } |
| if (!this._overlayRef.hasAttached()) { |
| this._overlayRef.attach(this._templatePortal); |
| this.attach.emit(); |
| } |
| if (this.hasBackdrop) { |
| this._backdropSubscription = this._overlayRef.backdropClick().subscribe((/** |
| * @param {?} event |
| * @return {?} |
| */ |
| function (event) { |
| _this.backdropClick.emit(event); |
| })); |
| } |
| else { |
| this._backdropSubscription.unsubscribe(); |
| } |
| }; |
| /** Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists */ |
| /** |
| * Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists |
| * @private |
| * @return {?} |
| */ |
| CdkConnectedOverlay.prototype._detachOverlay = /** |
| * Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (this._overlayRef) { |
| this._overlayRef.detach(); |
| this.detach.emit(); |
| } |
| this._backdropSubscription.unsubscribe(); |
| }; |
| CdkConnectedOverlay.decorators = [ |
| { type: Directive, args: [{ |
| selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]', |
| exportAs: 'cdkConnectedOverlay' |
| },] }, |
| ]; |
| /** @nocollapse */ |
| CdkConnectedOverlay.ctorParameters = function () { return [ |
| { type: Overlay }, |
| { type: TemplateRef }, |
| { type: ViewContainerRef }, |
| { type: undefined, decorators: [{ type: Inject, args: [CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,] }] }, |
| { type: Directionality, decorators: [{ type: Optional }] } |
| ]; }; |
| CdkConnectedOverlay.propDecorators = { |
| origin: [{ type: Input, args: ['cdkConnectedOverlayOrigin',] }], |
| positions: [{ type: Input, args: ['cdkConnectedOverlayPositions',] }], |
| offsetX: [{ type: Input, args: ['cdkConnectedOverlayOffsetX',] }], |
| offsetY: [{ type: Input, args: ['cdkConnectedOverlayOffsetY',] }], |
| width: [{ type: Input, args: ['cdkConnectedOverlayWidth',] }], |
| height: [{ type: Input, args: ['cdkConnectedOverlayHeight',] }], |
| minWidth: [{ type: Input, args: ['cdkConnectedOverlayMinWidth',] }], |
| minHeight: [{ type: Input, args: ['cdkConnectedOverlayMinHeight',] }], |
| backdropClass: [{ type: Input, args: ['cdkConnectedOverlayBackdropClass',] }], |
| panelClass: [{ type: Input, args: ['cdkConnectedOverlayPanelClass',] }], |
| viewportMargin: [{ type: Input, args: ['cdkConnectedOverlayViewportMargin',] }], |
| scrollStrategy: [{ type: Input, args: ['cdkConnectedOverlayScrollStrategy',] }], |
| open: [{ type: Input, args: ['cdkConnectedOverlayOpen',] }], |
| hasBackdrop: [{ type: Input, args: ['cdkConnectedOverlayHasBackdrop',] }], |
| lockPosition: [{ type: Input, args: ['cdkConnectedOverlayLockPosition',] }], |
| flexibleDimensions: [{ type: Input, args: ['cdkConnectedOverlayFlexibleDimensions',] }], |
| growAfterOpen: [{ type: Input, args: ['cdkConnectedOverlayGrowAfterOpen',] }], |
| push: [{ type: Input, args: ['cdkConnectedOverlayPush',] }], |
| backdropClick: [{ type: Output }], |
| positionChange: [{ type: Output }], |
| attach: [{ type: Output }], |
| detach: [{ type: Output }], |
| overlayKeydown: [{ type: Output }] |
| }; |
| return CdkConnectedOverlay; |
| }()); |
| /** |
| * \@docs-private |
| * @param {?} overlay |
| * @return {?} |
| */ |
| function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) { |
| return (/** |
| * @return {?} |
| */ |
| function () { return overlay.scrollStrategies.reposition(); }); |
| } |
| /** |
| * \@docs-private |
| * @type {?} |
| */ |
| var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = { |
| provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY, |
| deps: [Overlay], |
| useFactory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY, |
| }; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| var OverlayModule = /** @class */ (function () { |
| function OverlayModule() { |
| } |
| OverlayModule.decorators = [ |
| { type: NgModule, args: [{ |
| imports: [BidiModule, PortalModule, ScrollingModule], |
| exports: [CdkConnectedOverlay, CdkOverlayOrigin, ScrollingModule], |
| declarations: [CdkConnectedOverlay, CdkOverlayOrigin], |
| providers: [ |
| Overlay, |
| CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER, |
| ], |
| },] }, |
| ]; |
| return OverlayModule; |
| }()); |
| /** |
| * @deprecated Use `OverlayModule` instead. |
| * \@breaking-change 8.0.0 |
| * \@docs-private |
| * @type {?} |
| */ |
| var OVERLAY_PROVIDERS = [ |
| Overlay, |
| OverlayPositionBuilder, |
| OVERLAY_KEYBOARD_DISPATCHER_PROVIDER, |
| VIEWPORT_RULER_PROVIDER, |
| OVERLAY_CONTAINER_PROVIDER, |
| CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Alternative to OverlayContainer that supports correct displaying of overlay elements in |
| * Fullscreen mode |
| * https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen |
| * |
| * Should be provided in the root component. |
| */ |
| var FullscreenOverlayContainer = /** @class */ (function (_super) { |
| __extends(FullscreenOverlayContainer, _super); |
| function FullscreenOverlayContainer(_document) { |
| return _super.call(this, _document) || this; |
| } |
| /** |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype.ngOnDestroy = /** |
| * @return {?} |
| */ |
| function () { |
| _super.prototype.ngOnDestroy.call(this); |
| if (this._fullScreenEventName && this._fullScreenListener) { |
| this._document.removeEventListener(this._fullScreenEventName, this._fullScreenListener); |
| } |
| }; |
| /** |
| * @protected |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype._createContainer = /** |
| * @protected |
| * @return {?} |
| */ |
| function () { |
| var _this = this; |
| _super.prototype._createContainer.call(this); |
| this._adjustParentForFullscreenChange(); |
| this._addFullscreenChangeListener((/** |
| * @return {?} |
| */ |
| function () { return _this._adjustParentForFullscreenChange(); })); |
| }; |
| /** |
| * @private |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype._adjustParentForFullscreenChange = /** |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (!this._containerElement) { |
| return; |
| } |
| /** @type {?} */ |
| var fullscreenElement = this.getFullscreenElement(); |
| /** @type {?} */ |
| var parent = fullscreenElement || this._document.body; |
| parent.appendChild(this._containerElement); |
| }; |
| /** |
| * @private |
| * @param {?} fn |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype._addFullscreenChangeListener = /** |
| * @private |
| * @param {?} fn |
| * @return {?} |
| */ |
| function (fn) { |
| /** @type {?} */ |
| var eventName = this._getEventName(); |
| if (eventName) { |
| if (this._fullScreenListener) { |
| this._document.removeEventListener(eventName, this._fullScreenListener); |
| } |
| this._document.addEventListener(eventName, fn); |
| this._fullScreenListener = fn; |
| } |
| }; |
| /** |
| * @private |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype._getEventName = /** |
| * @private |
| * @return {?} |
| */ |
| function () { |
| if (!this._fullScreenEventName) { |
| if (this._document.fullscreenEnabled) { |
| this._fullScreenEventName = 'fullscreenchange'; |
| } |
| else if (this._document.webkitFullscreenEnabled) { |
| this._fullScreenEventName = 'webkitfullscreenchange'; |
| } |
| else if (((/** @type {?} */ (this._document))).mozFullScreenEnabled) { |
| this._fullScreenEventName = 'mozfullscreenchange'; |
| } |
| else if (((/** @type {?} */ (this._document))).msFullscreenEnabled) { |
| this._fullScreenEventName = 'MSFullscreenChange'; |
| } |
| } |
| return this._fullScreenEventName; |
| }; |
| /** |
| * When the page is put into fullscreen mode, a specific element is specified. |
| * Only that element and its children are visible when in fullscreen mode. |
| */ |
| /** |
| * When the page is put into fullscreen mode, a specific element is specified. |
| * Only that element and its children are visible when in fullscreen mode. |
| * @return {?} |
| */ |
| FullscreenOverlayContainer.prototype.getFullscreenElement = /** |
| * When the page is put into fullscreen mode, a specific element is specified. |
| * Only that element and its children are visible when in fullscreen mode. |
| * @return {?} |
| */ |
| function () { |
| return this._document.fullscreenElement || |
| this._document.webkitFullscreenElement || |
| ((/** @type {?} */ (this._document))).mozFullScreenElement || |
| ((/** @type {?} */ (this._document))).msFullscreenElement || |
| null; |
| }; |
| FullscreenOverlayContainer.decorators = [ |
| { type: Injectable, args: [{ providedIn: 'root' },] }, |
| ]; |
| /** @nocollapse */ |
| FullscreenOverlayContainer.ctorParameters = function () { return [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } |
| ]; }; |
| /** @nocollapse */ FullscreenOverlayContainer.ngInjectableDef = ɵɵdefineInjectable({ factory: function FullscreenOverlayContainer_Factory() { return new FullscreenOverlayContainer(ɵɵinject(DOCUMENT)); }, token: FullscreenOverlayContainer, providedIn: "root" }); |
| return FullscreenOverlayContainer; |
| }(OverlayContainer)); |
| |
| /** |
| * @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 { Overlay, OverlayContainer, CdkOverlayOrigin, CdkConnectedOverlay, FullscreenOverlayContainer, OverlayRef, OverlayKeyboardDispatcher, OverlayPositionBuilder, GlobalPositionStrategy, ConnectedPositionStrategy, FlexibleConnectedPositionStrategy, OverlayConfig, validateVerticalPosition, validateHorizontalPosition, ConnectionPositionPair, ScrollingVisibility, ConnectedOverlayPositionChange, ScrollStrategyOptions, RepositionScrollStrategy, CloseScrollStrategy, NoopScrollStrategy, BlockScrollStrategy, OverlayModule, OVERLAY_PROVIDERS, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER as ɵg, OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY as ɵf, OVERLAY_CONTAINER_PROVIDER as ɵb, OVERLAY_CONTAINER_PROVIDER_FACTORY as ɵa, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY as ɵc, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER as ɵe, CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY as ɵd }; |
| //# sourceMappingURL=overlay.es5.js.map |