@angular/cdk
Version:
Angular Material Component Development Kit
1,016 lines (999 loc) • 176 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/cdk/scrolling'), require('@angular/common'), require('@angular/core'), require('@angular/cdk/coercion'), require('@angular/cdk/bidi'), require('@angular/cdk/portal'), require('@angular/cdk/platform'), require('rxjs'), require('rxjs/operators'), require('@angular/cdk/keycodes')) :
typeof define === 'function' && define.amd ? define('@angular/cdk/overlay', ['exports', '@angular/cdk/scrolling', '@angular/common', '@angular/core', '@angular/cdk/coercion', '@angular/cdk/bidi', '@angular/cdk/portal', '@angular/cdk/platform', 'rxjs', 'rxjs/operators', '@angular/cdk/keycodes'], factory) :
(global = global || self, factory((global.ng = global.ng || {}, global.ng.cdk = global.ng.cdk || {}, global.ng.cdk.overlay = {}), global.ng.cdk.scrolling, global.ng.common, global.ng.core, global.ng.cdk.coercion, global.ng.cdk.bidi, global.ng.cdk.portal, global.ng.cdk.platform, global.rxjs, global.rxjs.operators, global.ng.cdk.keycodes));
}(this, (function (exports, i1, i1$1, i0, coercion, bidi, portal, i2, rxjs, operators, keycodes) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (Object.prototype.hasOwnProperty.call(b, p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); };
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try {
step(generator.next(value));
}
catch (e) {
reject(e);
} }
function rejected(value) { try {
step(generator["throw"](value));
}
catch (e) {
reject(e);
} }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function () { if (t[0] & 1)
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
}
catch (e) {
op = [6, e];
y = 0;
}
finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
}
var __createBinding = Object.create ? (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
}) : (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
o[k2] = m[k];
});
function __exportStar(m, o) {
for (var p in m)
if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
__createBinding(o, m, p);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
;
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n])
i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try {
step(g[n](v));
}
catch (e) {
settle(q[0][3], e);
} }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
}
else {
cooked.raw = raw;
}
return cooked;
}
;
var __setModuleDefault = Object.create ? (function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o, v) {
o["default"] = v;
};
function __importStar(mod) {
if (mod && mod.__esModule)
return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
function __classPrivateFieldGet(receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
}
function __classPrivateFieldSet(receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
}
/**
* @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
*/
/**
* Strategy that will prevent the user from scrolling while the overlay is visible.
*/
var 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. */
BlockScrollStrategy.prototype.attach = function () { };
/** Blocks page-level scroll while the attached overlay is open. */
BlockScrollStrategy.prototype.enable = function () {
if (this._canBeEnabled()) {
var root = 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 = coercion.coerceCssPixelValue(-this._previousScrollPosition.left);
root.style.top = coercion.coerceCssPixelValue(-this._previousScrollPosition.top);
root.classList.add('cdk-global-scrollblock');
this._isEnabled = true;
}
};
/** Unblocks page-level scroll while the attached overlay is open. */
BlockScrollStrategy.prototype.disable = function () {
if (this._isEnabled) {
var html = this._document.documentElement;
var body = this._document.body;
var htmlStyle = html.style;
var bodyStyle = body.style;
var previousHtmlScrollBehavior = htmlStyle.scrollBehavior || '';
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;
}
};
BlockScrollStrategy.prototype._canBeEnabled = 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.
var html = this._document.documentElement;
if (html.classList.contains('cdk-global-scrollblock') || this._isEnabled) {
return false;
}
var body = this._document.body;
var viewport = this._viewportRuler.getViewportSize();
return body.scrollHeight > viewport.height || body.scrollWidth > viewport.width;
};
return BlockScrollStrategy;
}());
/**
* @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
*/
/**
* Returns an error to be thrown when attempting to attach an already-attached scroll strategy.
*/
function getMatScrollStrategyAlreadyAttachedError() {
return Error("Scroll strategy has already been attached.");
}
/**
* Strategy that will close the overlay as soon as the user starts scrolling.
*/
var 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 = function () {
_this.disable();
if (_this._overlayRef.hasAttached()) {
_this._ngZone.run(function () { return _this._overlayRef.detach(); });
}
};
}
/** Attaches this scroll strategy to an overlay. */
CloseScrollStrategy.prototype.attach = function (overlayRef) {
if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMatScrollStrategyAlreadyAttachedError();
}
this._overlayRef = overlayRef;
};
/** Enables the closing of the attached overlay on scroll. */
CloseScrollStrategy.prototype.enable = function () {
var _this = this;
if (this._scrollSubscription) {
return;
}
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(function () {
var scrollPosition = _this._viewportRuler.getViewportScrollPosition().top;
if (Math.abs(scrollPosition - _this._initialScrollPosition) > _this._config.threshold) {
_this._detach();
}
else {
_this._overlayRef.updatePosition();
}
});
}
else {
this._scrollSubscription = stream.subscribe(this._detach);
}
};
/** Disables the closing the attached overlay on scroll. */
CloseScrollStrategy.prototype.disable = function () {
if (this._scrollSubscription) {
this._scrollSubscription.unsubscribe();
this._scrollSubscription = null;
}
};
CloseScrollStrategy.prototype.detach = function () {
this.disable();
this._overlayRef = null;
};
return CloseScrollStrategy;
}());
/**
* @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
*/
/** Scroll strategy that doesn't do anything. */
var NoopScrollStrategy = /** @class */ (function () {
function NoopScrollStrategy() {
}
/** Does nothing, as this scroll strategy is a no-op. */
NoopScrollStrategy.prototype.enable = function () { };
/** Does nothing, as this scroll strategy is a no-op. */
NoopScrollStrategy.prototype.disable = function () { };
/** Does nothing, as this scroll strategy is a no-op. */
NoopScrollStrategy.prototype.attach = function () { };
return NoopScrollStrategy;
}());
/**
* @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
*/
// 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.
* @param element Dimensions of the element (from getBoundingClientRect)
* @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)
* @returns Whether the element is scrolled out of view
* @docs-private
*/
function isElementScrolledOutsideView(element, scrollContainers) {
return scrollContainers.some(function (containerBounds) {
var outsideAbove = element.bottom < containerBounds.top;
var outsideBelow = element.top > containerBounds.bottom;
var outsideLeft = element.right < containerBounds.left;
var outsideRight = element.left > containerBounds.right;
return outsideAbove || outsideBelow || outsideLeft || outsideRight;
});
}
/**
* Gets whether an element is clipped by any of its scrolling containers.
* @param element Dimensions of the element (from getBoundingClientRect)
* @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)
* @returns Whether the element is clipped
* @docs-private
*/
function isElementClippedByScrolling(element, scrollContainers) {
return scrollContainers.some(function (scrollContainerRect) {
var clippedAbove = element.top < scrollContainerRect.top;
var clippedBelow = element.bottom > scrollContainerRect.bottom;
var clippedLeft = element.left < scrollContainerRect.left;
var clippedRight = element.right > scrollContainerRect.right;
return clippedAbove || clippedBelow || clippedLeft || clippedRight;
});
}
/**
* @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
*/
/**
* Strategy that will update the element position as the user is scrolling.
*/
var 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. */
RepositionScrollStrategy.prototype.attach = function (overlayRef) {
if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw getMatScrollStrategyAlreadyAttachedError();
}
this._overlayRef = overlayRef;
};
/** Enables repositioning of the attached overlay on scroll. */
RepositionScrollStrategy.prototype.enable = function () {
var _this = this;
if (!this._scrollSubscription) {
var throttle = this._config ? this._config.scrollThrottle : 0;
this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe(function () {
_this._overlayRef.updatePosition();
// TODO(crisbeto): make `close` on by default once all components can handle it.
if (_this._config && _this._config.autoClose) {
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.
var parentRects = [{ width: width, height: height, bottom: height, right: width, top: 0, left: 0 }];
if (isElementScrolledOutsideView(overlayRect, parentRects)) {
_this.disable();
_this._ngZone.run(function () { return _this._overlayRef.detach(); });
}
}
});
}
};
/** Disables repositioning of the attached overlay on scroll. */
RepositionScrollStrategy.prototype.disable = function () {
if (this._scrollSubscription) {
this._scrollSubscription.unsubscribe();
this._scrollSubscription = null;
}
};
RepositionScrollStrategy.prototype.detach = function () {
this.disable();
this._overlayRef = null;
};
return RepositionScrollStrategy;
}());
/**
* @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
*/
/**
* 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 = 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 = function (config) { return new CloseScrollStrategy(_this._scrollDispatcher, _this._ngZone, _this._viewportRuler, config); };
/** Block scrolling. */
this.block = 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 = function (config) { return new RepositionScrollStrategy(_this._scrollDispatcher, _this._viewportRuler, _this._ngZone, config); };
this._document = document;
}
return ScrollStrategyOptions;
}());
ScrollStrategyOptions.ɵprov = i0.ɵɵdefineInjectable({ factory: function ScrollStrategyOptions_Factory() { return new ScrollStrategyOptions(i0.ɵɵinject(i1.ScrollDispatcher), i0.ɵɵinject(i1.ViewportRuler), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i1$1.DOCUMENT)); }, token: ScrollStrategyOptions, providedIn: "root" });
ScrollStrategyOptions.decorators = [
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
];
ScrollStrategyOptions.ctorParameters = function () { return [
{ type: i1.ScrollDispatcher },
{ type: i1.ViewportRuler },
{ type: i0.NgZone },
{ type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
]; };
/**
* @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
*/
/** Initial configuration used when creating an overlay. */
var OverlayConfig = /** @class */ (function () {
function OverlayConfig(config) {
var e_1, _a;
/** 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) {
// Use `Iterable` instead of `Array` because TypeScript, as of 3.6.3,
// loses the array generic type in the `for of`. But we *also* have to use `Array` because
// typescript won't iterate over an `Iterable` unless you compile with `--downlevelIteration`
var configKeys = Object.keys(config);
try {
for (var configKeys_1 = __values(configKeys), configKeys_1_1 = configKeys_1.next(); !configKeys_1_1.done; configKeys_1_1 = configKeys_1.next()) {
var key = configKeys_1_1.value;
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] = config[key];
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (configKeys_1_1 && !configKeys_1_1.done && (_a = configKeys_1.return)) _a.call(configKeys_1);
}
finally { if (e_1) throw e_1.error; }
}
}
}
return OverlayConfig;
}());
/**
* @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
*/
/** The points of the origin element and the overlay element to connect. */
var ConnectionPositionPair = /** @class */ (function () {
function ConnectionPositionPair(origin, overlay,
/** Offset along the X axis. */
offsetX,
/** Offset along the Y axis. */
offsetY,
/** Class(es) to be applied to the panel while this position is active. */
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 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(
/** The position used as a result of this change. */
connectionPair,
/** @docs-private */
scrollableViewProperties) {
this.connectionPair = connectionPair;
this.scrollableViewProperties = scrollableViewProperties;
}
return ConnectedOverlayPositionChange;
}());
ConnectedOverlayPositionChange.ctorParameters = function () { return [
{ type: ConnectionPositionPair },
{ type: ScrollingVisibility, decorators: [{ type: i0.Optional }] }
]; };
/**
* Validates whether a vertical position property matches the expected values.
* @param property Name of the property being validated.
* @param value Value of the property being validated.
* @docs-private
*/
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.
* @param property Name of the property being validated.
* @param value Value of the property being validated.
* @docs-private
*/
function validateHorizontalPosition(property, value) {
if (value !== 'start' && value !== 'end' && value !== 'center') {
throw Error("ConnectedPosition: Invalid " + property + " \"" + value + "\". " +
"Expected \"start\", \"end\" or \"center\".");
}
}
/**
* @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
*/
/**
* Service for dispatching 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 BaseOverlayDispatcher = /** @class */ (function () {
function BaseOverlayDispatcher(document) {
/** Currently attached overlays in the order they were attached. */
this._attachedOverlays = [];
this._document = document;
}
BaseOverlayDispatcher.prototype.ngOnDestroy = function () {
this.detach();
};
/** Add a new overlay to the list of attached overlay refs. */
BaseOverlayDispatcher.prototype.add = function (overlayRef) {
// Ensure that we don't get the same overlay multiple times.
this.remove(overlayRef);
this._attachedOverlays.push(overlayRef);
};
/** Remove an overlay from the list of attached overlay refs. */
BaseOverlayDispatcher.prototype.remove = function (overlayRef) {
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();
}
};
return BaseOverlayDispatcher;
}());
BaseOverlayDispatcher.ɵprov = i0.ɵɵdefineInjectable({ factory: function BaseOverlayDispatcher_Factory() { return new BaseOverlayDispatcher(i0.ɵɵinject(i1$1.DOCUMENT)); }, token: BaseOverlayDispatcher, providedIn: "root" });
BaseOverlayDispatcher.decorators = [
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
];
BaseOverlayDispatcher.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
]; };
/**
* 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 (_super) {
__extends(OverlayKeyboardDispatcher, _super);
function OverlayKeyboardDispatcher(document) {
var _this = _super.call(this, document) || this;
/** Keyboard event listener that will be attached to the body. */
_this._keydownListener = function (event) {
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]._keydownEvents.observers.length > 0) {
overlays[i]._keydownEvents.next(event);
break;
}
}
};
return _this;
}
/** Add a new overlay to the list of attached overlay refs. */
OverlayKeyboardDispatcher.prototype.add = function (overlayRef) {
_super.prototype.add.call(this, overlayRef);
// Lazily start dispatcher once first overlay is added
if (!this._isAttached) {
this._document.body.addEventListener('keydown', this._keydownListener);
this._isAttached = true;
}
};
/** Detaches the global keyboard event listener. */
OverlayKeyboardDispatcher.prototype.detach = function () {
if (this._isAttached) {
this._document.body.removeEventListener('keydown', this._keydownListener);
this._isAttached = false;
}
};
return OverlayKeyboardDispatcher;
}(BaseOverlayDispatcher));
OverlayKeyboardDispatcher.ɵprov = i0.ɵɵdefineInjectable({ factory: function OverlayKeyboardDispatcher_Factory() { return new OverlayKeyboardDispatcher(i0.ɵɵinject(i1$1.DOCUMENT)); }, token: OverlayKeyboardDispatcher, providedIn: "root" });
OverlayKeyboardDispatcher.decorators = [
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
];
OverlayKeyboardDispatcher.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
]; };
/**
* Service for dispatching mouse click 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 OverlayOutsideClickDispatcher = /** @class */ (function (_super) {
__extends(OverlayOutsideClickDispatcher, _super);
function OverlayOutsideClickDispatcher(document, _platform) {
var _this = _super.call(this, document) || this;
_this._platform = _platform;
_this._cursorStyleIsSet = false;
/** Click event listener that will be attached to the body propagate phase. */
_this._clickListener = function (event) {
// Get the target through the `composedPath` if possible to account for shadow DOM.
var target = event.composedPath ? event.composedPath()[0] : event.target;
// We copy the array because the original may be modified asynchronously if the
// outsidePointerEvents listener decides to detach overlays resulting in index errors inside
// the for loop.
var overlays = _this._attachedOverlays.slice();
// Dispatch the mouse event to the top overlay which has subscribers to its mouse events.
// We want to target all overlays for which the click could be considered as outside click.
// As soon as we reach an overlay for which the click is not outside click we break off
// the loop.
for (var i = overlays.length - 1; i > -1; i--) {
var overlayRef = overlays[i];
if (overlayRef._outsidePointerEvents.observers.length < 1 || !overlayRef.hasAttached()) {
continue;
}
// If it's a click inside the overlay, just break - we should do nothing
// If it's an outside click dispatch the mouse event, and proceed with the next overlay
if (overlayRef.overlayElement.contains(target)) {
break;
}
overlayRef._outsidePointerEvents.next(event);
}
};
return _this;
}
/** Add a new overlay to the list of attached overlay refs. */
OverlayOutsideClickDispatcher.prototype.add = function (overlayRef) {
_super.prototype.add.call(this, overlayRef);
// tslint:disable: max-line-length
// Safari on iOS does not generate click events for non-interactive
// elements. However, we want to receive a click for any element outside
// the overlay. We can force a "clickable" state by setting
// `cursor: pointer` on the document body.
// See https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event#Safari_Mobile
// and https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
// tslint:enable: max-line-length
if (!this._isAttached) {
this._document.body.addEventListener('click', this._clickListener, true);
this._document.body.addEventListener('contextmenu', this._clickListener, true);
// click event is not fired on iOS. To make element "clickable" we are
// setting the cursor to pointer
if (this._platform.IOS && !this._cursorStyleIsSet) {
this._cursorOriginalValue = this._document.body.style.cursor;
this._document.body.style.cursor = 'pointer';
this._cursorStyleIsSet = true;
}
this._isAttached = true;
}
};
/** Detaches the global keyboard event listener. */
OverlayOutsideClickDispatcher.prototype.detach = function () {
if (this._isAttached) {
this._document.body.removeEventListener('click', this._clickListener, true);
this._document.body.removeEventListener('contextmenu', this._clickListener, true);
if (this._platform.IOS && this._cursorStyleIsSet) {
this._document.body.style.cursor = this._cursorOriginalValue;
this._cursorStyleIsSet = false;
}
this._isAttached = false;
}
};
return OverlayOutsideClickDispatcher;
}(BaseOverlayDispatcher));
OverlayOutsideClickDispatcher.ɵprov = i0.ɵɵdefineInjectable({ factory: function OverlayOutsideClickDispatcher_Factory() { return new OverlayOutsideClickDispatcher(i0.ɵɵinject(i1$1.DOCUMENT), i0.ɵɵinject(i2.Platform)); }, token: OverlayOutsideClickDispatcher, providedIn: "root" });
OverlayOutsideClickDispatcher.decorators = [
{ type: i0.Injectable, args: [{ providedIn: 'root' },] }
];
OverlayOutsideClickDispatcher.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
{ type: i2.Platform }
]; };
/**
* @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
*/
/**
* Whether we're in a testing environment.
* TODO(crisbeto): remove this once we have an overlay testing module.
*/
var isTestEnvironment = typeof window !== 'undefined' && !!window &&
!!(window.__karma__ || window.jasmine);
/** Container inside which all overlays will render. */
var OverlayContainer = /** @class */ (function () {
function OverlayContainer(document, _platform) {
this._platform = _platform;
this._document = document;
}
OverlayContainer.prototype.ngOnDestroy = function () {
var container = this._containerElement;
if (container && container.parentNode) {
container.parentNode.removeChild(container);
}
};
/**
* 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
*/
OverlayContainer.prototype.getContainerElement = 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.
*/
OverlayContainer.prototype._createContainer = function () {
var containerClass = 'cdk-overlay-container';
if (this._platform.isBrowser || isTestEnvironment) {
var oppositePlatformContainers = this._document.querySelectorAll("." + containerClass + "[platform=\"server\"], " +
("." + containerClass + "[platform=\"test\"]"));
// Remove any old containers from the opposite platform.
// This can happen when transitioning from the server to the client.
for