UNPKG

180 kBJavaScriptView Raw
1(function (global, factory) {
2 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/platform'), require('@angular/cdk/bidi'), require('@angular/cdk/portal'), require('rxjs'), require('rxjs/operators'), require('@angular/cdk/keycodes')) :
3 typeof define === 'function' && define.amd ? define('@angular/cdk/overlay', ['exports', '@angular/cdk/scrolling', '@angular/common', '@angular/core', '@angular/cdk/coercion', '@angular/cdk/platform', '@angular/cdk/bidi', '@angular/cdk/portal', 'rxjs', 'rxjs/operators', '@angular/cdk/keycodes'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : 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.platform, global.ng.cdk.bidi, global.ng.cdk.portal, global.rxjs, global.rxjs.operators, global.ng.cdk.keycodes));
5}(this, (function (exports, i1, i1$1, i0, coercion, i2, bidi, portal, rxjs, operators, keycodes) { 'use strict';
6
7 function _interopNamespace(e) {
8 if (e && e.__esModule) return e;
9 var n = Object.create(null);
10 if (e) {
11 Object.keys(e).forEach(function (k) {
12 if (k !== 'default') {
13 var d = Object.getOwnPropertyDescriptor(e, k);
14 Object.defineProperty(n, k, d.get ? d : {
15 enumerable: true,
16 get: function () {
17 return e[k];
18 }
19 });
20 }
21 });
22 }
23 n['default'] = e;
24 return Object.freeze(n);
25 }
26
27 var i1__namespace = /*#__PURE__*/_interopNamespace(i1);
28 var i1__namespace$1 = /*#__PURE__*/_interopNamespace(i1$1);
29 var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
30 var i2__namespace = /*#__PURE__*/_interopNamespace(i2);
31
32 /*! *****************************************************************************
33 Copyright (c) Microsoft Corporation.
34
35 Permission to use, copy, modify, and/or distribute this software for any
36 purpose with or without fee is hereby granted.
37
38 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
39 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
40 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
41 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
42 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
43 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
44 PERFORMANCE OF THIS SOFTWARE.
45 ***************************************************************************** */
46 /* global Reflect, Promise */
47 var extendStatics = function (d, b) {
48 extendStatics = Object.setPrototypeOf ||
49 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
50 function (d, b) { for (var p in b)
51 if (Object.prototype.hasOwnProperty.call(b, p))
52 d[p] = b[p]; };
53 return extendStatics(d, b);
54 };
55 function __extends(d, b) {
56 if (typeof b !== "function" && b !== null)
57 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
58 extendStatics(d, b);
59 function __() { this.constructor = d; }
60 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
61 }
62 var __assign = function () {
63 __assign = Object.assign || function __assign(t) {
64 for (var s, i = 1, n = arguments.length; i < n; i++) {
65 s = arguments[i];
66 for (var p in s)
67 if (Object.prototype.hasOwnProperty.call(s, p))
68 t[p] = s[p];
69 }
70 return t;
71 };
72 return __assign.apply(this, arguments);
73 };
74 function __rest(s, e) {
75 var t = {};
76 for (var p in s)
77 if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
78 t[p] = s[p];
79 if (s != null && typeof Object.getOwnPropertySymbols === "function")
80 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
81 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
82 t[p[i]] = s[p[i]];
83 }
84 return t;
85 }
86 function __decorate(decorators, target, key, desc) {
87 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
88 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
89 r = Reflect.decorate(decorators, target, key, desc);
90 else
91 for (var i = decorators.length - 1; i >= 0; i--)
92 if (d = decorators[i])
93 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
94 return c > 3 && r && Object.defineProperty(target, key, r), r;
95 }
96 function __param(paramIndex, decorator) {
97 return function (target, key) { decorator(target, key, paramIndex); };
98 }
99 function __metadata(metadataKey, metadataValue) {
100 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
101 return Reflect.metadata(metadataKey, metadataValue);
102 }
103 function __awaiter(thisArg, _arguments, P, generator) {
104 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
105 return new (P || (P = Promise))(function (resolve, reject) {
106 function fulfilled(value) { try {
107 step(generator.next(value));
108 }
109 catch (e) {
110 reject(e);
111 } }
112 function rejected(value) { try {
113 step(generator["throw"](value));
114 }
115 catch (e) {
116 reject(e);
117 } }
118 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
119 step((generator = generator.apply(thisArg, _arguments || [])).next());
120 });
121 }
122 function __generator(thisArg, body) {
123 var _ = { label: 0, sent: function () { if (t[0] & 1)
124 throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
125 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
126 function verb(n) { return function (v) { return step([n, v]); }; }
127 function step(op) {
128 if (f)
129 throw new TypeError("Generator is already executing.");
130 while (_)
131 try {
132 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)
133 return t;
134 if (y = 0, t)
135 op = [op[0] & 2, t.value];
136 switch (op[0]) {
137 case 0:
138 case 1:
139 t = op;
140 break;
141 case 4:
142 _.label++;
143 return { value: op[1], done: false };
144 case 5:
145 _.label++;
146 y = op[1];
147 op = [0];
148 continue;
149 case 7:
150 op = _.ops.pop();
151 _.trys.pop();
152 continue;
153 default:
154 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
155 _ = 0;
156 continue;
157 }
158 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
159 _.label = op[1];
160 break;
161 }
162 if (op[0] === 6 && _.label < t[1]) {
163 _.label = t[1];
164 t = op;
165 break;
166 }
167 if (t && _.label < t[2]) {
168 _.label = t[2];
169 _.ops.push(op);
170 break;
171 }
172 if (t[2])
173 _.ops.pop();
174 _.trys.pop();
175 continue;
176 }
177 op = body.call(thisArg, _);
178 }
179 catch (e) {
180 op = [6, e];
181 y = 0;
182 }
183 finally {
184 f = t = 0;
185 }
186 if (op[0] & 5)
187 throw op[1];
188 return { value: op[0] ? op[1] : void 0, done: true };
189 }
190 }
191 var __createBinding = Object.create ? (function (o, m, k, k2) {
192 if (k2 === undefined)
193 k2 = k;
194 Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
195 }) : (function (o, m, k, k2) {
196 if (k2 === undefined)
197 k2 = k;
198 o[k2] = m[k];
199 });
200 function __exportStar(m, o) {
201 for (var p in m)
202 if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
203 __createBinding(o, m, p);
204 }
205 function __values(o) {
206 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
207 if (m)
208 return m.call(o);
209 if (o && typeof o.length === "number")
210 return {
211 next: function () {
212 if (o && i >= o.length)
213 o = void 0;
214 return { value: o && o[i++], done: !o };
215 }
216 };
217 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
218 }
219 function __read(o, n) {
220 var m = typeof Symbol === "function" && o[Symbol.iterator];
221 if (!m)
222 return o;
223 var i = m.call(o), r, ar = [], e;
224 try {
225 while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
226 ar.push(r.value);
227 }
228 catch (error) {
229 e = { error: error };
230 }
231 finally {
232 try {
233 if (r && !r.done && (m = i["return"]))
234 m.call(i);
235 }
236 finally {
237 if (e)
238 throw e.error;
239 }
240 }
241 return ar;
242 }
243 /** @deprecated */
244 function __spread() {
245 for (var ar = [], i = 0; i < arguments.length; i++)
246 ar = ar.concat(__read(arguments[i]));
247 return ar;
248 }
249 /** @deprecated */
250 function __spreadArrays() {
251 for (var s = 0, i = 0, il = arguments.length; i < il; i++)
252 s += arguments[i].length;
253 for (var r = Array(s), k = 0, i = 0; i < il; i++)
254 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
255 r[k] = a[j];
256 return r;
257 }
258 function __spreadArray(to, from, pack) {
259 if (pack || arguments.length === 2)
260 for (var i = 0, l = from.length, ar; i < l; i++) {
261 if (ar || !(i in from)) {
262 if (!ar)
263 ar = Array.prototype.slice.call(from, 0, i);
264 ar[i] = from[i];
265 }
266 }
267 return to.concat(ar || from);
268 }
269 function __await(v) {
270 return this instanceof __await ? (this.v = v, this) : new __await(v);
271 }
272 function __asyncGenerator(thisArg, _arguments, generator) {
273 if (!Symbol.asyncIterator)
274 throw new TypeError("Symbol.asyncIterator is not defined.");
275 var g = generator.apply(thisArg, _arguments || []), i, q = [];
276 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
277 function verb(n) { if (g[n])
278 i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
279 function resume(n, v) { try {
280 step(g[n](v));
281 }
282 catch (e) {
283 settle(q[0][3], e);
284 } }
285 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
286 function fulfill(value) { resume("next", value); }
287 function reject(value) { resume("throw", value); }
288 function settle(f, v) { if (f(v), q.shift(), q.length)
289 resume(q[0][0], q[0][1]); }
290 }
291 function __asyncDelegator(o) {
292 var i, p;
293 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
294 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; }
295 }
296 function __asyncValues(o) {
297 if (!Symbol.asyncIterator)
298 throw new TypeError("Symbol.asyncIterator is not defined.");
299 var m = o[Symbol.asyncIterator], i;
300 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);
301 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); }); }; }
302 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
303 }
304 function __makeTemplateObject(cooked, raw) {
305 if (Object.defineProperty) {
306 Object.defineProperty(cooked, "raw", { value: raw });
307 }
308 else {
309 cooked.raw = raw;
310 }
311 return cooked;
312 }
313 ;
314 var __setModuleDefault = Object.create ? (function (o, v) {
315 Object.defineProperty(o, "default", { enumerable: true, value: v });
316 }) : function (o, v) {
317 o["default"] = v;
318 };
319 function __importStar(mod) {
320 if (mod && mod.__esModule)
321 return mod;
322 var result = {};
323 if (mod != null)
324 for (var k in mod)
325 if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
326 __createBinding(result, mod, k);
327 __setModuleDefault(result, mod);
328 return result;
329 }
330 function __importDefault(mod) {
331 return (mod && mod.__esModule) ? mod : { default: mod };
332 }
333 function __classPrivateFieldGet(receiver, state, kind, f) {
334 if (kind === "a" && !f)
335 throw new TypeError("Private accessor was defined without a getter");
336 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
337 throw new TypeError("Cannot read private member from an object whose class did not declare it");
338 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
339 }
340 function __classPrivateFieldSet(receiver, state, value, kind, f) {
341 if (kind === "m")
342 throw new TypeError("Private method is not writable");
343 if (kind === "a" && !f)
344 throw new TypeError("Private accessor was defined without a setter");
345 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
346 throw new TypeError("Cannot write private member to an object whose class did not declare it");
347 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
348 }
349
350 /**
351 * @license
352 * Copyright Google LLC All Rights Reserved.
353 *
354 * Use of this source code is governed by an MIT-style license that can be
355 * found in the LICENSE file at https://angular.io/license
356 */
357 var scrollBehaviorSupported = i2.supportsScrollBehavior();
358 /**
359 * Strategy that will prevent the user from scrolling while the overlay is visible.
360 */
361 var BlockScrollStrategy = /** @class */ (function () {
362 function BlockScrollStrategy(_viewportRuler, document) {
363 this._viewportRuler = _viewportRuler;
364 this._previousHTMLStyles = { top: '', left: '' };
365 this._isEnabled = false;
366 this._document = document;
367 }
368 /** Attaches this scroll strategy to an overlay. */
369 BlockScrollStrategy.prototype.attach = function () { };
370 /** Blocks page-level scroll while the attached overlay is open. */
371 BlockScrollStrategy.prototype.enable = function () {
372 if (this._canBeEnabled()) {
373 var root = this._document.documentElement;
374 this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition();
375 // Cache the previous inline styles in case the user had set them.
376 this._previousHTMLStyles.left = root.style.left || '';
377 this._previousHTMLStyles.top = root.style.top || '';
378 // Note: we're using the `html` node, instead of the `body`, because the `body` may
379 // have the user agent margin, whereas the `html` is guaranteed not to have one.
380 root.style.left = coercion.coerceCssPixelValue(-this._previousScrollPosition.left);
381 root.style.top = coercion.coerceCssPixelValue(-this._previousScrollPosition.top);
382 root.classList.add('cdk-global-scrollblock');
383 this._isEnabled = true;
384 }
385 };
386 /** Unblocks page-level scroll while the attached overlay is open. */
387 BlockScrollStrategy.prototype.disable = function () {
388 if (this._isEnabled) {
389 var html = this._document.documentElement;
390 var body = this._document.body;
391 var htmlStyle = html.style;
392 var bodyStyle = body.style;
393 var previousHtmlScrollBehavior = htmlStyle.scrollBehavior || '';
394 var previousBodyScrollBehavior = bodyStyle.scrollBehavior || '';
395 this._isEnabled = false;
396 htmlStyle.left = this._previousHTMLStyles.left;
397 htmlStyle.top = this._previousHTMLStyles.top;
398 html.classList.remove('cdk-global-scrollblock');
399 // Disable user-defined smooth scrolling temporarily while we restore the scroll position.
400 // See https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior
401 // Note that we don't mutate the property if the browser doesn't support `scroll-behavior`,
402 // because it can throw off feature detections in `supportsScrollBehavior` which
403 // checks for `'scrollBehavior' in documentElement.style`.
404 if (scrollBehaviorSupported) {
405 htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto';
406 }
407 window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top);
408 if (scrollBehaviorSupported) {
409 htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
410 bodyStyle.scrollBehavior = previousBodyScrollBehavior;
411 }
412 }
413 };
414 BlockScrollStrategy.prototype._canBeEnabled = function () {
415 // Since the scroll strategies can't be singletons, we have to use a global CSS class
416 // (`cdk-global-scrollblock`) to make sure that we don't try to disable global
417 // scrolling multiple times.
418 var html = this._document.documentElement;
419 if (html.classList.contains('cdk-global-scrollblock') || this._isEnabled) {
420 return false;
421 }
422 var body = this._document.body;
423 var viewport = this._viewportRuler.getViewportSize();
424 return body.scrollHeight > viewport.height || body.scrollWidth > viewport.width;
425 };
426 return BlockScrollStrategy;
427 }());
428
429 /**
430 * @license
431 * Copyright Google LLC All Rights Reserved.
432 *
433 * Use of this source code is governed by an MIT-style license that can be
434 * found in the LICENSE file at https://angular.io/license
435 */
436 /**
437 * Returns an error to be thrown when attempting to attach an already-attached scroll strategy.
438 */
439 function getMatScrollStrategyAlreadyAttachedError() {
440 return Error("Scroll strategy has already been attached.");
441 }
442
443 /**
444 * Strategy that will close the overlay as soon as the user starts scrolling.
445 */
446 var CloseScrollStrategy = /** @class */ (function () {
447 function CloseScrollStrategy(_scrollDispatcher, _ngZone, _viewportRuler, _config) {
448 var _this = this;
449 this._scrollDispatcher = _scrollDispatcher;
450 this._ngZone = _ngZone;
451 this._viewportRuler = _viewportRuler;
452 this._config = _config;
453 this._scrollSubscription = null;
454 /** Detaches the overlay ref and disables the scroll strategy. */
455 this._detach = function () {
456 _this.disable();
457 if (_this._overlayRef.hasAttached()) {
458 _this._ngZone.run(function () { return _this._overlayRef.detach(); });
459 }
460 };
461 }
462 /** Attaches this scroll strategy to an overlay. */
463 CloseScrollStrategy.prototype.attach = function (overlayRef) {
464 if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {
465 throw getMatScrollStrategyAlreadyAttachedError();
466 }
467 this._overlayRef = overlayRef;
468 };
469 /** Enables the closing of the attached overlay on scroll. */
470 CloseScrollStrategy.prototype.enable = function () {
471 var _this = this;
472 if (this._scrollSubscription) {
473 return;
474 }
475 var stream = this._scrollDispatcher.scrolled(0);
476 if (this._config && this._config.threshold && this._config.threshold > 1) {
477 this._initialScrollPosition = this._viewportRuler.getViewportScrollPosition().top;
478 this._scrollSubscription = stream.subscribe(function () {
479 var scrollPosition = _this._viewportRuler.getViewportScrollPosition().top;
480 if (Math.abs(scrollPosition - _this._initialScrollPosition) > _this._config.threshold) {
481 _this._detach();
482 }
483 else {
484 _this._overlayRef.updatePosition();
485 }
486 });
487 }
488 else {
489 this._scrollSubscription = stream.subscribe(this._detach);
490 }
491 };
492 /** Disables the closing the attached overlay on scroll. */
493 CloseScrollStrategy.prototype.disable = function () {
494 if (this._scrollSubscription) {
495 this._scrollSubscription.unsubscribe();
496 this._scrollSubscription = null;
497 }
498 };
499 CloseScrollStrategy.prototype.detach = function () {
500 this.disable();
501 this._overlayRef = null;
502 };
503 return CloseScrollStrategy;
504 }());
505
506 /**
507 * @license
508 * Copyright Google LLC All Rights Reserved.
509 *
510 * Use of this source code is governed by an MIT-style license that can be
511 * found in the LICENSE file at https://angular.io/license
512 */
513 /** Scroll strategy that doesn't do anything. */
514 var NoopScrollStrategy = /** @class */ (function () {
515 function NoopScrollStrategy() {
516 }
517 /** Does nothing, as this scroll strategy is a no-op. */
518 NoopScrollStrategy.prototype.enable = function () { };
519 /** Does nothing, as this scroll strategy is a no-op. */
520 NoopScrollStrategy.prototype.disable = function () { };
521 /** Does nothing, as this scroll strategy is a no-op. */
522 NoopScrollStrategy.prototype.attach = function () { };
523 return NoopScrollStrategy;
524 }());
525
526 /**
527 * @license
528 * Copyright Google LLC All Rights Reserved.
529 *
530 * Use of this source code is governed by an MIT-style license that can be
531 * found in the LICENSE file at https://angular.io/license
532 */
533 // TODO(jelbourn): move this to live with the rest of the scrolling code
534 // TODO(jelbourn): someday replace this with IntersectionObservers
535 /**
536 * Gets whether an element is scrolled outside of view by any of its parent scrolling containers.
537 * @param element Dimensions of the element (from getBoundingClientRect)
538 * @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)
539 * @returns Whether the element is scrolled out of view
540 * @docs-private
541 */
542 function isElementScrolledOutsideView(element, scrollContainers) {
543 return scrollContainers.some(function (containerBounds) {
544 var outsideAbove = element.bottom < containerBounds.top;
545 var outsideBelow = element.top > containerBounds.bottom;
546 var outsideLeft = element.right < containerBounds.left;
547 var outsideRight = element.left > containerBounds.right;
548 return outsideAbove || outsideBelow || outsideLeft || outsideRight;
549 });
550 }
551 /**
552 * Gets whether an element is clipped by any of its scrolling containers.
553 * @param element Dimensions of the element (from getBoundingClientRect)
554 * @param scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect)
555 * @returns Whether the element is clipped
556 * @docs-private
557 */
558 function isElementClippedByScrolling(element, scrollContainers) {
559 return scrollContainers.some(function (scrollContainerRect) {
560 var clippedAbove = element.top < scrollContainerRect.top;
561 var clippedBelow = element.bottom > scrollContainerRect.bottom;
562 var clippedLeft = element.left < scrollContainerRect.left;
563 var clippedRight = element.right > scrollContainerRect.right;
564 return clippedAbove || clippedBelow || clippedLeft || clippedRight;
565 });
566 }
567
568 /**
569 * @license
570 * Copyright Google LLC All Rights Reserved.
571 *
572 * Use of this source code is governed by an MIT-style license that can be
573 * found in the LICENSE file at https://angular.io/license
574 */
575 /**
576 * Strategy that will update the element position as the user is scrolling.
577 */
578 var RepositionScrollStrategy = /** @class */ (function () {
579 function RepositionScrollStrategy(_scrollDispatcher, _viewportRuler, _ngZone, _config) {
580 this._scrollDispatcher = _scrollDispatcher;
581 this._viewportRuler = _viewportRuler;
582 this._ngZone = _ngZone;
583 this._config = _config;
584 this._scrollSubscription = null;
585 }
586 /** Attaches this scroll strategy to an overlay. */
587 RepositionScrollStrategy.prototype.attach = function (overlayRef) {
588 if (this._overlayRef && (typeof ngDevMode === 'undefined' || ngDevMode)) {
589 throw getMatScrollStrategyAlreadyAttachedError();
590 }
591 this._overlayRef = overlayRef;
592 };
593 /** Enables repositioning of the attached overlay on scroll. */
594 RepositionScrollStrategy.prototype.enable = function () {
595 var _this = this;
596 if (!this._scrollSubscription) {
597 var throttle = this._config ? this._config.scrollThrottle : 0;
598 this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe(function () {
599 _this._overlayRef.updatePosition();
600 // TODO(crisbeto): make `close` on by default once all components can handle it.
601 if (_this._config && _this._config.autoClose) {
602 var overlayRect = _this._overlayRef.overlayElement.getBoundingClientRect();
603 var _a = _this._viewportRuler.getViewportSize(), width = _a.width, height = _a.height;
604 // TODO(crisbeto): include all ancestor scroll containers here once
605 // we have a way of exposing the trigger element to the scroll strategy.
606 var parentRects = [{ width: width, height: height, bottom: height, right: width, top: 0, left: 0 }];
607 if (isElementScrolledOutsideView(overlayRect, parentRects)) {
608 _this.disable();
609 _this._ngZone.run(function () { return _this._overlayRef.detach(); });
610 }
611 }
612 });
613 }
614 };
615 /** Disables repositioning of the attached overlay on scroll. */
616 RepositionScrollStrategy.prototype.disable = function () {
617 if (this._scrollSubscription) {
618 this._scrollSubscription.unsubscribe();
619 this._scrollSubscription = null;
620 }
621 };
622 RepositionScrollStrategy.prototype.detach = function () {
623 this.disable();
624 this._overlayRef = null;
625 };
626 return RepositionScrollStrategy;
627 }());
628
629 /**
630 * @license
631 * Copyright Google LLC All Rights Reserved.
632 *
633 * Use of this source code is governed by an MIT-style license that can be
634 * found in the LICENSE file at https://angular.io/license
635 */
636 /**
637 * Options for how an overlay will handle scrolling.
638 *
639 * Users can provide a custom value for `ScrollStrategyOptions` to replace the default
640 * behaviors. This class primarily acts as a factory for ScrollStrategy instances.
641 */
642 var ScrollStrategyOptions = /** @class */ (function () {
643 function ScrollStrategyOptions(_scrollDispatcher, _viewportRuler, _ngZone, document) {
644 var _this = this;
645 this._scrollDispatcher = _scrollDispatcher;
646 this._viewportRuler = _viewportRuler;
647 this._ngZone = _ngZone;
648 /** Do nothing on scroll. */
649 this.noop = function () { return new NoopScrollStrategy(); };
650 /**
651 * Close the overlay as soon as the user scrolls.
652 * @param config Configuration to be used inside the scroll strategy.
653 */
654 this.close = function (config) { return new CloseScrollStrategy(_this._scrollDispatcher, _this._ngZone, _this._viewportRuler, config); };
655 /** Block scrolling. */
656 this.block = function () { return new BlockScrollStrategy(_this._viewportRuler, _this._document); };
657 /**
658 * Update the overlay's position on scroll.
659 * @param config Configuration to be used inside the scroll strategy.
660 * Allows debouncing the reposition calls.
661 */
662 this.reposition = function (config) { return new RepositionScrollStrategy(_this._scrollDispatcher, _this._viewportRuler, _this._ngZone, config); };
663 this._document = document;
664 }
665 return ScrollStrategyOptions;
666 }());
667 ScrollStrategyOptions.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function ScrollStrategyOptions_Factory() { return new ScrollStrategyOptions(i0__namespace.ɵɵinject(i1__namespace.ScrollDispatcher), i0__namespace.ɵɵinject(i1__namespace.ViewportRuler), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT)); }, token: ScrollStrategyOptions, providedIn: "root" });
668 ScrollStrategyOptions.decorators = [
669 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
670 ];
671 ScrollStrategyOptions.ctorParameters = function () { return [
672 { type: i1.ScrollDispatcher },
673 { type: i1.ViewportRuler },
674 { type: i0.NgZone },
675 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
676 ]; };
677
678 /**
679 * @license
680 * Copyright Google LLC All Rights Reserved.
681 *
682 * Use of this source code is governed by an MIT-style license that can be
683 * found in the LICENSE file at https://angular.io/license
684 */
685
686 /** Initial configuration used when creating an overlay. */
687 var OverlayConfig = /** @class */ (function () {
688 function OverlayConfig(config) {
689 var e_1, _a;
690 /** Strategy to be used when handling scroll events while the overlay is open. */
691 this.scrollStrategy = new NoopScrollStrategy();
692 /** Custom class to add to the overlay pane. */
693 this.panelClass = '';
694 /** Whether the overlay has a backdrop. */
695 this.hasBackdrop = false;
696 /** Custom class to add to the backdrop */
697 this.backdropClass = 'cdk-overlay-dark-backdrop';
698 /**
699 * Whether the overlay should be disposed of when the user goes backwards/forwards in history.
700 * Note that this usually doesn't include clicking on links (unless the user is using
701 * the `HashLocationStrategy`).
702 */
703 this.disposeOnNavigation = false;
704 if (config) {
705 // Use `Iterable` instead of `Array` because TypeScript, as of 3.6.3,
706 // loses the array generic type in the `for of`. But we *also* have to use `Array` because
707 // typescript won't iterate over an `Iterable` unless you compile with `--downlevelIteration`
708 var configKeys = Object.keys(config);
709 try {
710 for (var configKeys_1 = __values(configKeys), configKeys_1_1 = configKeys_1.next(); !configKeys_1_1.done; configKeys_1_1 = configKeys_1.next()) {
711 var key = configKeys_1_1.value;
712 if (config[key] !== undefined) {
713 // TypeScript, as of version 3.5, sees the left-hand-side of this expression
714 // as "I don't know *which* key this is, so the only valid value is the intersection
715 // of all the posible values." In this case, that happens to be `undefined`. TypeScript
716 // is not smart enough to see that the right-hand-side is actually an access of the same
717 // exact type with the same exact key, meaning that the value type must be identical.
718 // So we use `any` to work around this.
719 this[key] = config[key];
720 }
721 }
722 }
723 catch (e_1_1) { e_1 = { error: e_1_1 }; }
724 finally {
725 try {
726 if (configKeys_1_1 && !configKeys_1_1.done && (_a = configKeys_1.return)) _a.call(configKeys_1);
727 }
728 finally { if (e_1) throw e_1.error; }
729 }
730 }
731 }
732 return OverlayConfig;
733 }());
734
735 /**
736 * @license
737 * Copyright Google LLC All Rights Reserved.
738 *
739 * Use of this source code is governed by an MIT-style license that can be
740 * found in the LICENSE file at https://angular.io/license
741 */
742 /** The points of the origin element and the overlay element to connect. */
743 var ConnectionPositionPair = /** @class */ (function () {
744 function ConnectionPositionPair(origin, overlay,
745 /** Offset along the X axis. */
746 offsetX,
747 /** Offset along the Y axis. */
748 offsetY,
749 /** Class(es) to be applied to the panel while this position is active. */
750 panelClass) {
751 this.offsetX = offsetX;
752 this.offsetY = offsetY;
753 this.panelClass = panelClass;
754 this.originX = origin.originX;
755 this.originY = origin.originY;
756 this.overlayX = overlay.overlayX;
757 this.overlayY = overlay.overlayY;
758 }
759 return ConnectionPositionPair;
760 }());
761 /**
762 * Set of properties regarding the position of the origin and overlay relative to the viewport
763 * with respect to the containing Scrollable elements.
764 *
765 * The overlay and origin are clipped if any part of their bounding client rectangle exceeds the
766 * bounds of any one of the strategy's Scrollable's bounding client rectangle.
767 *
768 * The overlay and origin are outside view if there is no overlap between their bounding client
769 * rectangle and any one of the strategy's Scrollable's bounding client rectangle.
770 *
771 * ----------- -----------
772 * | outside | | clipped |
773 * | view | --------------------------
774 * | | | | | |
775 * ---------- | ----------- |
776 * -------------------------- | |
777 * | | | Scrollable |
778 * | | | |
779 * | | --------------------------
780 * | Scrollable |
781 * | |
782 * --------------------------
783 *
784 * @docs-private
785 */
786 var ScrollingVisibility = /** @class */ (function () {
787 function ScrollingVisibility() {
788 }
789 return ScrollingVisibility;
790 }());
791 /** The change event emitted by the strategy when a fallback position is used. */
792 var ConnectedOverlayPositionChange = /** @class */ (function () {
793 function ConnectedOverlayPositionChange(
794 /** The position used as a result of this change. */
795 connectionPair,
796 /** @docs-private */
797 scrollableViewProperties) {
798 this.connectionPair = connectionPair;
799 this.scrollableViewProperties = scrollableViewProperties;
800 }
801 return ConnectedOverlayPositionChange;
802 }());
803 ConnectedOverlayPositionChange.ctorParameters = function () { return [
804 { type: ConnectionPositionPair },
805 { type: ScrollingVisibility, decorators: [{ type: i0.Optional }] }
806 ]; };
807 /**
808 * Validates whether a vertical position property matches the expected values.
809 * @param property Name of the property being validated.
810 * @param value Value of the property being validated.
811 * @docs-private
812 */
813 function validateVerticalPosition(property, value) {
814 if (value !== 'top' && value !== 'bottom' && value !== 'center') {
815 throw Error("ConnectedPosition: Invalid " + property + " \"" + value + "\". " +
816 "Expected \"top\", \"bottom\" or \"center\".");
817 }
818 }
819 /**
820 * Validates whether a horizontal position property matches the expected values.
821 * @param property Name of the property being validated.
822 * @param value Value of the property being validated.
823 * @docs-private
824 */
825 function validateHorizontalPosition(property, value) {
826 if (value !== 'start' && value !== 'end' && value !== 'center') {
827 throw Error("ConnectedPosition: Invalid " + property + " \"" + value + "\". " +
828 "Expected \"start\", \"end\" or \"center\".");
829 }
830 }
831
832 /**
833 * @license
834 * Copyright Google LLC All Rights Reserved.
835 *
836 * Use of this source code is governed by an MIT-style license that can be
837 * found in the LICENSE file at https://angular.io/license
838 */
839 /**
840 * Service for dispatching events that land on the body to appropriate overlay ref,
841 * if any. It maintains a list of attached overlays to determine best suited overlay based
842 * on event target and order of overlay opens.
843 */
844 var BaseOverlayDispatcher = /** @class */ (function () {
845 function BaseOverlayDispatcher(document) {
846 /** Currently attached overlays in the order they were attached. */
847 this._attachedOverlays = [];
848 this._document = document;
849 }
850 BaseOverlayDispatcher.prototype.ngOnDestroy = function () {
851 this.detach();
852 };
853 /** Add a new overlay to the list of attached overlay refs. */
854 BaseOverlayDispatcher.prototype.add = function (overlayRef) {
855 // Ensure that we don't get the same overlay multiple times.
856 this.remove(overlayRef);
857 this._attachedOverlays.push(overlayRef);
858 };
859 /** Remove an overlay from the list of attached overlay refs. */
860 BaseOverlayDispatcher.prototype.remove = function (overlayRef) {
861 var index = this._attachedOverlays.indexOf(overlayRef);
862 if (index > -1) {
863 this._attachedOverlays.splice(index, 1);
864 }
865 // Remove the global listener once there are no more overlays.
866 if (this._attachedOverlays.length === 0) {
867 this.detach();
868 }
869 };
870 return BaseOverlayDispatcher;
871 }());
872 BaseOverlayDispatcher.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function BaseOverlayDispatcher_Factory() { return new BaseOverlayDispatcher(i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT)); }, token: BaseOverlayDispatcher, providedIn: "root" });
873 BaseOverlayDispatcher.decorators = [
874 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
875 ];
876 BaseOverlayDispatcher.ctorParameters = function () { return [
877 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
878 ]; };
879
880 /**
881 * Service for dispatching keyboard events that land on the body to appropriate overlay ref,
882 * if any. It maintains a list of attached overlays to determine best suited overlay based
883 * on event target and order of overlay opens.
884 */
885 var OverlayKeyboardDispatcher = /** @class */ (function (_super) {
886 __extends(OverlayKeyboardDispatcher, _super);
887 function OverlayKeyboardDispatcher(document) {
888 var _this = _super.call(this, document) || this;
889 /** Keyboard event listener that will be attached to the body. */
890 _this._keydownListener = function (event) {
891 var overlays = _this._attachedOverlays;
892 for (var i = overlays.length - 1; i > -1; i--) {
893 // Dispatch the keydown event to the top overlay which has subscribers to its keydown events.
894 // We want to target the most recent overlay, rather than trying to match where the event came
895 // from, because some components might open an overlay, but keep focus on a trigger element
896 // (e.g. for select and autocomplete). We skip overlays without keydown event subscriptions,
897 // because we don't want overlays that don't handle keyboard events to block the ones below
898 // them that do.
899 if (overlays[i]._keydownEvents.observers.length > 0) {
900 overlays[i]._keydownEvents.next(event);
901 break;
902 }
903 }
904 };
905 return _this;
906 }
907 /** Add a new overlay to the list of attached overlay refs. */
908 OverlayKeyboardDispatcher.prototype.add = function (overlayRef) {
909 _super.prototype.add.call(this, overlayRef);
910 // Lazily start dispatcher once first overlay is added
911 if (!this._isAttached) {
912 this._document.body.addEventListener('keydown', this._keydownListener);
913 this._isAttached = true;
914 }
915 };
916 /** Detaches the global keyboard event listener. */
917 OverlayKeyboardDispatcher.prototype.detach = function () {
918 if (this._isAttached) {
919 this._document.body.removeEventListener('keydown', this._keydownListener);
920 this._isAttached = false;
921 }
922 };
923 return OverlayKeyboardDispatcher;
924 }(BaseOverlayDispatcher));
925 OverlayKeyboardDispatcher.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function OverlayKeyboardDispatcher_Factory() { return new OverlayKeyboardDispatcher(i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT)); }, token: OverlayKeyboardDispatcher, providedIn: "root" });
926 OverlayKeyboardDispatcher.decorators = [
927 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
928 ];
929 OverlayKeyboardDispatcher.ctorParameters = function () { return [
930 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] }
931 ]; };
932
933 /**
934 * Service for dispatching mouse click events that land on the body to appropriate overlay ref,
935 * if any. It maintains a list of attached overlays to determine best suited overlay based
936 * on event target and order of overlay opens.
937 */
938 var OverlayOutsideClickDispatcher = /** @class */ (function (_super) {
939 __extends(OverlayOutsideClickDispatcher, _super);
940 function OverlayOutsideClickDispatcher(document, _platform) {
941 var _this = _super.call(this, document) || this;
942 _this._platform = _platform;
943 _this._cursorStyleIsSet = false;
944 /** Click event listener that will be attached to the body propagate phase. */
945 _this._clickListener = function (event) {
946 var target = i2._getEventTarget(event);
947 // We copy the array because the original may be modified asynchronously if the
948 // outsidePointerEvents listener decides to detach overlays resulting in index errors inside
949 // the for loop.
950 var overlays = _this._attachedOverlays.slice();
951 // Dispatch the mouse event to the top overlay which has subscribers to its mouse events.
952 // We want to target all overlays for which the click could be considered as outside click.
953 // As soon as we reach an overlay for which the click is not outside click we break off
954 // the loop.
955 for (var i = overlays.length - 1; i > -1; i--) {
956 var overlayRef = overlays[i];
957 if (overlayRef._outsidePointerEvents.observers.length < 1 || !overlayRef.hasAttached()) {
958 continue;
959 }
960 // If it's a click inside the overlay, just break - we should do nothing
961 // If it's an outside click dispatch the mouse event, and proceed with the next overlay
962 if (overlayRef.overlayElement.contains(target)) {
963 break;
964 }
965 overlayRef._outsidePointerEvents.next(event);
966 }
967 };
968 return _this;
969 }
970 /** Add a new overlay to the list of attached overlay refs. */
971 OverlayOutsideClickDispatcher.prototype.add = function (overlayRef) {
972 _super.prototype.add.call(this, overlayRef);
973 // Safari on iOS does not generate click events for non-interactive
974 // elements. However, we want to receive a click for any element outside
975 // the overlay. We can force a "clickable" state by setting
976 // `cursor: pointer` on the document body. See:
977 // https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event#Safari_Mobile
978 // https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
979 if (!this._isAttached) {
980 var body = this._document.body;
981 body.addEventListener('click', this._clickListener, true);
982 body.addEventListener('auxclick', this._clickListener, true);
983 body.addEventListener('contextmenu', this._clickListener, true);
984 // click event is not fired on iOS. To make element "clickable" we are
985 // setting the cursor to pointer
986 if (this._platform.IOS && !this._cursorStyleIsSet) {
987 this._cursorOriginalValue = body.style.cursor;
988 body.style.cursor = 'pointer';
989 this._cursorStyleIsSet = true;
990 }
991 this._isAttached = true;
992 }
993 };
994 /** Detaches the global keyboard event listener. */
995 OverlayOutsideClickDispatcher.prototype.detach = function () {
996 if (this._isAttached) {
997 var body = this._document.body;
998 body.removeEventListener('click', this._clickListener, true);
999 body.removeEventListener('auxclick', this._clickListener, true);
1000 body.removeEventListener('contextmenu', this._clickListener, true);
1001 if (this._platform.IOS && this._cursorStyleIsSet) {
1002 body.style.cursor = this._cursorOriginalValue;
1003 this._cursorStyleIsSet = false;
1004 }
1005 this._isAttached = false;
1006 }
1007 };
1008 return OverlayOutsideClickDispatcher;
1009 }(BaseOverlayDispatcher));
1010 OverlayOutsideClickDispatcher.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function OverlayOutsideClickDispatcher_Factory() { return new OverlayOutsideClickDispatcher(i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT), i0__namespace.ɵɵinject(i2__namespace.Platform)); }, token: OverlayOutsideClickDispatcher, providedIn: "root" });
1011 OverlayOutsideClickDispatcher.decorators = [
1012 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1013 ];
1014 OverlayOutsideClickDispatcher.ctorParameters = function () { return [
1015 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
1016 { type: i2.Platform }
1017 ]; };
1018
1019 /**
1020 * @license
1021 * Copyright Google LLC All Rights Reserved.
1022 *
1023 * Use of this source code is governed by an MIT-style license that can be
1024 * found in the LICENSE file at https://angular.io/license
1025 */
1026 var globalsForTest = (typeof window !== 'undefined' ? window : {});
1027 /**
1028 * Whether we're in a testing environment.
1029 * TODO(crisbeto): remove this once we have an overlay testing module or Angular starts tearing
1030 * down the testing `NgModule` (see https://github.com/angular/angular/issues/18831).
1031 */
1032 var isTestEnvironment = (typeof globalsForTest.__karma__ !== 'undefined' && !!globalsForTest.__karma__) ||
1033 (typeof globalsForTest.jasmine !== 'undefined' && !!globalsForTest.jasmine) ||
1034 (typeof globalsForTest.jest !== 'undefined' && !!globalsForTest.jest) ||
1035 (typeof globalsForTest.Mocha !== 'undefined' && !!globalsForTest.Mocha);
1036 /** Container inside which all overlays will render. */
1037 var OverlayContainer = /** @class */ (function () {
1038 function OverlayContainer(document, _platform) {
1039 this._platform = _platform;
1040 this._document = document;
1041 }
1042 OverlayContainer.prototype.ngOnDestroy = function () {
1043 var container = this._containerElement;
1044 if (container && container.parentNode) {
1045 container.parentNode.removeChild(container);
1046 }
1047 };
1048 /**
1049 * This method returns the overlay container element. It will lazily
1050 * create the element the first time it is called to facilitate using
1051 * the container in non-browser environments.
1052 * @returns the container element
1053 */
1054 OverlayContainer.prototype.getContainerElement = function () {
1055 if (!this._containerElement) {
1056 this._createContainer();
1057 }
1058 return this._containerElement;
1059 };
1060 /**
1061 * Create the overlay container element, which is simply a div
1062 * with the 'cdk-overlay-container' class on the document body.
1063 */
1064 OverlayContainer.prototype._createContainer = function () {
1065 var containerClass = 'cdk-overlay-container';
1066 if (this._platform.isBrowser || isTestEnvironment) {
1067 var oppositePlatformContainers = this._document.querySelectorAll("." + containerClass + "[platform=\"server\"], " +
1068 ("." + containerClass + "[platform=\"test\"]"));
1069 // Remove any old containers from the opposite platform.
1070 // This can happen when transitioning from the server to the client.
1071 for (var i = 0; i < oppositePlatformContainers.length; i++) {
1072 oppositePlatformContainers[i].parentNode.removeChild(oppositePlatformContainers[i]);
1073 }
1074 }
1075 var container = this._document.createElement('div');
1076 container.classList.add(containerClass);
1077 // A long time ago we kept adding new overlay containers whenever a new app was instantiated,
1078 // but at some point we added logic which clears the duplicate ones in order to avoid leaks.
1079 // The new logic was a little too aggressive since it was breaking some legitimate use cases.
1080 // To mitigate the problem we made it so that only containers from a different platform are
1081 // cleared, but the side-effect was that people started depending on the overly-aggressive
1082 // logic to clean up their tests for them. Until we can introduce an overlay-specific testing
1083 // module which does the cleanup, we try to detect that we're in a test environment and we
1084 // always clear the container. See #17006.
1085 // TODO(crisbeto): remove the test environment check once we have an overlay testing module.
1086 if (isTestEnvironment) {
1087 container.setAttribute('platform', 'test');
1088 }
1089 else if (!this._platform.isBrowser) {
1090 container.setAttribute('platform', 'server');
1091 }
1092 this._document.body.appendChild(container);
1093 this._containerElement = container;
1094 };
1095 return OverlayContainer;
1096 }());
1097 OverlayContainer.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function OverlayContainer_Factory() { return new OverlayContainer(i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT), i0__namespace.ɵɵinject(i2__namespace.Platform)); }, token: OverlayContainer, providedIn: "root" });
1098 OverlayContainer.decorators = [
1099 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1100 ];
1101 OverlayContainer.ctorParameters = function () { return [
1102 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
1103 { type: i2.Platform }
1104 ]; };
1105
1106 /**
1107 * @license
1108 * Copyright Google LLC All Rights Reserved.
1109 *
1110 * Use of this source code is governed by an MIT-style license that can be
1111 * found in the LICENSE file at https://angular.io/license
1112 */
1113 /**
1114 * Reference to an overlay that has been created with the Overlay service.
1115 * Used to manipulate or dispose of said overlay.
1116 */
1117 var OverlayRef = /** @class */ (function () {
1118 function OverlayRef(_portalOutlet, _host, _pane, _config, _ngZone, _keyboardDispatcher, _document, _location, _outsideClickDispatcher) {
1119 var _this = this;
1120 this._portalOutlet = _portalOutlet;
1121 this._host = _host;
1122 this._pane = _pane;
1123 this._config = _config;
1124 this._ngZone = _ngZone;
1125 this._keyboardDispatcher = _keyboardDispatcher;
1126 this._document = _document;
1127 this._location = _location;
1128 this._outsideClickDispatcher = _outsideClickDispatcher;
1129 this._backdropElement = null;
1130 this._backdropClick = new rxjs.Subject();
1131 this._attachments = new rxjs.Subject();
1132 this._detachments = new rxjs.Subject();
1133 this._locationChanges = rxjs.Subscription.EMPTY;
1134 this._backdropClickHandler = function (event) { return _this._backdropClick.next(event); };
1135 /** Stream of keydown events dispatched to this overlay. */
1136 this._keydownEvents = new rxjs.Subject();
1137 /** Stream of mouse outside events dispatched to this overlay. */
1138 this._outsidePointerEvents = new rxjs.Subject();
1139 if (_config.scrollStrategy) {
1140 this._scrollStrategy = _config.scrollStrategy;
1141 this._scrollStrategy.attach(this);
1142 }
1143 this._positionStrategy = _config.positionStrategy;
1144 }
1145 Object.defineProperty(OverlayRef.prototype, "overlayElement", {
1146 /** The overlay's HTML element */
1147 get: function () {
1148 return this._pane;
1149 },
1150 enumerable: false,
1151 configurable: true
1152 });
1153 Object.defineProperty(OverlayRef.prototype, "backdropElement", {
1154 /** The overlay's backdrop HTML element. */
1155 get: function () {
1156 return this._backdropElement;
1157 },
1158 enumerable: false,
1159 configurable: true
1160 });
1161 Object.defineProperty(OverlayRef.prototype, "hostElement", {
1162 /**
1163 * Wrapper around the panel element. Can be used for advanced
1164 * positioning where a wrapper with specific styling is
1165 * required around the overlay pane.
1166 */
1167 get: function () {
1168 return this._host;
1169 },
1170 enumerable: false,
1171 configurable: true
1172 });
1173 /**
1174 * Attaches content, given via a Portal, to the overlay.
1175 * If the overlay is configured to have a backdrop, it will be created.
1176 *
1177 * @param portal Portal instance to which to attach the overlay.
1178 * @returns The portal attachment result.
1179 */
1180 OverlayRef.prototype.attach = function (portal) {
1181 var _this = this;
1182 var attachResult = this._portalOutlet.attach(portal);
1183 // Update the pane element with the given configuration.
1184 if (!this._host.parentElement && this._previousHostParent) {
1185 this._previousHostParent.appendChild(this._host);
1186 }
1187 if (this._positionStrategy) {
1188 this._positionStrategy.attach(this);
1189 }
1190 this._updateStackingOrder();
1191 this._updateElementSize();
1192 this._updateElementDirection();
1193 if (this._scrollStrategy) {
1194 this._scrollStrategy.enable();
1195 }
1196 // Update the position once the zone is stable so that the overlay will be fully rendered
1197 // before attempting to position it, as the position may depend on the size of the rendered
1198 // content.
1199 this._ngZone.onStable
1200 .pipe(operators.take(1))
1201 .subscribe(function () {
1202 // The overlay could've been detached before the zone has stabilized.
1203 if (_this.hasAttached()) {
1204 _this.updatePosition();
1205 }
1206 });
1207 // Enable pointer events for the overlay pane element.
1208 this._togglePointerEvents(true);
1209 if (this._config.hasBackdrop) {
1210 this._attachBackdrop();
1211 }
1212 if (this._config.panelClass) {
1213 this._toggleClasses(this._pane, this._config.panelClass, true);
1214 }
1215 // Only emit the `attachments` event once all other setup is done.
1216 this._attachments.next();
1217 // Track this overlay by the keyboard dispatcher
1218 this._keyboardDispatcher.add(this);
1219 if (this._config.disposeOnNavigation) {
1220 this._locationChanges = this._location.subscribe(function () { return _this.dispose(); });
1221 }
1222 this._outsideClickDispatcher.add(this);
1223 return attachResult;
1224 };
1225 /**
1226 * Detaches an overlay from a portal.
1227 * @returns The portal detachment result.
1228 */
1229 OverlayRef.prototype.detach = function () {
1230 if (!this.hasAttached()) {
1231 return;
1232 }
1233 this.detachBackdrop();
1234 // When the overlay is detached, the pane element should disable pointer events.
1235 // This is necessary because otherwise the pane element will cover the page and disable
1236 // pointer events therefore. Depends on the position strategy and the applied pane boundaries.
1237 this._togglePointerEvents(false);
1238 if (this._positionStrategy && this._positionStrategy.detach) {
1239 this._positionStrategy.detach();
1240 }
1241 if (this._scrollStrategy) {
1242 this._scrollStrategy.disable();
1243 }
1244 var detachmentResult = this._portalOutlet.detach();
1245 // Only emit after everything is detached.
1246 this._detachments.next();
1247 // Remove this overlay from keyboard dispatcher tracking.
1248 this._keyboardDispatcher.remove(this);
1249 // Keeping the host element in the DOM can cause scroll jank, because it still gets
1250 // rendered, even though it's transparent and unclickable which is why we remove it.
1251 this._detachContentWhenStable();
1252 this._locationChanges.unsubscribe();
1253 this._outsideClickDispatcher.remove(this);
1254 return detachmentResult;
1255 };
1256 /** Cleans up the overlay from the DOM. */
1257 OverlayRef.prototype.dispose = function () {
1258 var isAttached = this.hasAttached();
1259 if (this._positionStrategy) {
1260 this._positionStrategy.dispose();
1261 }
1262 this._disposeScrollStrategy();
1263 this.detachBackdrop();
1264 this._locationChanges.unsubscribe();
1265 this._keyboardDispatcher.remove(this);
1266 this._portalOutlet.dispose();
1267 this._attachments.complete();
1268 this._backdropClick.complete();
1269 this._keydownEvents.complete();
1270 this._outsidePointerEvents.complete();
1271 this._outsideClickDispatcher.remove(this);
1272 if (this._host && this._host.parentNode) {
1273 this._host.parentNode.removeChild(this._host);
1274 this._host = null;
1275 }
1276 this._previousHostParent = this._pane = null;
1277 if (isAttached) {
1278 this._detachments.next();
1279 }
1280 this._detachments.complete();
1281 };
1282 /** Whether the overlay has attached content. */
1283 OverlayRef.prototype.hasAttached = function () {
1284 return this._portalOutlet.hasAttached();
1285 };
1286 /** Gets an observable that emits when the backdrop has been clicked. */
1287 OverlayRef.prototype.backdropClick = function () {
1288 return this._backdropClick;
1289 };
1290 /** Gets an observable that emits when the overlay has been attached. */
1291 OverlayRef.prototype.attachments = function () {
1292 return this._attachments;
1293 };
1294 /** Gets an observable that emits when the overlay has been detached. */
1295 OverlayRef.prototype.detachments = function () {
1296 return this._detachments;
1297 };
1298 /** Gets an observable of keydown events targeted to this overlay. */
1299 OverlayRef.prototype.keydownEvents = function () {
1300 return this._keydownEvents;
1301 };
1302 /** Gets an observable of pointer events targeted outside this overlay. */
1303 OverlayRef.prototype.outsidePointerEvents = function () {
1304 return this._outsidePointerEvents;
1305 };
1306 /** Gets the current overlay configuration, which is immutable. */
1307 OverlayRef.prototype.getConfig = function () {
1308 return this._config;
1309 };
1310 /** Updates the position of the overlay based on the position strategy. */
1311 OverlayRef.prototype.updatePosition = function () {
1312 if (this._positionStrategy) {
1313 this._positionStrategy.apply();
1314 }
1315 };
1316 /** Switches to a new position strategy and updates the overlay position. */
1317 OverlayRef.prototype.updatePositionStrategy = function (strategy) {
1318 if (strategy === this._positionStrategy) {
1319 return;
1320 }
1321 if (this._positionStrategy) {
1322 this._positionStrategy.dispose();
1323 }
1324 this._positionStrategy = strategy;
1325 if (this.hasAttached()) {
1326 strategy.attach(this);
1327 this.updatePosition();
1328 }
1329 };
1330 /** Update the size properties of the overlay. */
1331 OverlayRef.prototype.updateSize = function (sizeConfig) {
1332 this._config = Object.assign(Object.assign({}, this._config), sizeConfig);
1333 this._updateElementSize();
1334 };
1335 /** Sets the LTR/RTL direction for the overlay. */
1336 OverlayRef.prototype.setDirection = function (dir) {
1337 this._config = Object.assign(Object.assign({}, this._config), { direction: dir });
1338 this._updateElementDirection();
1339 };
1340 /** Add a CSS class or an array of classes to the overlay pane. */
1341 OverlayRef.prototype.addPanelClass = function (classes) {
1342 if (this._pane) {
1343 this._toggleClasses(this._pane, classes, true);
1344 }
1345 };
1346 /** Remove a CSS class or an array of classes from the overlay pane. */
1347 OverlayRef.prototype.removePanelClass = function (classes) {
1348 if (this._pane) {
1349 this._toggleClasses(this._pane, classes, false);
1350 }
1351 };
1352 /**
1353 * Returns the layout direction of the overlay panel.
1354 */
1355 OverlayRef.prototype.getDirection = function () {
1356 var direction = this._config.direction;
1357 if (!direction) {
1358 return 'ltr';
1359 }
1360 return typeof direction === 'string' ? direction : direction.value;
1361 };
1362 /** Switches to a new scroll strategy. */
1363 OverlayRef.prototype.updateScrollStrategy = function (strategy) {
1364 if (strategy === this._scrollStrategy) {
1365 return;
1366 }
1367 this._disposeScrollStrategy();
1368 this._scrollStrategy = strategy;
1369 if (this.hasAttached()) {
1370 strategy.attach(this);
1371 strategy.enable();
1372 }
1373 };
1374 /** Updates the text direction of the overlay panel. */
1375 OverlayRef.prototype._updateElementDirection = function () {
1376 this._host.setAttribute('dir', this.getDirection());
1377 };
1378 /** Updates the size of the overlay element based on the overlay config. */
1379 OverlayRef.prototype._updateElementSize = function () {
1380 if (!this._pane) {
1381 return;
1382 }
1383 var style = this._pane.style;
1384 style.width = coercion.coerceCssPixelValue(this._config.width);
1385 style.height = coercion.coerceCssPixelValue(this._config.height);
1386 style.minWidth = coercion.coerceCssPixelValue(this._config.minWidth);
1387 style.minHeight = coercion.coerceCssPixelValue(this._config.minHeight);
1388 style.maxWidth = coercion.coerceCssPixelValue(this._config.maxWidth);
1389 style.maxHeight = coercion.coerceCssPixelValue(this._config.maxHeight);
1390 };
1391 /** Toggles the pointer events for the overlay pane element. */
1392 OverlayRef.prototype._togglePointerEvents = function (enablePointer) {
1393 this._pane.style.pointerEvents = enablePointer ? '' : 'none';
1394 };
1395 /** Attaches a backdrop for this overlay. */
1396 OverlayRef.prototype._attachBackdrop = function () {
1397 var _this = this;
1398 var showingClass = 'cdk-overlay-backdrop-showing';
1399 this._backdropElement = this._document.createElement('div');
1400 this._backdropElement.classList.add('cdk-overlay-backdrop');
1401 if (this._config.backdropClass) {
1402 this._toggleClasses(this._backdropElement, this._config.backdropClass, true);
1403 }
1404 // Insert the backdrop before the pane in the DOM order,
1405 // in order to handle stacked overlays properly.
1406 this._host.parentElement.insertBefore(this._backdropElement, this._host);
1407 // Forward backdrop clicks such that the consumer of the overlay can perform whatever
1408 // action desired when such a click occurs (usually closing the overlay).
1409 this._backdropElement.addEventListener('click', this._backdropClickHandler);
1410 // Add class to fade-in the backdrop after one frame.
1411 if (typeof requestAnimationFrame !== 'undefined') {
1412 this._ngZone.runOutsideAngular(function () {
1413 requestAnimationFrame(function () {
1414 if (_this._backdropElement) {
1415 _this._backdropElement.classList.add(showingClass);
1416 }
1417 });
1418 });
1419 }
1420 else {
1421 this._backdropElement.classList.add(showingClass);
1422 }
1423 };
1424 /**
1425 * Updates the stacking order of the element, moving it to the top if necessary.
1426 * This is required in cases where one overlay was detached, while another one,
1427 * that should be behind it, was destroyed. The next time both of them are opened,
1428 * the stacking will be wrong, because the detached element's pane will still be
1429 * in its original DOM position.
1430 */
1431 OverlayRef.prototype._updateStackingOrder = function () {
1432 if (this._host.nextSibling) {
1433 this._host.parentNode.appendChild(this._host);
1434 }
1435 };
1436 /** Detaches the backdrop (if any) associated with the overlay. */
1437 OverlayRef.prototype.detachBackdrop = function () {
1438 var _this = this;
1439 var backdropToDetach = this._backdropElement;
1440 if (!backdropToDetach) {
1441 return;
1442 }
1443 var timeoutId;
1444 var finishDetach = function () {
1445 // It may not be attached to anything in certain cases (e.g. unit tests).
1446 if (backdropToDetach) {
1447 backdropToDetach.removeEventListener('click', _this._backdropClickHandler);
1448 backdropToDetach.removeEventListener('transitionend', finishDetach);
1449 if (backdropToDetach.parentNode) {
1450 backdropToDetach.parentNode.removeChild(backdropToDetach);
1451 }
1452 }
1453 // It is possible that a new portal has been attached to this overlay since we started
1454 // removing the backdrop. If that is the case, only clear the backdrop reference if it
1455 // is still the same instance that we started to remove.
1456 if (_this._backdropElement == backdropToDetach) {
1457 _this._backdropElement = null;
1458 }
1459 if (_this._config.backdropClass) {
1460 _this._toggleClasses(backdropToDetach, _this._config.backdropClass, false);
1461 }
1462 clearTimeout(timeoutId);
1463 };
1464 backdropToDetach.classList.remove('cdk-overlay-backdrop-showing');
1465 this._ngZone.runOutsideAngular(function () {
1466 backdropToDetach.addEventListener('transitionend', finishDetach);
1467 });
1468 // If the backdrop doesn't have a transition, the `transitionend` event won't fire.
1469 // In this case we make it unclickable and we try to remove it after a delay.
1470 backdropToDetach.style.pointerEvents = 'none';
1471 // Run this outside the Angular zone because there's nothing that Angular cares about.
1472 // If it were to run inside the Angular zone, every test that used Overlay would have to be
1473 // either async or fakeAsync.
1474 timeoutId = this._ngZone.runOutsideAngular(function () { return setTimeout(finishDetach, 500); });
1475 };
1476 /** Toggles a single CSS class or an array of classes on an element. */
1477 OverlayRef.prototype._toggleClasses = function (element, cssClasses, isAdd) {
1478 var classList = element.classList;
1479 coercion.coerceArray(cssClasses).forEach(function (cssClass) {
1480 // We can't do a spread here, because IE doesn't support setting multiple classes.
1481 // Also trying to add an empty string to a DOMTokenList will throw.
1482 if (cssClass) {
1483 isAdd ? classList.add(cssClass) : classList.remove(cssClass);
1484 }
1485 });
1486 };
1487 /** Detaches the overlay content next time the zone stabilizes. */
1488 OverlayRef.prototype._detachContentWhenStable = function () {
1489 var _this = this;
1490 // Normally we wouldn't have to explicitly run this outside the `NgZone`, however
1491 // if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will
1492 // be patched to run inside the zone, which will throw us into an infinite loop.
1493 this._ngZone.runOutsideAngular(function () {
1494 // We can't remove the host here immediately, because the overlay pane's content
1495 // might still be animating. This stream helps us avoid interrupting the animation
1496 // by waiting for the pane to become empty.
1497 var subscription = _this._ngZone.onStable
1498 .pipe(operators.takeUntil(rxjs.merge(_this._attachments, _this._detachments)))
1499 .subscribe(function () {
1500 // Needs a couple of checks for the pane and host, because
1501 // they may have been removed by the time the zone stabilizes.
1502 if (!_this._pane || !_this._host || _this._pane.children.length === 0) {
1503 if (_this._pane && _this._config.panelClass) {
1504 _this._toggleClasses(_this._pane, _this._config.panelClass, false);
1505 }
1506 if (_this._host && _this._host.parentElement) {
1507 _this._previousHostParent = _this._host.parentElement;
1508 _this._previousHostParent.removeChild(_this._host);
1509 }
1510 subscription.unsubscribe();
1511 }
1512 });
1513 });
1514 };
1515 /** Disposes of a scroll strategy. */
1516 OverlayRef.prototype._disposeScrollStrategy = function () {
1517 var scrollStrategy = this._scrollStrategy;
1518 if (scrollStrategy) {
1519 scrollStrategy.disable();
1520 if (scrollStrategy.detach) {
1521 scrollStrategy.detach();
1522 }
1523 }
1524 };
1525 return OverlayRef;
1526 }());
1527
1528 // TODO: refactor clipping detection into a separate thing (part of scrolling module)
1529 // TODO: doesn't handle both flexible width and height when it has to scroll along both axis.
1530 /** Class to be added to the overlay bounding box. */
1531 var boundingBoxClass = 'cdk-overlay-connected-position-bounding-box';
1532 /** Regex used to split a string on its CSS units. */
1533 var cssUnitPattern = /([A-Za-z%]+)$/;
1534 /**
1535 * A strategy for positioning overlays. Using this strategy, an overlay is given an
1536 * implicit position relative some origin element. The relative position is defined in terms of
1537 * a point on the origin element that is connected to a point on the overlay element. For example,
1538 * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner
1539 * of the overlay.
1540 */
1541 var FlexibleConnectedPositionStrategy = /** @class */ (function () {
1542 function FlexibleConnectedPositionStrategy(connectedTo, _viewportRuler, _document, _platform, _overlayContainer) {
1543 this._viewportRuler = _viewportRuler;
1544 this._document = _document;
1545 this._platform = _platform;
1546 this._overlayContainer = _overlayContainer;
1547 /** Last size used for the bounding box. Used to avoid resizing the overlay after open. */
1548 this._lastBoundingBoxSize = { width: 0, height: 0 };
1549 /** Whether the overlay was pushed in a previous positioning. */
1550 this._isPushed = false;
1551 /** Whether the overlay can be pushed on-screen on the initial open. */
1552 this._canPush = true;
1553 /** Whether the overlay can grow via flexible width/height after the initial open. */
1554 this._growAfterOpen = false;
1555 /** Whether the overlay's width and height can be constrained to fit within the viewport. */
1556 this._hasFlexibleDimensions = true;
1557 /** Whether the overlay position is locked. */
1558 this._positionLocked = false;
1559 /** Amount of space that must be maintained between the overlay and the edge of the viewport. */
1560 this._viewportMargin = 0;
1561 /** The Scrollable containers used to check scrollable view properties on position change. */
1562 this._scrollables = [];
1563 /** Ordered list of preferred positions, from most to least desirable. */
1564 this._preferredPositions = [];
1565 /** Subject that emits whenever the position changes. */
1566 this._positionChanges = new rxjs.Subject();
1567 /** Subscription to viewport size changes. */
1568 this._resizeSubscription = rxjs.Subscription.EMPTY;
1569 /** Default offset for the overlay along the x axis. */
1570 this._offsetX = 0;
1571 /** Default offset for the overlay along the y axis. */
1572 this._offsetY = 0;
1573 /** Keeps track of the CSS classes that the position strategy has applied on the overlay panel. */
1574 this._appliedPanelClasses = [];
1575 /** Observable sequence of position changes. */
1576 this.positionChanges = this._positionChanges;
1577 this.setOrigin(connectedTo);
1578 }
1579 Object.defineProperty(FlexibleConnectedPositionStrategy.prototype, "positions", {
1580 /** Ordered list of preferred positions, from most to least desirable. */
1581 get: function () {
1582 return this._preferredPositions;
1583 },
1584 enumerable: false,
1585 configurable: true
1586 });
1587 /** Attaches this position strategy to an overlay. */
1588 FlexibleConnectedPositionStrategy.prototype.attach = function (overlayRef) {
1589 var _this = this;
1590 if (this._overlayRef && overlayRef !== this._overlayRef &&
1591 (typeof ngDevMode === 'undefined' || ngDevMode)) {
1592 throw Error('This position strategy is already attached to an overlay');
1593 }
1594 this._validatePositions();
1595 overlayRef.hostElement.classList.add(boundingBoxClass);
1596 this._overlayRef = overlayRef;
1597 this._boundingBox = overlayRef.hostElement;
1598 this._pane = overlayRef.overlayElement;
1599 this._isDisposed = false;
1600 this._isInitialRender = true;
1601 this._lastPosition = null;
1602 this._resizeSubscription.unsubscribe();
1603 this._resizeSubscription = this._viewportRuler.change().subscribe(function () {
1604 // When the window is resized, we want to trigger the next reposition as if it
1605 // was an initial render, in order for the strategy to pick a new optimal position,
1606 // otherwise position locking will cause it to stay at the old one.
1607 _this._isInitialRender = true;
1608 _this.apply();
1609 });
1610 };
1611 /**
1612 * Updates the position of the overlay element, using whichever preferred position relative
1613 * to the origin best fits on-screen.
1614 *
1615 * The selection of a position goes as follows:
1616 * - If any positions fit completely within the viewport as-is,
1617 * choose the first position that does so.
1618 * - If flexible dimensions are enabled and at least one satifies the given minimum width/height,
1619 * choose the position with the greatest available size modified by the positions' weight.
1620 * - If pushing is enabled, take the position that went off-screen the least and push it
1621 * on-screen.
1622 * - If none of the previous criteria were met, use the position that goes off-screen the least.
1623 * @docs-private
1624 */
1625 FlexibleConnectedPositionStrategy.prototype.apply = function () {
1626 var e_1, _a, e_2, _b;
1627 // We shouldn't do anything if the strategy was disposed or we're on the server.
1628 if (this._isDisposed || !this._platform.isBrowser) {
1629 return;
1630 }
1631 // If the position has been applied already (e.g. when the overlay was opened) and the
1632 // consumer opted into locking in the position, re-use the old position, in order to
1633 // prevent the overlay from jumping around.
1634 if (!this._isInitialRender && this._positionLocked && this._lastPosition) {
1635 this.reapplyLastPosition();
1636 return;
1637 }
1638 this._clearPanelClasses();
1639 this._resetOverlayElementStyles();
1640 this._resetBoundingBoxStyles();
1641 // We need the bounding rects for the origin and the overlay to determine how to position
1642 // the overlay relative to the origin.
1643 // We use the viewport rect to determine whether a position would go off-screen.
1644 this._viewportRect = this._getNarrowedViewportRect();
1645 this._originRect = this._getOriginRect();
1646 this._overlayRect = this._pane.getBoundingClientRect();
1647 var originRect = this._originRect;
1648 var overlayRect = this._overlayRect;
1649 var viewportRect = this._viewportRect;
1650 // Positions where the overlay will fit with flexible dimensions.
1651 var flexibleFits = [];
1652 // Fallback if none of the preferred positions fit within the viewport.
1653 var fallback;
1654 try {
1655 // Go through each of the preferred positions looking for a good fit.
1656 // If a good fit is found, it will be applied immediately.
1657 for (var _c = __values(this._preferredPositions), _d = _c.next(); !_d.done; _d = _c.next()) {
1658 var pos = _d.value;
1659 // Get the exact (x, y) coordinate for the point-of-origin on the origin element.
1660 var originPoint = this._getOriginPoint(originRect, pos);
1661 // From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the
1662 // overlay in this position. We use the top-left corner for calculations and later translate
1663 // this into an appropriate (top, left, bottom, right) style.
1664 var overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);
1665 // Calculate how well the overlay would fit into the viewport with this point.
1666 var overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos);
1667 // If the overlay, without any further work, fits into the viewport, use this position.
1668 if (overlayFit.isCompletelyWithinViewport) {
1669 this._isPushed = false;
1670 this._applyPosition(pos, originPoint);
1671 return;
1672 }
1673 // If the overlay has flexible dimensions, we can use this position
1674 // so long as there's enough space for the minimum dimensions.
1675 if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) {
1676 // Save positions where the overlay will fit with flexible dimensions. We will use these
1677 // if none of the positions fit *without* flexible dimensions.
1678 flexibleFits.push({
1679 position: pos,
1680 origin: originPoint,
1681 overlayRect: overlayRect,
1682 boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos)
1683 });
1684 continue;
1685 }
1686 // If the current preferred position does not fit on the screen, remember the position
1687 // if it has more visible area on-screen than we've seen and move onto the next preferred
1688 // position.
1689 if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) {
1690 fallback = { overlayFit: overlayFit, overlayPoint: overlayPoint, originPoint: originPoint, position: pos, overlayRect: overlayRect };
1691 }
1692 }
1693 }
1694 catch (e_1_1) { e_1 = { error: e_1_1 }; }
1695 finally {
1696 try {
1697 if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
1698 }
1699 finally { if (e_1) throw e_1.error; }
1700 }
1701 // If there are any positions where the overlay would fit with flexible dimensions, choose the
1702 // one that has the greatest area available modified by the position's weight
1703 if (flexibleFits.length) {
1704 var bestFit = null;
1705 var bestScore = -1;
1706 try {
1707 for (var flexibleFits_1 = __values(flexibleFits), flexibleFits_1_1 = flexibleFits_1.next(); !flexibleFits_1_1.done; flexibleFits_1_1 = flexibleFits_1.next()) {
1708 var fit = flexibleFits_1_1.value;
1709 var score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1);
1710 if (score > bestScore) {
1711 bestScore = score;
1712 bestFit = fit;
1713 }
1714 }
1715 }
1716 catch (e_2_1) { e_2 = { error: e_2_1 }; }
1717 finally {
1718 try {
1719 if (flexibleFits_1_1 && !flexibleFits_1_1.done && (_b = flexibleFits_1.return)) _b.call(flexibleFits_1);
1720 }
1721 finally { if (e_2) throw e_2.error; }
1722 }
1723 this._isPushed = false;
1724 this._applyPosition(bestFit.position, bestFit.origin);
1725 return;
1726 }
1727 // When none of the preferred positions fit within the viewport, take the position
1728 // that went off-screen the least and attempt to push it on-screen.
1729 if (this._canPush) {
1730 // TODO(jelbourn): after pushing, the opening "direction" of the overlay might not make sense.
1731 this._isPushed = true;
1732 this._applyPosition(fallback.position, fallback.originPoint);
1733 return;
1734 }
1735 // All options for getting the overlay within the viewport have been exhausted, so go with the
1736 // position that went off-screen the least.
1737 this._applyPosition(fallback.position, fallback.originPoint);
1738 };
1739 FlexibleConnectedPositionStrategy.prototype.detach = function () {
1740 this._clearPanelClasses();
1741 this._lastPosition = null;
1742 this._previousPushAmount = null;
1743 this._resizeSubscription.unsubscribe();
1744 };
1745 /** Cleanup after the element gets destroyed. */
1746 FlexibleConnectedPositionStrategy.prototype.dispose = function () {
1747 if (this._isDisposed) {
1748 return;
1749 }
1750 // We can't use `_resetBoundingBoxStyles` here, because it resets
1751 // some properties to zero, rather than removing them.
1752 if (this._boundingBox) {
1753 extendStyles(this._boundingBox.style, {
1754 top: '',
1755 left: '',
1756 right: '',
1757 bottom: '',
1758 height: '',
1759 width: '',
1760 alignItems: '',
1761 justifyContent: '',
1762 });
1763 }
1764 if (this._pane) {
1765 this._resetOverlayElementStyles();
1766 }
1767 if (this._overlayRef) {
1768 this._overlayRef.hostElement.classList.remove(boundingBoxClass);
1769 }
1770 this.detach();
1771 this._positionChanges.complete();
1772 this._overlayRef = this._boundingBox = null;
1773 this._isDisposed = true;
1774 };
1775 /**
1776 * This re-aligns the overlay element with the trigger in its last calculated position,
1777 * even if a position higher in the "preferred positions" list would now fit. This
1778 * allows one to re-align the panel without changing the orientation of the panel.
1779 */
1780 FlexibleConnectedPositionStrategy.prototype.reapplyLastPosition = function () {
1781 if (!this._isDisposed && (!this._platform || this._platform.isBrowser)) {
1782 this._originRect = this._getOriginRect();
1783 this._overlayRect = this._pane.getBoundingClientRect();
1784 this._viewportRect = this._getNarrowedViewportRect();
1785 var lastPosition = this._lastPosition || this._preferredPositions[0];
1786 var originPoint = this._getOriginPoint(this._originRect, lastPosition);
1787 this._applyPosition(lastPosition, originPoint);
1788 }
1789 };
1790 /**
1791 * Sets the list of Scrollable containers that host the origin element so that
1792 * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every
1793 * Scrollable must be an ancestor element of the strategy's origin element.
1794 */
1795 FlexibleConnectedPositionStrategy.prototype.withScrollableContainers = function (scrollables) {
1796 this._scrollables = scrollables;
1797 return this;
1798 };
1799 /**
1800 * Adds new preferred positions.
1801 * @param positions List of positions options for this overlay.
1802 */
1803 FlexibleConnectedPositionStrategy.prototype.withPositions = function (positions) {
1804 this._preferredPositions = positions;
1805 // If the last calculated position object isn't part of the positions anymore, clear
1806 // it in order to avoid it being picked up if the consumer tries to re-apply.
1807 if (positions.indexOf(this._lastPosition) === -1) {
1808 this._lastPosition = null;
1809 }
1810 this._validatePositions();
1811 return this;
1812 };
1813 /**
1814 * Sets a minimum distance the overlay may be positioned to the edge of the viewport.
1815 * @param margin Required margin between the overlay and the viewport edge in pixels.
1816 */
1817 FlexibleConnectedPositionStrategy.prototype.withViewportMargin = function (margin) {
1818 this._viewportMargin = margin;
1819 return this;
1820 };
1821 /** Sets whether the overlay's width and height can be constrained to fit within the viewport. */
1822 FlexibleConnectedPositionStrategy.prototype.withFlexibleDimensions = function (flexibleDimensions) {
1823 if (flexibleDimensions === void 0) { flexibleDimensions = true; }
1824 this._hasFlexibleDimensions = flexibleDimensions;
1825 return this;
1826 };
1827 /** Sets whether the overlay can grow after the initial open via flexible width/height. */
1828 FlexibleConnectedPositionStrategy.prototype.withGrowAfterOpen = function (growAfterOpen) {
1829 if (growAfterOpen === void 0) { growAfterOpen = true; }
1830 this._growAfterOpen = growAfterOpen;
1831 return this;
1832 };
1833 /** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */
1834 FlexibleConnectedPositionStrategy.prototype.withPush = function (canPush) {
1835 if (canPush === void 0) { canPush = true; }
1836 this._canPush = canPush;
1837 return this;
1838 };
1839 /**
1840 * Sets whether the overlay's position should be locked in after it is positioned
1841 * initially. When an overlay is locked in, it won't attempt to reposition itself
1842 * when the position is re-applied (e.g. when the user scrolls away).
1843 * @param isLocked Whether the overlay should locked in.
1844 */
1845 FlexibleConnectedPositionStrategy.prototype.withLockedPosition = function (isLocked) {
1846 if (isLocked === void 0) { isLocked = true; }
1847 this._positionLocked = isLocked;
1848 return this;
1849 };
1850 /**
1851 * Sets the origin, relative to which to position the overlay.
1852 * Using an element origin is useful for building components that need to be positioned
1853 * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be
1854 * used for cases like contextual menus which open relative to the user's pointer.
1855 * @param origin Reference to the new origin.
1856 */
1857 FlexibleConnectedPositionStrategy.prototype.setOrigin = function (origin) {
1858 this._origin = origin;
1859 return this;
1860 };
1861 /**
1862 * Sets the default offset for the overlay's connection point on the x-axis.
1863 * @param offset New offset in the X axis.
1864 */
1865 FlexibleConnectedPositionStrategy.prototype.withDefaultOffsetX = function (offset) {
1866 this._offsetX = offset;
1867 return this;
1868 };
1869 /**
1870 * Sets the default offset for the overlay's connection point on the y-axis.
1871 * @param offset New offset in the Y axis.
1872 */
1873 FlexibleConnectedPositionStrategy.prototype.withDefaultOffsetY = function (offset) {
1874 this._offsetY = offset;
1875 return this;
1876 };
1877 /**
1878 * Configures that the position strategy should set a `transform-origin` on some elements
1879 * inside the overlay, depending on the current position that is being applied. This is
1880 * useful for the cases where the origin of an animation can change depending on the
1881 * alignment of the overlay.
1882 * @param selector CSS selector that will be used to find the target
1883 * elements onto which to set the transform origin.
1884 */
1885 FlexibleConnectedPositionStrategy.prototype.withTransformOriginOn = function (selector) {
1886 this._transformOriginSelector = selector;
1887 return this;
1888 };
1889 /**
1890 * Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
1891 */
1892 FlexibleConnectedPositionStrategy.prototype._getOriginPoint = function (originRect, pos) {
1893 var x;
1894 if (pos.originX == 'center') {
1895 // Note: when centering we should always use the `left`
1896 // offset, otherwise the position will be wrong in RTL.
1897 x = originRect.left + (originRect.width / 2);
1898 }
1899 else {
1900 var startX = this._isRtl() ? originRect.right : originRect.left;
1901 var endX = this._isRtl() ? originRect.left : originRect.right;
1902 x = pos.originX == 'start' ? startX : endX;
1903 }
1904 var y;
1905 if (pos.originY == 'center') {
1906 y = originRect.top + (originRect.height / 2);
1907 }
1908 else {
1909 y = pos.originY == 'top' ? originRect.top : originRect.bottom;
1910 }
1911 return { x: x, y: y };
1912 };
1913 /**
1914 * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and
1915 * origin point to which the overlay should be connected.
1916 */
1917 FlexibleConnectedPositionStrategy.prototype._getOverlayPoint = function (originPoint, overlayRect, pos) {
1918 // Calculate the (overlayStartX, overlayStartY), the start of the
1919 // potential overlay position relative to the origin point.
1920 var overlayStartX;
1921 if (pos.overlayX == 'center') {
1922 overlayStartX = -overlayRect.width / 2;
1923 }
1924 else if (pos.overlayX === 'start') {
1925 overlayStartX = this._isRtl() ? -overlayRect.width : 0;
1926 }
1927 else {
1928 overlayStartX = this._isRtl() ? 0 : -overlayRect.width;
1929 }
1930 var overlayStartY;
1931 if (pos.overlayY == 'center') {
1932 overlayStartY = -overlayRect.height / 2;
1933 }
1934 else {
1935 overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;
1936 }
1937 // The (x, y) coordinates of the overlay.
1938 return {
1939 x: originPoint.x + overlayStartX,
1940 y: originPoint.y + overlayStartY,
1941 };
1942 };
1943 /** Gets how well an overlay at the given point will fit within the viewport. */
1944 FlexibleConnectedPositionStrategy.prototype._getOverlayFit = function (point, rawOverlayRect, viewport, position) {
1945 // Round the overlay rect when comparing against the
1946 // viewport, because the viewport is always rounded.
1947 var overlay = getRoundedBoundingClientRect(rawOverlayRect);
1948 var x = point.x, y = point.y;
1949 var offsetX = this._getOffset(position, 'x');
1950 var offsetY = this._getOffset(position, 'y');
1951 // Account for the offsets since they could push the overlay out of the viewport.
1952 if (offsetX) {
1953 x += offsetX;
1954 }
1955 if (offsetY) {
1956 y += offsetY;
1957 }
1958 // How much the overlay would overflow at this position, on each side.
1959 var leftOverflow = 0 - x;
1960 var rightOverflow = (x + overlay.width) - viewport.width;
1961 var topOverflow = 0 - y;
1962 var bottomOverflow = (y + overlay.height) - viewport.height;
1963 // Visible parts of the element on each axis.
1964 var visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow);
1965 var visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow);
1966 var visibleArea = visibleWidth * visibleHeight;
1967 return {
1968 visibleArea: visibleArea,
1969 isCompletelyWithinViewport: (overlay.width * overlay.height) === visibleArea,
1970 fitsInViewportVertically: visibleHeight === overlay.height,
1971 fitsInViewportHorizontally: visibleWidth == overlay.width,
1972 };
1973 };
1974 /**
1975 * Whether the overlay can fit within the viewport when it may resize either its width or height.
1976 * @param fit How well the overlay fits in the viewport at some position.
1977 * @param point The (x, y) coordinates of the overlat at some position.
1978 * @param viewport The geometry of the viewport.
1979 */
1980 FlexibleConnectedPositionStrategy.prototype._canFitWithFlexibleDimensions = function (fit, point, viewport) {
1981 if (this._hasFlexibleDimensions) {
1982 var availableHeight = viewport.bottom - point.y;
1983 var availableWidth = viewport.right - point.x;
1984 var minHeight = getPixelValue(this._overlayRef.getConfig().minHeight);
1985 var minWidth = getPixelValue(this._overlayRef.getConfig().minWidth);
1986 var verticalFit = fit.fitsInViewportVertically ||
1987 (minHeight != null && minHeight <= availableHeight);
1988 var horizontalFit = fit.fitsInViewportHorizontally ||
1989 (minWidth != null && minWidth <= availableWidth);
1990 return verticalFit && horizontalFit;
1991 }
1992 return false;
1993 };
1994 /**
1995 * Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than
1996 * the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the
1997 * right and bottom).
1998 *
1999 * @param start Starting point from which the overlay is pushed.
2000 * @param overlay Dimensions of the overlay.
2001 * @param scrollPosition Current viewport scroll position.
2002 * @returns The point at which to position the overlay after pushing. This is effectively a new
2003 * originPoint.
2004 */
2005 FlexibleConnectedPositionStrategy.prototype._pushOverlayOnScreen = function (start, rawOverlayRect, scrollPosition) {
2006 // If the position is locked and we've pushed the overlay already, reuse the previous push
2007 // amount, rather than pushing it again. If we were to continue pushing, the element would
2008 // remain in the viewport, which goes against the expectations when position locking is enabled.
2009 if (this._previousPushAmount && this._positionLocked) {
2010 return {
2011 x: start.x + this._previousPushAmount.x,
2012 y: start.y + this._previousPushAmount.y
2013 };
2014 }
2015 // Round the overlay rect when comparing against the
2016 // viewport, because the viewport is always rounded.
2017 var overlay = getRoundedBoundingClientRect(rawOverlayRect);
2018 var viewport = this._viewportRect;
2019 // Determine how much the overlay goes outside the viewport on each
2020 // side, which we'll use to decide which direction to push it.
2021 var overflowRight = Math.max(start.x + overlay.width - viewport.width, 0);
2022 var overflowBottom = Math.max(start.y + overlay.height - viewport.height, 0);
2023 var overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0);
2024 var overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0);
2025 // Amount by which to push the overlay in each axis such that it remains on-screen.
2026 var pushX = 0;
2027 var pushY = 0;
2028 // If the overlay fits completely within the bounds of the viewport, push it from whichever
2029 // direction is goes off-screen. Otherwise, push the top-left corner such that its in the
2030 // viewport and allow for the trailing end of the overlay to go out of bounds.
2031 if (overlay.width <= viewport.width) {
2032 pushX = overflowLeft || -overflowRight;
2033 }
2034 else {
2035 pushX = start.x < this._viewportMargin ? (viewport.left - scrollPosition.left) - start.x : 0;
2036 }
2037 if (overlay.height <= viewport.height) {
2038 pushY = overflowTop || -overflowBottom;
2039 }
2040 else {
2041 pushY = start.y < this._viewportMargin ? (viewport.top - scrollPosition.top) - start.y : 0;
2042 }
2043 this._previousPushAmount = { x: pushX, y: pushY };
2044 return {
2045 x: start.x + pushX,
2046 y: start.y + pushY,
2047 };
2048 };
2049 /**
2050 * Applies a computed position to the overlay and emits a position change.
2051 * @param position The position preference
2052 * @param originPoint The point on the origin element where the overlay is connected.
2053 */
2054 FlexibleConnectedPositionStrategy.prototype._applyPosition = function (position, originPoint) {
2055 this._setTransformOrigin(position);
2056 this._setOverlayElementStyles(originPoint, position);
2057 this._setBoundingBoxStyles(originPoint, position);
2058 if (position.panelClass) {
2059 this._addPanelClasses(position.panelClass);
2060 }
2061 // Save the last connected position in case the position needs to be re-calculated.
2062 this._lastPosition = position;
2063 // Notify that the position has been changed along with its change properties.
2064 // We only emit if we've got any subscriptions, because the scroll visibility
2065 // calculcations can be somewhat expensive.
2066 if (this._positionChanges.observers.length) {
2067 var scrollableViewProperties = this._getScrollVisibility();
2068 var changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);
2069 this._positionChanges.next(changeEvent);
2070 }
2071 this._isInitialRender = false;
2072 };
2073 /** Sets the transform origin based on the configured selector and the passed-in position. */
2074 FlexibleConnectedPositionStrategy.prototype._setTransformOrigin = function (position) {
2075 if (!this._transformOriginSelector) {
2076 return;
2077 }
2078 var elements = this._boundingBox.querySelectorAll(this._transformOriginSelector);
2079 var xOrigin;
2080 var yOrigin = position.overlayY;
2081 if (position.overlayX === 'center') {
2082 xOrigin = 'center';
2083 }
2084 else if (this._isRtl()) {
2085 xOrigin = position.overlayX === 'start' ? 'right' : 'left';
2086 }
2087 else {
2088 xOrigin = position.overlayX === 'start' ? 'left' : 'right';
2089 }
2090 for (var i = 0; i < elements.length; i++) {
2091 elements[i].style.transformOrigin = xOrigin + " " + yOrigin;
2092 }
2093 };
2094 /**
2095 * Gets the position and size of the overlay's sizing container.
2096 *
2097 * This method does no measuring and applies no styles so that we can cheaply compute the
2098 * bounds for all positions and choose the best fit based on these results.
2099 */
2100 FlexibleConnectedPositionStrategy.prototype._calculateBoundingBoxRect = function (origin, position) {
2101 var viewport = this._viewportRect;
2102 var isRtl = this._isRtl();
2103 var height, top, bottom;
2104 if (position.overlayY === 'top') {
2105 // Overlay is opening "downward" and thus is bound by the bottom viewport edge.
2106 top = origin.y;
2107 height = viewport.height - top + this._viewportMargin;
2108 }
2109 else if (position.overlayY === 'bottom') {
2110 // Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add
2111 // the viewport margin back in, because the viewport rect is narrowed down to remove the
2112 // margin, whereas the `origin` position is calculated based on its `ClientRect`.
2113 bottom = viewport.height - origin.y + this._viewportMargin * 2;
2114 height = viewport.height - bottom + this._viewportMargin;
2115 }
2116 else {
2117 // If neither top nor bottom, it means that the overlay is vertically centered on the
2118 // origin point. Note that we want the position relative to the viewport, rather than
2119 // the page, which is why we don't use something like `viewport.bottom - origin.y` and
2120 // `origin.y - viewport.top`.
2121 var smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y);
2122 var previousHeight = this._lastBoundingBoxSize.height;
2123 height = smallestDistanceToViewportEdge * 2;
2124 top = origin.y - smallestDistanceToViewportEdge;
2125 if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) {
2126 top = origin.y - (previousHeight / 2);
2127 }
2128 }
2129 // The overlay is opening 'right-ward' (the content flows to the right).
2130 var isBoundedByRightViewportEdge = (position.overlayX === 'start' && !isRtl) ||
2131 (position.overlayX === 'end' && isRtl);
2132 // The overlay is opening 'left-ward' (the content flows to the left).
2133 var isBoundedByLeftViewportEdge = (position.overlayX === 'end' && !isRtl) ||
2134 (position.overlayX === 'start' && isRtl);
2135 var width, left, right;
2136 if (isBoundedByLeftViewportEdge) {
2137 right = viewport.width - origin.x + this._viewportMargin;
2138 width = origin.x - this._viewportMargin;
2139 }
2140 else if (isBoundedByRightViewportEdge) {
2141 left = origin.x;
2142 width = viewport.right - origin.x;
2143 }
2144 else {
2145 // If neither start nor end, it means that the overlay is horizontally centered on the
2146 // origin point. Note that we want the position relative to the viewport, rather than
2147 // the page, which is why we don't use something like `viewport.right - origin.x` and
2148 // `origin.x - viewport.left`.
2149 var smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x);
2150 var previousWidth = this._lastBoundingBoxSize.width;
2151 width = smallestDistanceToViewportEdge * 2;
2152 left = origin.x - smallestDistanceToViewportEdge;
2153 if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) {
2154 left = origin.x - (previousWidth / 2);
2155 }
2156 }
2157 return { top: top, left: left, bottom: bottom, right: right, width: width, height: height };
2158 };
2159 /**
2160 * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the
2161 * origin's connection point and stetches to the bounds of the viewport.
2162 *
2163 * @param origin The point on the origin element where the overlay is connected.
2164 * @param position The position preference
2165 */
2166 FlexibleConnectedPositionStrategy.prototype._setBoundingBoxStyles = function (origin, position) {
2167 var boundingBoxRect = this._calculateBoundingBoxRect(origin, position);
2168 // It's weird if the overlay *grows* while scrolling, so we take the last size into account
2169 // when applying a new size.
2170 if (!this._isInitialRender && !this._growAfterOpen) {
2171 boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height);
2172 boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width);
2173 }
2174 var styles = {};
2175 if (this._hasExactPosition()) {
2176 styles.top = styles.left = '0';
2177 styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = '';
2178 styles.width = styles.height = '100%';
2179 }
2180 else {
2181 var maxHeight = this._overlayRef.getConfig().maxHeight;
2182 var maxWidth = this._overlayRef.getConfig().maxWidth;
2183 styles.height = coercion.coerceCssPixelValue(boundingBoxRect.height);
2184 styles.top = coercion.coerceCssPixelValue(boundingBoxRect.top);
2185 styles.bottom = coercion.coerceCssPixelValue(boundingBoxRect.bottom);
2186 styles.width = coercion.coerceCssPixelValue(boundingBoxRect.width);
2187 styles.left = coercion.coerceCssPixelValue(boundingBoxRect.left);
2188 styles.right = coercion.coerceCssPixelValue(boundingBoxRect.right);
2189 // Push the pane content towards the proper direction.
2190 if (position.overlayX === 'center') {
2191 styles.alignItems = 'center';
2192 }
2193 else {
2194 styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start';
2195 }
2196 if (position.overlayY === 'center') {
2197 styles.justifyContent = 'center';
2198 }
2199 else {
2200 styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start';
2201 }
2202 if (maxHeight) {
2203 styles.maxHeight = coercion.coerceCssPixelValue(maxHeight);
2204 }
2205 if (maxWidth) {
2206 styles.maxWidth = coercion.coerceCssPixelValue(maxWidth);
2207 }
2208 }
2209 this._lastBoundingBoxSize = boundingBoxRect;
2210 extendStyles(this._boundingBox.style, styles);
2211 };
2212 /** Resets the styles for the bounding box so that a new positioning can be computed. */
2213 FlexibleConnectedPositionStrategy.prototype._resetBoundingBoxStyles = function () {
2214 extendStyles(this._boundingBox.style, {
2215 top: '0',
2216 left: '0',
2217 right: '0',
2218 bottom: '0',
2219 height: '',
2220 width: '',
2221 alignItems: '',
2222 justifyContent: '',
2223 });
2224 };
2225 /** Resets the styles for the overlay pane so that a new positioning can be computed. */
2226 FlexibleConnectedPositionStrategy.prototype._resetOverlayElementStyles = function () {
2227 extendStyles(this._pane.style, {
2228 top: '',
2229 left: '',
2230 bottom: '',
2231 right: '',
2232 position: '',
2233 transform: '',
2234 });
2235 };
2236 /** Sets positioning styles to the overlay element. */
2237 FlexibleConnectedPositionStrategy.prototype._setOverlayElementStyles = function (originPoint, position) {
2238 var styles = {};
2239 var hasExactPosition = this._hasExactPosition();
2240 var hasFlexibleDimensions = this._hasFlexibleDimensions;
2241 var config = this._overlayRef.getConfig();
2242 if (hasExactPosition) {
2243 var scrollPosition = this._viewportRuler.getViewportScrollPosition();
2244 extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition));
2245 extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition));
2246 }
2247 else {
2248 styles.position = 'static';
2249 }
2250 // Use a transform to apply the offsets. We do this because the `center` positions rely on
2251 // being in the normal flex flow and setting a `top` / `left` at all will completely throw
2252 // off the position. We also can't use margins, because they won't have an effect in some
2253 // cases where the element doesn't have anything to "push off of". Finally, this works
2254 // better both with flexible and non-flexible positioning.
2255 var transformString = '';
2256 var offsetX = this._getOffset(position, 'x');
2257 var offsetY = this._getOffset(position, 'y');
2258 if (offsetX) {
2259 transformString += "translateX(" + offsetX + "px) ";
2260 }
2261 if (offsetY) {
2262 transformString += "translateY(" + offsetY + "px)";
2263 }
2264 styles.transform = transformString.trim();
2265 // If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because
2266 // we need these values to both be set to "100%" for the automatic flexible sizing to work.
2267 // The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint.
2268 // Note that this doesn't apply when we have an exact position, in which case we do want to
2269 // apply them because they'll be cleared from the bounding box.
2270 if (config.maxHeight) {
2271 if (hasExactPosition) {
2272 styles.maxHeight = coercion.coerceCssPixelValue(config.maxHeight);
2273 }
2274 else if (hasFlexibleDimensions) {
2275 styles.maxHeight = '';
2276 }
2277 }
2278 if (config.maxWidth) {
2279 if (hasExactPosition) {
2280 styles.maxWidth = coercion.coerceCssPixelValue(config.maxWidth);
2281 }
2282 else if (hasFlexibleDimensions) {
2283 styles.maxWidth = '';
2284 }
2285 }
2286 extendStyles(this._pane.style, styles);
2287 };
2288 /** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */
2289 FlexibleConnectedPositionStrategy.prototype._getExactOverlayY = function (position, originPoint, scrollPosition) {
2290 // Reset any existing styles. This is necessary in case the
2291 // preferred position has changed since the last `apply`.
2292 var styles = { top: '', bottom: '' };
2293 var overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
2294 if (this._isPushed) {
2295 overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
2296 }
2297 var virtualKeyboardOffset = this._overlayContainer.getContainerElement().getBoundingClientRect().top;
2298 // Normally this would be zero, however when the overlay is attached to an input (e.g. in an
2299 // autocomplete), mobile browsers will shift everything in order to put the input in the middle
2300 // of the screen and to make space for the virtual keyboard. We need to account for this offset,
2301 // otherwise our positioning will be thrown off.
2302 overlayPoint.y -= virtualKeyboardOffset;
2303 // We want to set either `top` or `bottom` based on whether the overlay wants to appear
2304 // above or below the origin and the direction in which the element will expand.
2305 if (position.overlayY === 'bottom') {
2306 // When using `bottom`, we adjust the y position such that it is the distance
2307 // from the bottom of the viewport rather than the top.
2308 var documentHeight = this._document.documentElement.clientHeight;
2309 styles.bottom = documentHeight - (overlayPoint.y + this._overlayRect.height) + "px";
2310 }
2311 else {
2312 styles.top = coercion.coerceCssPixelValue(overlayPoint.y);
2313 }
2314 return styles;
2315 };
2316 /** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */
2317 FlexibleConnectedPositionStrategy.prototype._getExactOverlayX = function (position, originPoint, scrollPosition) {
2318 // Reset any existing styles. This is necessary in case the preferred position has
2319 // changed since the last `apply`.
2320 var styles = { left: '', right: '' };
2321 var overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
2322 if (this._isPushed) {
2323 overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
2324 }
2325 // We want to set either `left` or `right` based on whether the overlay wants to appear "before"
2326 // or "after" the origin, which determines the direction in which the element will expand.
2327 // For the horizontal axis, the meaning of "before" and "after" change based on whether the
2328 // page is in RTL or LTR.
2329 var horizontalStyleProperty;
2330 if (this._isRtl()) {
2331 horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right';
2332 }
2333 else {
2334 horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left';
2335 }
2336 // When we're setting `right`, we adjust the x position such that it is the distance
2337 // from the right edge of the viewport rather than the left edge.
2338 if (horizontalStyleProperty === 'right') {
2339 var documentWidth = this._document.documentElement.clientWidth;
2340 styles.right = documentWidth - (overlayPoint.x + this._overlayRect.width) + "px";
2341 }
2342 else {
2343 styles.left = coercion.coerceCssPixelValue(overlayPoint.x);
2344 }
2345 return styles;
2346 };
2347 /**
2348 * Gets the view properties of the trigger and overlay, including whether they are clipped
2349 * or completely outside the view of any of the strategy's scrollables.
2350 */
2351 FlexibleConnectedPositionStrategy.prototype._getScrollVisibility = function () {
2352 // Note: needs fresh rects since the position could've changed.
2353 var originBounds = this._getOriginRect();
2354 var overlayBounds = this._pane.getBoundingClientRect();
2355 // TODO(jelbourn): instead of needing all of the client rects for these scrolling containers
2356 // every time, we should be able to use the scrollTop of the containers if the size of those
2357 // containers hasn't changed.
2358 var scrollContainerBounds = this._scrollables.map(function (scrollable) {
2359 return scrollable.getElementRef().nativeElement.getBoundingClientRect();
2360 });
2361 return {
2362 isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds),
2363 isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds),
2364 isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds),
2365 isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds),
2366 };
2367 };
2368 /** Subtracts the amount that an element is overflowing on an axis from its length. */
2369 FlexibleConnectedPositionStrategy.prototype._subtractOverflows = function (length) {
2370 var overflows = [];
2371 for (var _i = 1; _i < arguments.length; _i++) {
2372 overflows[_i - 1] = arguments[_i];
2373 }
2374 return overflows.reduce(function (currentValue, currentOverflow) {
2375 return currentValue - Math.max(currentOverflow, 0);
2376 }, length);
2377 };
2378 /** Narrows the given viewport rect by the current _viewportMargin. */
2379 FlexibleConnectedPositionStrategy.prototype._getNarrowedViewportRect = function () {
2380 // We recalculate the viewport rect here ourselves, rather than using the ViewportRuler,
2381 // because we want to use the `clientWidth` and `clientHeight` as the base. The difference
2382 // being that the client properties don't include the scrollbar, as opposed to `innerWidth`
2383 // and `innerHeight` that do. This is necessary, because the overlay container uses
2384 // 100% `width` and `height` which don't include the scrollbar either.
2385 var width = this._document.documentElement.clientWidth;
2386 var height = this._document.documentElement.clientHeight;
2387 var scrollPosition = this._viewportRuler.getViewportScrollPosition();
2388 return {
2389 top: scrollPosition.top + this._viewportMargin,
2390 left: scrollPosition.left + this._viewportMargin,
2391 right: scrollPosition.left + width - this._viewportMargin,
2392 bottom: scrollPosition.top + height - this._viewportMargin,
2393 width: width - (2 * this._viewportMargin),
2394 height: height - (2 * this._viewportMargin),
2395 };
2396 };
2397 /** Whether the we're dealing with an RTL context */
2398 FlexibleConnectedPositionStrategy.prototype._isRtl = function () {
2399 return this._overlayRef.getDirection() === 'rtl';
2400 };
2401 /** Determines whether the overlay uses exact or flexible positioning. */
2402 FlexibleConnectedPositionStrategy.prototype._hasExactPosition = function () {
2403 return !this._hasFlexibleDimensions || this._isPushed;
2404 };
2405 /** Retrieves the offset of a position along the x or y axis. */
2406 FlexibleConnectedPositionStrategy.prototype._getOffset = function (position, axis) {
2407 if (axis === 'x') {
2408 // We don't do something like `position['offset' + axis]` in
2409 // order to avoid breking minifiers that rename properties.
2410 return position.offsetX == null ? this._offsetX : position.offsetX;
2411 }
2412 return position.offsetY == null ? this._offsetY : position.offsetY;
2413 };
2414 /** Validates that the current position match the expected values. */
2415 FlexibleConnectedPositionStrategy.prototype._validatePositions = function () {
2416 if (typeof ngDevMode === 'undefined' || ngDevMode) {
2417 if (!this._preferredPositions.length) {
2418 throw Error('FlexibleConnectedPositionStrategy: At least one position is required.');
2419 }
2420 // TODO(crisbeto): remove these once Angular's template type
2421 // checking is advanced enough to catch these cases.
2422 this._preferredPositions.forEach(function (pair) {
2423 validateHorizontalPosition('originX', pair.originX);
2424 validateVerticalPosition('originY', pair.originY);
2425 validateHorizontalPosition('overlayX', pair.overlayX);
2426 validateVerticalPosition('overlayY', pair.overlayY);
2427 });
2428 }
2429 };
2430 /** Adds a single CSS class or an array of classes on the overlay panel. */
2431 FlexibleConnectedPositionStrategy.prototype._addPanelClasses = function (cssClasses) {
2432 var _this = this;
2433 if (this._pane) {
2434 coercion.coerceArray(cssClasses).forEach(function (cssClass) {
2435 if (cssClass !== '' && _this._appliedPanelClasses.indexOf(cssClass) === -1) {
2436 _this._appliedPanelClasses.push(cssClass);
2437 _this._pane.classList.add(cssClass);
2438 }
2439 });
2440 }
2441 };
2442 /** Clears the classes that the position strategy has applied from the overlay panel. */
2443 FlexibleConnectedPositionStrategy.prototype._clearPanelClasses = function () {
2444 var _this = this;
2445 if (this._pane) {
2446 this._appliedPanelClasses.forEach(function (cssClass) {
2447 _this._pane.classList.remove(cssClass);
2448 });
2449 this._appliedPanelClasses = [];
2450 }
2451 };
2452 /** Returns the ClientRect of the current origin. */
2453 FlexibleConnectedPositionStrategy.prototype._getOriginRect = function () {
2454 var origin = this._origin;
2455 if (origin instanceof i0.ElementRef) {
2456 return origin.nativeElement.getBoundingClientRect();
2457 }
2458 // Check for Element so SVG elements are also supported.
2459 if (origin instanceof Element) {
2460 return origin.getBoundingClientRect();
2461 }
2462 var width = origin.width || 0;
2463 var height = origin.height || 0;
2464 // If the origin is a point, return a client rect as if it was a 0x0 element at the point.
2465 return {
2466 top: origin.y,
2467 bottom: origin.y + height,
2468 left: origin.x,
2469 right: origin.x + width,
2470 height: height,
2471 width: width
2472 };
2473 };
2474 return FlexibleConnectedPositionStrategy;
2475 }());
2476 /** Shallow-extends a stylesheet object with another stylesheet object. */
2477 function extendStyles(destination, source) {
2478 for (var key in source) {
2479 if (source.hasOwnProperty(key)) {
2480 destination[key] = source[key];
2481 }
2482 }
2483 return destination;
2484 }
2485 /**
2486 * Extracts the pixel value as a number from a value, if it's a number
2487 * or a CSS pixel string (e.g. `1337px`). Otherwise returns null.
2488 */
2489 function getPixelValue(input) {
2490 if (typeof input !== 'number' && input != null) {
2491 var _a = __read(input.split(cssUnitPattern), 2), value = _a[0], units = _a[1];
2492 return (!units || units === 'px') ? parseFloat(value) : null;
2493 }
2494 return input || null;
2495 }
2496 /**
2497 * Gets a version of an element's bounding `ClientRect` where all the values are rounded down to
2498 * the nearest pixel. This allows us to account for the cases where there may be sub-pixel
2499 * deviations in the `ClientRect` returned by the browser (e.g. when zoomed in with a percentage
2500 * size, see #21350).
2501 */
2502 function getRoundedBoundingClientRect(clientRect) {
2503 return {
2504 top: Math.floor(clientRect.top),
2505 right: Math.floor(clientRect.right),
2506 bottom: Math.floor(clientRect.bottom),
2507 left: Math.floor(clientRect.left),
2508 width: Math.floor(clientRect.width),
2509 height: Math.floor(clientRect.height)
2510 };
2511 }
2512
2513 /**
2514 * @license
2515 * Copyright Google LLC All Rights Reserved.
2516 *
2517 * Use of this source code is governed by an MIT-style license that can be
2518 * found in the LICENSE file at https://angular.io/license
2519 */
2520 /**
2521 * A strategy for positioning overlays. Using this strategy, an overlay is given an
2522 * implicit position relative to some origin element. The relative position is defined in terms of
2523 * a point on the origin element that is connected to a point on the overlay element. For example,
2524 * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner
2525 * of the overlay.
2526 * @deprecated Use `FlexibleConnectedPositionStrategy` instead.
2527 * @breaking-change 8.0.0
2528 */
2529 var ConnectedPositionStrategy = /** @class */ (function () {
2530 function ConnectedPositionStrategy(originPos, overlayPos, connectedTo, viewportRuler, document, platform, overlayContainer) {
2531 /** Ordered list of preferred positions, from most to least desirable. */
2532 this._preferredPositions = [];
2533 // Since the `ConnectedPositionStrategy` is deprecated and we don't want to maintain
2534 // the extra logic, we create an instance of the positioning strategy that has some
2535 // defaults that make it behave as the old position strategy and to which we'll
2536 // proxy all of the API calls.
2537 this._positionStrategy = new FlexibleConnectedPositionStrategy(connectedTo, viewportRuler, document, platform, overlayContainer)
2538 .withFlexibleDimensions(false)
2539 .withPush(false)
2540 .withViewportMargin(0);
2541 this.withFallbackPosition(originPos, overlayPos);
2542 this.onPositionChange = this._positionStrategy.positionChanges;
2543 }
2544 Object.defineProperty(ConnectedPositionStrategy.prototype, "positions", {
2545 /** Ordered list of preferred positions, from most to least desirable. */
2546 get: function () {
2547 return this._preferredPositions;
2548 },
2549 enumerable: false,
2550 configurable: true
2551 });
2552 /** Attach this position strategy to an overlay. */
2553 ConnectedPositionStrategy.prototype.attach = function (overlayRef) {
2554 this._overlayRef = overlayRef;
2555 this._positionStrategy.attach(overlayRef);
2556 if (this._direction) {
2557 overlayRef.setDirection(this._direction);
2558 this._direction = null;
2559 }
2560 };
2561 /** Disposes all resources used by the position strategy. */
2562 ConnectedPositionStrategy.prototype.dispose = function () {
2563 this._positionStrategy.dispose();
2564 };
2565 /** @docs-private */
2566 ConnectedPositionStrategy.prototype.detach = function () {
2567 this._positionStrategy.detach();
2568 };
2569 /**
2570 * Updates the position of the overlay element, using whichever preferred position relative
2571 * to the origin fits on-screen.
2572 * @docs-private
2573 */
2574 ConnectedPositionStrategy.prototype.apply = function () {
2575 this._positionStrategy.apply();
2576 };
2577 /**
2578 * Re-positions the overlay element with the trigger in its last calculated position,
2579 * even if a position higher in the "preferred positions" list would now fit. This
2580 * allows one to re-align the panel without changing the orientation of the panel.
2581 */
2582 ConnectedPositionStrategy.prototype.recalculateLastPosition = function () {
2583 this._positionStrategy.reapplyLastPosition();
2584 };
2585 /**
2586 * Sets the list of Scrollable containers that host the origin element so that
2587 * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every
2588 * Scrollable must be an ancestor element of the strategy's origin element.
2589 */
2590 ConnectedPositionStrategy.prototype.withScrollableContainers = function (scrollables) {
2591 this._positionStrategy.withScrollableContainers(scrollables);
2592 };
2593 /**
2594 * Adds a new preferred fallback position.
2595 * @param originPos
2596 * @param overlayPos
2597 */
2598 ConnectedPositionStrategy.prototype.withFallbackPosition = function (originPos, overlayPos, offsetX, offsetY) {
2599 var position = new ConnectionPositionPair(originPos, overlayPos, offsetX, offsetY);
2600 this._preferredPositions.push(position);
2601 this._positionStrategy.withPositions(this._preferredPositions);
2602 return this;
2603 };
2604 /**
2605 * Sets the layout direction so the overlay's position can be adjusted to match.
2606 * @param dir New layout direction.
2607 */
2608 ConnectedPositionStrategy.prototype.withDirection = function (dir) {
2609 // Since the direction might be declared before the strategy is attached,
2610 // we save the value in a temporary property and we'll transfer it to the
2611 // overlay ref on attachment.
2612 if (this._overlayRef) {
2613 this._overlayRef.setDirection(dir);
2614 }
2615 else {
2616 this._direction = dir;
2617 }
2618 return this;
2619 };
2620 /**
2621 * Sets an offset for the overlay's connection point on the x-axis
2622 * @param offset New offset in the X axis.
2623 */
2624 ConnectedPositionStrategy.prototype.withOffsetX = function (offset) {
2625 this._positionStrategy.withDefaultOffsetX(offset);
2626 return this;
2627 };
2628 /**
2629 * Sets an offset for the overlay's connection point on the y-axis
2630 * @param offset New offset in the Y axis.
2631 */
2632 ConnectedPositionStrategy.prototype.withOffsetY = function (offset) {
2633 this._positionStrategy.withDefaultOffsetY(offset);
2634 return this;
2635 };
2636 /**
2637 * Sets whether the overlay's position should be locked in after it is positioned
2638 * initially. When an overlay is locked in, it won't attempt to reposition itself
2639 * when the position is re-applied (e.g. when the user scrolls away).
2640 * @param isLocked Whether the overlay should locked in.
2641 */
2642 ConnectedPositionStrategy.prototype.withLockedPosition = function (isLocked) {
2643 this._positionStrategy.withLockedPosition(isLocked);
2644 return this;
2645 };
2646 /**
2647 * Overwrites the current set of positions with an array of new ones.
2648 * @param positions Position pairs to be set on the strategy.
2649 */
2650 ConnectedPositionStrategy.prototype.withPositions = function (positions) {
2651 this._preferredPositions = positions.slice();
2652 this._positionStrategy.withPositions(this._preferredPositions);
2653 return this;
2654 };
2655 /**
2656 * Sets the origin element, relative to which to position the overlay.
2657 * @param origin Reference to the new origin element.
2658 */
2659 ConnectedPositionStrategy.prototype.setOrigin = function (origin) {
2660 this._positionStrategy.setOrigin(origin);
2661 return this;
2662 };
2663 return ConnectedPositionStrategy;
2664 }());
2665
2666 /**
2667 * @license
2668 * Copyright Google LLC All Rights Reserved.
2669 *
2670 * Use of this source code is governed by an MIT-style license that can be
2671 * found in the LICENSE file at https://angular.io/license
2672 */
2673 /** Class to be added to the overlay pane wrapper. */
2674 var wrapperClass = 'cdk-global-overlay-wrapper';
2675 /**
2676 * A strategy for positioning overlays. Using this strategy, an overlay is given an
2677 * explicit position relative to the browser's viewport. We use flexbox, instead of
2678 * transforms, in order to avoid issues with subpixel rendering which can cause the
2679 * element to become blurry.
2680 */
2681 var GlobalPositionStrategy = /** @class */ (function () {
2682 function GlobalPositionStrategy() {
2683 this._cssPosition = 'static';
2684 this._topOffset = '';
2685 this._bottomOffset = '';
2686 this._leftOffset = '';
2687 this._rightOffset = '';
2688 this._alignItems = '';
2689 this._justifyContent = '';
2690 this._width = '';
2691 this._height = '';
2692 }
2693 GlobalPositionStrategy.prototype.attach = function (overlayRef) {
2694 var config = overlayRef.getConfig();
2695 this._overlayRef = overlayRef;
2696 if (this._width && !config.width) {
2697 overlayRef.updateSize({ width: this._width });
2698 }
2699 if (this._height && !config.height) {
2700 overlayRef.updateSize({ height: this._height });
2701 }
2702 overlayRef.hostElement.classList.add(wrapperClass);
2703 this._isDisposed = false;
2704 };
2705 /**
2706 * Sets the top position of the overlay. Clears any previously set vertical position.
2707 * @param value New top offset.
2708 */
2709 GlobalPositionStrategy.prototype.top = function (value) {
2710 if (value === void 0) { value = ''; }
2711 this._bottomOffset = '';
2712 this._topOffset = value;
2713 this._alignItems = 'flex-start';
2714 return this;
2715 };
2716 /**
2717 * Sets the left position of the overlay. Clears any previously set horizontal position.
2718 * @param value New left offset.
2719 */
2720 GlobalPositionStrategy.prototype.left = function (value) {
2721 if (value === void 0) { value = ''; }
2722 this._rightOffset = '';
2723 this._leftOffset = value;
2724 this._justifyContent = 'flex-start';
2725 return this;
2726 };
2727 /**
2728 * Sets the bottom position of the overlay. Clears any previously set vertical position.
2729 * @param value New bottom offset.
2730 */
2731 GlobalPositionStrategy.prototype.bottom = function (value) {
2732 if (value === void 0) { value = ''; }
2733 this._topOffset = '';
2734 this._bottomOffset = value;
2735 this._alignItems = 'flex-end';
2736 return this;
2737 };
2738 /**
2739 * Sets the right position of the overlay. Clears any previously set horizontal position.
2740 * @param value New right offset.
2741 */
2742 GlobalPositionStrategy.prototype.right = function (value) {
2743 if (value === void 0) { value = ''; }
2744 this._leftOffset = '';
2745 this._rightOffset = value;
2746 this._justifyContent = 'flex-end';
2747 return this;
2748 };
2749 /**
2750 * Sets the overlay width and clears any previously set width.
2751 * @param value New width for the overlay
2752 * @deprecated Pass the `width` through the `OverlayConfig`.
2753 * @breaking-change 8.0.0
2754 */
2755 GlobalPositionStrategy.prototype.width = function (value) {
2756 if (value === void 0) { value = ''; }
2757 if (this._overlayRef) {
2758 this._overlayRef.updateSize({ width: value });
2759 }
2760 else {
2761 this._width = value;
2762 }
2763 return this;
2764 };
2765 /**
2766 * Sets the overlay height and clears any previously set height.
2767 * @param value New height for the overlay
2768 * @deprecated Pass the `height` through the `OverlayConfig`.
2769 * @breaking-change 8.0.0
2770 */
2771 GlobalPositionStrategy.prototype.height = function (value) {
2772 if (value === void 0) { value = ''; }
2773 if (this._overlayRef) {
2774 this._overlayRef.updateSize({ height: value });
2775 }
2776 else {
2777 this._height = value;
2778 }
2779 return this;
2780 };
2781 /**
2782 * Centers the overlay horizontally with an optional offset.
2783 * Clears any previously set horizontal position.
2784 *
2785 * @param offset Overlay offset from the horizontal center.
2786 */
2787 GlobalPositionStrategy.prototype.centerHorizontally = function (offset) {
2788 if (offset === void 0) { offset = ''; }
2789 this.left(offset);
2790 this._justifyContent = 'center';
2791 return this;
2792 };
2793 /**
2794 * Centers the overlay vertically with an optional offset.
2795 * Clears any previously set vertical position.
2796 *
2797 * @param offset Overlay offset from the vertical center.
2798 */
2799 GlobalPositionStrategy.prototype.centerVertically = function (offset) {
2800 if (offset === void 0) { offset = ''; }
2801 this.top(offset);
2802 this._alignItems = 'center';
2803 return this;
2804 };
2805 /**
2806 * Apply the position to the element.
2807 * @docs-private
2808 */
2809 GlobalPositionStrategy.prototype.apply = function () {
2810 // Since the overlay ref applies the strategy asynchronously, it could
2811 // have been disposed before it ends up being applied. If that is the
2812 // case, we shouldn't do anything.
2813 if (!this._overlayRef || !this._overlayRef.hasAttached()) {
2814 return;
2815 }
2816 var styles = this._overlayRef.overlayElement.style;
2817 var parentStyles = this._overlayRef.hostElement.style;
2818 var config = this._overlayRef.getConfig();
2819 var width = config.width, height = config.height, maxWidth = config.maxWidth, maxHeight = config.maxHeight;
2820 var shouldBeFlushHorizontally = (width === '100%' || width === '100vw') &&
2821 (!maxWidth || maxWidth === '100%' || maxWidth === '100vw');
2822 var shouldBeFlushVertically = (height === '100%' || height === '100vh') &&
2823 (!maxHeight || maxHeight === '100%' || maxHeight === '100vh');
2824 styles.position = this._cssPosition;
2825 styles.marginLeft = shouldBeFlushHorizontally ? '0' : this._leftOffset;
2826 styles.marginTop = shouldBeFlushVertically ? '0' : this._topOffset;
2827 styles.marginBottom = this._bottomOffset;
2828 styles.marginRight = this._rightOffset;
2829 if (shouldBeFlushHorizontally) {
2830 parentStyles.justifyContent = 'flex-start';
2831 }
2832 else if (this._justifyContent === 'center') {
2833 parentStyles.justifyContent = 'center';
2834 }
2835 else if (this._overlayRef.getConfig().direction === 'rtl') {
2836 // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we
2837 // don't want that because our positioning is explicitly `left` and `right`, hence
2838 // why we do another inversion to ensure that the overlay stays in the same position.
2839 // TODO: reconsider this if we add `start` and `end` methods.
2840 if (this._justifyContent === 'flex-start') {
2841 parentStyles.justifyContent = 'flex-end';
2842 }
2843 else if (this._justifyContent === 'flex-end') {
2844 parentStyles.justifyContent = 'flex-start';
2845 }
2846 }
2847 else {
2848 parentStyles.justifyContent = this._justifyContent;
2849 }
2850 parentStyles.alignItems = shouldBeFlushVertically ? 'flex-start' : this._alignItems;
2851 };
2852 /**
2853 * Cleans up the DOM changes from the position strategy.
2854 * @docs-private
2855 */
2856 GlobalPositionStrategy.prototype.dispose = function () {
2857 if (this._isDisposed || !this._overlayRef) {
2858 return;
2859 }
2860 var styles = this._overlayRef.overlayElement.style;
2861 var parent = this._overlayRef.hostElement;
2862 var parentStyles = parent.style;
2863 parent.classList.remove(wrapperClass);
2864 parentStyles.justifyContent = parentStyles.alignItems = styles.marginTop =
2865 styles.marginBottom = styles.marginLeft = styles.marginRight = styles.position = '';
2866 this._overlayRef = null;
2867 this._isDisposed = true;
2868 };
2869 return GlobalPositionStrategy;
2870 }());
2871
2872 /**
2873 * @license
2874 * Copyright Google LLC All Rights Reserved.
2875 *
2876 * Use of this source code is governed by an MIT-style license that can be
2877 * found in the LICENSE file at https://angular.io/license
2878 */
2879 /** Builder for overlay position strategy. */
2880 var OverlayPositionBuilder = /** @class */ (function () {
2881 function OverlayPositionBuilder(_viewportRuler, _document, _platform, _overlayContainer) {
2882 this._viewportRuler = _viewportRuler;
2883 this._document = _document;
2884 this._platform = _platform;
2885 this._overlayContainer = _overlayContainer;
2886 }
2887 /**
2888 * Creates a global position strategy.
2889 */
2890 OverlayPositionBuilder.prototype.global = function () {
2891 return new GlobalPositionStrategy();
2892 };
2893 /**
2894 * Creates a relative position strategy.
2895 * @param elementRef
2896 * @param originPos
2897 * @param overlayPos
2898 * @deprecated Use `flexibleConnectedTo` instead.
2899 * @breaking-change 8.0.0
2900 */
2901 OverlayPositionBuilder.prototype.connectedTo = function (elementRef, originPos, overlayPos) {
2902 return new ConnectedPositionStrategy(originPos, overlayPos, elementRef, this._viewportRuler, this._document, this._platform, this._overlayContainer);
2903 };
2904 /**
2905 * Creates a flexible position strategy.
2906 * @param origin Origin relative to which to position the overlay.
2907 */
2908 OverlayPositionBuilder.prototype.flexibleConnectedTo = function (origin) {
2909 return new FlexibleConnectedPositionStrategy(origin, this._viewportRuler, this._document, this._platform, this._overlayContainer);
2910 };
2911 return OverlayPositionBuilder;
2912 }());
2913 OverlayPositionBuilder.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function OverlayPositionBuilder_Factory() { return new OverlayPositionBuilder(i0__namespace.ɵɵinject(i1__namespace.ViewportRuler), i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT), i0__namespace.ɵɵinject(i2__namespace.Platform), i0__namespace.ɵɵinject(OverlayContainer)); }, token: OverlayPositionBuilder, providedIn: "root" });
2914 OverlayPositionBuilder.decorators = [
2915 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2916 ];
2917 OverlayPositionBuilder.ctorParameters = function () { return [
2918 { type: i1.ViewportRuler },
2919 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
2920 { type: i2.Platform },
2921 { type: OverlayContainer }
2922 ]; };
2923
2924 /**
2925 * @license
2926 * Copyright Google LLC All Rights Reserved.
2927 *
2928 * Use of this source code is governed by an MIT-style license that can be
2929 * found in the LICENSE file at https://angular.io/license
2930 */
2931 /** Next overlay unique ID. */
2932 var nextUniqueId = 0;
2933 // Note that Overlay is *not* scoped to the app root because of the ComponentFactoryResolver
2934 // which needs to be different depending on where OverlayModule is imported.
2935 /**
2936 * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be
2937 * used as a low-level building block for other components. Dialogs, tooltips, menus,
2938 * selects, etc. can all be built using overlays. The service should primarily be used by authors
2939 * of re-usable components rather than developers building end-user applications.
2940 *
2941 * An overlay *is* a PortalOutlet, so any kind of Portal can be loaded into one.
2942 */
2943 var Overlay = /** @class */ (function () {
2944 function Overlay(
2945 /** Scrolling strategies that can be used when creating an overlay. */
2946 scrollStrategies, _overlayContainer, _componentFactoryResolver, _positionBuilder, _keyboardDispatcher, _injector, _ngZone, _document, _directionality, _location, _outsideClickDispatcher) {
2947 this.scrollStrategies = scrollStrategies;
2948 this._overlayContainer = _overlayContainer;
2949 this._componentFactoryResolver = _componentFactoryResolver;
2950 this._positionBuilder = _positionBuilder;
2951 this._keyboardDispatcher = _keyboardDispatcher;
2952 this._injector = _injector;
2953 this._ngZone = _ngZone;
2954 this._document = _document;
2955 this._directionality = _directionality;
2956 this._location = _location;
2957 this._outsideClickDispatcher = _outsideClickDispatcher;
2958 }
2959 /**
2960 * Creates an overlay.
2961 * @param config Configuration applied to the overlay.
2962 * @returns Reference to the created overlay.
2963 */
2964 Overlay.prototype.create = function (config) {
2965 var host = this._createHostElement();
2966 var pane = this._createPaneElement(host);
2967 var portalOutlet = this._createPortalOutlet(pane);
2968 var overlayConfig = new OverlayConfig(config);
2969 overlayConfig.direction = overlayConfig.direction || this._directionality.value;
2970 return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location, this._outsideClickDispatcher);
2971 };
2972 /**
2973 * Gets a position builder that can be used, via fluent API,
2974 * to construct and configure a position strategy.
2975 * @returns An overlay position builder.
2976 */
2977 Overlay.prototype.position = function () {
2978 return this._positionBuilder;
2979 };
2980 /**
2981 * Creates the DOM element for an overlay and appends it to the overlay container.
2982 * @returns Newly-created pane element
2983 */
2984 Overlay.prototype._createPaneElement = function (host) {
2985 var pane = this._document.createElement('div');
2986 pane.id = "cdk-overlay-" + nextUniqueId++;
2987 pane.classList.add('cdk-overlay-pane');
2988 host.appendChild(pane);
2989 return pane;
2990 };
2991 /**
2992 * Creates the host element that wraps around an overlay
2993 * and can be used for advanced positioning.
2994 * @returns Newly-create host element.
2995 */
2996 Overlay.prototype._createHostElement = function () {
2997 var host = this._document.createElement('div');
2998 this._overlayContainer.getContainerElement().appendChild(host);
2999 return host;
3000 };
3001 /**
3002 * Create a DomPortalOutlet into which the overlay content can be loaded.
3003 * @param pane The DOM element to turn into a portal outlet.
3004 * @returns A portal outlet for the given DOM element.
3005 */
3006 Overlay.prototype._createPortalOutlet = function (pane) {
3007 // We have to resolve the ApplicationRef later in order to allow people
3008 // to use overlay-based providers during app initialization.
3009 if (!this._appRef) {
3010 this._appRef = this._injector.get(i0.ApplicationRef);
3011 }
3012 return new portal.DomPortalOutlet(pane, this._componentFactoryResolver, this._appRef, this._injector, this._document);
3013 };
3014 return Overlay;
3015 }());
3016 Overlay.decorators = [
3017 { type: i0.Injectable }
3018 ];
3019 Overlay.ctorParameters = function () { return [
3020 { type: ScrollStrategyOptions },
3021 { type: OverlayContainer },
3022 { type: i0.ComponentFactoryResolver },
3023 { type: OverlayPositionBuilder },
3024 { type: OverlayKeyboardDispatcher },
3025 { type: i0.Injector },
3026 { type: i0.NgZone },
3027 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
3028 { type: bidi.Directionality },
3029 { type: i1$1.Location },
3030 { type: OverlayOutsideClickDispatcher }
3031 ]; };
3032
3033 /**
3034 * @license
3035 * Copyright Google LLC All Rights Reserved.
3036 *
3037 * Use of this source code is governed by an MIT-style license that can be
3038 * found in the LICENSE file at https://angular.io/license
3039 */
3040 /** Default set of positions for the overlay. Follows the behavior of a dropdown. */
3041 var defaultPositionList = [
3042 {
3043 originX: 'start',
3044 originY: 'bottom',
3045 overlayX: 'start',
3046 overlayY: 'top'
3047 },
3048 {
3049 originX: 'start',
3050 originY: 'top',
3051 overlayX: 'start',
3052 overlayY: 'bottom'
3053 },
3054 {
3055 originX: 'end',
3056 originY: 'top',
3057 overlayX: 'end',
3058 overlayY: 'bottom'
3059 },
3060 {
3061 originX: 'end',
3062 originY: 'bottom',
3063 overlayX: 'end',
3064 overlayY: 'top'
3065 }
3066 ];
3067 /** Injection token that determines the scroll handling while the connected overlay is open. */
3068 var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = new i0.InjectionToken('cdk-connected-overlay-scroll-strategy');
3069 /**
3070 * Directive applied to an element to make it usable as an origin for an Overlay using a
3071 * ConnectedPositionStrategy.
3072 */
3073 var CdkOverlayOrigin = /** @class */ (function () {
3074 function CdkOverlayOrigin(
3075 /** Reference to the element on which the directive is applied. */
3076 elementRef) {
3077 this.elementRef = elementRef;
3078 }
3079 return CdkOverlayOrigin;
3080 }());
3081 CdkOverlayOrigin.decorators = [
3082 { type: i0.Directive, args: [{
3083 selector: '[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]',
3084 exportAs: 'cdkOverlayOrigin',
3085 },] }
3086 ];
3087 CdkOverlayOrigin.ctorParameters = function () { return [
3088 { type: i0.ElementRef }
3089 ]; };
3090 /**
3091 * Directive to facilitate declarative creation of an
3092 * Overlay using a FlexibleConnectedPositionStrategy.
3093 */
3094 var CdkConnectedOverlay = /** @class */ (function () {
3095 // TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
3096 function CdkConnectedOverlay(_overlay, templateRef, viewContainerRef, scrollStrategyFactory, _dir) {
3097 this._overlay = _overlay;
3098 this._dir = _dir;
3099 this._hasBackdrop = false;
3100 this._lockPosition = false;
3101 this._growAfterOpen = false;
3102 this._flexibleDimensions = false;
3103 this._push = false;
3104 this._backdropSubscription = rxjs.Subscription.EMPTY;
3105 this._attachSubscription = rxjs.Subscription.EMPTY;
3106 this._detachSubscription = rxjs.Subscription.EMPTY;
3107 this._positionSubscription = rxjs.Subscription.EMPTY;
3108 /** Margin between the overlay and the viewport edges. */
3109 this.viewportMargin = 0;
3110 /** Whether the overlay is open. */
3111 this.open = false;
3112 /** Whether the overlay can be closed by user interaction. */
3113 this.disableClose = false;
3114 /** Event emitted when the backdrop is clicked. */
3115 this.backdropClick = new i0.EventEmitter();
3116 /** Event emitted when the position has changed. */
3117 this.positionChange = new i0.EventEmitter();
3118 /** Event emitted when the overlay has been attached. */
3119 this.attach = new i0.EventEmitter();
3120 /** Event emitted when the overlay has been detached. */
3121 this.detach = new i0.EventEmitter();
3122 /** Emits when there are keyboard events that are targeted at the overlay. */
3123 this.overlayKeydown = new i0.EventEmitter();
3124 /** Emits when there are mouse outside click events that are targeted at the overlay. */
3125 this.overlayOutsideClick = new i0.EventEmitter();
3126 this._templatePortal = new portal.TemplatePortal(templateRef, viewContainerRef);
3127 this._scrollStrategyFactory = scrollStrategyFactory;
3128 this.scrollStrategy = this._scrollStrategyFactory();
3129 }
3130 Object.defineProperty(CdkConnectedOverlay.prototype, "offsetX", {
3131 /** The offset in pixels for the overlay connection point on the x-axis */
3132 get: function () { return this._offsetX; },
3133 set: function (offsetX) {
3134 this._offsetX = offsetX;
3135 if (this._position) {
3136 this._updatePositionStrategy(this._position);
3137 }
3138 },
3139 enumerable: false,
3140 configurable: true
3141 });
3142 Object.defineProperty(CdkConnectedOverlay.prototype, "offsetY", {
3143 /** The offset in pixels for the overlay connection point on the y-axis */
3144 get: function () { return this._offsetY; },
3145 set: function (offsetY) {
3146 this._offsetY = offsetY;
3147 if (this._position) {
3148 this._updatePositionStrategy(this._position);
3149 }
3150 },
3151 enumerable: false,
3152 configurable: true
3153 });
3154 Object.defineProperty(CdkConnectedOverlay.prototype, "hasBackdrop", {
3155 /** Whether or not the overlay should attach a backdrop. */
3156 get: function () { return this._hasBackdrop; },
3157 set: function (value) { this._hasBackdrop = coercion.coerceBooleanProperty(value); },
3158 enumerable: false,
3159 configurable: true
3160 });
3161 Object.defineProperty(CdkConnectedOverlay.prototype, "lockPosition", {
3162 /** Whether or not the overlay should be locked when scrolling. */
3163 get: function () { return this._lockPosition; },
3164 set: function (value) { this._lockPosition = coercion.coerceBooleanProperty(value); },
3165 enumerable: false,
3166 configurable: true
3167 });
3168 Object.defineProperty(CdkConnectedOverlay.prototype, "flexibleDimensions", {
3169 /** Whether the overlay's width and height can be constrained to fit within the viewport. */
3170 get: function () { return this._flexibleDimensions; },
3171 set: function (value) {
3172 this._flexibleDimensions = coercion.coerceBooleanProperty(value);
3173 },
3174 enumerable: false,
3175 configurable: true
3176 });
3177 Object.defineProperty(CdkConnectedOverlay.prototype, "growAfterOpen", {
3178 /** Whether the overlay can grow after the initial open when flexible positioning is turned on. */
3179 get: function () { return this._growAfterOpen; },
3180 set: function (value) { this._growAfterOpen = coercion.coerceBooleanProperty(value); },
3181 enumerable: false,
3182 configurable: true
3183 });
3184 Object.defineProperty(CdkConnectedOverlay.prototype, "push", {
3185 /** Whether the overlay can be pushed on-screen if none of the provided positions fit. */
3186 get: function () { return this._push; },
3187 set: function (value) { this._push = coercion.coerceBooleanProperty(value); },
3188 enumerable: false,
3189 configurable: true
3190 });
3191 Object.defineProperty(CdkConnectedOverlay.prototype, "overlayRef", {
3192 /** The associated overlay reference. */
3193 get: function () {
3194 return this._overlayRef;
3195 },
3196 enumerable: false,
3197 configurable: true
3198 });
3199 Object.defineProperty(CdkConnectedOverlay.prototype, "dir", {
3200 /** The element's layout direction. */
3201 get: function () {
3202 return this._dir ? this._dir.value : 'ltr';
3203 },
3204 enumerable: false,
3205 configurable: true
3206 });
3207 CdkConnectedOverlay.prototype.ngOnDestroy = function () {
3208 this._attachSubscription.unsubscribe();
3209 this._detachSubscription.unsubscribe();
3210 this._backdropSubscription.unsubscribe();
3211 this._positionSubscription.unsubscribe();
3212 if (this._overlayRef) {
3213 this._overlayRef.dispose();
3214 }
3215 };
3216 CdkConnectedOverlay.prototype.ngOnChanges = function (changes) {
3217 if (this._position) {
3218 this._updatePositionStrategy(this._position);
3219 this._overlayRef.updateSize({
3220 width: this.width,
3221 minWidth: this.minWidth,
3222 height: this.height,
3223 minHeight: this.minHeight,
3224 });
3225 if (changes['origin'] && this.open) {
3226 this._position.apply();
3227 }
3228 }
3229 if (changes['open']) {
3230 this.open ? this._attachOverlay() : this._detachOverlay();
3231 }
3232 };
3233 /** Creates an overlay */
3234 CdkConnectedOverlay.prototype._createOverlay = function () {
3235 var _this = this;
3236 if (!this.positions || !this.positions.length) {
3237 this.positions = defaultPositionList;
3238 }
3239 var overlayRef = this._overlayRef = this._overlay.create(this._buildConfig());
3240 this._attachSubscription = overlayRef.attachments().subscribe(function () { return _this.attach.emit(); });
3241 this._detachSubscription = overlayRef.detachments().subscribe(function () { return _this.detach.emit(); });
3242 overlayRef.keydownEvents().subscribe(function (event) {
3243 _this.overlayKeydown.next(event);
3244 if (event.keyCode === keycodes.ESCAPE && !_this.disableClose && !keycodes.hasModifierKey(event)) {
3245 event.preventDefault();
3246 _this._detachOverlay();
3247 }
3248 });
3249 this._overlayRef.outsidePointerEvents().subscribe(function (event) {
3250 _this.overlayOutsideClick.next(event);
3251 });
3252 };
3253 /** Builds the overlay config based on the directive's inputs */
3254 CdkConnectedOverlay.prototype._buildConfig = function () {
3255 var positionStrategy = this._position =
3256 this.positionStrategy || this._createPositionStrategy();
3257 var overlayConfig = new OverlayConfig({
3258 direction: this._dir,
3259 positionStrategy: positionStrategy,
3260 scrollStrategy: this.scrollStrategy,
3261 hasBackdrop: this.hasBackdrop
3262 });
3263 if (this.width || this.width === 0) {
3264 overlayConfig.width = this.width;
3265 }
3266 if (this.height || this.height === 0) {
3267 overlayConfig.height = this.height;
3268 }
3269 if (this.minWidth || this.minWidth === 0) {
3270 overlayConfig.minWidth = this.minWidth;
3271 }
3272 if (this.minHeight || this.minHeight === 0) {
3273 overlayConfig.minHeight = this.minHeight;
3274 }
3275 if (this.backdropClass) {
3276 overlayConfig.backdropClass = this.backdropClass;
3277 }
3278 if (this.panelClass) {
3279 overlayConfig.panelClass = this.panelClass;
3280 }
3281 return overlayConfig;
3282 };
3283 /** Updates the state of a position strategy, based on the values of the directive inputs. */
3284 CdkConnectedOverlay.prototype._updatePositionStrategy = function (positionStrategy) {
3285 var _this = this;
3286 var positions = this.positions.map(function (currentPosition) { return ({
3287 originX: currentPosition.originX,
3288 originY: currentPosition.originY,
3289 overlayX: currentPosition.overlayX,
3290 overlayY: currentPosition.overlayY,
3291 offsetX: currentPosition.offsetX || _this.offsetX,
3292 offsetY: currentPosition.offsetY || _this.offsetY,
3293 panelClass: currentPosition.panelClass || undefined,
3294 }); });
3295 return positionStrategy
3296 .setOrigin(this.origin.elementRef)
3297 .withPositions(positions)
3298 .withFlexibleDimensions(this.flexibleDimensions)
3299 .withPush(this.push)
3300 .withGrowAfterOpen(this.growAfterOpen)
3301 .withViewportMargin(this.viewportMargin)
3302 .withLockedPosition(this.lockPosition)
3303 .withTransformOriginOn(this.transformOriginSelector);
3304 };
3305 /** Returns the position strategy of the overlay to be set on the overlay config */
3306 CdkConnectedOverlay.prototype._createPositionStrategy = function () {
3307 var strategy = this._overlay.position().flexibleConnectedTo(this.origin.elementRef);
3308 this._updatePositionStrategy(strategy);
3309 return strategy;
3310 };
3311 /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */
3312 CdkConnectedOverlay.prototype._attachOverlay = function () {
3313 var _this = this;
3314 if (!this._overlayRef) {
3315 this._createOverlay();
3316 }
3317 else {
3318 // Update the overlay size, in case the directive's inputs have changed
3319 this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop;
3320 }
3321 if (!this._overlayRef.hasAttached()) {
3322 this._overlayRef.attach(this._templatePortal);
3323 }
3324 if (this.hasBackdrop) {
3325 this._backdropSubscription = this._overlayRef.backdropClick().subscribe(function (event) {
3326 _this.backdropClick.emit(event);
3327 });
3328 }
3329 else {
3330 this._backdropSubscription.unsubscribe();
3331 }
3332 this._positionSubscription.unsubscribe();
3333 // Only subscribe to `positionChanges` if requested, because putting
3334 // together all the information for it can be expensive.
3335 if (this.positionChange.observers.length > 0) {
3336 this._positionSubscription = this._position.positionChanges
3337 .pipe(operators.takeWhile(function () { return _this.positionChange.observers.length > 0; }))
3338 .subscribe(function (position) {
3339 _this.positionChange.emit(position);
3340 if (_this.positionChange.observers.length === 0) {
3341 _this._positionSubscription.unsubscribe();
3342 }
3343 });
3344 }
3345 };
3346 /** Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists */
3347 CdkConnectedOverlay.prototype._detachOverlay = function () {
3348 if (this._overlayRef) {
3349 this._overlayRef.detach();
3350 }
3351 this._backdropSubscription.unsubscribe();
3352 this._positionSubscription.unsubscribe();
3353 };
3354 return CdkConnectedOverlay;
3355 }());
3356 CdkConnectedOverlay.decorators = [
3357 { type: i0.Directive, args: [{
3358 selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]',
3359 exportAs: 'cdkConnectedOverlay'
3360 },] }
3361 ];
3362 CdkConnectedOverlay.ctorParameters = function () { return [
3363 { type: Overlay },
3364 { type: i0.TemplateRef },
3365 { type: i0.ViewContainerRef },
3366 { type: undefined, decorators: [{ type: i0.Inject, args: [CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,] }] },
3367 { type: bidi.Directionality, decorators: [{ type: i0.Optional }] }
3368 ]; };
3369 CdkConnectedOverlay.propDecorators = {
3370 origin: [{ type: i0.Input, args: ['cdkConnectedOverlayOrigin',] }],
3371 positions: [{ type: i0.Input, args: ['cdkConnectedOverlayPositions',] }],
3372 positionStrategy: [{ type: i0.Input, args: ['cdkConnectedOverlayPositionStrategy',] }],
3373 offsetX: [{ type: i0.Input, args: ['cdkConnectedOverlayOffsetX',] }],
3374 offsetY: [{ type: i0.Input, args: ['cdkConnectedOverlayOffsetY',] }],
3375 width: [{ type: i0.Input, args: ['cdkConnectedOverlayWidth',] }],
3376 height: [{ type: i0.Input, args: ['cdkConnectedOverlayHeight',] }],
3377 minWidth: [{ type: i0.Input, args: ['cdkConnectedOverlayMinWidth',] }],
3378 minHeight: [{ type: i0.Input, args: ['cdkConnectedOverlayMinHeight',] }],
3379 backdropClass: [{ type: i0.Input, args: ['cdkConnectedOverlayBackdropClass',] }],
3380 panelClass: [{ type: i0.Input, args: ['cdkConnectedOverlayPanelClass',] }],
3381 viewportMargin: [{ type: i0.Input, args: ['cdkConnectedOverlayViewportMargin',] }],
3382 scrollStrategy: [{ type: i0.Input, args: ['cdkConnectedOverlayScrollStrategy',] }],
3383 open: [{ type: i0.Input, args: ['cdkConnectedOverlayOpen',] }],
3384 disableClose: [{ type: i0.Input, args: ['cdkConnectedOverlayDisableClose',] }],
3385 transformOriginSelector: [{ type: i0.Input, args: ['cdkConnectedOverlayTransformOriginOn',] }],
3386 hasBackdrop: [{ type: i0.Input, args: ['cdkConnectedOverlayHasBackdrop',] }],
3387 lockPosition: [{ type: i0.Input, args: ['cdkConnectedOverlayLockPosition',] }],
3388 flexibleDimensions: [{ type: i0.Input, args: ['cdkConnectedOverlayFlexibleDimensions',] }],
3389 growAfterOpen: [{ type: i0.Input, args: ['cdkConnectedOverlayGrowAfterOpen',] }],
3390 push: [{ type: i0.Input, args: ['cdkConnectedOverlayPush',] }],
3391 backdropClick: [{ type: i0.Output }],
3392 positionChange: [{ type: i0.Output }],
3393 attach: [{ type: i0.Output }],
3394 detach: [{ type: i0.Output }],
3395 overlayKeydown: [{ type: i0.Output }],
3396 overlayOutsideClick: [{ type: i0.Output }]
3397 };
3398 /** @docs-private */
3399 function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) {
3400 return function () { return overlay.scrollStrategies.reposition(); };
3401 }
3402 /** @docs-private */
3403 var CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = {
3404 provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,
3405 deps: [Overlay],
3406 useFactory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY,
3407 };
3408
3409 /**
3410 * @license
3411 * Copyright Google LLC All Rights Reserved.
3412 *
3413 * Use of this source code is governed by an MIT-style license that can be
3414 * found in the LICENSE file at https://angular.io/license
3415 */
3416 var OverlayModule = /** @class */ (function () {
3417 function OverlayModule() {
3418 }
3419 return OverlayModule;
3420 }());
3421 OverlayModule.decorators = [
3422 { type: i0.NgModule, args: [{
3423 imports: [bidi.BidiModule, portal.PortalModule, i1.ScrollingModule],
3424 exports: [CdkConnectedOverlay, CdkOverlayOrigin, i1.ScrollingModule],
3425 declarations: [CdkConnectedOverlay, CdkOverlayOrigin],
3426 providers: [
3427 Overlay,
3428 CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER,
3429 ],
3430 },] }
3431 ];
3432
3433 /**
3434 * @license
3435 * Copyright Google LLC All Rights Reserved.
3436 *
3437 * Use of this source code is governed by an MIT-style license that can be
3438 * found in the LICENSE file at https://angular.io/license
3439 */
3440
3441 /**
3442 * Alternative to OverlayContainer that supports correct displaying of overlay elements in
3443 * Fullscreen mode
3444 * https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen
3445 *
3446 * Should be provided in the root component.
3447 */
3448 var FullscreenOverlayContainer = /** @class */ (function (_super) {
3449 __extends(FullscreenOverlayContainer, _super);
3450 function FullscreenOverlayContainer(_document, platform) {
3451 return _super.call(this, _document, platform) || this;
3452 }
3453 FullscreenOverlayContainer.prototype.ngOnDestroy = function () {
3454 _super.prototype.ngOnDestroy.call(this);
3455 if (this._fullScreenEventName && this._fullScreenListener) {
3456 this._document.removeEventListener(this._fullScreenEventName, this._fullScreenListener);
3457 }
3458 };
3459 FullscreenOverlayContainer.prototype._createContainer = function () {
3460 var _this = this;
3461 _super.prototype._createContainer.call(this);
3462 this._adjustParentForFullscreenChange();
3463 this._addFullscreenChangeListener(function () { return _this._adjustParentForFullscreenChange(); });
3464 };
3465 FullscreenOverlayContainer.prototype._adjustParentForFullscreenChange = function () {
3466 if (!this._containerElement) {
3467 return;
3468 }
3469 var fullscreenElement = this.getFullscreenElement();
3470 var parent = fullscreenElement || this._document.body;
3471 parent.appendChild(this._containerElement);
3472 };
3473 FullscreenOverlayContainer.prototype._addFullscreenChangeListener = function (fn) {
3474 var eventName = this._getEventName();
3475 if (eventName) {
3476 if (this._fullScreenListener) {
3477 this._document.removeEventListener(eventName, this._fullScreenListener);
3478 }
3479 this._document.addEventListener(eventName, fn);
3480 this._fullScreenListener = fn;
3481 }
3482 };
3483 FullscreenOverlayContainer.prototype._getEventName = function () {
3484 if (!this._fullScreenEventName) {
3485 var _document = this._document;
3486 if (_document.fullscreenEnabled) {
3487 this._fullScreenEventName = 'fullscreenchange';
3488 }
3489 else if (_document.webkitFullscreenEnabled) {
3490 this._fullScreenEventName = 'webkitfullscreenchange';
3491 }
3492 else if (_document.mozFullScreenEnabled) {
3493 this._fullScreenEventName = 'mozfullscreenchange';
3494 }
3495 else if (_document.msFullscreenEnabled) {
3496 this._fullScreenEventName = 'MSFullscreenChange';
3497 }
3498 }
3499 return this._fullScreenEventName;
3500 };
3501 /**
3502 * When the page is put into fullscreen mode, a specific element is specified.
3503 * Only that element and its children are visible when in fullscreen mode.
3504 */
3505 FullscreenOverlayContainer.prototype.getFullscreenElement = function () {
3506 var _document = this._document;
3507 return _document.fullscreenElement ||
3508 _document.webkitFullscreenElement ||
3509 _document.mozFullScreenElement ||
3510 _document.msFullscreenElement ||
3511 null;
3512 };
3513 return FullscreenOverlayContainer;
3514 }(OverlayContainer));
3515 FullscreenOverlayContainer.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FullscreenOverlayContainer_Factory() { return new FullscreenOverlayContainer(i0__namespace.ɵɵinject(i1__namespace$1.DOCUMENT), i0__namespace.ɵɵinject(i2__namespace.Platform)); }, token: FullscreenOverlayContainer, providedIn: "root" });
3516 FullscreenOverlayContainer.decorators = [
3517 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3518 ];
3519 FullscreenOverlayContainer.ctorParameters = function () { return [
3520 { type: undefined, decorators: [{ type: i0.Inject, args: [i1$1.DOCUMENT,] }] },
3521 { type: i2.Platform }
3522 ]; };
3523
3524 /**
3525 * @license
3526 * Copyright Google LLC All Rights Reserved.
3527 *
3528 * Use of this source code is governed by an MIT-style license that can be
3529 * found in the LICENSE file at https://angular.io/license
3530 */
3531
3532 /**
3533 * Generated bundle index. Do not edit.
3534 */
3535
3536 Object.defineProperty(exports, 'CdkScrollable', {
3537 enumerable: true,
3538 get: function () {
3539 return i1.CdkScrollable;
3540 }
3541 });
3542 Object.defineProperty(exports, 'ScrollDispatcher', {
3543 enumerable: true,
3544 get: function () {
3545 return i1.ScrollDispatcher;
3546 }
3547 });
3548 Object.defineProperty(exports, 'ViewportRuler', {
3549 enumerable: true,
3550 get: function () {
3551 return i1.ViewportRuler;
3552 }
3553 });
3554 exports.BlockScrollStrategy = BlockScrollStrategy;
3555 exports.CdkConnectedOverlay = CdkConnectedOverlay;
3556 exports.CdkOverlayOrigin = CdkOverlayOrigin;
3557 exports.CloseScrollStrategy = CloseScrollStrategy;
3558 exports.ConnectedOverlayPositionChange = ConnectedOverlayPositionChange;
3559 exports.ConnectedPositionStrategy = ConnectedPositionStrategy;
3560 exports.ConnectionPositionPair = ConnectionPositionPair;
3561 exports.FlexibleConnectedPositionStrategy = FlexibleConnectedPositionStrategy;
3562 exports.FullscreenOverlayContainer = FullscreenOverlayContainer;
3563 exports.GlobalPositionStrategy = GlobalPositionStrategy;
3564 exports.NoopScrollStrategy = NoopScrollStrategy;
3565 exports.Overlay = Overlay;
3566 exports.OverlayConfig = OverlayConfig;
3567 exports.OverlayContainer = OverlayContainer;
3568 exports.OverlayKeyboardDispatcher = OverlayKeyboardDispatcher;
3569 exports.OverlayModule = OverlayModule;
3570 exports.OverlayOutsideClickDispatcher = OverlayOutsideClickDispatcher;
3571 exports.OverlayPositionBuilder = OverlayPositionBuilder;
3572 exports.OverlayRef = OverlayRef;
3573 exports.RepositionScrollStrategy = RepositionScrollStrategy;
3574 exports.ScrollStrategyOptions = ScrollStrategyOptions;
3575 exports.ScrollingVisibility = ScrollingVisibility;
3576 exports.validateHorizontalPosition = validateHorizontalPosition;
3577 exports.validateVerticalPosition = validateVerticalPosition;
3578 exports.ɵangular_material_src_cdk_overlay_overlay_a = CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY;
3579 exports.ɵangular_material_src_cdk_overlay_overlay_b = CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY;
3580 exports.ɵangular_material_src_cdk_overlay_overlay_c = CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER;
3581 exports.ɵangular_material_src_cdk_overlay_overlay_d = BaseOverlayDispatcher;
3582
3583 Object.defineProperty(exports, '__esModule', { value: true });
3584
3585})));
3586//# sourceMappingURL=cdk-overlay.umd.js.map