UNPKG

140 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/common'), require('@angular/core'), require('rxjs'), require('@angular/cdk/keycodes'), require('rxjs/operators'), require('@angular/cdk/coercion'), require('@angular/cdk/platform'), require('@angular/cdk/observers')) :
3 typeof define === 'function' && define.amd ? define('@angular/cdk/a11y', ['exports', '@angular/common', '@angular/core', 'rxjs', '@angular/cdk/keycodes', 'rxjs/operators', '@angular/cdk/coercion', '@angular/cdk/platform', '@angular/cdk/observers'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ng = global.ng || {}, global.ng.cdk = global.ng.cdk || {}, global.ng.cdk.a11y = {}), global.ng.common, global.ng.core, global.rxjs, global.ng.cdk.keycodes, global.rxjs.operators, global.ng.cdk.coercion, global.ng.cdk.platform, global.ng.cdk.observers));
5}(this, (function (exports, i2, i0, rxjs, keycodes, operators, coercion, i1, observers) { '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 i2__namespace = /*#__PURE__*/_interopNamespace(i2);
28 var i0__namespace = /*#__PURE__*/_interopNamespace(i0);
29 var i1__namespace = /*#__PURE__*/_interopNamespace(i1);
30
31 /**
32 * @license
33 * Copyright Google LLC All Rights Reserved.
34 *
35 * Use of this source code is governed by an MIT-style license that can be
36 * found in the LICENSE file at https://angular.io/license
37 */
38 /** IDs are delimited by an empty space, as per the spec. */
39 var ID_DELIMITER = ' ';
40 /**
41 * Adds the given ID to the specified ARIA attribute on an element.
42 * Used for attributes such as aria-labelledby, aria-owns, etc.
43 */
44 function addAriaReferencedId(el, attr, id) {
45 var ids = getAriaReferenceIds(el, attr);
46 if (ids.some(function (existingId) { return existingId.trim() == id.trim(); })) {
47 return;
48 }
49 ids.push(id.trim());
50 el.setAttribute(attr, ids.join(ID_DELIMITER));
51 }
52 /**
53 * Removes the given ID from the specified ARIA attribute on an element.
54 * Used for attributes such as aria-labelledby, aria-owns, etc.
55 */
56 function removeAriaReferencedId(el, attr, id) {
57 var ids = getAriaReferenceIds(el, attr);
58 var filteredIds = ids.filter(function (val) { return val != id.trim(); });
59 if (filteredIds.length) {
60 el.setAttribute(attr, filteredIds.join(ID_DELIMITER));
61 }
62 else {
63 el.removeAttribute(attr);
64 }
65 }
66 /**
67 * Gets the list of IDs referenced by the given ARIA attribute on an element.
68 * Used for attributes such as aria-labelledby, aria-owns, etc.
69 */
70 function getAriaReferenceIds(el, attr) {
71 // Get string array of all individual ids (whitespace delimited) in the attribute value
72 return (el.getAttribute(attr) || '').match(/\S+/g) || [];
73 }
74
75 /**
76 * @license
77 * Copyright Google LLC All Rights Reserved.
78 *
79 * Use of this source code is governed by an MIT-style license that can be
80 * found in the LICENSE file at https://angular.io/license
81 */
82 /** ID used for the body container where all messages are appended. */
83 var MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
84 /** ID prefix used for each created message element. */
85 var CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
86 /** Attribute given to each host element that is described by a message element. */
87 var CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
88 /** Global incremental identifier for each registered message element. */
89 var nextId = 0;
90 /** Global map of all registered message elements that have been placed into the document. */
91 var messageRegistry = new Map();
92 /** Container for all registered messages. */
93 var messagesContainer = null;
94 /**
95 * Utility that creates visually hidden elements with a message content. Useful for elements that
96 * want to use aria-describedby to further describe themselves without adding additional visual
97 * content.
98 */
99 var AriaDescriber = /** @class */ (function () {
100 function AriaDescriber(_document) {
101 this._document = _document;
102 }
103 AriaDescriber.prototype.describe = function (hostElement, message, role) {
104 if (!this._canBeDescribed(hostElement, message)) {
105 return;
106 }
107 var key = getKey(message, role);
108 if (typeof message !== 'string') {
109 // We need to ensure that the element has an ID.
110 setMessageId(message);
111 messageRegistry.set(key, { messageElement: message, referenceCount: 0 });
112 }
113 else if (!messageRegistry.has(key)) {
114 this._createMessageElement(message, role);
115 }
116 if (!this._isElementDescribedByMessage(hostElement, key)) {
117 this._addMessageReference(hostElement, key);
118 }
119 };
120 AriaDescriber.prototype.removeDescription = function (hostElement, message, role) {
121 if (!message || !this._isElementNode(hostElement)) {
122 return;
123 }
124 var key = getKey(message, role);
125 if (this._isElementDescribedByMessage(hostElement, key)) {
126 this._removeMessageReference(hostElement, key);
127 }
128 // If the message is a string, it means that it's one that we created for the
129 // consumer so we can remove it safely, otherwise we should leave it in place.
130 if (typeof message === 'string') {
131 var registeredMessage = messageRegistry.get(key);
132 if (registeredMessage && registeredMessage.referenceCount === 0) {
133 this._deleteMessageElement(key);
134 }
135 }
136 if (messagesContainer && messagesContainer.childNodes.length === 0) {
137 this._deleteMessagesContainer();
138 }
139 };
140 /** Unregisters all created message elements and removes the message container. */
141 AriaDescriber.prototype.ngOnDestroy = function () {
142 var describedElements = this._document.querySelectorAll("[" + CDK_DESCRIBEDBY_HOST_ATTRIBUTE + "]");
143 for (var i = 0; i < describedElements.length; i++) {
144 this._removeCdkDescribedByReferenceIds(describedElements[i]);
145 describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
146 }
147 if (messagesContainer) {
148 this._deleteMessagesContainer();
149 }
150 messageRegistry.clear();
151 };
152 /**
153 * Creates a new element in the visually hidden message container element with the message
154 * as its content and adds it to the message registry.
155 */
156 AriaDescriber.prototype._createMessageElement = function (message, role) {
157 var messageElement = this._document.createElement('div');
158 setMessageId(messageElement);
159 messageElement.textContent = message;
160 if (role) {
161 messageElement.setAttribute('role', role);
162 }
163 this._createMessagesContainer();
164 messagesContainer.appendChild(messageElement);
165 messageRegistry.set(getKey(message, role), { messageElement: messageElement, referenceCount: 0 });
166 };
167 /** Deletes the message element from the global messages container. */
168 AriaDescriber.prototype._deleteMessageElement = function (key) {
169 var registeredMessage = messageRegistry.get(key);
170 var messageElement = registeredMessage && registeredMessage.messageElement;
171 if (messagesContainer && messageElement) {
172 messagesContainer.removeChild(messageElement);
173 }
174 messageRegistry.delete(key);
175 };
176 /** Creates the global container for all aria-describedby messages. */
177 AriaDescriber.prototype._createMessagesContainer = function () {
178 if (!messagesContainer) {
179 var preExistingContainer = this._document.getElementById(MESSAGES_CONTAINER_ID);
180 // When going from the server to the client, we may end up in a situation where there's
181 // already a container on the page, but we don't have a reference to it. Clear the
182 // old container so we don't get duplicates. Doing this, instead of emptying the previous
183 // container, should be slightly faster.
184 if (preExistingContainer && preExistingContainer.parentNode) {
185 preExistingContainer.parentNode.removeChild(preExistingContainer);
186 }
187 messagesContainer = this._document.createElement('div');
188 messagesContainer.id = MESSAGES_CONTAINER_ID;
189 // We add `visibility: hidden` in order to prevent text in this container from
190 // being searchable by the browser's Ctrl + F functionality.
191 // Screen-readers will still read the description for elements with aria-describedby even
192 // when the description element is not visible.
193 messagesContainer.style.visibility = 'hidden';
194 // Even though we use `visibility: hidden`, we still apply `cdk-visually-hidden` so that
195 // the description element doesn't impact page layout.
196 messagesContainer.classList.add('cdk-visually-hidden');
197 this._document.body.appendChild(messagesContainer);
198 }
199 };
200 /** Deletes the global messages container. */
201 AriaDescriber.prototype._deleteMessagesContainer = function () {
202 if (messagesContainer && messagesContainer.parentNode) {
203 messagesContainer.parentNode.removeChild(messagesContainer);
204 messagesContainer = null;
205 }
206 };
207 /** Removes all cdk-describedby messages that are hosted through the element. */
208 AriaDescriber.prototype._removeCdkDescribedByReferenceIds = function (element) {
209 // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
210 var originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
211 .filter(function (id) { return id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0; });
212 element.setAttribute('aria-describedby', originalReferenceIds.join(' '));
213 };
214 /**
215 * Adds a message reference to the element using aria-describedby and increments the registered
216 * message's reference count.
217 */
218 AriaDescriber.prototype._addMessageReference = function (element, key) {
219 var registeredMessage = messageRegistry.get(key);
220 // Add the aria-describedby reference and set the
221 // describedby_host attribute to mark the element.
222 addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
223 element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, '');
224 registeredMessage.referenceCount++;
225 };
226 /**
227 * Removes a message reference from the element using aria-describedby
228 * and decrements the registered message's reference count.
229 */
230 AriaDescriber.prototype._removeMessageReference = function (element, key) {
231 var registeredMessage = messageRegistry.get(key);
232 registeredMessage.referenceCount--;
233 removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
234 element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
235 };
236 /** Returns true if the element has been described by the provided message ID. */
237 AriaDescriber.prototype._isElementDescribedByMessage = function (element, key) {
238 var referenceIds = getAriaReferenceIds(element, 'aria-describedby');
239 var registeredMessage = messageRegistry.get(key);
240 var messageId = registeredMessage && registeredMessage.messageElement.id;
241 return !!messageId && referenceIds.indexOf(messageId) != -1;
242 };
243 /** Determines whether a message can be described on a particular element. */
244 AriaDescriber.prototype._canBeDescribed = function (element, message) {
245 if (!this._isElementNode(element)) {
246 return false;
247 }
248 if (message && typeof message === 'object') {
249 // We'd have to make some assumptions about the description element's text, if the consumer
250 // passed in an element. Assume that if an element is passed in, the consumer has verified
251 // that it can be used as a description.
252 return true;
253 }
254 var trimmedMessage = message == null ? '' : ("" + message).trim();
255 var ariaLabel = element.getAttribute('aria-label');
256 // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the
257 // element, because screen readers will end up reading out the same text twice in a row.
258 return trimmedMessage ? (!ariaLabel || ariaLabel.trim() !== trimmedMessage) : false;
259 };
260 /** Checks whether a node is an Element node. */
261 AriaDescriber.prototype._isElementNode = function (element) {
262 return element.nodeType === this._document.ELEMENT_NODE;
263 };
264 return AriaDescriber;
265 }());
266 AriaDescriber.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function AriaDescriber_Factory() { return new AriaDescriber(i0__namespace.ɵɵinject(i2__namespace.DOCUMENT)); }, token: AriaDescriber, providedIn: "root" });
267 AriaDescriber.decorators = [
268 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
269 ];
270 AriaDescriber.ctorParameters = function () { return [
271 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
272 ]; };
273 /** Gets a key that can be used to look messages up in the registry. */
274 function getKey(message, role) {
275 return typeof message === 'string' ? (role || '') + "/" + message : message;
276 }
277 /** Assigns a unique ID to an element, if it doesn't have one already. */
278 function setMessageId(element) {
279 if (!element.id) {
280 element.id = CDK_DESCRIBEDBY_ID_PREFIX + "-" + nextId++;
281 }
282 }
283
284 /*! *****************************************************************************
285 Copyright (c) Microsoft Corporation.
286
287 Permission to use, copy, modify, and/or distribute this software for any
288 purpose with or without fee is hereby granted.
289
290 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
291 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
292 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
293 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
294 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
295 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
296 PERFORMANCE OF THIS SOFTWARE.
297 ***************************************************************************** */
298 /* global Reflect, Promise */
299 var extendStatics = function (d, b) {
300 extendStatics = Object.setPrototypeOf ||
301 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
302 function (d, b) { for (var p in b)
303 if (Object.prototype.hasOwnProperty.call(b, p))
304 d[p] = b[p]; };
305 return extendStatics(d, b);
306 };
307 function __extends(d, b) {
308 if (typeof b !== "function" && b !== null)
309 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
310 extendStatics(d, b);
311 function __() { this.constructor = d; }
312 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
313 }
314 var __assign = function () {
315 __assign = Object.assign || function __assign(t) {
316 for (var s, i = 1, n = arguments.length; i < n; i++) {
317 s = arguments[i];
318 for (var p in s)
319 if (Object.prototype.hasOwnProperty.call(s, p))
320 t[p] = s[p];
321 }
322 return t;
323 };
324 return __assign.apply(this, arguments);
325 };
326 function __rest(s, e) {
327 var t = {};
328 for (var p in s)
329 if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
330 t[p] = s[p];
331 if (s != null && typeof Object.getOwnPropertySymbols === "function")
332 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
333 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
334 t[p[i]] = s[p[i]];
335 }
336 return t;
337 }
338 function __decorate(decorators, target, key, desc) {
339 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
340 if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
341 r = Reflect.decorate(decorators, target, key, desc);
342 else
343 for (var i = decorators.length - 1; i >= 0; i--)
344 if (d = decorators[i])
345 r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
346 return c > 3 && r && Object.defineProperty(target, key, r), r;
347 }
348 function __param(paramIndex, decorator) {
349 return function (target, key) { decorator(target, key, paramIndex); };
350 }
351 function __metadata(metadataKey, metadataValue) {
352 if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
353 return Reflect.metadata(metadataKey, metadataValue);
354 }
355 function __awaiter(thisArg, _arguments, P, generator) {
356 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
357 return new (P || (P = Promise))(function (resolve, reject) {
358 function fulfilled(value) { try {
359 step(generator.next(value));
360 }
361 catch (e) {
362 reject(e);
363 } }
364 function rejected(value) { try {
365 step(generator["throw"](value));
366 }
367 catch (e) {
368 reject(e);
369 } }
370 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
371 step((generator = generator.apply(thisArg, _arguments || [])).next());
372 });
373 }
374 function __generator(thisArg, body) {
375 var _ = { label: 0, sent: function () { if (t[0] & 1)
376 throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
377 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
378 function verb(n) { return function (v) { return step([n, v]); }; }
379 function step(op) {
380 if (f)
381 throw new TypeError("Generator is already executing.");
382 while (_)
383 try {
384 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)
385 return t;
386 if (y = 0, t)
387 op = [op[0] & 2, t.value];
388 switch (op[0]) {
389 case 0:
390 case 1:
391 t = op;
392 break;
393 case 4:
394 _.label++;
395 return { value: op[1], done: false };
396 case 5:
397 _.label++;
398 y = op[1];
399 op = [0];
400 continue;
401 case 7:
402 op = _.ops.pop();
403 _.trys.pop();
404 continue;
405 default:
406 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
407 _ = 0;
408 continue;
409 }
410 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
411 _.label = op[1];
412 break;
413 }
414 if (op[0] === 6 && _.label < t[1]) {
415 _.label = t[1];
416 t = op;
417 break;
418 }
419 if (t && _.label < t[2]) {
420 _.label = t[2];
421 _.ops.push(op);
422 break;
423 }
424 if (t[2])
425 _.ops.pop();
426 _.trys.pop();
427 continue;
428 }
429 op = body.call(thisArg, _);
430 }
431 catch (e) {
432 op = [6, e];
433 y = 0;
434 }
435 finally {
436 f = t = 0;
437 }
438 if (op[0] & 5)
439 throw op[1];
440 return { value: op[0] ? op[1] : void 0, done: true };
441 }
442 }
443 var __createBinding = Object.create ? (function (o, m, k, k2) {
444 if (k2 === undefined)
445 k2 = k;
446 Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
447 }) : (function (o, m, k, k2) {
448 if (k2 === undefined)
449 k2 = k;
450 o[k2] = m[k];
451 });
452 function __exportStar(m, o) {
453 for (var p in m)
454 if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
455 __createBinding(o, m, p);
456 }
457 function __values(o) {
458 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
459 if (m)
460 return m.call(o);
461 if (o && typeof o.length === "number")
462 return {
463 next: function () {
464 if (o && i >= o.length)
465 o = void 0;
466 return { value: o && o[i++], done: !o };
467 }
468 };
469 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
470 }
471 function __read(o, n) {
472 var m = typeof Symbol === "function" && o[Symbol.iterator];
473 if (!m)
474 return o;
475 var i = m.call(o), r, ar = [], e;
476 try {
477 while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
478 ar.push(r.value);
479 }
480 catch (error) {
481 e = { error: error };
482 }
483 finally {
484 try {
485 if (r && !r.done && (m = i["return"]))
486 m.call(i);
487 }
488 finally {
489 if (e)
490 throw e.error;
491 }
492 }
493 return ar;
494 }
495 /** @deprecated */
496 function __spread() {
497 for (var ar = [], i = 0; i < arguments.length; i++)
498 ar = ar.concat(__read(arguments[i]));
499 return ar;
500 }
501 /** @deprecated */
502 function __spreadArrays() {
503 for (var s = 0, i = 0, il = arguments.length; i < il; i++)
504 s += arguments[i].length;
505 for (var r = Array(s), k = 0, i = 0; i < il; i++)
506 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
507 r[k] = a[j];
508 return r;
509 }
510 function __spreadArray(to, from, pack) {
511 if (pack || arguments.length === 2)
512 for (var i = 0, l = from.length, ar; i < l; i++) {
513 if (ar || !(i in from)) {
514 if (!ar)
515 ar = Array.prototype.slice.call(from, 0, i);
516 ar[i] = from[i];
517 }
518 }
519 return to.concat(ar || from);
520 }
521 function __await(v) {
522 return this instanceof __await ? (this.v = v, this) : new __await(v);
523 }
524 function __asyncGenerator(thisArg, _arguments, generator) {
525 if (!Symbol.asyncIterator)
526 throw new TypeError("Symbol.asyncIterator is not defined.");
527 var g = generator.apply(thisArg, _arguments || []), i, q = [];
528 return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
529 function verb(n) { if (g[n])
530 i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
531 function resume(n, v) { try {
532 step(g[n](v));
533 }
534 catch (e) {
535 settle(q[0][3], e);
536 } }
537 function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
538 function fulfill(value) { resume("next", value); }
539 function reject(value) { resume("throw", value); }
540 function settle(f, v) { if (f(v), q.shift(), q.length)
541 resume(q[0][0], q[0][1]); }
542 }
543 function __asyncDelegator(o) {
544 var i, p;
545 return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
546 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; }
547 }
548 function __asyncValues(o) {
549 if (!Symbol.asyncIterator)
550 throw new TypeError("Symbol.asyncIterator is not defined.");
551 var m = o[Symbol.asyncIterator], i;
552 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);
553 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); }); }; }
554 function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
555 }
556 function __makeTemplateObject(cooked, raw) {
557 if (Object.defineProperty) {
558 Object.defineProperty(cooked, "raw", { value: raw });
559 }
560 else {
561 cooked.raw = raw;
562 }
563 return cooked;
564 }
565 ;
566 var __setModuleDefault = Object.create ? (function (o, v) {
567 Object.defineProperty(o, "default", { enumerable: true, value: v });
568 }) : function (o, v) {
569 o["default"] = v;
570 };
571 function __importStar(mod) {
572 if (mod && mod.__esModule)
573 return mod;
574 var result = {};
575 if (mod != null)
576 for (var k in mod)
577 if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
578 __createBinding(result, mod, k);
579 __setModuleDefault(result, mod);
580 return result;
581 }
582 function __importDefault(mod) {
583 return (mod && mod.__esModule) ? mod : { default: mod };
584 }
585 function __classPrivateFieldGet(receiver, state, kind, f) {
586 if (kind === "a" && !f)
587 throw new TypeError("Private accessor was defined without a getter");
588 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
589 throw new TypeError("Cannot read private member from an object whose class did not declare it");
590 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
591 }
592 function __classPrivateFieldSet(receiver, state, value, kind, f) {
593 if (kind === "m")
594 throw new TypeError("Private method is not writable");
595 if (kind === "a" && !f)
596 throw new TypeError("Private accessor was defined without a setter");
597 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
598 throw new TypeError("Cannot write private member to an object whose class did not declare it");
599 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
600 }
601
602 /**
603 * @license
604 * Copyright Google LLC All Rights Reserved.
605 *
606 * Use of this source code is governed by an MIT-style license that can be
607 * found in the LICENSE file at https://angular.io/license
608 */
609 /**
610 * This class manages keyboard events for selectable lists. If you pass it a query list
611 * of items, it will set the active item correctly when arrow events occur.
612 */
613 var ListKeyManager = /** @class */ (function () {
614 function ListKeyManager(_items) {
615 var _this = this;
616 this._items = _items;
617 this._activeItemIndex = -1;
618 this._activeItem = null;
619 this._wrap = false;
620 this._letterKeyStream = new rxjs.Subject();
621 this._typeaheadSubscription = rxjs.Subscription.EMPTY;
622 this._vertical = true;
623 this._allowedModifierKeys = [];
624 this._homeAndEnd = false;
625 /**
626 * Predicate function that can be used to check whether an item should be skipped
627 * by the key manager. By default, disabled items are skipped.
628 */
629 this._skipPredicateFn = function (item) { return item.disabled; };
630 // Buffer for the letters that the user has pressed when the typeahead option is turned on.
631 this._pressedLetters = [];
632 /**
633 * Stream that emits any time the TAB key is pressed, so components can react
634 * when focus is shifted off of the list.
635 */
636 this.tabOut = new rxjs.Subject();
637 /** Stream that emits whenever the active item of the list manager changes. */
638 this.change = new rxjs.Subject();
639 // We allow for the items to be an array because, in some cases, the consumer may
640 // not have access to a QueryList of the items they want to manage (e.g. when the
641 // items aren't being collected via `ViewChildren` or `ContentChildren`).
642 if (_items instanceof i0.QueryList) {
643 _items.changes.subscribe(function (newItems) {
644 if (_this._activeItem) {
645 var itemArray = newItems.toArray();
646 var newIndex = itemArray.indexOf(_this._activeItem);
647 if (newIndex > -1 && newIndex !== _this._activeItemIndex) {
648 _this._activeItemIndex = newIndex;
649 }
650 }
651 });
652 }
653 }
654 /**
655 * Sets the predicate function that determines which items should be skipped by the
656 * list key manager.
657 * @param predicate Function that determines whether the given item should be skipped.
658 */
659 ListKeyManager.prototype.skipPredicate = function (predicate) {
660 this._skipPredicateFn = predicate;
661 return this;
662 };
663 /**
664 * Configures wrapping mode, which determines whether the active item will wrap to
665 * the other end of list when there are no more items in the given direction.
666 * @param shouldWrap Whether the list should wrap when reaching the end.
667 */
668 ListKeyManager.prototype.withWrap = function (shouldWrap) {
669 if (shouldWrap === void 0) { shouldWrap = true; }
670 this._wrap = shouldWrap;
671 return this;
672 };
673 /**
674 * Configures whether the key manager should be able to move the selection vertically.
675 * @param enabled Whether vertical selection should be enabled.
676 */
677 ListKeyManager.prototype.withVerticalOrientation = function (enabled) {
678 if (enabled === void 0) { enabled = true; }
679 this._vertical = enabled;
680 return this;
681 };
682 /**
683 * Configures the key manager to move the selection horizontally.
684 * Passing in `null` will disable horizontal movement.
685 * @param direction Direction in which the selection can be moved.
686 */
687 ListKeyManager.prototype.withHorizontalOrientation = function (direction) {
688 this._horizontal = direction;
689 return this;
690 };
691 /**
692 * Modifier keys which are allowed to be held down and whose default actions will be prevented
693 * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
694 */
695 ListKeyManager.prototype.withAllowedModifierKeys = function (keys) {
696 this._allowedModifierKeys = keys;
697 return this;
698 };
699 /**
700 * Turns on typeahead mode which allows users to set the active item by typing.
701 * @param debounceInterval Time to wait after the last keystroke before setting the active item.
702 */
703 ListKeyManager.prototype.withTypeAhead = function (debounceInterval) {
704 var _this = this;
705 if (debounceInterval === void 0) { debounceInterval = 200; }
706 if ((typeof ngDevMode === 'undefined' || ngDevMode) && (this._items.length &&
707 this._items.some(function (item) { return typeof item.getLabel !== 'function'; }))) {
708 throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
709 }
710 this._typeaheadSubscription.unsubscribe();
711 // Debounce the presses of non-navigational keys, collect the ones that correspond to letters
712 // and convert those letters back into a string. Afterwards find the first item that starts
713 // with that string and select it.
714 this._typeaheadSubscription = this._letterKeyStream.pipe(operators.tap(function (letter) { return _this._pressedLetters.push(letter); }), operators.debounceTime(debounceInterval), operators.filter(function () { return _this._pressedLetters.length > 0; }), operators.map(function () { return _this._pressedLetters.join(''); })).subscribe(function (inputString) {
715 var items = _this._getItemsArray();
716 // Start at 1 because we want to start searching at the item immediately
717 // following the current active item.
718 for (var i = 1; i < items.length + 1; i++) {
719 var index = (_this._activeItemIndex + i) % items.length;
720 var item = items[index];
721 if (!_this._skipPredicateFn(item) &&
722 item.getLabel().toUpperCase().trim().indexOf(inputString) === 0) {
723 _this.setActiveItem(index);
724 break;
725 }
726 }
727 _this._pressedLetters = [];
728 });
729 return this;
730 };
731 /**
732 * Configures the key manager to activate the first and last items
733 * respectively when the Home or End key is pressed.
734 * @param enabled Whether pressing the Home or End key activates the first/last item.
735 */
736 ListKeyManager.prototype.withHomeAndEnd = function (enabled) {
737 if (enabled === void 0) { enabled = true; }
738 this._homeAndEnd = enabled;
739 return this;
740 };
741 ListKeyManager.prototype.setActiveItem = function (item) {
742 var previousActiveItem = this._activeItem;
743 this.updateActiveItem(item);
744 if (this._activeItem !== previousActiveItem) {
745 this.change.next(this._activeItemIndex);
746 }
747 };
748 /**
749 * Sets the active item depending on the key event passed in.
750 * @param event Keyboard event to be used for determining which element should be active.
751 */
752 ListKeyManager.prototype.onKeydown = function (event) {
753 var _this = this;
754 var keyCode = event.keyCode;
755 var modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];
756 var isModifierAllowed = modifiers.every(function (modifier) {
757 return !event[modifier] || _this._allowedModifierKeys.indexOf(modifier) > -1;
758 });
759 switch (keyCode) {
760 case keycodes.TAB:
761 this.tabOut.next();
762 return;
763 case keycodes.DOWN_ARROW:
764 if (this._vertical && isModifierAllowed) {
765 this.setNextItemActive();
766 break;
767 }
768 else {
769 return;
770 }
771 case keycodes.UP_ARROW:
772 if (this._vertical && isModifierAllowed) {
773 this.setPreviousItemActive();
774 break;
775 }
776 else {
777 return;
778 }
779 case keycodes.RIGHT_ARROW:
780 if (this._horizontal && isModifierAllowed) {
781 this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();
782 break;
783 }
784 else {
785 return;
786 }
787 case keycodes.LEFT_ARROW:
788 if (this._horizontal && isModifierAllowed) {
789 this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();
790 break;
791 }
792 else {
793 return;
794 }
795 case keycodes.HOME:
796 if (this._homeAndEnd && isModifierAllowed) {
797 this.setFirstItemActive();
798 break;
799 }
800 else {
801 return;
802 }
803 case keycodes.END:
804 if (this._homeAndEnd && isModifierAllowed) {
805 this.setLastItemActive();
806 break;
807 }
808 else {
809 return;
810 }
811 default:
812 if (isModifierAllowed || keycodes.hasModifierKey(event, 'shiftKey')) {
813 // Attempt to use the `event.key` which also maps it to the user's keyboard language,
814 // otherwise fall back to resolving alphanumeric characters via the keyCode.
815 if (event.key && event.key.length === 1) {
816 this._letterKeyStream.next(event.key.toLocaleUpperCase());
817 }
818 else if ((keyCode >= keycodes.A && keyCode <= keycodes.Z) || (keyCode >= keycodes.ZERO && keyCode <= keycodes.NINE)) {
819 this._letterKeyStream.next(String.fromCharCode(keyCode));
820 }
821 }
822 // Note that we return here, in order to avoid preventing
823 // the default action of non-navigational keys.
824 return;
825 }
826 this._pressedLetters = [];
827 event.preventDefault();
828 };
829 Object.defineProperty(ListKeyManager.prototype, "activeItemIndex", {
830 /** Index of the currently active item. */
831 get: function () {
832 return this._activeItemIndex;
833 },
834 enumerable: false,
835 configurable: true
836 });
837 Object.defineProperty(ListKeyManager.prototype, "activeItem", {
838 /** The active item. */
839 get: function () {
840 return this._activeItem;
841 },
842 enumerable: false,
843 configurable: true
844 });
845 /** Gets whether the user is currently typing into the manager using the typeahead feature. */
846 ListKeyManager.prototype.isTyping = function () {
847 return this._pressedLetters.length > 0;
848 };
849 /** Sets the active item to the first enabled item in the list. */
850 ListKeyManager.prototype.setFirstItemActive = function () {
851 this._setActiveItemByIndex(0, 1);
852 };
853 /** Sets the active item to the last enabled item in the list. */
854 ListKeyManager.prototype.setLastItemActive = function () {
855 this._setActiveItemByIndex(this._items.length - 1, -1);
856 };
857 /** Sets the active item to the next enabled item in the list. */
858 ListKeyManager.prototype.setNextItemActive = function () {
859 this._activeItemIndex < 0 ? this.setFirstItemActive() : this._setActiveItemByDelta(1);
860 };
861 /** Sets the active item to a previous enabled item in the list. */
862 ListKeyManager.prototype.setPreviousItemActive = function () {
863 this._activeItemIndex < 0 && this._wrap ? this.setLastItemActive()
864 : this._setActiveItemByDelta(-1);
865 };
866 ListKeyManager.prototype.updateActiveItem = function (item) {
867 var itemArray = this._getItemsArray();
868 var index = typeof item === 'number' ? item : itemArray.indexOf(item);
869 var activeItem = itemArray[index];
870 // Explicitly check for `null` and `undefined` because other falsy values are valid.
871 this._activeItem = activeItem == null ? null : activeItem;
872 this._activeItemIndex = index;
873 };
874 /**
875 * This method sets the active item, given a list of items and the delta between the
876 * currently active item and the new active item. It will calculate differently
877 * depending on whether wrap mode is turned on.
878 */
879 ListKeyManager.prototype._setActiveItemByDelta = function (delta) {
880 this._wrap ? this._setActiveInWrapMode(delta) : this._setActiveInDefaultMode(delta);
881 };
882 /**
883 * Sets the active item properly given "wrap" mode. In other words, it will continue to move
884 * down the list until it finds an item that is not disabled, and it will wrap if it
885 * encounters either end of the list.
886 */
887 ListKeyManager.prototype._setActiveInWrapMode = function (delta) {
888 var items = this._getItemsArray();
889 for (var i = 1; i <= items.length; i++) {
890 var index = (this._activeItemIndex + (delta * i) + items.length) % items.length;
891 var item = items[index];
892 if (!this._skipPredicateFn(item)) {
893 this.setActiveItem(index);
894 return;
895 }
896 }
897 };
898 /**
899 * Sets the active item properly given the default mode. In other words, it will
900 * continue to move down the list until it finds an item that is not disabled. If
901 * it encounters either end of the list, it will stop and not wrap.
902 */
903 ListKeyManager.prototype._setActiveInDefaultMode = function (delta) {
904 this._setActiveItemByIndex(this._activeItemIndex + delta, delta);
905 };
906 /**
907 * Sets the active item to the first enabled item starting at the index specified. If the
908 * item is disabled, it will move in the fallbackDelta direction until it either
909 * finds an enabled item or encounters the end of the list.
910 */
911 ListKeyManager.prototype._setActiveItemByIndex = function (index, fallbackDelta) {
912 var items = this._getItemsArray();
913 if (!items[index]) {
914 return;
915 }
916 while (this._skipPredicateFn(items[index])) {
917 index += fallbackDelta;
918 if (!items[index]) {
919 return;
920 }
921 }
922 this.setActiveItem(index);
923 };
924 /** Returns the items as an array. */
925 ListKeyManager.prototype._getItemsArray = function () {
926 return this._items instanceof i0.QueryList ? this._items.toArray() : this._items;
927 };
928 return ListKeyManager;
929 }());
930
931 var ActiveDescendantKeyManager = /** @class */ (function (_super) {
932 __extends(ActiveDescendantKeyManager, _super);
933 function ActiveDescendantKeyManager() {
934 return _super !== null && _super.apply(this, arguments) || this;
935 }
936 ActiveDescendantKeyManager.prototype.setActiveItem = function (index) {
937 if (this.activeItem) {
938 this.activeItem.setInactiveStyles();
939 }
940 _super.prototype.setActiveItem.call(this, index);
941 if (this.activeItem) {
942 this.activeItem.setActiveStyles();
943 }
944 };
945 return ActiveDescendantKeyManager;
946 }(ListKeyManager));
947
948 var FocusKeyManager = /** @class */ (function (_super) {
949 __extends(FocusKeyManager, _super);
950 function FocusKeyManager() {
951 var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this;
952 _this._origin = 'program';
953 return _this;
954 }
955 /**
956 * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
957 * @param origin Focus origin to be used when focusing items.
958 */
959 FocusKeyManager.prototype.setFocusOrigin = function (origin) {
960 this._origin = origin;
961 return this;
962 };
963 FocusKeyManager.prototype.setActiveItem = function (item) {
964 _super.prototype.setActiveItem.call(this, item);
965 if (this.activeItem) {
966 this.activeItem.focus(this._origin);
967 }
968 };
969 return FocusKeyManager;
970 }(ListKeyManager));
971
972 /**
973 * @license
974 * Copyright Google LLC All Rights Reserved.
975 *
976 * Use of this source code is governed by an MIT-style license that can be
977 * found in the LICENSE file at https://angular.io/license
978 */
979 /**
980 * Configuration for the isFocusable method.
981 */
982 var IsFocusableConfig = /** @class */ (function () {
983 function IsFocusableConfig() {
984 /**
985 * Whether to count an element as focusable even if it is not currently visible.
986 */
987 this.ignoreVisibility = false;
988 }
989 return IsFocusableConfig;
990 }());
991 // The InteractivityChecker leans heavily on the ally.js accessibility utilities.
992 // Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
993 // supported.
994 /**
995 * Utility for checking the interactivity of an element, such as whether is is focusable or
996 * tabbable.
997 */
998 var InteractivityChecker = /** @class */ (function () {
999 function InteractivityChecker(_platform) {
1000 this._platform = _platform;
1001 }
1002 /**
1003 * Gets whether an element is disabled.
1004 *
1005 * @param element Element to be checked.
1006 * @returns Whether the element is disabled.
1007 */
1008 InteractivityChecker.prototype.isDisabled = function (element) {
1009 // This does not capture some cases, such as a non-form control with a disabled attribute or
1010 // a form control inside of a disabled form, but should capture the most common cases.
1011 return element.hasAttribute('disabled');
1012 };
1013 /**
1014 * Gets whether an element is visible for the purposes of interactivity.
1015 *
1016 * This will capture states like `display: none` and `visibility: hidden`, but not things like
1017 * being clipped by an `overflow: hidden` parent or being outside the viewport.
1018 *
1019 * @returns Whether the element is visible.
1020 */
1021 InteractivityChecker.prototype.isVisible = function (element) {
1022 return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';
1023 };
1024 /**
1025 * Gets whether an element can be reached via Tab key.
1026 * Assumes that the element has already been checked with isFocusable.
1027 *
1028 * @param element Element to be checked.
1029 * @returns Whether the element is tabbable.
1030 */
1031 InteractivityChecker.prototype.isTabbable = function (element) {
1032 // Nothing is tabbable on the server 😎
1033 if (!this._platform.isBrowser) {
1034 return false;
1035 }
1036 var frameElement = getFrameElement(getWindow(element));
1037 if (frameElement) {
1038 // Frame elements inherit their tabindex onto all child elements.
1039 if (getTabIndexValue(frameElement) === -1) {
1040 return false;
1041 }
1042 // Browsers disable tabbing to an element inside of an invisible frame.
1043 if (!this.isVisible(frameElement)) {
1044 return false;
1045 }
1046 }
1047 var nodeName = element.nodeName.toLowerCase();
1048 var tabIndexValue = getTabIndexValue(element);
1049 if (element.hasAttribute('contenteditable')) {
1050 return tabIndexValue !== -1;
1051 }
1052 if (nodeName === 'iframe' || nodeName === 'object') {
1053 // The frame or object's content may be tabbable depending on the content, but it's
1054 // not possibly to reliably detect the content of the frames. We always consider such
1055 // elements as non-tabbable.
1056 return false;
1057 }
1058 // In iOS, the browser only considers some specific elements as tabbable.
1059 if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {
1060 return false;
1061 }
1062 if (nodeName === 'audio') {
1063 // Audio elements without controls enabled are never tabbable, regardless
1064 // of the tabindex attribute explicitly being set.
1065 if (!element.hasAttribute('controls')) {
1066 return false;
1067 }
1068 // Audio elements with controls are by default tabbable unless the
1069 // tabindex attribute is set to `-1` explicitly.
1070 return tabIndexValue !== -1;
1071 }
1072 if (nodeName === 'video') {
1073 // For all video elements, if the tabindex attribute is set to `-1`, the video
1074 // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`
1075 // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The
1076 // tabindex attribute is the source of truth here.
1077 if (tabIndexValue === -1) {
1078 return false;
1079 }
1080 // If the tabindex is explicitly set, and not `-1` (as per check before), the
1081 // video element is always tabbable (regardless of whether it has controls or not).
1082 if (tabIndexValue !== null) {
1083 return true;
1084 }
1085 // Otherwise (when no explicit tabindex is set), a video is only tabbable if it
1086 // has controls enabled. Firefox is special as videos are always tabbable regardless
1087 // of whether there are controls or not.
1088 return this._platform.FIREFOX || element.hasAttribute('controls');
1089 }
1090 return element.tabIndex >= 0;
1091 };
1092 /**
1093 * Gets whether an element can be focused by the user.
1094 *
1095 * @param element Element to be checked.
1096 * @param config The config object with options to customize this method's behavior
1097 * @returns Whether the element is focusable.
1098 */
1099 InteractivityChecker.prototype.isFocusable = function (element, config) {
1100 // Perform checks in order of left to most expensive.
1101 // Again, naive approach that does not capture many edge cases and browser quirks.
1102 return isPotentiallyFocusable(element) && !this.isDisabled(element) &&
1103 ((config === null || config === void 0 ? void 0 : config.ignoreVisibility) || this.isVisible(element));
1104 };
1105 return InteractivityChecker;
1106 }());
1107 InteractivityChecker.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function InteractivityChecker_Factory() { return new InteractivityChecker(i0__namespace.ɵɵinject(i1__namespace.Platform)); }, token: InteractivityChecker, providedIn: "root" });
1108 InteractivityChecker.decorators = [
1109 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1110 ];
1111 InteractivityChecker.ctorParameters = function () { return [
1112 { type: i1.Platform }
1113 ]; };
1114 /**
1115 * Returns the frame element from a window object. Since browsers like MS Edge throw errors if
1116 * the frameElement property is being accessed from a different host address, this property
1117 * should be accessed carefully.
1118 */
1119 function getFrameElement(window) {
1120 try {
1121 return window.frameElement;
1122 }
1123 catch (_a) {
1124 return null;
1125 }
1126 }
1127 /** Checks whether the specified element has any geometry / rectangles. */
1128 function hasGeometry(element) {
1129 // Use logic from jQuery to check for an invisible element.
1130 // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12
1131 return !!(element.offsetWidth || element.offsetHeight ||
1132 (typeof element.getClientRects === 'function' && element.getClientRects().length));
1133 }
1134 /** Gets whether an element's */
1135 function isNativeFormElement(element) {
1136 var nodeName = element.nodeName.toLowerCase();
1137 return nodeName === 'input' ||
1138 nodeName === 'select' ||
1139 nodeName === 'button' ||
1140 nodeName === 'textarea';
1141 }
1142 /** Gets whether an element is an `<input type="hidden">`. */
1143 function isHiddenInput(element) {
1144 return isInputElement(element) && element.type == 'hidden';
1145 }
1146 /** Gets whether an element is an anchor that has an href attribute. */
1147 function isAnchorWithHref(element) {
1148 return isAnchorElement(element) && element.hasAttribute('href');
1149 }
1150 /** Gets whether an element is an input element. */
1151 function isInputElement(element) {
1152 return element.nodeName.toLowerCase() == 'input';
1153 }
1154 /** Gets whether an element is an anchor element. */
1155 function isAnchorElement(element) {
1156 return element.nodeName.toLowerCase() == 'a';
1157 }
1158 /** Gets whether an element has a valid tabindex. */
1159 function hasValidTabIndex(element) {
1160 if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {
1161 return false;
1162 }
1163 var tabIndex = element.getAttribute('tabindex');
1164 // IE11 parses tabindex="" as the value "-32768"
1165 if (tabIndex == '-32768') {
1166 return false;
1167 }
1168 return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));
1169 }
1170 /**
1171 * Returns the parsed tabindex from the element attributes instead of returning the
1172 * evaluated tabindex from the browsers defaults.
1173 */
1174 function getTabIndexValue(element) {
1175 if (!hasValidTabIndex(element)) {
1176 return null;
1177 }
1178 // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054
1179 var tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
1180 return isNaN(tabIndex) ? -1 : tabIndex;
1181 }
1182 /** Checks whether the specified element is potentially tabbable on iOS */
1183 function isPotentiallyTabbableIOS(element) {
1184 var nodeName = element.nodeName.toLowerCase();
1185 var inputType = nodeName === 'input' && element.type;
1186 return inputType === 'text'
1187 || inputType === 'password'
1188 || nodeName === 'select'
1189 || nodeName === 'textarea';
1190 }
1191 /**
1192 * Gets whether an element is potentially focusable without taking current visible/disabled state
1193 * into account.
1194 */
1195 function isPotentiallyFocusable(element) {
1196 // Inputs are potentially focusable *unless* they're type="hidden".
1197 if (isHiddenInput(element)) {
1198 return false;
1199 }
1200 return isNativeFormElement(element) ||
1201 isAnchorWithHref(element) ||
1202 element.hasAttribute('contenteditable') ||
1203 hasValidTabIndex(element);
1204 }
1205 /** Gets the parent window of a DOM node with regards of being inside of an iframe. */
1206 function getWindow(node) {
1207 // ownerDocument is null if `node` itself *is* a document.
1208 return node.ownerDocument && node.ownerDocument.defaultView || window;
1209 }
1210
1211 /**
1212 * @license
1213 * Copyright Google LLC All Rights Reserved.
1214 *
1215 * Use of this source code is governed by an MIT-style license that can be
1216 * found in the LICENSE file at https://angular.io/license
1217 */
1218 /**
1219 * Class that allows for trapping focus within a DOM element.
1220 *
1221 * This class currently uses a relatively simple approach to focus trapping.
1222 * It assumes that the tab order is the same as DOM order, which is not necessarily true.
1223 * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to be misaligned.
1224 *
1225 * @deprecated Use `ConfigurableFocusTrap` instead.
1226 * @breaking-change 11.0.0
1227 */
1228 var FocusTrap = /** @class */ (function () {
1229 function FocusTrap(_element, _checker, _ngZone, _document, deferAnchors) {
1230 var _this = this;
1231 if (deferAnchors === void 0) { deferAnchors = false; }
1232 this._element = _element;
1233 this._checker = _checker;
1234 this._ngZone = _ngZone;
1235 this._document = _document;
1236 this._hasAttached = false;
1237 // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
1238 this.startAnchorListener = function () { return _this.focusLastTabbableElement(); };
1239 this.endAnchorListener = function () { return _this.focusFirstTabbableElement(); };
1240 this._enabled = true;
1241 if (!deferAnchors) {
1242 this.attachAnchors();
1243 }
1244 }
1245 Object.defineProperty(FocusTrap.prototype, "enabled", {
1246 /** Whether the focus trap is active. */
1247 get: function () { return this._enabled; },
1248 set: function (value) {
1249 this._enabled = value;
1250 if (this._startAnchor && this._endAnchor) {
1251 this._toggleAnchorTabIndex(value, this._startAnchor);
1252 this._toggleAnchorTabIndex(value, this._endAnchor);
1253 }
1254 },
1255 enumerable: false,
1256 configurable: true
1257 });
1258 /** Destroys the focus trap by cleaning up the anchors. */
1259 FocusTrap.prototype.destroy = function () {
1260 var startAnchor = this._startAnchor;
1261 var endAnchor = this._endAnchor;
1262 if (startAnchor) {
1263 startAnchor.removeEventListener('focus', this.startAnchorListener);
1264 if (startAnchor.parentNode) {
1265 startAnchor.parentNode.removeChild(startAnchor);
1266 }
1267 }
1268 if (endAnchor) {
1269 endAnchor.removeEventListener('focus', this.endAnchorListener);
1270 if (endAnchor.parentNode) {
1271 endAnchor.parentNode.removeChild(endAnchor);
1272 }
1273 }
1274 this._startAnchor = this._endAnchor = null;
1275 this._hasAttached = false;
1276 };
1277 /**
1278 * Inserts the anchors into the DOM. This is usually done automatically
1279 * in the constructor, but can be deferred for cases like directives with `*ngIf`.
1280 * @returns Whether the focus trap managed to attach successfully. This may not be the case
1281 * if the target element isn't currently in the DOM.
1282 */
1283 FocusTrap.prototype.attachAnchors = function () {
1284 var _this = this;
1285 // If we're not on the browser, there can be no focus to trap.
1286 if (this._hasAttached) {
1287 return true;
1288 }
1289 this._ngZone.runOutsideAngular(function () {
1290 if (!_this._startAnchor) {
1291 _this._startAnchor = _this._createAnchor();
1292 _this._startAnchor.addEventListener('focus', _this.startAnchorListener);
1293 }
1294 if (!_this._endAnchor) {
1295 _this._endAnchor = _this._createAnchor();
1296 _this._endAnchor.addEventListener('focus', _this.endAnchorListener);
1297 }
1298 });
1299 if (this._element.parentNode) {
1300 this._element.parentNode.insertBefore(this._startAnchor, this._element);
1301 this._element.parentNode.insertBefore(this._endAnchor, this._element.nextSibling);
1302 this._hasAttached = true;
1303 }
1304 return this._hasAttached;
1305 };
1306 /**
1307 * Waits for the zone to stabilize, then either focuses the first element that the
1308 * user specified, or the first tabbable element.
1309 * @returns Returns a promise that resolves with a boolean, depending
1310 * on whether focus was moved successfully.
1311 */
1312 FocusTrap.prototype.focusInitialElementWhenReady = function (options) {
1313 var _this = this;
1314 return new Promise(function (resolve) {
1315 _this._executeOnStable(function () { return resolve(_this.focusInitialElement(options)); });
1316 });
1317 };
1318 /**
1319 * Waits for the zone to stabilize, then focuses
1320 * the first tabbable element within the focus trap region.
1321 * @returns Returns a promise that resolves with a boolean, depending
1322 * on whether focus was moved successfully.
1323 */
1324 FocusTrap.prototype.focusFirstTabbableElementWhenReady = function (options) {
1325 var _this = this;
1326 return new Promise(function (resolve) {
1327 _this._executeOnStable(function () { return resolve(_this.focusFirstTabbableElement(options)); });
1328 });
1329 };
1330 /**
1331 * Waits for the zone to stabilize, then focuses
1332 * the last tabbable element within the focus trap region.
1333 * @returns Returns a promise that resolves with a boolean, depending
1334 * on whether focus was moved successfully.
1335 */
1336 FocusTrap.prototype.focusLastTabbableElementWhenReady = function (options) {
1337 var _this = this;
1338 return new Promise(function (resolve) {
1339 _this._executeOnStable(function () { return resolve(_this.focusLastTabbableElement(options)); });
1340 });
1341 };
1342 /**
1343 * Get the specified boundary element of the trapped region.
1344 * @param bound The boundary to get (start or end of trapped region).
1345 * @returns The boundary element.
1346 */
1347 FocusTrap.prototype._getRegionBoundary = function (bound) {
1348 // Contains the deprecated version of selector, for temporary backwards comparability.
1349 var markers = this._element.querySelectorAll("[cdk-focus-region-" + bound + "], " +
1350 ("[cdkFocusRegion" + bound + "], ") +
1351 ("[cdk-focus-" + bound + "]"));
1352 for (var i = 0; i < markers.length; i++) {
1353 // @breaking-change 8.0.0
1354 if (markers[i].hasAttribute("cdk-focus-" + bound)) {
1355 console.warn("Found use of deprecated attribute 'cdk-focus-" + bound + "', " +
1356 ("use 'cdkFocusRegion" + bound + "' instead. The deprecated ") +
1357 "attribute will be removed in 8.0.0.", markers[i]);
1358 }
1359 else if (markers[i].hasAttribute("cdk-focus-region-" + bound)) {
1360 console.warn("Found use of deprecated attribute 'cdk-focus-region-" + bound + "', " +
1361 ("use 'cdkFocusRegion" + bound + "' instead. The deprecated attribute ") +
1362 "will be removed in 8.0.0.", markers[i]);
1363 }
1364 }
1365 if (bound == 'start') {
1366 return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);
1367 }
1368 return markers.length ?
1369 markers[markers.length - 1] : this._getLastTabbableElement(this._element);
1370 };
1371 /**
1372 * Focuses the element that should be focused when the focus trap is initialized.
1373 * @returns Whether focus was moved successfully.
1374 */
1375 FocusTrap.prototype.focusInitialElement = function (options) {
1376 // Contains the deprecated version of selector, for temporary backwards comparability.
1377 var redirectToElement = this._element.querySelector("[cdk-focus-initial], " +
1378 "[cdkFocusInitial]");
1379 if (redirectToElement) {
1380 // @breaking-change 8.0.0
1381 if (redirectToElement.hasAttribute("cdk-focus-initial")) {
1382 console.warn("Found use of deprecated attribute 'cdk-focus-initial', " +
1383 "use 'cdkFocusInitial' instead. The deprecated attribute " +
1384 "will be removed in 8.0.0", redirectToElement);
1385 }
1386 // Warn the consumer if the element they've pointed to
1387 // isn't focusable, when not in production mode.
1388 if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
1389 !this._checker.isFocusable(redirectToElement)) {
1390 console.warn("Element matching '[cdkFocusInitial]' is not focusable.", redirectToElement);
1391 }
1392 if (!this._checker.isFocusable(redirectToElement)) {
1393 var focusableChild = this._getFirstTabbableElement(redirectToElement);
1394 focusableChild === null || focusableChild === void 0 ? void 0 : focusableChild.focus(options);
1395 return !!focusableChild;
1396 }
1397 redirectToElement.focus(options);
1398 return true;
1399 }
1400 return this.focusFirstTabbableElement(options);
1401 };
1402 /**
1403 * Focuses the first tabbable element within the focus trap region.
1404 * @returns Whether focus was moved successfully.
1405 */
1406 FocusTrap.prototype.focusFirstTabbableElement = function (options) {
1407 var redirectToElement = this._getRegionBoundary('start');
1408 if (redirectToElement) {
1409 redirectToElement.focus(options);
1410 }
1411 return !!redirectToElement;
1412 };
1413 /**
1414 * Focuses the last tabbable element within the focus trap region.
1415 * @returns Whether focus was moved successfully.
1416 */
1417 FocusTrap.prototype.focusLastTabbableElement = function (options) {
1418 var redirectToElement = this._getRegionBoundary('end');
1419 if (redirectToElement) {
1420 redirectToElement.focus(options);
1421 }
1422 return !!redirectToElement;
1423 };
1424 /**
1425 * Checks whether the focus trap has successfully been attached.
1426 */
1427 FocusTrap.prototype.hasAttached = function () {
1428 return this._hasAttached;
1429 };
1430 /** Get the first tabbable element from a DOM subtree (inclusive). */
1431 FocusTrap.prototype._getFirstTabbableElement = function (root) {
1432 if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
1433 return root;
1434 }
1435 // Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
1436 // back to `childNodes` which includes text nodes, comments etc.
1437 var children = root.children || root.childNodes;
1438 for (var i = 0; i < children.length; i++) {
1439 var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
1440 this._getFirstTabbableElement(children[i]) :
1441 null;
1442 if (tabbableChild) {
1443 return tabbableChild;
1444 }
1445 }
1446 return null;
1447 };
1448 /** Get the last tabbable element from a DOM subtree (inclusive). */
1449 FocusTrap.prototype._getLastTabbableElement = function (root) {
1450 if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
1451 return root;
1452 }
1453 // Iterate in reverse DOM order.
1454 var children = root.children || root.childNodes;
1455 for (var i = children.length - 1; i >= 0; i--) {
1456 var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
1457 this._getLastTabbableElement(children[i]) :
1458 null;
1459 if (tabbableChild) {
1460 return tabbableChild;
1461 }
1462 }
1463 return null;
1464 };
1465 /** Creates an anchor element. */
1466 FocusTrap.prototype._createAnchor = function () {
1467 var anchor = this._document.createElement('div');
1468 this._toggleAnchorTabIndex(this._enabled, anchor);
1469 anchor.classList.add('cdk-visually-hidden');
1470 anchor.classList.add('cdk-focus-trap-anchor');
1471 anchor.setAttribute('aria-hidden', 'true');
1472 return anchor;
1473 };
1474 /**
1475 * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
1476 * @param isEnabled Whether the focus trap is enabled.
1477 * @param anchor Anchor on which to toggle the tabindex.
1478 */
1479 FocusTrap.prototype._toggleAnchorTabIndex = function (isEnabled, anchor) {
1480 // Remove the tabindex completely, rather than setting it to -1, because if the
1481 // element has a tabindex, the user might still hit it when navigating with the arrow keys.
1482 isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');
1483 };
1484 /**
1485 * Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.
1486 * @param enabled: Whether the anchors should trap Tab.
1487 */
1488 FocusTrap.prototype.toggleAnchors = function (enabled) {
1489 if (this._startAnchor && this._endAnchor) {
1490 this._toggleAnchorTabIndex(enabled, this._startAnchor);
1491 this._toggleAnchorTabIndex(enabled, this._endAnchor);
1492 }
1493 };
1494 /** Executes a function when the zone is stable. */
1495 FocusTrap.prototype._executeOnStable = function (fn) {
1496 if (this._ngZone.isStable) {
1497 fn();
1498 }
1499 else {
1500 this._ngZone.onStable.pipe(operators.take(1)).subscribe(fn);
1501 }
1502 };
1503 return FocusTrap;
1504 }());
1505 /**
1506 * Factory that allows easy instantiation of focus traps.
1507 * @deprecated Use `ConfigurableFocusTrapFactory` instead.
1508 * @breaking-change 11.0.0
1509 */
1510 var FocusTrapFactory = /** @class */ (function () {
1511 function FocusTrapFactory(_checker, _ngZone, _document) {
1512 this._checker = _checker;
1513 this._ngZone = _ngZone;
1514 this._document = _document;
1515 }
1516 /**
1517 * Creates a focus-trapped region around the given element.
1518 * @param element The element around which focus will be trapped.
1519 * @param deferCaptureElements Defers the creation of focus-capturing elements to be done
1520 * manually by the user.
1521 * @returns The created focus trap instance.
1522 */
1523 FocusTrapFactory.prototype.create = function (element, deferCaptureElements) {
1524 if (deferCaptureElements === void 0) { deferCaptureElements = false; }
1525 return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements);
1526 };
1527 return FocusTrapFactory;
1528 }());
1529 FocusTrapFactory.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FocusTrapFactory_Factory() { return new FocusTrapFactory(i0__namespace.ɵɵinject(InteractivityChecker), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT)); }, token: FocusTrapFactory, providedIn: "root" });
1530 FocusTrapFactory.decorators = [
1531 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1532 ];
1533 FocusTrapFactory.ctorParameters = function () { return [
1534 { type: InteractivityChecker },
1535 { type: i0.NgZone },
1536 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
1537 ]; };
1538 /** Directive for trapping focus within a region. */
1539 var CdkTrapFocus = /** @class */ (function () {
1540 function CdkTrapFocus(_elementRef, _focusTrapFactory,
1541 /**
1542 * @deprecated No longer being used. To be removed.
1543 * @breaking-change 13.0.0
1544 */
1545 _document) {
1546 this._elementRef = _elementRef;
1547 this._focusTrapFactory = _focusTrapFactory;
1548 /** Previously focused element to restore focus to upon destroy when using autoCapture. */
1549 this._previouslyFocusedElement = null;
1550 this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
1551 }
1552 Object.defineProperty(CdkTrapFocus.prototype, "enabled", {
1553 /** Whether the focus trap is active. */
1554 get: function () { return this.focusTrap.enabled; },
1555 set: function (value) { this.focusTrap.enabled = coercion.coerceBooleanProperty(value); },
1556 enumerable: false,
1557 configurable: true
1558 });
1559 Object.defineProperty(CdkTrapFocus.prototype, "autoCapture", {
1560 /**
1561 * Whether the directive should automatically move focus into the trapped region upon
1562 * initialization and return focus to the previous activeElement upon destruction.
1563 */
1564 get: function () { return this._autoCapture; },
1565 set: function (value) { this._autoCapture = coercion.coerceBooleanProperty(value); },
1566 enumerable: false,
1567 configurable: true
1568 });
1569 CdkTrapFocus.prototype.ngOnDestroy = function () {
1570 this.focusTrap.destroy();
1571 // If we stored a previously focused element when using autoCapture, return focus to that
1572 // element now that the trapped region is being destroyed.
1573 if (this._previouslyFocusedElement) {
1574 this._previouslyFocusedElement.focus();
1575 this._previouslyFocusedElement = null;
1576 }
1577 };
1578 CdkTrapFocus.prototype.ngAfterContentInit = function () {
1579 this.focusTrap.attachAnchors();
1580 if (this.autoCapture) {
1581 this._captureFocus();
1582 }
1583 };
1584 CdkTrapFocus.prototype.ngDoCheck = function () {
1585 if (!this.focusTrap.hasAttached()) {
1586 this.focusTrap.attachAnchors();
1587 }
1588 };
1589 CdkTrapFocus.prototype.ngOnChanges = function (changes) {
1590 var autoCaptureChange = changes['autoCapture'];
1591 if (autoCaptureChange && !autoCaptureChange.firstChange && this.autoCapture &&
1592 this.focusTrap.hasAttached()) {
1593 this._captureFocus();
1594 }
1595 };
1596 CdkTrapFocus.prototype._captureFocus = function () {
1597 this._previouslyFocusedElement = i1._getFocusedElementPierceShadowDom();
1598 this.focusTrap.focusInitialElementWhenReady();
1599 };
1600 return CdkTrapFocus;
1601 }());
1602 CdkTrapFocus.decorators = [
1603 { type: i0.Directive, args: [{
1604 selector: '[cdkTrapFocus]',
1605 exportAs: 'cdkTrapFocus',
1606 },] }
1607 ];
1608 CdkTrapFocus.ctorParameters = function () { return [
1609 { type: i0.ElementRef },
1610 { type: FocusTrapFactory },
1611 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
1612 ]; };
1613 CdkTrapFocus.propDecorators = {
1614 enabled: [{ type: i0.Input, args: ['cdkTrapFocus',] }],
1615 autoCapture: [{ type: i0.Input, args: ['cdkTrapFocusAutoCapture',] }]
1616 };
1617
1618 /**
1619 * Class that allows for trapping focus within a DOM element.
1620 *
1621 * This class uses a strategy pattern that determines how it traps focus.
1622 * See FocusTrapInertStrategy.
1623 */
1624 var ConfigurableFocusTrap = /** @class */ (function (_super) {
1625 __extends(ConfigurableFocusTrap, _super);
1626 function ConfigurableFocusTrap(_element, _checker, _ngZone, _document, _focusTrapManager, _inertStrategy, config) {
1627 var _this = _super.call(this, _element, _checker, _ngZone, _document, config.defer) || this;
1628 _this._focusTrapManager = _focusTrapManager;
1629 _this._inertStrategy = _inertStrategy;
1630 _this._focusTrapManager.register(_this);
1631 return _this;
1632 }
1633 Object.defineProperty(ConfigurableFocusTrap.prototype, "enabled", {
1634 /** Whether the FocusTrap is enabled. */
1635 get: function () { return this._enabled; },
1636 set: function (value) {
1637 this._enabled = value;
1638 if (this._enabled) {
1639 this._focusTrapManager.register(this);
1640 }
1641 else {
1642 this._focusTrapManager.deregister(this);
1643 }
1644 },
1645 enumerable: false,
1646 configurable: true
1647 });
1648 /** Notifies the FocusTrapManager that this FocusTrap will be destroyed. */
1649 ConfigurableFocusTrap.prototype.destroy = function () {
1650 this._focusTrapManager.deregister(this);
1651 _super.prototype.destroy.call(this);
1652 };
1653 /** @docs-private Implemented as part of ManagedFocusTrap. */
1654 ConfigurableFocusTrap.prototype._enable = function () {
1655 this._inertStrategy.preventFocus(this);
1656 this.toggleAnchors(true);
1657 };
1658 /** @docs-private Implemented as part of ManagedFocusTrap. */
1659 ConfigurableFocusTrap.prototype._disable = function () {
1660 this._inertStrategy.allowFocus(this);
1661 this.toggleAnchors(false);
1662 };
1663 return ConfigurableFocusTrap;
1664 }(FocusTrap));
1665
1666 /**
1667 * @license
1668 * Copyright Google LLC All Rights Reserved.
1669 *
1670 * Use of this source code is governed by an MIT-style license that can be
1671 * found in the LICENSE file at https://angular.io/license
1672 */
1673 /** The injection token used to specify the inert strategy. */
1674 var FOCUS_TRAP_INERT_STRATEGY = new i0.InjectionToken('FOCUS_TRAP_INERT_STRATEGY');
1675
1676 /**
1677 * @license
1678 * Copyright Google LLC All Rights Reserved.
1679 *
1680 * Use of this source code is governed by an MIT-style license that can be
1681 * found in the LICENSE file at https://angular.io/license
1682 */
1683 /** IE 11 compatible closest implementation that is able to start from non-Element Nodes. */
1684 function closest(element, selector) {
1685 if (!(element instanceof Node)) {
1686 return null;
1687 }
1688 var curr = element;
1689 while (curr != null && !(curr instanceof Element)) {
1690 curr = curr.parentNode;
1691 }
1692 return curr && (hasNativeClosest ?
1693 curr.closest(selector) : polyfillClosest(curr, selector));
1694 }
1695 /** Polyfill for browsers without Element.closest. */
1696 function polyfillClosest(element, selector) {
1697 var curr = element;
1698 while (curr != null && !(curr instanceof Element && matches(curr, selector))) {
1699 curr = curr.parentNode;
1700 }
1701 return (curr || null);
1702 }
1703 var hasNativeClosest = typeof Element != 'undefined' && !!Element.prototype.closest;
1704 /** IE 11 compatible matches implementation. */
1705 function matches(element, selector) {
1706 return element.matches ?
1707 element.matches(selector) :
1708 element['msMatchesSelector'](selector);
1709 }
1710
1711 /**
1712 * @license
1713 * Copyright Google LLC All Rights Reserved.
1714 *
1715 * Use of this source code is governed by an MIT-style license that can be
1716 * found in the LICENSE file at https://angular.io/license
1717 */
1718 /**
1719 * Lightweight FocusTrapInertStrategy that adds a document focus event
1720 * listener to redirect focus back inside the FocusTrap.
1721 */
1722 var EventListenerFocusTrapInertStrategy = /** @class */ (function () {
1723 function EventListenerFocusTrapInertStrategy() {
1724 /** Focus event handler. */
1725 this._listener = null;
1726 }
1727 /** Adds a document event listener that keeps focus inside the FocusTrap. */
1728 EventListenerFocusTrapInertStrategy.prototype.preventFocus = function (focusTrap) {
1729 var _this = this;
1730 // Ensure there's only one listener per document
1731 if (this._listener) {
1732 focusTrap._document.removeEventListener('focus', this._listener, true);
1733 }
1734 this._listener = function (e) { return _this._trapFocus(focusTrap, e); };
1735 focusTrap._ngZone.runOutsideAngular(function () {
1736 focusTrap._document.addEventListener('focus', _this._listener, true);
1737 });
1738 };
1739 /** Removes the event listener added in preventFocus. */
1740 EventListenerFocusTrapInertStrategy.prototype.allowFocus = function (focusTrap) {
1741 if (!this._listener) {
1742 return;
1743 }
1744 focusTrap._document.removeEventListener('focus', this._listener, true);
1745 this._listener = null;
1746 };
1747 /**
1748 * Refocuses the first element in the FocusTrap if the focus event target was outside
1749 * the FocusTrap.
1750 *
1751 * This is an event listener callback. The event listener is added in runOutsideAngular,
1752 * so all this code runs outside Angular as well.
1753 */
1754 EventListenerFocusTrapInertStrategy.prototype._trapFocus = function (focusTrap, event) {
1755 var target = event.target;
1756 var focusTrapRoot = focusTrap._element;
1757 // Don't refocus if target was in an overlay, because the overlay might be associated
1758 // with an element inside the FocusTrap, ex. mat-select.
1759 if (!focusTrapRoot.contains(target) && closest(target, 'div.cdk-overlay-pane') === null) {
1760 // Some legacy FocusTrap usages have logic that focuses some element on the page
1761 // just before FocusTrap is destroyed. For backwards compatibility, wait
1762 // to be sure FocusTrap is still enabled before refocusing.
1763 setTimeout(function () {
1764 // Check whether focus wasn't put back into the focus trap while the timeout was pending.
1765 if (focusTrap.enabled && !focusTrapRoot.contains(focusTrap._document.activeElement)) {
1766 focusTrap.focusFirstTabbableElement();
1767 }
1768 });
1769 }
1770 };
1771 return EventListenerFocusTrapInertStrategy;
1772 }());
1773
1774 /**
1775 * @license
1776 * Copyright Google LLC All Rights Reserved.
1777 *
1778 * Use of this source code is governed by an MIT-style license that can be
1779 * found in the LICENSE file at https://angular.io/license
1780 */
1781 /** Injectable that ensures only the most recently enabled FocusTrap is active. */
1782 var FocusTrapManager = /** @class */ (function () {
1783 function FocusTrapManager() {
1784 // A stack of the FocusTraps on the page. Only the FocusTrap at the
1785 // top of the stack is active.
1786 this._focusTrapStack = [];
1787 }
1788 /**
1789 * Disables the FocusTrap at the top of the stack, and then pushes
1790 * the new FocusTrap onto the stack.
1791 */
1792 FocusTrapManager.prototype.register = function (focusTrap) {
1793 // Dedupe focusTraps that register multiple times.
1794 this._focusTrapStack = this._focusTrapStack.filter(function (ft) { return ft !== focusTrap; });
1795 var stack = this._focusTrapStack;
1796 if (stack.length) {
1797 stack[stack.length - 1]._disable();
1798 }
1799 stack.push(focusTrap);
1800 focusTrap._enable();
1801 };
1802 /**
1803 * Removes the FocusTrap from the stack, and activates the
1804 * FocusTrap that is the new top of the stack.
1805 */
1806 FocusTrapManager.prototype.deregister = function (focusTrap) {
1807 focusTrap._disable();
1808 var stack = this._focusTrapStack;
1809 var i = stack.indexOf(focusTrap);
1810 if (i !== -1) {
1811 stack.splice(i, 1);
1812 if (stack.length) {
1813 stack[stack.length - 1]._enable();
1814 }
1815 }
1816 };
1817 return FocusTrapManager;
1818 }());
1819 FocusTrapManager.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FocusTrapManager_Factory() { return new FocusTrapManager(); }, token: FocusTrapManager, providedIn: "root" });
1820 FocusTrapManager.decorators = [
1821 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1822 ];
1823
1824 /**
1825 * @license
1826 * Copyright Google LLC All Rights Reserved.
1827 *
1828 * Use of this source code is governed by an MIT-style license that can be
1829 * found in the LICENSE file at https://angular.io/license
1830 */
1831 /** Factory that allows easy instantiation of configurable focus traps. */
1832 var ConfigurableFocusTrapFactory = /** @class */ (function () {
1833 function ConfigurableFocusTrapFactory(_checker, _ngZone, _focusTrapManager, _document, _inertStrategy) {
1834 this._checker = _checker;
1835 this._ngZone = _ngZone;
1836 this._focusTrapManager = _focusTrapManager;
1837 this._document = _document;
1838 // TODO split up the strategies into different modules, similar to DateAdapter.
1839 this._inertStrategy = _inertStrategy || new EventListenerFocusTrapInertStrategy();
1840 }
1841 ConfigurableFocusTrapFactory.prototype.create = function (element, config) {
1842 if (config === void 0) { config = { defer: false }; }
1843 var configObject;
1844 if (typeof config === 'boolean') {
1845 configObject = { defer: config };
1846 }
1847 else {
1848 configObject = config;
1849 }
1850 return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject);
1851 };
1852 return ConfigurableFocusTrapFactory;
1853 }());
1854 ConfigurableFocusTrapFactory.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function ConfigurableFocusTrapFactory_Factory() { return new ConfigurableFocusTrapFactory(i0__namespace.ɵɵinject(InteractivityChecker), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(FocusTrapManager), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT), i0__namespace.ɵɵinject(FOCUS_TRAP_INERT_STRATEGY, 8)); }, token: ConfigurableFocusTrapFactory, providedIn: "root" });
1855 ConfigurableFocusTrapFactory.decorators = [
1856 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
1857 ];
1858 ConfigurableFocusTrapFactory.ctorParameters = function () { return [
1859 { type: InteractivityChecker },
1860 { type: i0.NgZone },
1861 { type: FocusTrapManager },
1862 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] },
1863 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FOCUS_TRAP_INERT_STRATEGY,] }] }
1864 ]; };
1865
1866 /**
1867 * @license
1868 * Copyright Google LLC All Rights Reserved.
1869 *
1870 * Use of this source code is governed by an MIT-style license that can be
1871 * found in the LICENSE file at https://angular.io/license
1872 */
1873 /** Gets whether an event could be a faked `mousedown` event dispatched by a screen reader. */
1874 function isFakeMousedownFromScreenReader(event) {
1875 // Some screen readers will dispatch a fake `mousedown` event when pressing enter or space on
1876 // a clickable element. We can distinguish these events when both `offsetX` and `offsetY` are
1877 // zero. Note that there's an edge case where the user could click the 0x0 spot of the screen
1878 // themselves, but that is unlikely to contain interaction elements. Historially we used to check
1879 // `event.buttons === 0`, however that no longer works on recent versions of NVDA.
1880 return event.offsetX === 0 && event.offsetY === 0;
1881 }
1882 /** Gets whether an event could be a faked `touchstart` event dispatched by a screen reader. */
1883 function isFakeTouchstartFromScreenReader(event) {
1884 var touch = (event.touches && event.touches[0]) ||
1885 (event.changedTouches && event.changedTouches[0]);
1886 // A fake `touchstart` can be distinguished from a real one by looking at the `identifier`
1887 // which is typically >= 0 on a real device versus -1 from a screen reader. Just to be safe,
1888 // we can also look at `radiusX` and `radiusY`. This behavior was observed against a Windows 10
1889 // device with a touch screen running NVDA v2020.4 and Firefox 85 or Chrome 88.
1890 return !!touch && touch.identifier === -1 && (touch.radiusX == null || touch.radiusX === 1) &&
1891 (touch.radiusY == null || touch.radiusY === 1);
1892 }
1893
1894 /**
1895 * @license
1896 * Copyright Google LLC All Rights Reserved.
1897 *
1898 * Use of this source code is governed by an MIT-style license that can be
1899 * found in the LICENSE file at https://angular.io/license
1900 */
1901 /**
1902 * Injectable options for the InputModalityDetector. These are shallowly merged with the default
1903 * options.
1904 */
1905 var INPUT_MODALITY_DETECTOR_OPTIONS = new i0.InjectionToken('cdk-input-modality-detector-options');
1906 /**
1907 * Default options for the InputModalityDetector.
1908 *
1909 * Modifier keys are ignored by default (i.e. when pressed won't cause the service to detect
1910 * keyboard input modality) for two reasons:
1911 *
1912 * 1. Modifier keys are commonly used with mouse to perform actions such as 'right click' or 'open
1913 * in new tab', and are thus less representative of actual keyboard interaction.
1914 * 2. VoiceOver triggers some keyboard events when linearly navigating with Control + Option (but
1915 * confusingly not with Caps Lock). Thus, to have parity with other screen readers, we ignore
1916 * these keys so as to not update the input modality.
1917 *
1918 * Note that we do not by default ignore the right Meta key on Safari because it has the same key
1919 * code as the ContextMenu key on other browsers. When we switch to using event.key, we can
1920 * distinguish between the two.
1921 */
1922 var INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS = {
1923 ignoreKeys: [keycodes.ALT, keycodes.CONTROL, keycodes.MAC_META, keycodes.META, keycodes.SHIFT],
1924 };
1925 /**
1926 * The amount of time needed to pass after a touchstart event in order for a subsequent mousedown
1927 * event to be attributed as mouse and not touch.
1928 *
1929 * This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
1930 * that a value of around 650ms seems appropriate.
1931 */
1932 var TOUCH_BUFFER_MS = 650;
1933 /**
1934 * Event listener options that enable capturing and also mark the listener as passive if the browser
1935 * supports it.
1936 */
1937 var modalityEventListenerOptions = i1.normalizePassiveListenerOptions({
1938 passive: true,
1939 capture: true,
1940 });
1941 /**
1942 * Service that detects the user's input modality.
1943 *
1944 * This service does not update the input modality when a user navigates with a screen reader
1945 * (e.g. linear navigation with VoiceOver, object navigation / browse mode with NVDA, virtual PC
1946 * cursor mode with JAWS). This is in part due to technical limitations (i.e. keyboard events do not
1947 * fire as expected in these modes) but is also arguably the correct behavior. Navigating with a
1948 * screen reader is akin to visually scanning a page, and should not be interpreted as actual user
1949 * input interaction.
1950 *
1951 * When a user is not navigating but *interacting* with a screen reader, this service attempts to
1952 * update the input modality to keyboard, but in general this service's behavior is largely
1953 * undefined.
1954 */
1955 var InputModalityDetector = /** @class */ (function () {
1956 function InputModalityDetector(_platform, ngZone, document, options) {
1957 var _this = this;
1958 this._platform = _platform;
1959 /**
1960 * The most recently detected input modality event target. Is null if no input modality has been
1961 * detected or if the associated event target is null for some unknown reason.
1962 */
1963 this._mostRecentTarget = null;
1964 /** The underlying BehaviorSubject that emits whenever an input modality is detected. */
1965 this._modality = new rxjs.BehaviorSubject(null);
1966 /**
1967 * The timestamp of the last touch input modality. Used to determine whether mousedown events
1968 * should be attributed to mouse or touch.
1969 */
1970 this._lastTouchMs = 0;
1971 /**
1972 * Handles keydown events. Must be an arrow function in order to preserve the context when it gets
1973 * bound.
1974 */
1975 this._onKeydown = function (event) {
1976 var _a, _b;
1977 // If this is one of the keys we should ignore, then ignore it and don't update the input
1978 // modality to keyboard.
1979 if ((_b = (_a = _this._options) === null || _a === void 0 ? void 0 : _a.ignoreKeys) === null || _b === void 0 ? void 0 : _b.some(function (keyCode) { return keyCode === event.keyCode; })) {
1980 return;
1981 }
1982 _this._modality.next('keyboard');
1983 _this._mostRecentTarget = i1._getEventTarget(event);
1984 };
1985 /**
1986 * Handles mousedown events. Must be an arrow function in order to preserve the context when it
1987 * gets bound.
1988 */
1989 this._onMousedown = function (event) {
1990 // Touches trigger both touch and mouse events, so we need to distinguish between mouse events
1991 // that were triggered via mouse vs touch. To do so, check if the mouse event occurs closely
1992 // after the previous touch event.
1993 if (Date.now() - _this._lastTouchMs < TOUCH_BUFFER_MS) {
1994 return;
1995 }
1996 // Fake mousedown events are fired by some screen readers when controls are activated by the
1997 // screen reader. Attribute them to keyboard input modality.
1998 _this._modality.next(isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse');
1999 _this._mostRecentTarget = i1._getEventTarget(event);
2000 };
2001 /**
2002 * Handles touchstart events. Must be an arrow function in order to preserve the context when it
2003 * gets bound.
2004 */
2005 this._onTouchstart = function (event) {
2006 // Same scenario as mentioned in _onMousedown, but on touch screen devices, fake touchstart
2007 // events are fired. Again, attribute to keyboard input modality.
2008 if (isFakeTouchstartFromScreenReader(event)) {
2009 _this._modality.next('keyboard');
2010 return;
2011 }
2012 // Store the timestamp of this touch event, as it's used to distinguish between mouse events
2013 // triggered via mouse vs touch.
2014 _this._lastTouchMs = Date.now();
2015 _this._modality.next('touch');
2016 _this._mostRecentTarget = i1._getEventTarget(event);
2017 };
2018 this._options = Object.assign(Object.assign({}, INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS), options);
2019 // Skip the first emission as it's null.
2020 this.modalityDetected = this._modality.pipe(operators.skip(1));
2021 this.modalityChanged = this.modalityDetected.pipe(operators.distinctUntilChanged());
2022 // If we're not in a browser, this service should do nothing, as there's no relevant input
2023 // modality to detect.
2024 if (!_platform.isBrowser) {
2025 return;
2026 }
2027 // Add the event listeners used to detect the user's input modality.
2028 ngZone.runOutsideAngular(function () {
2029 document.addEventListener('keydown', _this._onKeydown, modalityEventListenerOptions);
2030 document.addEventListener('mousedown', _this._onMousedown, modalityEventListenerOptions);
2031 document.addEventListener('touchstart', _this._onTouchstart, modalityEventListenerOptions);
2032 });
2033 }
2034 Object.defineProperty(InputModalityDetector.prototype, "mostRecentModality", {
2035 /** The most recently detected input modality. */
2036 get: function () {
2037 return this._modality.value;
2038 },
2039 enumerable: false,
2040 configurable: true
2041 });
2042 InputModalityDetector.prototype.ngOnDestroy = function () {
2043 if (!this._platform.isBrowser) {
2044 return;
2045 }
2046 document.removeEventListener('keydown', this._onKeydown, modalityEventListenerOptions);
2047 document.removeEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);
2048 document.removeEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);
2049 };
2050 return InputModalityDetector;
2051 }());
2052 InputModalityDetector.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function InputModalityDetector_Factory() { return new InputModalityDetector(i0__namespace.ɵɵinject(i1__namespace.Platform), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT), i0__namespace.ɵɵinject(INPUT_MODALITY_DETECTOR_OPTIONS, 8)); }, token: InputModalityDetector, providedIn: "root" });
2053 InputModalityDetector.decorators = [
2054 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2055 ];
2056 InputModalityDetector.ctorParameters = function () { return [
2057 { type: i1.Platform },
2058 { type: i0.NgZone },
2059 { type: Document, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] },
2060 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [INPUT_MODALITY_DETECTOR_OPTIONS,] }] }
2061 ]; };
2062
2063 /**
2064 * @license
2065 * Copyright Google LLC All Rights Reserved.
2066 *
2067 * Use of this source code is governed by an MIT-style license that can be
2068 * found in the LICENSE file at https://angular.io/license
2069 */
2070 var LIVE_ANNOUNCER_ELEMENT_TOKEN = new i0.InjectionToken('liveAnnouncerElement', {
2071 providedIn: 'root',
2072 factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY,
2073 });
2074 /** @docs-private */
2075 function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
2076 return null;
2077 }
2078 /** Injection token that can be used to configure the default options for the LiveAnnouncer. */
2079 var LIVE_ANNOUNCER_DEFAULT_OPTIONS = new i0.InjectionToken('LIVE_ANNOUNCER_DEFAULT_OPTIONS');
2080
2081 var LiveAnnouncer = /** @class */ (function () {
2082 function LiveAnnouncer(elementToken, _ngZone, _document, _defaultOptions) {
2083 this._ngZone = _ngZone;
2084 this._defaultOptions = _defaultOptions;
2085 // We inject the live element and document as `any` because the constructor signature cannot
2086 // reference browser globals (HTMLElement, Document) on non-browser environments, since having
2087 // a class decorator causes TypeScript to preserve the constructor signature types.
2088 this._document = _document;
2089 this._liveElement = elementToken || this._createLiveElement();
2090 }
2091 LiveAnnouncer.prototype.announce = function (message) {
2092 var _a;
2093 var _this = this;
2094 var args = [];
2095 for (var _i = 1; _i < arguments.length; _i++) {
2096 args[_i - 1] = arguments[_i];
2097 }
2098 var defaultOptions = this._defaultOptions;
2099 var politeness;
2100 var duration;
2101 if (args.length === 1 && typeof args[0] === 'number') {
2102 duration = args[0];
2103 }
2104 else {
2105 _a = __read(args, 2), politeness = _a[0], duration = _a[1];
2106 }
2107 this.clear();
2108 clearTimeout(this._previousTimeout);
2109 if (!politeness) {
2110 politeness =
2111 (defaultOptions && defaultOptions.politeness) ? defaultOptions.politeness : 'polite';
2112 }
2113 if (duration == null && defaultOptions) {
2114 duration = defaultOptions.duration;
2115 }
2116 // TODO: ensure changing the politeness works on all environments we support.
2117 this._liveElement.setAttribute('aria-live', politeness);
2118 // This 100ms timeout is necessary for some browser + screen-reader combinations:
2119 // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
2120 // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
2121 // second time without clearing and then using a non-zero delay.
2122 // (using JAWS 17 at time of this writing).
2123 return this._ngZone.runOutsideAngular(function () {
2124 return new Promise(function (resolve) {
2125 clearTimeout(_this._previousTimeout);
2126 _this._previousTimeout = setTimeout(function () {
2127 _this._liveElement.textContent = message;
2128 resolve();
2129 if (typeof duration === 'number') {
2130 _this._previousTimeout = setTimeout(function () { return _this.clear(); }, duration);
2131 }
2132 }, 100);
2133 });
2134 });
2135 };
2136 /**
2137 * Clears the current text from the announcer element. Can be used to prevent
2138 * screen readers from reading the text out again while the user is going
2139 * through the page landmarks.
2140 */
2141 LiveAnnouncer.prototype.clear = function () {
2142 if (this._liveElement) {
2143 this._liveElement.textContent = '';
2144 }
2145 };
2146 LiveAnnouncer.prototype.ngOnDestroy = function () {
2147 clearTimeout(this._previousTimeout);
2148 if (this._liveElement && this._liveElement.parentNode) {
2149 this._liveElement.parentNode.removeChild(this._liveElement);
2150 this._liveElement = null;
2151 }
2152 };
2153 LiveAnnouncer.prototype._createLiveElement = function () {
2154 var elementClass = 'cdk-live-announcer-element';
2155 var previousElements = this._document.getElementsByClassName(elementClass);
2156 var liveEl = this._document.createElement('div');
2157 // Remove any old containers. This can happen when coming in from a server-side-rendered page.
2158 for (var i = 0; i < previousElements.length; i++) {
2159 previousElements[i].parentNode.removeChild(previousElements[i]);
2160 }
2161 liveEl.classList.add(elementClass);
2162 liveEl.classList.add('cdk-visually-hidden');
2163 liveEl.setAttribute('aria-atomic', 'true');
2164 liveEl.setAttribute('aria-live', 'polite');
2165 this._document.body.appendChild(liveEl);
2166 return liveEl;
2167 };
2168 return LiveAnnouncer;
2169 }());
2170 LiveAnnouncer.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function LiveAnnouncer_Factory() { return new LiveAnnouncer(i0__namespace.ɵɵinject(LIVE_ANNOUNCER_ELEMENT_TOKEN, 8), i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT), i0__namespace.ɵɵinject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, 8)); }, token: LiveAnnouncer, providedIn: "root" });
2171 LiveAnnouncer.decorators = [
2172 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2173 ];
2174 LiveAnnouncer.ctorParameters = function () { return [
2175 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [LIVE_ANNOUNCER_ELEMENT_TOKEN,] }] },
2176 { type: i0.NgZone },
2177 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] },
2178 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [LIVE_ANNOUNCER_DEFAULT_OPTIONS,] }] }
2179 ]; };
2180 /**
2181 * A directive that works similarly to aria-live, but uses the LiveAnnouncer to ensure compatibility
2182 * with a wider range of browsers and screen readers.
2183 */
2184 var CdkAriaLive = /** @class */ (function () {
2185 function CdkAriaLive(_elementRef, _liveAnnouncer, _contentObserver, _ngZone) {
2186 this._elementRef = _elementRef;
2187 this._liveAnnouncer = _liveAnnouncer;
2188 this._contentObserver = _contentObserver;
2189 this._ngZone = _ngZone;
2190 this._politeness = 'polite';
2191 }
2192 Object.defineProperty(CdkAriaLive.prototype, "politeness", {
2193 /** The aria-live politeness level to use when announcing messages. */
2194 get: function () { return this._politeness; },
2195 set: function (value) {
2196 var _this = this;
2197 this._politeness = value === 'off' || value === 'assertive' ? value : 'polite';
2198 if (this._politeness === 'off') {
2199 if (this._subscription) {
2200 this._subscription.unsubscribe();
2201 this._subscription = null;
2202 }
2203 }
2204 else if (!this._subscription) {
2205 this._subscription = this._ngZone.runOutsideAngular(function () {
2206 return _this._contentObserver
2207 .observe(_this._elementRef)
2208 .subscribe(function () {
2209 // Note that we use textContent here, rather than innerText, in order to avoid a reflow.
2210 var elementText = _this._elementRef.nativeElement.textContent;
2211 // The `MutationObserver` fires also for attribute
2212 // changes which we don't want to announce.
2213 if (elementText !== _this._previousAnnouncedText) {
2214 _this._liveAnnouncer.announce(elementText, _this._politeness);
2215 _this._previousAnnouncedText = elementText;
2216 }
2217 });
2218 });
2219 }
2220 },
2221 enumerable: false,
2222 configurable: true
2223 });
2224 CdkAriaLive.prototype.ngOnDestroy = function () {
2225 if (this._subscription) {
2226 this._subscription.unsubscribe();
2227 }
2228 };
2229 return CdkAriaLive;
2230 }());
2231 CdkAriaLive.decorators = [
2232 { type: i0.Directive, args: [{
2233 selector: '[cdkAriaLive]',
2234 exportAs: 'cdkAriaLive',
2235 },] }
2236 ];
2237 CdkAriaLive.ctorParameters = function () { return [
2238 { type: i0.ElementRef },
2239 { type: LiveAnnouncer },
2240 { type: observers.ContentObserver },
2241 { type: i0.NgZone }
2242 ]; };
2243 CdkAriaLive.propDecorators = {
2244 politeness: [{ type: i0.Input, args: ['cdkAriaLive',] }]
2245 };
2246
2247 /** InjectionToken for FocusMonitorOptions. */
2248 var FOCUS_MONITOR_DEFAULT_OPTIONS = new i0.InjectionToken('cdk-focus-monitor-default-options');
2249 /**
2250 * Event listener options that enable capturing and also
2251 * mark the listener as passive if the browser supports it.
2252 */
2253 var captureEventListenerOptions = i1.normalizePassiveListenerOptions({
2254 passive: true,
2255 capture: true
2256 });
2257 /** Monitors mouse and keyboard events to determine the cause of focus events. */
2258 var FocusMonitor = /** @class */ (function () {
2259 function FocusMonitor(_ngZone, _platform, _inputModalityDetector,
2260 /** @breaking-change 11.0.0 make document required */
2261 document, options) {
2262 var _this = this;
2263 this._ngZone = _ngZone;
2264 this._platform = _platform;
2265 this._inputModalityDetector = _inputModalityDetector;
2266 /** The focus origin that the next focus event is a result of. */
2267 this._origin = null;
2268 /** Whether the window has just been focused. */
2269 this._windowFocused = false;
2270 /**
2271 * Whether the origin was determined via a touch interaction. Necessary as properly attributing
2272 * focus events to touch interactions requires special logic.
2273 */
2274 this._originFromTouchInteraction = false;
2275 /** Map of elements being monitored to their info. */
2276 this._elementInfo = new Map();
2277 /** The number of elements currently being monitored. */
2278 this._monitoredElementCount = 0;
2279 /**
2280 * Keeps track of the root nodes to which we've currently bound a focus/blur handler,
2281 * as well as the number of monitored elements that they contain. We have to treat focus/blur
2282 * handlers differently from the rest of the events, because the browser won't emit events
2283 * to the document when focus moves inside of a shadow root.
2284 */
2285 this._rootNodeFocusListenerCount = new Map();
2286 /**
2287 * Event listener for `focus` events on the window.
2288 * Needs to be an arrow function in order to preserve the context when it gets bound.
2289 */
2290 this._windowFocusListener = function () {
2291 // Make a note of when the window regains focus, so we can
2292 // restore the origin info for the focused element.
2293 _this._windowFocused = true;
2294 _this._windowFocusTimeoutId = setTimeout(function () { return _this._windowFocused = false; });
2295 };
2296 /** Subject for stopping our InputModalityDetector subscription. */
2297 this._stopInputModalityDetector = new rxjs.Subject();
2298 /**
2299 * Event listener for `focus` and 'blur' events on the document.
2300 * Needs to be an arrow function in order to preserve the context when it gets bound.
2301 */
2302 this._rootNodeFocusAndBlurListener = function (event) {
2303 var target = i1._getEventTarget(event);
2304 var handler = event.type === 'focus' ? _this._onFocus : _this._onBlur;
2305 // We need to walk up the ancestor chain in order to support `checkChildren`.
2306 for (var element = target; element; element = element.parentElement) {
2307 handler.call(_this, event, element);
2308 }
2309 };
2310 this._document = document;
2311 this._detectionMode = (options === null || options === void 0 ? void 0 : options.detectionMode) || 0 /* IMMEDIATE */;
2312 }
2313 FocusMonitor.prototype.monitor = function (element, checkChildren) {
2314 if (checkChildren === void 0) { checkChildren = false; }
2315 var nativeElement = coercion.coerceElement(element);
2316 // Do nothing if we're not on the browser platform or the passed in node isn't an element.
2317 if (!this._platform.isBrowser || nativeElement.nodeType !== 1) {
2318 return rxjs.of(null);
2319 }
2320 // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to
2321 // the shadow root, rather than the `document`, because the browser won't emit focus events
2322 // to the `document`, if focus is moving within the same shadow root.
2323 var rootNode = i1._getShadowRoot(nativeElement) || this._getDocument();
2324 var cachedInfo = this._elementInfo.get(nativeElement);
2325 // Check if we're already monitoring this element.
2326 if (cachedInfo) {
2327 if (checkChildren) {
2328 // TODO(COMP-318): this can be problematic, because it'll turn all non-checkChildren
2329 // observers into ones that behave as if `checkChildren` was turned on. We need a more
2330 // robust solution.
2331 cachedInfo.checkChildren = true;
2332 }
2333 return cachedInfo.subject;
2334 }
2335 // Create monitored element info.
2336 var info = {
2337 checkChildren: checkChildren,
2338 subject: new rxjs.Subject(),
2339 rootNode: rootNode
2340 };
2341 this._elementInfo.set(nativeElement, info);
2342 this._registerGlobalListeners(info);
2343 return info.subject;
2344 };
2345 FocusMonitor.prototype.stopMonitoring = function (element) {
2346 var nativeElement = coercion.coerceElement(element);
2347 var elementInfo = this._elementInfo.get(nativeElement);
2348 if (elementInfo) {
2349 elementInfo.subject.complete();
2350 this._setClasses(nativeElement);
2351 this._elementInfo.delete(nativeElement);
2352 this._removeGlobalListeners(elementInfo);
2353 }
2354 };
2355 FocusMonitor.prototype.focusVia = function (element, origin, options) {
2356 var _this = this;
2357 var nativeElement = coercion.coerceElement(element);
2358 var focusedElement = this._getDocument().activeElement;
2359 // If the element is focused already, calling `focus` again won't trigger the event listener
2360 // which means that the focus classes won't be updated. If that's the case, update the classes
2361 // directly without waiting for an event.
2362 if (nativeElement === focusedElement) {
2363 this._getClosestElementsInfo(nativeElement)
2364 .forEach(function (_a) {
2365 var _b = __read(_a, 2), currentElement = _b[0], info = _b[1];
2366 return _this._originChanged(currentElement, origin, info);
2367 });
2368 }
2369 else {
2370 this._setOrigin(origin);
2371 // `focus` isn't available on the server
2372 if (typeof nativeElement.focus === 'function') {
2373 nativeElement.focus(options);
2374 }
2375 }
2376 };
2377 FocusMonitor.prototype.ngOnDestroy = function () {
2378 var _this = this;
2379 this._elementInfo.forEach(function (_info, element) { return _this.stopMonitoring(element); });
2380 };
2381 /** Access injected document if available or fallback to global document reference */
2382 FocusMonitor.prototype._getDocument = function () {
2383 return this._document || document;
2384 };
2385 /** Use defaultView of injected document if available or fallback to global window reference */
2386 FocusMonitor.prototype._getWindow = function () {
2387 var doc = this._getDocument();
2388 return doc.defaultView || window;
2389 };
2390 FocusMonitor.prototype._toggleClass = function (element, className, shouldSet) {
2391 if (shouldSet) {
2392 element.classList.add(className);
2393 }
2394 else {
2395 element.classList.remove(className);
2396 }
2397 };
2398 FocusMonitor.prototype._getFocusOrigin = function (focusEventTarget) {
2399 if (this._origin) {
2400 // If the origin was realized via a touch interaction, we need to perform additional checks
2401 // to determine whether the focus origin should be attributed to touch or program.
2402 if (this._originFromTouchInteraction) {
2403 return this._shouldBeAttributedToTouch(focusEventTarget) ? 'touch' : 'program';
2404 }
2405 else {
2406 return this._origin;
2407 }
2408 }
2409 // If the window has just regained focus, we can restore the most recent origin from before the
2410 // window blurred. Otherwise, we've reached the point where we can't identify the source of the
2411 // focus. This typically means one of two things happened:
2412 //
2413 // 1) The element was programmatically focused, or
2414 // 2) The element was focused via screen reader navigation (which generally doesn't fire
2415 // events).
2416 //
2417 // Because we can't distinguish between these two cases, we default to setting `program`.
2418 return (this._windowFocused && this._lastFocusOrigin) ? this._lastFocusOrigin : 'program';
2419 };
2420 /**
2421 * Returns whether the focus event should be attributed to touch. Recall that in IMMEDIATE mode, a
2422 * touch origin isn't immediately reset at the next tick (see _setOrigin). This means that when we
2423 * handle a focus event following a touch interaction, we need to determine whether (1) the focus
2424 * event was directly caused by the touch interaction or (2) the focus event was caused by a
2425 * subsequent programmatic focus call triggered by the touch interaction.
2426 * @param focusEventTarget The target of the focus event under examination.
2427 */
2428 FocusMonitor.prototype._shouldBeAttributedToTouch = function (focusEventTarget) {
2429 // Please note that this check is not perfect. Consider the following edge case:
2430 //
2431 // <div #parent tabindex="0">
2432 // <div #child tabindex="0" (click)="#parent.focus()"></div>
2433 // </div>
2434 //
2435 // Suppose there is a FocusMonitor in IMMEDIATE mode attached to #parent. When the user touches
2436 // #child, #parent is programmatically focused. This code will attribute the focus to touch
2437 // instead of program. This is a relatively minor edge-case that can be worked around by using
2438 // focusVia(parent, 'program') to focus #parent.
2439 return (this._detectionMode === 1 /* EVENTUAL */) ||
2440 !!(focusEventTarget === null || focusEventTarget === void 0 ? void 0 : focusEventTarget.contains(this._inputModalityDetector._mostRecentTarget));
2441 };
2442 /**
2443 * Sets the focus classes on the element based on the given focus origin.
2444 * @param element The element to update the classes on.
2445 * @param origin The focus origin.
2446 */
2447 FocusMonitor.prototype._setClasses = function (element, origin) {
2448 this._toggleClass(element, 'cdk-focused', !!origin);
2449 this._toggleClass(element, 'cdk-touch-focused', origin === 'touch');
2450 this._toggleClass(element, 'cdk-keyboard-focused', origin === 'keyboard');
2451 this._toggleClass(element, 'cdk-mouse-focused', origin === 'mouse');
2452 this._toggleClass(element, 'cdk-program-focused', origin === 'program');
2453 };
2454 /**
2455 * Updates the focus origin. If we're using immediate detection mode, we schedule an async
2456 * function to clear the origin at the end of a timeout. The duration of the timeout depends on
2457 * the origin being set.
2458 * @param origin The origin to set.
2459 * @param isFromInteraction Whether we are setting the origin from an interaction event.
2460 */
2461 FocusMonitor.prototype._setOrigin = function (origin, isFromInteraction) {
2462 var _this = this;
2463 if (isFromInteraction === void 0) { isFromInteraction = false; }
2464 this._ngZone.runOutsideAngular(function () {
2465 _this._origin = origin;
2466 _this._originFromTouchInteraction = (origin === 'touch') && isFromInteraction;
2467 // If we're in IMMEDIATE mode, reset the origin at the next tick (or in `TOUCH_BUFFER_MS` ms
2468 // for a touch event). We reset the origin at the next tick because Firefox focuses one tick
2469 // after the interaction event. We wait `TOUCH_BUFFER_MS` ms before resetting the origin for
2470 // a touch event because when a touch event is fired, the associated focus event isn't yet in
2471 // the event queue. Before doing so, clear any pending timeouts.
2472 if (_this._detectionMode === 0 /* IMMEDIATE */) {
2473 clearTimeout(_this._originTimeoutId);
2474 var ms = _this._originFromTouchInteraction ? TOUCH_BUFFER_MS : 1;
2475 _this._originTimeoutId = setTimeout(function () { return _this._origin = null; }, ms);
2476 }
2477 });
2478 };
2479 /**
2480 * Handles focus events on a registered element.
2481 * @param event The focus event.
2482 * @param element The monitored element.
2483 */
2484 FocusMonitor.prototype._onFocus = function (event, element) {
2485 // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
2486 // focus event affecting the monitored element. If we want to use the origin of the first event
2487 // instead we should check for the cdk-focused class here and return if the element already has
2488 // it. (This only matters for elements that have includesChildren = true).
2489 // If we are not counting child-element-focus as focused, make sure that the event target is the
2490 // monitored element itself.
2491 var elementInfo = this._elementInfo.get(element);
2492 var focusEventTarget = i1._getEventTarget(event);
2493 if (!elementInfo || (!elementInfo.checkChildren && element !== focusEventTarget)) {
2494 return;
2495 }
2496 this._originChanged(element, this._getFocusOrigin(focusEventTarget), elementInfo);
2497 };
2498 /**
2499 * Handles blur events on a registered element.
2500 * @param event The blur event.
2501 * @param element The monitored element.
2502 */
2503 FocusMonitor.prototype._onBlur = function (event, element) {
2504 // If we are counting child-element-focus as focused, make sure that we aren't just blurring in
2505 // order to focus another child of the monitored element.
2506 var elementInfo = this._elementInfo.get(element);
2507 if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
2508 element.contains(event.relatedTarget))) {
2509 return;
2510 }
2511 this._setClasses(element);
2512 this._emitOrigin(elementInfo.subject, null);
2513 };
2514 FocusMonitor.prototype._emitOrigin = function (subject, origin) {
2515 this._ngZone.run(function () { return subject.next(origin); });
2516 };
2517 FocusMonitor.prototype._registerGlobalListeners = function (elementInfo) {
2518 var _this = this;
2519 if (!this._platform.isBrowser) {
2520 return;
2521 }
2522 var rootNode = elementInfo.rootNode;
2523 var rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;
2524 if (!rootNodeFocusListeners) {
2525 this._ngZone.runOutsideAngular(function () {
2526 rootNode.addEventListener('focus', _this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2527 rootNode.addEventListener('blur', _this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2528 });
2529 }
2530 this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1);
2531 // Register global listeners when first element is monitored.
2532 if (++this._monitoredElementCount === 1) {
2533 // Note: we listen to events in the capture phase so we
2534 // can detect them even if the user stops propagation.
2535 this._ngZone.runOutsideAngular(function () {
2536 var window = _this._getWindow();
2537 window.addEventListener('focus', _this._windowFocusListener);
2538 });
2539 // The InputModalityDetector is also just a collection of global listeners.
2540 this._inputModalityDetector.modalityDetected
2541 .pipe(operators.takeUntil(this._stopInputModalityDetector))
2542 .subscribe(function (modality) { _this._setOrigin(modality, true /* isFromInteraction */); });
2543 }
2544 };
2545 FocusMonitor.prototype._removeGlobalListeners = function (elementInfo) {
2546 var rootNode = elementInfo.rootNode;
2547 if (this._rootNodeFocusListenerCount.has(rootNode)) {
2548 var rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode);
2549 if (rootNodeFocusListeners > 1) {
2550 this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);
2551 }
2552 else {
2553 rootNode.removeEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2554 rootNode.removeEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
2555 this._rootNodeFocusListenerCount.delete(rootNode);
2556 }
2557 }
2558 // Unregister global listeners when last element is unmonitored.
2559 if (!--this._monitoredElementCount) {
2560 var window = this._getWindow();
2561 window.removeEventListener('focus', this._windowFocusListener);
2562 // Equivalently, stop our InputModalityDetector subscription.
2563 this._stopInputModalityDetector.next();
2564 // Clear timeouts for all potentially pending timeouts to prevent the leaks.
2565 clearTimeout(this._windowFocusTimeoutId);
2566 clearTimeout(this._originTimeoutId);
2567 }
2568 };
2569 /** Updates all the state on an element once its focus origin has changed. */
2570 FocusMonitor.prototype._originChanged = function (element, origin, elementInfo) {
2571 this._setClasses(element, origin);
2572 this._emitOrigin(elementInfo.subject, origin);
2573 this._lastFocusOrigin = origin;
2574 };
2575 /**
2576 * Collects the `MonitoredElementInfo` of a particular element and
2577 * all of its ancestors that have enabled `checkChildren`.
2578 * @param element Element from which to start the search.
2579 */
2580 FocusMonitor.prototype._getClosestElementsInfo = function (element) {
2581 var results = [];
2582 this._elementInfo.forEach(function (info, currentElement) {
2583 if (currentElement === element || (info.checkChildren && currentElement.contains(element))) {
2584 results.push([currentElement, info]);
2585 }
2586 });
2587 return results;
2588 };
2589 return FocusMonitor;
2590 }());
2591 FocusMonitor.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function FocusMonitor_Factory() { return new FocusMonitor(i0__namespace.ɵɵinject(i0__namespace.NgZone), i0__namespace.ɵɵinject(i1__namespace.Platform), i0__namespace.ɵɵinject(InputModalityDetector), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT, 8), i0__namespace.ɵɵinject(FOCUS_MONITOR_DEFAULT_OPTIONS, 8)); }, token: FocusMonitor, providedIn: "root" });
2592 FocusMonitor.decorators = [
2593 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2594 ];
2595 FocusMonitor.ctorParameters = function () { return [
2596 { type: i0.NgZone },
2597 { type: i1.Platform },
2598 { type: InputModalityDetector },
2599 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [i2.DOCUMENT,] }] },
2600 { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FOCUS_MONITOR_DEFAULT_OPTIONS,] }] }
2601 ]; };
2602 /**
2603 * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or
2604 * programmatically) and adds corresponding classes to the element.
2605 *
2606 * There are two variants of this directive:
2607 * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is
2608 * focused.
2609 * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.
2610 */
2611 var CdkMonitorFocus = /** @class */ (function () {
2612 function CdkMonitorFocus(_elementRef, _focusMonitor) {
2613 this._elementRef = _elementRef;
2614 this._focusMonitor = _focusMonitor;
2615 this.cdkFocusChange = new i0.EventEmitter();
2616 }
2617 CdkMonitorFocus.prototype.ngAfterViewInit = function () {
2618 var _this = this;
2619 var element = this._elementRef.nativeElement;
2620 this._monitorSubscription = this._focusMonitor.monitor(element, element.nodeType === 1 && element.hasAttribute('cdkMonitorSubtreeFocus'))
2621 .subscribe(function (origin) { return _this.cdkFocusChange.emit(origin); });
2622 };
2623 CdkMonitorFocus.prototype.ngOnDestroy = function () {
2624 this._focusMonitor.stopMonitoring(this._elementRef);
2625 if (this._monitorSubscription) {
2626 this._monitorSubscription.unsubscribe();
2627 }
2628 };
2629 return CdkMonitorFocus;
2630 }());
2631 CdkMonitorFocus.decorators = [
2632 { type: i0.Directive, args: [{
2633 selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]',
2634 },] }
2635 ];
2636 CdkMonitorFocus.ctorParameters = function () { return [
2637 { type: i0.ElementRef },
2638 { type: FocusMonitor }
2639 ]; };
2640 CdkMonitorFocus.propDecorators = {
2641 cdkFocusChange: [{ type: i0.Output }]
2642 };
2643
2644 /**
2645 * @license
2646 * Copyright Google LLC All Rights Reserved.
2647 *
2648 * Use of this source code is governed by an MIT-style license that can be
2649 * found in the LICENSE file at https://angular.io/license
2650 */
2651 /** CSS class applied to the document body when in black-on-white high-contrast mode. */
2652 var BLACK_ON_WHITE_CSS_CLASS = 'cdk-high-contrast-black-on-white';
2653 /** CSS class applied to the document body when in white-on-black high-contrast mode. */
2654 var WHITE_ON_BLACK_CSS_CLASS = 'cdk-high-contrast-white-on-black';
2655 /** CSS class applied to the document body when in high-contrast mode. */
2656 var HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';
2657 /**
2658 * Service to determine whether the browser is currently in a high-contrast-mode environment.
2659 *
2660 * Microsoft Windows supports an accessibility feature called "High Contrast Mode". This mode
2661 * changes the appearance of all applications, including web applications, to dramatically increase
2662 * contrast.
2663 *
2664 * IE, Edge, and Firefox currently support this mode. Chrome does not support Windows High Contrast
2665 * Mode. This service does not detect high-contrast mode as added by the Chrome "High Contrast"
2666 * browser extension.
2667 */
2668 var HighContrastModeDetector = /** @class */ (function () {
2669 function HighContrastModeDetector(_platform, document) {
2670 this._platform = _platform;
2671 this._document = document;
2672 }
2673 /** Gets the current high-contrast-mode for the page. */
2674 HighContrastModeDetector.prototype.getHighContrastMode = function () {
2675 if (!this._platform.isBrowser) {
2676 return 0 /* NONE */;
2677 }
2678 // Create a test element with an arbitrary background-color that is neither black nor
2679 // white; high-contrast mode will coerce the color to either black or white. Also ensure that
2680 // appending the test element to the DOM does not affect layout by absolutely positioning it
2681 var testElement = this._document.createElement('div');
2682 testElement.style.backgroundColor = 'rgb(1,2,3)';
2683 testElement.style.position = 'absolute';
2684 this._document.body.appendChild(testElement);
2685 // Get the computed style for the background color, collapsing spaces to normalize between
2686 // browsers. Once we get this color, we no longer need the test element. Access the `window`
2687 // via the document so we can fake it in tests. Note that we have extra null checks, because
2688 // this logic will likely run during app bootstrap and throwing can break the entire app.
2689 var documentWindow = this._document.defaultView || window;
2690 var computedStyle = (documentWindow && documentWindow.getComputedStyle) ?
2691 documentWindow.getComputedStyle(testElement) : null;
2692 var computedColor = (computedStyle && computedStyle.backgroundColor || '').replace(/ /g, '');
2693 this._document.body.removeChild(testElement);
2694 switch (computedColor) {
2695 case 'rgb(0,0,0)': return 2 /* WHITE_ON_BLACK */;
2696 case 'rgb(255,255,255)': return 1 /* BLACK_ON_WHITE */;
2697 }
2698 return 0 /* NONE */;
2699 };
2700 /** Applies CSS classes indicating high-contrast mode to document body (browser-only). */
2701 HighContrastModeDetector.prototype._applyBodyHighContrastModeCssClasses = function () {
2702 if (!this._hasCheckedHighContrastMode && this._platform.isBrowser && this._document.body) {
2703 var bodyClasses = this._document.body.classList;
2704 // IE11 doesn't support `classList` operations with multiple arguments
2705 bodyClasses.remove(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
2706 bodyClasses.remove(BLACK_ON_WHITE_CSS_CLASS);
2707 bodyClasses.remove(WHITE_ON_BLACK_CSS_CLASS);
2708 this._hasCheckedHighContrastMode = true;
2709 var mode = this.getHighContrastMode();
2710 if (mode === 1 /* BLACK_ON_WHITE */) {
2711 bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
2712 bodyClasses.add(BLACK_ON_WHITE_CSS_CLASS);
2713 }
2714 else if (mode === 2 /* WHITE_ON_BLACK */) {
2715 bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
2716 bodyClasses.add(WHITE_ON_BLACK_CSS_CLASS);
2717 }
2718 }
2719 };
2720 return HighContrastModeDetector;
2721 }());
2722 HighContrastModeDetector.ɵprov = i0__namespace.ɵɵdefineInjectable({ factory: function HighContrastModeDetector_Factory() { return new HighContrastModeDetector(i0__namespace.ɵɵinject(i1__namespace.Platform), i0__namespace.ɵɵinject(i2__namespace.DOCUMENT)); }, token: HighContrastModeDetector, providedIn: "root" });
2723 HighContrastModeDetector.decorators = [
2724 { type: i0.Injectable, args: [{ providedIn: 'root' },] }
2725 ];
2726 HighContrastModeDetector.ctorParameters = function () { return [
2727 { type: i1.Platform },
2728 { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
2729 ]; };
2730
2731 /**
2732 * @license
2733 * Copyright Google LLC All Rights Reserved.
2734 *
2735 * Use of this source code is governed by an MIT-style license that can be
2736 * found in the LICENSE file at https://angular.io/license
2737 */
2738 var A11yModule = /** @class */ (function () {
2739 function A11yModule(highContrastModeDetector) {
2740 highContrastModeDetector._applyBodyHighContrastModeCssClasses();
2741 }
2742 return A11yModule;
2743 }());
2744 A11yModule.decorators = [
2745 { type: i0.NgModule, args: [{
2746 imports: [i1.PlatformModule, observers.ObserversModule],
2747 declarations: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
2748 exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
2749 },] }
2750 ];
2751 A11yModule.ctorParameters = function () { return [
2752 { type: HighContrastModeDetector }
2753 ]; };
2754
2755 /**
2756 * @license
2757 * Copyright Google LLC All Rights Reserved.
2758 *
2759 * Use of this source code is governed by an MIT-style license that can be
2760 * found in the LICENSE file at https://angular.io/license
2761 */
2762
2763 /**
2764 * Generated bundle index. Do not edit.
2765 */
2766
2767 exports.A11yModule = A11yModule;
2768 exports.ActiveDescendantKeyManager = ActiveDescendantKeyManager;
2769 exports.AriaDescriber = AriaDescriber;
2770 exports.CDK_DESCRIBEDBY_HOST_ATTRIBUTE = CDK_DESCRIBEDBY_HOST_ATTRIBUTE;
2771 exports.CDK_DESCRIBEDBY_ID_PREFIX = CDK_DESCRIBEDBY_ID_PREFIX;
2772 exports.CdkAriaLive = CdkAriaLive;
2773 exports.CdkMonitorFocus = CdkMonitorFocus;
2774 exports.CdkTrapFocus = CdkTrapFocus;
2775 exports.ConfigurableFocusTrap = ConfigurableFocusTrap;
2776 exports.ConfigurableFocusTrapFactory = ConfigurableFocusTrapFactory;
2777 exports.EventListenerFocusTrapInertStrategy = EventListenerFocusTrapInertStrategy;
2778 exports.FOCUS_MONITOR_DEFAULT_OPTIONS = FOCUS_MONITOR_DEFAULT_OPTIONS;
2779 exports.FOCUS_TRAP_INERT_STRATEGY = FOCUS_TRAP_INERT_STRATEGY;
2780 exports.FocusKeyManager = FocusKeyManager;
2781 exports.FocusMonitor = FocusMonitor;
2782 exports.FocusTrap = FocusTrap;
2783 exports.FocusTrapFactory = FocusTrapFactory;
2784 exports.HighContrastModeDetector = HighContrastModeDetector;
2785 exports.INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS = INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS;
2786 exports.INPUT_MODALITY_DETECTOR_OPTIONS = INPUT_MODALITY_DETECTOR_OPTIONS;
2787 exports.InputModalityDetector = InputModalityDetector;
2788 exports.InteractivityChecker = InteractivityChecker;
2789 exports.IsFocusableConfig = IsFocusableConfig;
2790 exports.LIVE_ANNOUNCER_DEFAULT_OPTIONS = LIVE_ANNOUNCER_DEFAULT_OPTIONS;
2791 exports.LIVE_ANNOUNCER_ELEMENT_TOKEN = LIVE_ANNOUNCER_ELEMENT_TOKEN;
2792 exports.LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY = LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY;
2793 exports.ListKeyManager = ListKeyManager;
2794 exports.LiveAnnouncer = LiveAnnouncer;
2795 exports.MESSAGES_CONTAINER_ID = MESSAGES_CONTAINER_ID;
2796 exports.isFakeMousedownFromScreenReader = isFakeMousedownFromScreenReader;
2797 exports.isFakeTouchstartFromScreenReader = isFakeTouchstartFromScreenReader;
2798 exports.ɵangular_material_src_cdk_a11y_a11y_a = FocusTrapManager;
2799
2800 Object.defineProperty(exports, '__esModule', { value: true });
2801
2802})));
2803//# sourceMappingURL=cdk-a11y.umd.js.map