(function (global, factory) {
    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')) :
    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) :
    (global = 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));
}(this, (function (exports, i2, i0, rxjs, keycodes, operators, coercion, i1, observers) { 'use strict';

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** IDs are delimited by an empty space, as per the spec. */
    var ID_DELIMITER = ' ';
    /**
     * Adds the given ID to the specified ARIA attribute on an element.
     * Used for attributes such as aria-labelledby, aria-owns, etc.
     */
    function addAriaReferencedId(el, attr, id) {
        var ids = getAriaReferenceIds(el, attr);
        if (ids.some(function (existingId) { return existingId.trim() == id.trim(); })) {
            return;
        }
        ids.push(id.trim());
        el.setAttribute(attr, ids.join(ID_DELIMITER));
    }
    /**
     * Removes the given ID from the specified ARIA attribute on an element.
     * Used for attributes such as aria-labelledby, aria-owns, etc.
     */
    function removeAriaReferencedId(el, attr, id) {
        var ids = getAriaReferenceIds(el, attr);
        var filteredIds = ids.filter(function (val) { return val != id.trim(); });
        if (filteredIds.length) {
            el.setAttribute(attr, filteredIds.join(ID_DELIMITER));
        }
        else {
            el.removeAttribute(attr);
        }
    }
    /**
     * Gets the list of IDs referenced by the given ARIA attribute on an element.
     * Used for attributes such as aria-labelledby, aria-owns, etc.
     */
    function getAriaReferenceIds(el, attr) {
        // Get string array of all individual ids (whitespace delimited) in the attribute value
        return (el.getAttribute(attr) || '').match(/\S+/g) || [];
    }

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** ID used for the body container where all messages are appended. */
    var MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
    /** ID prefix used for each created message element. */
    var CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
    /** Attribute given to each host element that is described by a message element. */
    var CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
    /** Global incremental identifier for each registered message element. */
    var nextId = 0;
    /** Global map of all registered message elements that have been placed into the document. */
    var messageRegistry = new Map();
    /** Container for all registered messages. */
    var messagesContainer = null;
    /**
     * Utility that creates visually hidden elements with a message content. Useful for elements that
     * want to use aria-describedby to further describe themselves without adding additional visual
     * content.
     */
    var AriaDescriber = /** @class */ (function () {
        function AriaDescriber(_document) {
            this._document = _document;
        }
        AriaDescriber.prototype.describe = function (hostElement, message, role) {
            if (!this._canBeDescribed(hostElement, message)) {
                return;
            }
            var key = getKey(message, role);
            if (typeof message !== 'string') {
                // We need to ensure that the element has an ID.
                setMessageId(message);
                messageRegistry.set(key, { messageElement: message, referenceCount: 0 });
            }
            else if (!messageRegistry.has(key)) {
                this._createMessageElement(message, role);
            }
            if (!this._isElementDescribedByMessage(hostElement, key)) {
                this._addMessageReference(hostElement, key);
            }
        };
        AriaDescriber.prototype.removeDescription = function (hostElement, message, role) {
            if (!message || !this._isElementNode(hostElement)) {
                return;
            }
            var key = getKey(message, role);
            if (this._isElementDescribedByMessage(hostElement, key)) {
                this._removeMessageReference(hostElement, key);
            }
            // If the message is a string, it means that it's one that we created for the
            // consumer so we can remove it safely, otherwise we should leave it in place.
            if (typeof message === 'string') {
                var registeredMessage = messageRegistry.get(key);
                if (registeredMessage && registeredMessage.referenceCount === 0) {
                    this._deleteMessageElement(key);
                }
            }
            if (messagesContainer && messagesContainer.childNodes.length === 0) {
                this._deleteMessagesContainer();
            }
        };
        /** Unregisters all created message elements and removes the message container. */
        AriaDescriber.prototype.ngOnDestroy = function () {
            var describedElements = this._document.querySelectorAll("[" + CDK_DESCRIBEDBY_HOST_ATTRIBUTE + "]");
            for (var i = 0; i < describedElements.length; i++) {
                this._removeCdkDescribedByReferenceIds(describedElements[i]);
                describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
            }
            if (messagesContainer) {
                this._deleteMessagesContainer();
            }
            messageRegistry.clear();
        };
        /**
         * Creates a new element in the visually hidden message container element with the message
         * as its content and adds it to the message registry.
         */
        AriaDescriber.prototype._createMessageElement = function (message, role) {
            var messageElement = this._document.createElement('div');
            setMessageId(messageElement);
            messageElement.textContent = message;
            if (role) {
                messageElement.setAttribute('role', role);
            }
            this._createMessagesContainer();
            messagesContainer.appendChild(messageElement);
            messageRegistry.set(getKey(message, role), { messageElement: messageElement, referenceCount: 0 });
        };
        /** Deletes the message element from the global messages container. */
        AriaDescriber.prototype._deleteMessageElement = function (key) {
            var registeredMessage = messageRegistry.get(key);
            var messageElement = registeredMessage && registeredMessage.messageElement;
            if (messagesContainer && messageElement) {
                messagesContainer.removeChild(messageElement);
            }
            messageRegistry.delete(key);
        };
        /** Creates the global container for all aria-describedby messages. */
        AriaDescriber.prototype._createMessagesContainer = function () {
            if (!messagesContainer) {
                var preExistingContainer = this._document.getElementById(MESSAGES_CONTAINER_ID);
                // When going from the server to the client, we may end up in a situation where there's
                // already a container on the page, but we don't have a reference to it. Clear the
                // old container so we don't get duplicates. Doing this, instead of emptying the previous
                // container, should be slightly faster.
                if (preExistingContainer && preExistingContainer.parentNode) {
                    preExistingContainer.parentNode.removeChild(preExistingContainer);
                }
                messagesContainer = this._document.createElement('div');
                messagesContainer.id = MESSAGES_CONTAINER_ID;
                // We add `visibility: hidden` in order to prevent text in this container from
                // being searchable by the browser's Ctrl + F functionality.
                // Screen-readers will still read the description for elements with aria-describedby even
                // when the description element is not visible.
                messagesContainer.style.visibility = 'hidden';
                // Even though we use `visibility: hidden`, we still apply `cdk-visually-hidden` so that
                // the description element doesn't impact page layout.
                messagesContainer.classList.add('cdk-visually-hidden');
                this._document.body.appendChild(messagesContainer);
            }
        };
        /** Deletes the global messages container. */
        AriaDescriber.prototype._deleteMessagesContainer = function () {
            if (messagesContainer && messagesContainer.parentNode) {
                messagesContainer.parentNode.removeChild(messagesContainer);
                messagesContainer = null;
            }
        };
        /** Removes all cdk-describedby messages that are hosted through the element. */
        AriaDescriber.prototype._removeCdkDescribedByReferenceIds = function (element) {
            // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
            var originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
                .filter(function (id) { return id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0; });
            element.setAttribute('aria-describedby', originalReferenceIds.join(' '));
        };
        /**
         * Adds a message reference to the element using aria-describedby and increments the registered
         * message's reference count.
         */
        AriaDescriber.prototype._addMessageReference = function (element, key) {
            var registeredMessage = messageRegistry.get(key);
            // Add the aria-describedby reference and set the
            // describedby_host attribute to mark the element.
            addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
            element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, '');
            registeredMessage.referenceCount++;
        };
        /**
         * Removes a message reference from the element using aria-describedby
         * and decrements the registered message's reference count.
         */
        AriaDescriber.prototype._removeMessageReference = function (element, key) {
            var registeredMessage = messageRegistry.get(key);
            registeredMessage.referenceCount--;
            removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
            element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
        };
        /** Returns true if the element has been described by the provided message ID. */
        AriaDescriber.prototype._isElementDescribedByMessage = function (element, key) {
            var referenceIds = getAriaReferenceIds(element, 'aria-describedby');
            var registeredMessage = messageRegistry.get(key);
            var messageId = registeredMessage && registeredMessage.messageElement.id;
            return !!messageId && referenceIds.indexOf(messageId) != -1;
        };
        /** Determines whether a message can be described on a particular element. */
        AriaDescriber.prototype._canBeDescribed = function (element, message) {
            if (!this._isElementNode(element)) {
                return false;
            }
            if (message && typeof message === 'object') {
                // We'd have to make some assumptions about the description element's text, if the consumer
                // passed in an element. Assume that if an element is passed in, the consumer has verified
                // that it can be used as a description.
                return true;
            }
            var trimmedMessage = message == null ? '' : ("" + message).trim();
            var ariaLabel = element.getAttribute('aria-label');
            // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the
            // element, because screen readers will end up reading out the same text twice in a row.
            return trimmedMessage ? (!ariaLabel || ariaLabel.trim() !== trimmedMessage) : false;
        };
        /** Checks whether a node is an Element node. */
        AriaDescriber.prototype._isElementNode = function (element) {
            return element.nodeType === this._document.ELEMENT_NODE;
        };
        return AriaDescriber;
    }());
    AriaDescriber.ɵprov = i0.ɵɵdefineInjectable({ factory: function AriaDescriber_Factory() { return new AriaDescriber(i0.ɵɵinject(i2.DOCUMENT)); }, token: AriaDescriber, providedIn: "root" });
    AriaDescriber.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    AriaDescriber.ctorParameters = function () { return [
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
    ]; };
    /** Gets a key that can be used to look messages up in the registry. */
    function getKey(message, role) {
        return typeof message === 'string' ? (role || '') + "/" + message : message;
    }
    /** Assigns a unique ID to an element, if it doesn't have one already. */
    function setMessageId(element) {
        if (!element.id) {
            element.id = CDK_DESCRIBEDBY_ID_PREFIX + "-" + nextId++;
        }
    }

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b)
                if (Object.prototype.hasOwnProperty.call(b, p))
                    d[p] = b[p]; };
        return extendStatics(d, b);
    };
    function __extends(d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    }
    var __assign = function () {
        __assign = Object.assign || function __assign(t) {
            for (var s, i = 1, n = arguments.length; i < n; i++) {
                s = arguments[i];
                for (var p in s)
                    if (Object.prototype.hasOwnProperty.call(s, p))
                        t[p] = s[p];
            }
            return t;
        };
        return __assign.apply(this, arguments);
    };
    function __rest(s, e) {
        var t = {};
        for (var p in s)
            if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
                t[p] = s[p];
        if (s != null && typeof Object.getOwnPropertySymbols === "function")
            for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
                if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                    t[p[i]] = s[p[i]];
            }
        return t;
    }
    function __decorate(decorators, target, key, desc) {
        var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
        if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
            r = Reflect.decorate(decorators, target, key, desc);
        else
            for (var i = decorators.length - 1; i >= 0; i--)
                if (d = decorators[i])
                    r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
        return c > 3 && r && Object.defineProperty(target, key, r), r;
    }
    function __param(paramIndex, decorator) {
        return function (target, key) { decorator(target, key, paramIndex); };
    }
    function __metadata(metadataKey, metadataValue) {
        if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
            return Reflect.metadata(metadataKey, metadataValue);
    }
    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try {
                step(generator.next(value));
            }
            catch (e) {
                reject(e);
            } }
            function rejected(value) { try {
                step(generator["throw"](value));
            }
            catch (e) {
                reject(e);
            } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }
    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function () { if (t[0] & 1)
                throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f)
                throw new TypeError("Generator is already executing.");
            while (_)
                try {
                    if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
                        return t;
                    if (y = 0, t)
                        op = [op[0] & 2, t.value];
                    switch (op[0]) {
                        case 0:
                        case 1:
                            t = op;
                            break;
                        case 4:
                            _.label++;
                            return { value: op[1], done: false };
                        case 5:
                            _.label++;
                            y = op[1];
                            op = [0];
                            continue;
                        case 7:
                            op = _.ops.pop();
                            _.trys.pop();
                            continue;
                        default:
                            if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                                _ = 0;
                                continue;
                            }
                            if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
                                _.label = op[1];
                                break;
                            }
                            if (op[0] === 6 && _.label < t[1]) {
                                _.label = t[1];
                                t = op;
                                break;
                            }
                            if (t && _.label < t[2]) {
                                _.label = t[2];
                                _.ops.push(op);
                                break;
                            }
                            if (t[2])
                                _.ops.pop();
                            _.trys.pop();
                            continue;
                    }
                    op = body.call(thisArg, _);
                }
                catch (e) {
                    op = [6, e];
                    y = 0;
                }
                finally {
                    f = t = 0;
                }
            if (op[0] & 5)
                throw op[1];
            return { value: op[0] ? op[1] : void 0, done: true };
        }
    }
    var __createBinding = Object.create ? (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
    }) : (function (o, m, k, k2) {
        if (k2 === undefined)
            k2 = k;
        o[k2] = m[k];
    });
    function __exportStar(m, o) {
        for (var p in m)
            if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p))
                __createBinding(o, m, p);
    }
    function __values(o) {
        var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
        if (m)
            return m.call(o);
        if (o && typeof o.length === "number")
            return {
                next: function () {
                    if (o && i >= o.length)
                        o = void 0;
                    return { value: o && o[i++], done: !o };
                }
            };
        throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
    }
    function __read(o, n) {
        var m = typeof Symbol === "function" && o[Symbol.iterator];
        if (!m)
            return o;
        var i = m.call(o), r, ar = [], e;
        try {
            while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
                ar.push(r.value);
        }
        catch (error) {
            e = { error: error };
        }
        finally {
            try {
                if (r && !r.done && (m = i["return"]))
                    m.call(i);
            }
            finally {
                if (e)
                    throw e.error;
            }
        }
        return ar;
    }
    /** @deprecated */
    function __spread() {
        for (var ar = [], i = 0; i < arguments.length; i++)
            ar = ar.concat(__read(arguments[i]));
        return ar;
    }
    /** @deprecated */
    function __spreadArrays() {
        for (var s = 0, i = 0, il = arguments.length; i < il; i++)
            s += arguments[i].length;
        for (var r = Array(s), k = 0, i = 0; i < il; i++)
            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
                r[k] = a[j];
        return r;
    }
    function __spreadArray(to, from) {
        for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
            to[j] = from[i];
        return to;
    }
    function __await(v) {
        return this instanceof __await ? (this.v = v, this) : new __await(v);
    }
    function __asyncGenerator(thisArg, _arguments, generator) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var g = generator.apply(thisArg, _arguments || []), i, q = [];
        return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
        function verb(n) { if (g[n])
            i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
        function resume(n, v) { try {
            step(g[n](v));
        }
        catch (e) {
            settle(q[0][3], e);
        } }
        function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
        function fulfill(value) { resume("next", value); }
        function reject(value) { resume("throw", value); }
        function settle(f, v) { if (f(v), q.shift(), q.length)
            resume(q[0][0], q[0][1]); }
    }
    function __asyncDelegator(o) {
        var i, p;
        return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
        function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
    }
    function __asyncValues(o) {
        if (!Symbol.asyncIterator)
            throw new TypeError("Symbol.asyncIterator is not defined.");
        var m = o[Symbol.asyncIterator], i;
        return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
        function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
        function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
    }
    function __makeTemplateObject(cooked, raw) {
        if (Object.defineProperty) {
            Object.defineProperty(cooked, "raw", { value: raw });
        }
        else {
            cooked.raw = raw;
        }
        return cooked;
    }
    ;
    var __setModuleDefault = Object.create ? (function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v });
    }) : function (o, v) {
        o["default"] = v;
    };
    function __importStar(mod) {
        if (mod && mod.__esModule)
            return mod;
        var result = {};
        if (mod != null)
            for (var k in mod)
                if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
                    __createBinding(result, mod, k);
        __setModuleDefault(result, mod);
        return result;
    }
    function __importDefault(mod) {
        return (mod && mod.__esModule) ? mod : { default: mod };
    }
    function __classPrivateFieldGet(receiver, privateMap) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to get private field on non-instance");
        }
        return privateMap.get(receiver);
    }
    function __classPrivateFieldSet(receiver, privateMap, value) {
        if (!privateMap.has(receiver)) {
            throw new TypeError("attempted to set private field on non-instance");
        }
        privateMap.set(receiver, value);
        return value;
    }

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /**
     * This class manages keyboard events for selectable lists. If you pass it a query list
     * of items, it will set the active item correctly when arrow events occur.
     */
    var ListKeyManager = /** @class */ (function () {
        function ListKeyManager(_items) {
            var _this = this;
            this._items = _items;
            this._activeItemIndex = -1;
            this._activeItem = null;
            this._wrap = false;
            this._letterKeyStream = new rxjs.Subject();
            this._typeaheadSubscription = rxjs.Subscription.EMPTY;
            this._vertical = true;
            this._allowedModifierKeys = [];
            this._homeAndEnd = false;
            /**
             * Predicate function that can be used to check whether an item should be skipped
             * by the key manager. By default, disabled items are skipped.
             */
            this._skipPredicateFn = function (item) { return item.disabled; };
            // Buffer for the letters that the user has pressed when the typeahead option is turned on.
            this._pressedLetters = [];
            /**
             * Stream that emits any time the TAB key is pressed, so components can react
             * when focus is shifted off of the list.
             */
            this.tabOut = new rxjs.Subject();
            /** Stream that emits whenever the active item of the list manager changes. */
            this.change = new rxjs.Subject();
            // We allow for the items to be an array because, in some cases, the consumer may
            // not have access to a QueryList of the items they want to manage (e.g. when the
            // items aren't being collected via `ViewChildren` or `ContentChildren`).
            if (_items instanceof i0.QueryList) {
                _items.changes.subscribe(function (newItems) {
                    if (_this._activeItem) {
                        var itemArray = newItems.toArray();
                        var newIndex = itemArray.indexOf(_this._activeItem);
                        if (newIndex > -1 && newIndex !== _this._activeItemIndex) {
                            _this._activeItemIndex = newIndex;
                        }
                    }
                });
            }
        }
        /**
         * Sets the predicate function that determines which items should be skipped by the
         * list key manager.
         * @param predicate Function that determines whether the given item should be skipped.
         */
        ListKeyManager.prototype.skipPredicate = function (predicate) {
            this._skipPredicateFn = predicate;
            return this;
        };
        /**
         * Configures wrapping mode, which determines whether the active item will wrap to
         * the other end of list when there are no more items in the given direction.
         * @param shouldWrap Whether the list should wrap when reaching the end.
         */
        ListKeyManager.prototype.withWrap = function (shouldWrap) {
            if (shouldWrap === void 0) { shouldWrap = true; }
            this._wrap = shouldWrap;
            return this;
        };
        /**
         * Configures whether the key manager should be able to move the selection vertically.
         * @param enabled Whether vertical selection should be enabled.
         */
        ListKeyManager.prototype.withVerticalOrientation = function (enabled) {
            if (enabled === void 0) { enabled = true; }
            this._vertical = enabled;
            return this;
        };
        /**
         * Configures the key manager to move the selection horizontally.
         * Passing in `null` will disable horizontal movement.
         * @param direction Direction in which the selection can be moved.
         */
        ListKeyManager.prototype.withHorizontalOrientation = function (direction) {
            this._horizontal = direction;
            return this;
        };
        /**
         * Modifier keys which are allowed to be held down and whose default actions will be prevented
         * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
         */
        ListKeyManager.prototype.withAllowedModifierKeys = function (keys) {
            this._allowedModifierKeys = keys;
            return this;
        };
        /**
         * Turns on typeahead mode which allows users to set the active item by typing.
         * @param debounceInterval Time to wait after the last keystroke before setting the active item.
         */
        ListKeyManager.prototype.withTypeAhead = function (debounceInterval) {
            var _this = this;
            if (debounceInterval === void 0) { debounceInterval = 200; }
            if ((typeof ngDevMode === 'undefined' || ngDevMode) && (this._items.length &&
                this._items.some(function (item) { return typeof item.getLabel !== 'function'; }))) {
                throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
            }
            this._typeaheadSubscription.unsubscribe();
            // Debounce the presses of non-navigational keys, collect the ones that correspond to letters
            // and convert those letters back into a string. Afterwards find the first item that starts
            // with that string and select it.
            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) {
                var items = _this._getItemsArray();
                // Start at 1 because we want to start searching at the item immediately
                // following the current active item.
                for (var i = 1; i < items.length + 1; i++) {
                    var index = (_this._activeItemIndex + i) % items.length;
                    var item = items[index];
                    if (!_this._skipPredicateFn(item) &&
                        item.getLabel().toUpperCase().trim().indexOf(inputString) === 0) {
                        _this.setActiveItem(index);
                        break;
                    }
                }
                _this._pressedLetters = [];
            });
            return this;
        };
        /**
         * Configures the key manager to activate the first and last items
         * respectively when the Home or End key is pressed.
         * @param enabled Whether pressing the Home or End key activates the first/last item.
         */
        ListKeyManager.prototype.withHomeAndEnd = function (enabled) {
            if (enabled === void 0) { enabled = true; }
            this._homeAndEnd = enabled;
            return this;
        };
        ListKeyManager.prototype.setActiveItem = function (item) {
            var previousActiveItem = this._activeItem;
            this.updateActiveItem(item);
            if (this._activeItem !== previousActiveItem) {
                this.change.next(this._activeItemIndex);
            }
        };
        /**
         * Sets the active item depending on the key event passed in.
         * @param event Keyboard event to be used for determining which element should be active.
         */
        ListKeyManager.prototype.onKeydown = function (event) {
            var _this = this;
            var keyCode = event.keyCode;
            var modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];
            var isModifierAllowed = modifiers.every(function (modifier) {
                return !event[modifier] || _this._allowedModifierKeys.indexOf(modifier) > -1;
            });
            switch (keyCode) {
                case keycodes.TAB:
                    this.tabOut.next();
                    return;
                case keycodes.DOWN_ARROW:
                    if (this._vertical && isModifierAllowed) {
                        this.setNextItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                case keycodes.UP_ARROW:
                    if (this._vertical && isModifierAllowed) {
                        this.setPreviousItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                case keycodes.RIGHT_ARROW:
                    if (this._horizontal && isModifierAllowed) {
                        this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                case keycodes.LEFT_ARROW:
                    if (this._horizontal && isModifierAllowed) {
                        this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                case keycodes.HOME:
                    if (this._homeAndEnd && isModifierAllowed) {
                        this.setFirstItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                case keycodes.END:
                    if (this._homeAndEnd && isModifierAllowed) {
                        this.setLastItemActive();
                        break;
                    }
                    else {
                        return;
                    }
                default:
                    if (isModifierAllowed || keycodes.hasModifierKey(event, 'shiftKey')) {
                        // Attempt to use the `event.key` which also maps it to the user's keyboard language,
                        // otherwise fall back to resolving alphanumeric characters via the keyCode.
                        if (event.key && event.key.length === 1) {
                            this._letterKeyStream.next(event.key.toLocaleUpperCase());
                        }
                        else if ((keyCode >= keycodes.A && keyCode <= keycodes.Z) || (keyCode >= keycodes.ZERO && keyCode <= keycodes.NINE)) {
                            this._letterKeyStream.next(String.fromCharCode(keyCode));
                        }
                    }
                    // Note that we return here, in order to avoid preventing
                    // the default action of non-navigational keys.
                    return;
            }
            this._pressedLetters = [];
            event.preventDefault();
        };
        Object.defineProperty(ListKeyManager.prototype, "activeItemIndex", {
            /** Index of the currently active item. */
            get: function () {
                return this._activeItemIndex;
            },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(ListKeyManager.prototype, "activeItem", {
            /** The active item. */
            get: function () {
                return this._activeItem;
            },
            enumerable: false,
            configurable: true
        });
        /** Gets whether the user is currently typing into the manager using the typeahead feature. */
        ListKeyManager.prototype.isTyping = function () {
            return this._pressedLetters.length > 0;
        };
        /** Sets the active item to the first enabled item in the list. */
        ListKeyManager.prototype.setFirstItemActive = function () {
            this._setActiveItemByIndex(0, 1);
        };
        /** Sets the active item to the last enabled item in the list. */
        ListKeyManager.prototype.setLastItemActive = function () {
            this._setActiveItemByIndex(this._items.length - 1, -1);
        };
        /** Sets the active item to the next enabled item in the list. */
        ListKeyManager.prototype.setNextItemActive = function () {
            this._activeItemIndex < 0 ? this.setFirstItemActive() : this._setActiveItemByDelta(1);
        };
        /** Sets the active item to a previous enabled item in the list. */
        ListKeyManager.prototype.setPreviousItemActive = function () {
            this._activeItemIndex < 0 && this._wrap ? this.setLastItemActive()
                : this._setActiveItemByDelta(-1);
        };
        ListKeyManager.prototype.updateActiveItem = function (item) {
            var itemArray = this._getItemsArray();
            var index = typeof item === 'number' ? item : itemArray.indexOf(item);
            var activeItem = itemArray[index];
            // Explicitly check for `null` and `undefined` because other falsy values are valid.
            this._activeItem = activeItem == null ? null : activeItem;
            this._activeItemIndex = index;
        };
        /**
         * This method sets the active item, given a list of items and the delta between the
         * currently active item and the new active item. It will calculate differently
         * depending on whether wrap mode is turned on.
         */
        ListKeyManager.prototype._setActiveItemByDelta = function (delta) {
            this._wrap ? this._setActiveInWrapMode(delta) : this._setActiveInDefaultMode(delta);
        };
        /**
         * Sets the active item properly given "wrap" mode. In other words, it will continue to move
         * down the list until it finds an item that is not disabled, and it will wrap if it
         * encounters either end of the list.
         */
        ListKeyManager.prototype._setActiveInWrapMode = function (delta) {
            var items = this._getItemsArray();
            for (var i = 1; i <= items.length; i++) {
                var index = (this._activeItemIndex + (delta * i) + items.length) % items.length;
                var item = items[index];
                if (!this._skipPredicateFn(item)) {
                    this.setActiveItem(index);
                    return;
                }
            }
        };
        /**
         * Sets the active item properly given the default mode. In other words, it will
         * continue to move down the list until it finds an item that is not disabled. If
         * it encounters either end of the list, it will stop and not wrap.
         */
        ListKeyManager.prototype._setActiveInDefaultMode = function (delta) {
            this._setActiveItemByIndex(this._activeItemIndex + delta, delta);
        };
        /**
         * Sets the active item to the first enabled item starting at the index specified. If the
         * item is disabled, it will move in the fallbackDelta direction until it either
         * finds an enabled item or encounters the end of the list.
         */
        ListKeyManager.prototype._setActiveItemByIndex = function (index, fallbackDelta) {
            var items = this._getItemsArray();
            if (!items[index]) {
                return;
            }
            while (this._skipPredicateFn(items[index])) {
                index += fallbackDelta;
                if (!items[index]) {
                    return;
                }
            }
            this.setActiveItem(index);
        };
        /** Returns the items as an array. */
        ListKeyManager.prototype._getItemsArray = function () {
            return this._items instanceof i0.QueryList ? this._items.toArray() : this._items;
        };
        return ListKeyManager;
    }());

    var ActiveDescendantKeyManager = /** @class */ (function (_super) {
        __extends(ActiveDescendantKeyManager, _super);
        function ActiveDescendantKeyManager() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        ActiveDescendantKeyManager.prototype.setActiveItem = function (index) {
            if (this.activeItem) {
                this.activeItem.setInactiveStyles();
            }
            _super.prototype.setActiveItem.call(this, index);
            if (this.activeItem) {
                this.activeItem.setActiveStyles();
            }
        };
        return ActiveDescendantKeyManager;
    }(ListKeyManager));

    var FocusKeyManager = /** @class */ (function (_super) {
        __extends(FocusKeyManager, _super);
        function FocusKeyManager() {
            var _this = _super.apply(this, __spread(arguments)) || this;
            _this._origin = 'program';
            return _this;
        }
        /**
         * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
         * @param origin Focus origin to be used when focusing items.
         */
        FocusKeyManager.prototype.setFocusOrigin = function (origin) {
            this._origin = origin;
            return this;
        };
        FocusKeyManager.prototype.setActiveItem = function (item) {
            _super.prototype.setActiveItem.call(this, item);
            if (this.activeItem) {
                this.activeItem.focus(this._origin);
            }
        };
        return FocusKeyManager;
    }(ListKeyManager));

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /**
     * Configuration for the isFocusable method.
     */
    var IsFocusableConfig = /** @class */ (function () {
        function IsFocusableConfig() {
            /**
             * Whether to count an element as focusable even if it is not currently visible.
             */
            this.ignoreVisibility = false;
        }
        return IsFocusableConfig;
    }());
    // The InteractivityChecker leans heavily on the ally.js accessibility utilities.
    // Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
    // supported.
    /**
     * Utility for checking the interactivity of an element, such as whether is is focusable or
     * tabbable.
     */
    var InteractivityChecker = /** @class */ (function () {
        function InteractivityChecker(_platform) {
            this._platform = _platform;
        }
        /**
         * Gets whether an element is disabled.
         *
         * @param element Element to be checked.
         * @returns Whether the element is disabled.
         */
        InteractivityChecker.prototype.isDisabled = function (element) {
            // This does not capture some cases, such as a non-form control with a disabled attribute or
            // a form control inside of a disabled form, but should capture the most common cases.
            return element.hasAttribute('disabled');
        };
        /**
         * Gets whether an element is visible for the purposes of interactivity.
         *
         * This will capture states like `display: none` and `visibility: hidden`, but not things like
         * being clipped by an `overflow: hidden` parent or being outside the viewport.
         *
         * @returns Whether the element is visible.
         */
        InteractivityChecker.prototype.isVisible = function (element) {
            return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';
        };
        /**
         * Gets whether an element can be reached via Tab key.
         * Assumes that the element has already been checked with isFocusable.
         *
         * @param element Element to be checked.
         * @returns Whether the element is tabbable.
         */
        InteractivityChecker.prototype.isTabbable = function (element) {
            // Nothing is tabbable on the server 😎
            if (!this._platform.isBrowser) {
                return false;
            }
            var frameElement = getFrameElement(getWindow(element));
            if (frameElement) {
                // Frame elements inherit their tabindex onto all child elements.
                if (getTabIndexValue(frameElement) === -1) {
                    return false;
                }
                // Browsers disable tabbing to an element inside of an invisible frame.
                if (!this.isVisible(frameElement)) {
                    return false;
                }
            }
            var nodeName = element.nodeName.toLowerCase();
            var tabIndexValue = getTabIndexValue(element);
            if (element.hasAttribute('contenteditable')) {
                return tabIndexValue !== -1;
            }
            if (nodeName === 'iframe' || nodeName === 'object') {
                // The frame or object's content may be tabbable depending on the content, but it's
                // not possibly to reliably detect the content of the frames. We always consider such
                // elements as non-tabbable.
                return false;
            }
            // In iOS, the browser only considers some specific elements as tabbable.
            if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {
                return false;
            }
            if (nodeName === 'audio') {
                // Audio elements without controls enabled are never tabbable, regardless
                // of the tabindex attribute explicitly being set.
                if (!element.hasAttribute('controls')) {
                    return false;
                }
                // Audio elements with controls are by default tabbable unless the
                // tabindex attribute is set to `-1` explicitly.
                return tabIndexValue !== -1;
            }
            if (nodeName === 'video') {
                // For all video elements, if the tabindex attribute is set to `-1`, the video
                // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`
                // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The
                // tabindex attribute is the source of truth here.
                if (tabIndexValue === -1) {
                    return false;
                }
                // If the tabindex is explicitly set, and not `-1` (as per check before), the
                // video element is always tabbable (regardless of whether it has controls or not).
                if (tabIndexValue !== null) {
                    return true;
                }
                // Otherwise (when no explicit tabindex is set), a video is only tabbable if it
                // has controls enabled. Firefox is special as videos are always tabbable regardless
                // of whether there are controls or not.
                return this._platform.FIREFOX || element.hasAttribute('controls');
            }
            return element.tabIndex >= 0;
        };
        /**
         * Gets whether an element can be focused by the user.
         *
         * @param element Element to be checked.
         * @param config The config object with options to customize this method's behavior
         * @returns Whether the element is focusable.
         */
        InteractivityChecker.prototype.isFocusable = function (element, config) {
            // Perform checks in order of left to most expensive.
            // Again, naive approach that does not capture many edge cases and browser quirks.
            return isPotentiallyFocusable(element) && !this.isDisabled(element) &&
                ((config === null || config === void 0 ? void 0 : config.ignoreVisibility) || this.isVisible(element));
        };
        return InteractivityChecker;
    }());
    InteractivityChecker.ɵprov = i0.ɵɵdefineInjectable({ factory: function InteractivityChecker_Factory() { return new InteractivityChecker(i0.ɵɵinject(i1.Platform)); }, token: InteractivityChecker, providedIn: "root" });
    InteractivityChecker.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    InteractivityChecker.ctorParameters = function () { return [
        { type: i1.Platform }
    ]; };
    /**
     * Returns the frame element from a window object. Since browsers like MS Edge throw errors if
     * the frameElement property is being accessed from a different host address, this property
     * should be accessed carefully.
     */
    function getFrameElement(window) {
        try {
            return window.frameElement;
        }
        catch (_a) {
            return null;
        }
    }
    /** Checks whether the specified element has any geometry / rectangles. */
    function hasGeometry(element) {
        // Use logic from jQuery to check for an invisible element.
        // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12
        return !!(element.offsetWidth || element.offsetHeight ||
            (typeof element.getClientRects === 'function' && element.getClientRects().length));
    }
    /** Gets whether an element's  */
    function isNativeFormElement(element) {
        var nodeName = element.nodeName.toLowerCase();
        return nodeName === 'input' ||
            nodeName === 'select' ||
            nodeName === 'button' ||
            nodeName === 'textarea';
    }
    /** Gets whether an element is an `<input type="hidden">`. */
    function isHiddenInput(element) {
        return isInputElement(element) && element.type == 'hidden';
    }
    /** Gets whether an element is an anchor that has an href attribute. */
    function isAnchorWithHref(element) {
        return isAnchorElement(element) && element.hasAttribute('href');
    }
    /** Gets whether an element is an input element. */
    function isInputElement(element) {
        return element.nodeName.toLowerCase() == 'input';
    }
    /** Gets whether an element is an anchor element. */
    function isAnchorElement(element) {
        return element.nodeName.toLowerCase() == 'a';
    }
    /** Gets whether an element has a valid tabindex. */
    function hasValidTabIndex(element) {
        if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {
            return false;
        }
        var tabIndex = element.getAttribute('tabindex');
        // IE11 parses tabindex="" as the value "-32768"
        if (tabIndex == '-32768') {
            return false;
        }
        return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));
    }
    /**
     * Returns the parsed tabindex from the element attributes instead of returning the
     * evaluated tabindex from the browsers defaults.
     */
    function getTabIndexValue(element) {
        if (!hasValidTabIndex(element)) {
            return null;
        }
        // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054
        var tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
        return isNaN(tabIndex) ? -1 : tabIndex;
    }
    /** Checks whether the specified element is potentially tabbable on iOS */
    function isPotentiallyTabbableIOS(element) {
        var nodeName = element.nodeName.toLowerCase();
        var inputType = nodeName === 'input' && element.type;
        return inputType === 'text'
            || inputType === 'password'
            || nodeName === 'select'
            || nodeName === 'textarea';
    }
    /**
     * Gets whether an element is potentially focusable without taking current visible/disabled state
     * into account.
     */
    function isPotentiallyFocusable(element) {
        // Inputs are potentially focusable *unless* they're type="hidden".
        if (isHiddenInput(element)) {
            return false;
        }
        return isNativeFormElement(element) ||
            isAnchorWithHref(element) ||
            element.hasAttribute('contenteditable') ||
            hasValidTabIndex(element);
    }
    /** Gets the parent window of a DOM node with regards of being inside of an iframe. */
    function getWindow(node) {
        // ownerDocument is null if `node` itself *is* a document.
        return node.ownerDocument && node.ownerDocument.defaultView || window;
    }

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /**
     * Class that allows for trapping focus within a DOM element.
     *
     * This class currently uses a relatively simple approach to focus trapping.
     * It assumes that the tab order is the same as DOM order, which is not necessarily true.
     * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to be misaligned.
     *
     * @deprecated Use `ConfigurableFocusTrap` instead.
     * @breaking-change 11.0.0
     */
    var FocusTrap = /** @class */ (function () {
        function FocusTrap(_element, _checker, _ngZone, _document, deferAnchors) {
            var _this = this;
            if (deferAnchors === void 0) { deferAnchors = false; }
            this._element = _element;
            this._checker = _checker;
            this._ngZone = _ngZone;
            this._document = _document;
            this._hasAttached = false;
            // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
            this.startAnchorListener = function () { return _this.focusLastTabbableElement(); };
            this.endAnchorListener = function () { return _this.focusFirstTabbableElement(); };
            this._enabled = true;
            if (!deferAnchors) {
                this.attachAnchors();
            }
        }
        Object.defineProperty(FocusTrap.prototype, "enabled", {
            /** Whether the focus trap is active. */
            get: function () { return this._enabled; },
            set: function (value) {
                this._enabled = value;
                if (this._startAnchor && this._endAnchor) {
                    this._toggleAnchorTabIndex(value, this._startAnchor);
                    this._toggleAnchorTabIndex(value, this._endAnchor);
                }
            },
            enumerable: false,
            configurable: true
        });
        /** Destroys the focus trap by cleaning up the anchors. */
        FocusTrap.prototype.destroy = function () {
            var startAnchor = this._startAnchor;
            var endAnchor = this._endAnchor;
            if (startAnchor) {
                startAnchor.removeEventListener('focus', this.startAnchorListener);
                if (startAnchor.parentNode) {
                    startAnchor.parentNode.removeChild(startAnchor);
                }
            }
            if (endAnchor) {
                endAnchor.removeEventListener('focus', this.endAnchorListener);
                if (endAnchor.parentNode) {
                    endAnchor.parentNode.removeChild(endAnchor);
                }
            }
            this._startAnchor = this._endAnchor = null;
            this._hasAttached = false;
        };
        /**
         * Inserts the anchors into the DOM. This is usually done automatically
         * in the constructor, but can be deferred for cases like directives with `*ngIf`.
         * @returns Whether the focus trap managed to attach successfully. This may not be the case
         * if the target element isn't currently in the DOM.
         */
        FocusTrap.prototype.attachAnchors = function () {
            var _this = this;
            // If we're not on the browser, there can be no focus to trap.
            if (this._hasAttached) {
                return true;
            }
            this._ngZone.runOutsideAngular(function () {
                if (!_this._startAnchor) {
                    _this._startAnchor = _this._createAnchor();
                    _this._startAnchor.addEventListener('focus', _this.startAnchorListener);
                }
                if (!_this._endAnchor) {
                    _this._endAnchor = _this._createAnchor();
                    _this._endAnchor.addEventListener('focus', _this.endAnchorListener);
                }
            });
            if (this._element.parentNode) {
                this._element.parentNode.insertBefore(this._startAnchor, this._element);
                this._element.parentNode.insertBefore(this._endAnchor, this._element.nextSibling);
                this._hasAttached = true;
            }
            return this._hasAttached;
        };
        /**
         * Waits for the zone to stabilize, then either focuses the first element that the
         * user specified, or the first tabbable element.
         * @returns Returns a promise that resolves with a boolean, depending
         * on whether focus was moved successfully.
         */
        FocusTrap.prototype.focusInitialElementWhenReady = function () {
            var _this = this;
            return new Promise(function (resolve) {
                _this._executeOnStable(function () { return resolve(_this.focusInitialElement()); });
            });
        };
        /**
         * Waits for the zone to stabilize, then focuses
         * the first tabbable element within the focus trap region.
         * @returns Returns a promise that resolves with a boolean, depending
         * on whether focus was moved successfully.
         */
        FocusTrap.prototype.focusFirstTabbableElementWhenReady = function () {
            var _this = this;
            return new Promise(function (resolve) {
                _this._executeOnStable(function () { return resolve(_this.focusFirstTabbableElement()); });
            });
        };
        /**
         * Waits for the zone to stabilize, then focuses
         * the last tabbable element within the focus trap region.
         * @returns Returns a promise that resolves with a boolean, depending
         * on whether focus was moved successfully.
         */
        FocusTrap.prototype.focusLastTabbableElementWhenReady = function () {
            var _this = this;
            return new Promise(function (resolve) {
                _this._executeOnStable(function () { return resolve(_this.focusLastTabbableElement()); });
            });
        };
        /**
         * Get the specified boundary element of the trapped region.
         * @param bound The boundary to get (start or end of trapped region).
         * @returns The boundary element.
         */
        FocusTrap.prototype._getRegionBoundary = function (bound) {
            // Contains the deprecated version of selector, for temporary backwards comparability.
            var markers = this._element.querySelectorAll("[cdk-focus-region-" + bound + "], " +
                ("[cdkFocusRegion" + bound + "], ") +
                ("[cdk-focus-" + bound + "]"));
            for (var i = 0; i < markers.length; i++) {
                // @breaking-change 8.0.0
                if (markers[i].hasAttribute("cdk-focus-" + bound)) {
                    console.warn("Found use of deprecated attribute 'cdk-focus-" + bound + "', " +
                        ("use 'cdkFocusRegion" + bound + "' instead. The deprecated ") +
                        "attribute will be removed in 8.0.0.", markers[i]);
                }
                else if (markers[i].hasAttribute("cdk-focus-region-" + bound)) {
                    console.warn("Found use of deprecated attribute 'cdk-focus-region-" + bound + "', " +
                        ("use 'cdkFocusRegion" + bound + "' instead. The deprecated attribute ") +
                        "will be removed in 8.0.0.", markers[i]);
                }
            }
            if (bound == 'start') {
                return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);
            }
            return markers.length ?
                markers[markers.length - 1] : this._getLastTabbableElement(this._element);
        };
        /**
         * Focuses the element that should be focused when the focus trap is initialized.
         * @returns Whether focus was moved successfully.
         */
        FocusTrap.prototype.focusInitialElement = function () {
            // Contains the deprecated version of selector, for temporary backwards comparability.
            var redirectToElement = this._element.querySelector("[cdk-focus-initial], " +
                "[cdkFocusInitial]");
            if (redirectToElement) {
                // @breaking-change 8.0.0
                if (redirectToElement.hasAttribute("cdk-focus-initial")) {
                    console.warn("Found use of deprecated attribute 'cdk-focus-initial', " +
                        "use 'cdkFocusInitial' instead. The deprecated attribute " +
                        "will be removed in 8.0.0", redirectToElement);
                }
                // Warn the consumer if the element they've pointed to
                // isn't focusable, when not in production mode.
                if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
                    !this._checker.isFocusable(redirectToElement)) {
                    console.warn("Element matching '[cdkFocusInitial]' is not focusable.", redirectToElement);
                }
                if (!this._checker.isFocusable(redirectToElement)) {
                    var focusableChild = this._getFirstTabbableElement(redirectToElement);
                    focusableChild === null || focusableChild === void 0 ? void 0 : focusableChild.focus();
                    return !!focusableChild;
                }
                redirectToElement.focus();
                return true;
            }
            return this.focusFirstTabbableElement();
        };
        /**
         * Focuses the first tabbable element within the focus trap region.
         * @returns Whether focus was moved successfully.
         */
        FocusTrap.prototype.focusFirstTabbableElement = function () {
            var redirectToElement = this._getRegionBoundary('start');
            if (redirectToElement) {
                redirectToElement.focus();
            }
            return !!redirectToElement;
        };
        /**
         * Focuses the last tabbable element within the focus trap region.
         * @returns Whether focus was moved successfully.
         */
        FocusTrap.prototype.focusLastTabbableElement = function () {
            var redirectToElement = this._getRegionBoundary('end');
            if (redirectToElement) {
                redirectToElement.focus();
            }
            return !!redirectToElement;
        };
        /**
         * Checks whether the focus trap has successfully been attached.
         */
        FocusTrap.prototype.hasAttached = function () {
            return this._hasAttached;
        };
        /** Get the first tabbable element from a DOM subtree (inclusive). */
        FocusTrap.prototype._getFirstTabbableElement = function (root) {
            if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
                return root;
            }
            // Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
            // back to `childNodes` which includes text nodes, comments etc.
            var children = root.children || root.childNodes;
            for (var i = 0; i < children.length; i++) {
                var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
                    this._getFirstTabbableElement(children[i]) :
                    null;
                if (tabbableChild) {
                    return tabbableChild;
                }
            }
            return null;
        };
        /** Get the last tabbable element from a DOM subtree (inclusive). */
        FocusTrap.prototype._getLastTabbableElement = function (root) {
            if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
                return root;
            }
            // Iterate in reverse DOM order.
            var children = root.children || root.childNodes;
            for (var i = children.length - 1; i >= 0; i--) {
                var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
                    this._getLastTabbableElement(children[i]) :
                    null;
                if (tabbableChild) {
                    return tabbableChild;
                }
            }
            return null;
        };
        /** Creates an anchor element. */
        FocusTrap.prototype._createAnchor = function () {
            var anchor = this._document.createElement('div');
            this._toggleAnchorTabIndex(this._enabled, anchor);
            anchor.classList.add('cdk-visually-hidden');
            anchor.classList.add('cdk-focus-trap-anchor');
            anchor.setAttribute('aria-hidden', 'true');
            return anchor;
        };
        /**
         * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
         * @param isEnabled Whether the focus trap is enabled.
         * @param anchor Anchor on which to toggle the tabindex.
         */
        FocusTrap.prototype._toggleAnchorTabIndex = function (isEnabled, anchor) {
            // Remove the tabindex completely, rather than setting it to -1, because if the
            // element has a tabindex, the user might still hit it when navigating with the arrow keys.
            isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');
        };
        /**
         * Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.
         * @param enabled: Whether the anchors should trap Tab.
         */
        FocusTrap.prototype.toggleAnchors = function (enabled) {
            if (this._startAnchor && this._endAnchor) {
                this._toggleAnchorTabIndex(enabled, this._startAnchor);
                this._toggleAnchorTabIndex(enabled, this._endAnchor);
            }
        };
        /** Executes a function when the zone is stable. */
        FocusTrap.prototype._executeOnStable = function (fn) {
            if (this._ngZone.isStable) {
                fn();
            }
            else {
                this._ngZone.onStable.pipe(operators.take(1)).subscribe(fn);
            }
        };
        return FocusTrap;
    }());
    /**
     * Factory that allows easy instantiation of focus traps.
     * @deprecated Use `ConfigurableFocusTrapFactory` instead.
     * @breaking-change 11.0.0
     */
    var FocusTrapFactory = /** @class */ (function () {
        function FocusTrapFactory(_checker, _ngZone, _document) {
            this._checker = _checker;
            this._ngZone = _ngZone;
            this._document = _document;
        }
        /**
         * Creates a focus-trapped region around the given element.
         * @param element The element around which focus will be trapped.
         * @param deferCaptureElements Defers the creation of focus-capturing elements to be done
         *     manually by the user.
         * @returns The created focus trap instance.
         */
        FocusTrapFactory.prototype.create = function (element, deferCaptureElements) {
            if (deferCaptureElements === void 0) { deferCaptureElements = false; }
            return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements);
        };
        return FocusTrapFactory;
    }());
    FocusTrapFactory.ɵprov = i0.ɵɵdefineInjectable({ factory: function FocusTrapFactory_Factory() { return new FocusTrapFactory(i0.ɵɵinject(InteractivityChecker), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i2.DOCUMENT)); }, token: FocusTrapFactory, providedIn: "root" });
    FocusTrapFactory.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    FocusTrapFactory.ctorParameters = function () { return [
        { type: InteractivityChecker },
        { type: i0.NgZone },
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
    ]; };
    /** Directive for trapping focus within a region. */
    var CdkTrapFocus = /** @class */ (function () {
        function CdkTrapFocus(_elementRef, _focusTrapFactory, _document) {
            this._elementRef = _elementRef;
            this._focusTrapFactory = _focusTrapFactory;
            /** Previously focused element to restore focus to upon destroy when using autoCapture. */
            this._previouslyFocusedElement = null;
            this._document = _document;
            this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
        }
        Object.defineProperty(CdkTrapFocus.prototype, "enabled", {
            /** Whether the focus trap is active. */
            get: function () { return this.focusTrap.enabled; },
            set: function (value) { this.focusTrap.enabled = coercion.coerceBooleanProperty(value); },
            enumerable: false,
            configurable: true
        });
        Object.defineProperty(CdkTrapFocus.prototype, "autoCapture", {
            /**
             * Whether the directive should automatically move focus into the trapped region upon
             * initialization and return focus to the previous activeElement upon destruction.
             */
            get: function () { return this._autoCapture; },
            set: function (value) { this._autoCapture = coercion.coerceBooleanProperty(value); },
            enumerable: false,
            configurable: true
        });
        CdkTrapFocus.prototype.ngOnDestroy = function () {
            this.focusTrap.destroy();
            // If we stored a previously focused element when using autoCapture, return focus to that
            // element now that the trapped region is being destroyed.
            if (this._previouslyFocusedElement) {
                this._previouslyFocusedElement.focus();
                this._previouslyFocusedElement = null;
            }
        };
        CdkTrapFocus.prototype.ngAfterContentInit = function () {
            this.focusTrap.attachAnchors();
            if (this.autoCapture) {
                this._captureFocus();
            }
        };
        CdkTrapFocus.prototype.ngDoCheck = function () {
            if (!this.focusTrap.hasAttached()) {
                this.focusTrap.attachAnchors();
            }
        };
        CdkTrapFocus.prototype.ngOnChanges = function (changes) {
            var autoCaptureChange = changes['autoCapture'];
            if (autoCaptureChange && !autoCaptureChange.firstChange && this.autoCapture &&
                this.focusTrap.hasAttached()) {
                this._captureFocus();
            }
        };
        CdkTrapFocus.prototype._captureFocus = function () {
            var _a, _b;
            // If the `activeElement` is inside a shadow root, `document.activeElement` will
            // point to the shadow root so we have to descend into it ourselves.
            var activeElement = (_a = this._document) === null || _a === void 0 ? void 0 : _a.activeElement;
            this._previouslyFocusedElement =
                ((_b = activeElement === null || activeElement === void 0 ? void 0 : activeElement.shadowRoot) === null || _b === void 0 ? void 0 : _b.activeElement) || activeElement;
            this.focusTrap.focusInitialElementWhenReady();
        };
        return CdkTrapFocus;
    }());
    CdkTrapFocus.decorators = [
        { type: i0.Directive, args: [{
                    selector: '[cdkTrapFocus]',
                    exportAs: 'cdkTrapFocus',
                },] }
    ];
    CdkTrapFocus.ctorParameters = function () { return [
        { type: i0.ElementRef },
        { type: FocusTrapFactory },
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
    ]; };
    CdkTrapFocus.propDecorators = {
        enabled: [{ type: i0.Input, args: ['cdkTrapFocus',] }],
        autoCapture: [{ type: i0.Input, args: ['cdkTrapFocusAutoCapture',] }]
    };

    /**
     * Class that allows for trapping focus within a DOM element.
     *
     * This class uses a strategy pattern that determines how it traps focus.
     * See FocusTrapInertStrategy.
     */
    var ConfigurableFocusTrap = /** @class */ (function (_super) {
        __extends(ConfigurableFocusTrap, _super);
        function ConfigurableFocusTrap(_element, _checker, _ngZone, _document, _focusTrapManager, _inertStrategy, config) {
            var _this = _super.call(this, _element, _checker, _ngZone, _document, config.defer) || this;
            _this._focusTrapManager = _focusTrapManager;
            _this._inertStrategy = _inertStrategy;
            _this._focusTrapManager.register(_this);
            return _this;
        }
        Object.defineProperty(ConfigurableFocusTrap.prototype, "enabled", {
            /** Whether the FocusTrap is enabled. */
            get: function () { return this._enabled; },
            set: function (value) {
                this._enabled = value;
                if (this._enabled) {
                    this._focusTrapManager.register(this);
                }
                else {
                    this._focusTrapManager.deregister(this);
                }
            },
            enumerable: false,
            configurable: true
        });
        /** Notifies the FocusTrapManager that this FocusTrap will be destroyed. */
        ConfigurableFocusTrap.prototype.destroy = function () {
            this._focusTrapManager.deregister(this);
            _super.prototype.destroy.call(this);
        };
        /** @docs-private Implemented as part of ManagedFocusTrap. */
        ConfigurableFocusTrap.prototype._enable = function () {
            this._inertStrategy.preventFocus(this);
            this.toggleAnchors(true);
        };
        /** @docs-private Implemented as part of ManagedFocusTrap. */
        ConfigurableFocusTrap.prototype._disable = function () {
            this._inertStrategy.allowFocus(this);
            this.toggleAnchors(false);
        };
        return ConfigurableFocusTrap;
    }(FocusTrap));

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** IE 11 compatible closest implementation that is able to start from non-Element Nodes. */
    function closest(element, selector) {
        if (!(element instanceof Node)) {
            return null;
        }
        var curr = element;
        while (curr != null && !(curr instanceof Element)) {
            curr = curr.parentNode;
        }
        return curr && (hasNativeClosest ?
            curr.closest(selector) : polyfillClosest(curr, selector));
    }
    /** Polyfill for browsers without Element.closest. */
    function polyfillClosest(element, selector) {
        var curr = element;
        while (curr != null && !(curr instanceof Element && matches(curr, selector))) {
            curr = curr.parentNode;
        }
        return (curr || null);
    }
    var hasNativeClosest = typeof Element != 'undefined' && !!Element.prototype.closest;
    /** IE 11 compatible matches implementation. */
    function matches(element, selector) {
        return element.matches ?
            element.matches(selector) :
            element['msMatchesSelector'](selector);
    }

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /**
     * Lightweight FocusTrapInertStrategy that adds a document focus event
     * listener to redirect focus back inside the FocusTrap.
     */
    var EventListenerFocusTrapInertStrategy = /** @class */ (function () {
        function EventListenerFocusTrapInertStrategy() {
            /** Focus event handler. */
            this._listener = null;
        }
        /** Adds a document event listener that keeps focus inside the FocusTrap. */
        EventListenerFocusTrapInertStrategy.prototype.preventFocus = function (focusTrap) {
            var _this = this;
            // Ensure there's only one listener per document
            if (this._listener) {
                focusTrap._document.removeEventListener('focus', this._listener, true);
            }
            this._listener = function (e) { return _this._trapFocus(focusTrap, e); };
            focusTrap._ngZone.runOutsideAngular(function () {
                focusTrap._document.addEventListener('focus', _this._listener, true);
            });
        };
        /** Removes the event listener added in preventFocus. */
        EventListenerFocusTrapInertStrategy.prototype.allowFocus = function (focusTrap) {
            if (!this._listener) {
                return;
            }
            focusTrap._document.removeEventListener('focus', this._listener, true);
            this._listener = null;
        };
        /**
         * Refocuses the first element in the FocusTrap if the focus event target was outside
         * the FocusTrap.
         *
         * This is an event listener callback. The event listener is added in runOutsideAngular,
         * so all this code runs outside Angular as well.
         */
        EventListenerFocusTrapInertStrategy.prototype._trapFocus = function (focusTrap, event) {
            var target = event.target;
            var focusTrapRoot = focusTrap._element;
            // Don't refocus if target was in an overlay, because the overlay might be associated
            // with an element inside the FocusTrap, ex. mat-select.
            if (!focusTrapRoot.contains(target) && closest(target, 'div.cdk-overlay-pane') === null) {
                // Some legacy FocusTrap usages have logic that focuses some element on the page
                // just before FocusTrap is destroyed. For backwards compatibility, wait
                // to be sure FocusTrap is still enabled before refocusing.
                setTimeout(function () {
                    // Check whether focus wasn't put back into the focus trap while the timeout was pending.
                    if (focusTrap.enabled && !focusTrapRoot.contains(focusTrap._document.activeElement)) {
                        focusTrap.focusFirstTabbableElement();
                    }
                });
            }
        };
        return EventListenerFocusTrapInertStrategy;
    }());

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /**
     * Configuration for creating a ConfigurableFocusTrap.
     */
    var ConfigurableFocusTrapConfig = /** @class */ (function () {
        function ConfigurableFocusTrapConfig() {
            /**
             * Whether to defer the creation of FocusTrap elements to be
             * done manually by the user. Default is to create them
             * automatically.
             */
            this.defer = false;
        }
        return ConfigurableFocusTrapConfig;
    }());

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** The injection token used to specify the inert strategy. */
    var FOCUS_TRAP_INERT_STRATEGY = new i0.InjectionToken('FOCUS_TRAP_INERT_STRATEGY');

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** Injectable that ensures only the most recently enabled FocusTrap is active. */
    var FocusTrapManager = /** @class */ (function () {
        function FocusTrapManager() {
            // A stack of the FocusTraps on the page. Only the FocusTrap at the
            // top of the stack is active.
            this._focusTrapStack = [];
        }
        /**
         * Disables the FocusTrap at the top of the stack, and then pushes
         * the new FocusTrap onto the stack.
         */
        FocusTrapManager.prototype.register = function (focusTrap) {
            // Dedupe focusTraps that register multiple times.
            this._focusTrapStack = this._focusTrapStack.filter(function (ft) { return ft !== focusTrap; });
            var stack = this._focusTrapStack;
            if (stack.length) {
                stack[stack.length - 1]._disable();
            }
            stack.push(focusTrap);
            focusTrap._enable();
        };
        /**
         * Removes the FocusTrap from the stack, and activates the
         * FocusTrap that is the new top of the stack.
         */
        FocusTrapManager.prototype.deregister = function (focusTrap) {
            focusTrap._disable();
            var stack = this._focusTrapStack;
            var i = stack.indexOf(focusTrap);
            if (i !== -1) {
                stack.splice(i, 1);
                if (stack.length) {
                    stack[stack.length - 1]._enable();
                }
            }
        };
        return FocusTrapManager;
    }());
    FocusTrapManager.ɵprov = i0.ɵɵdefineInjectable({ factory: function FocusTrapManager_Factory() { return new FocusTrapManager(); }, token: FocusTrapManager, providedIn: "root" });
    FocusTrapManager.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** Factory that allows easy instantiation of configurable focus traps. */
    var ConfigurableFocusTrapFactory = /** @class */ (function () {
        function ConfigurableFocusTrapFactory(_checker, _ngZone, _focusTrapManager, _document, _inertStrategy) {
            this._checker = _checker;
            this._ngZone = _ngZone;
            this._focusTrapManager = _focusTrapManager;
            this._document = _document;
            // TODO split up the strategies into different modules, similar to DateAdapter.
            this._inertStrategy = _inertStrategy || new EventListenerFocusTrapInertStrategy();
        }
        ConfigurableFocusTrapFactory.prototype.create = function (element, config) {
            if (config === void 0) { config = new ConfigurableFocusTrapConfig(); }
            var configObject;
            if (typeof config === 'boolean') {
                configObject = new ConfigurableFocusTrapConfig();
                configObject.defer = config;
            }
            else {
                configObject = config;
            }
            return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject);
        };
        return ConfigurableFocusTrapFactory;
    }());
    ConfigurableFocusTrapFactory.ɵprov = i0.ɵɵdefineInjectable({ factory: function ConfigurableFocusTrapFactory_Factory() { return new ConfigurableFocusTrapFactory(i0.ɵɵinject(InteractivityChecker), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(FocusTrapManager), i0.ɵɵinject(i2.DOCUMENT), i0.ɵɵinject(FOCUS_TRAP_INERT_STRATEGY, 8)); }, token: ConfigurableFocusTrapFactory, providedIn: "root" });
    ConfigurableFocusTrapFactory.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    ConfigurableFocusTrapFactory.ctorParameters = function () { return [
        { type: InteractivityChecker },
        { type: i0.NgZone },
        { type: FocusTrapManager },
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] },
        { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FOCUS_TRAP_INERT_STRATEGY,] }] }
    ]; };

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    var LIVE_ANNOUNCER_ELEMENT_TOKEN = new i0.InjectionToken('liveAnnouncerElement', {
        providedIn: 'root',
        factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY,
    });
    /** @docs-private */
    function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
        return null;
    }
    /** Injection token that can be used to configure the default options for the LiveAnnouncer. */
    var LIVE_ANNOUNCER_DEFAULT_OPTIONS = new i0.InjectionToken('LIVE_ANNOUNCER_DEFAULT_OPTIONS');

    var LiveAnnouncer = /** @class */ (function () {
        function LiveAnnouncer(elementToken, _ngZone, _document, _defaultOptions) {
            this._ngZone = _ngZone;
            this._defaultOptions = _defaultOptions;
            // We inject the live element and document as `any` because the constructor signature cannot
            // reference browser globals (HTMLElement, Document) on non-browser environments, since having
            // a class decorator causes TypeScript to preserve the constructor signature types.
            this._document = _document;
            this._liveElement = elementToken || this._createLiveElement();
        }
        LiveAnnouncer.prototype.announce = function (message) {
            var _a;
            var _this = this;
            var args = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                args[_i - 1] = arguments[_i];
            }
            var defaultOptions = this._defaultOptions;
            var politeness;
            var duration;
            if (args.length === 1 && typeof args[0] === 'number') {
                duration = args[0];
            }
            else {
                _a = __read(args, 2), politeness = _a[0], duration = _a[1];
            }
            this.clear();
            clearTimeout(this._previousTimeout);
            if (!politeness) {
                politeness =
                    (defaultOptions && defaultOptions.politeness) ? defaultOptions.politeness : 'polite';
            }
            if (duration == null && defaultOptions) {
                duration = defaultOptions.duration;
            }
            // TODO: ensure changing the politeness works on all environments we support.
            this._liveElement.setAttribute('aria-live', politeness);
            // This 100ms timeout is necessary for some browser + screen-reader combinations:
            // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
            // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
            //   second time without clearing and then using a non-zero delay.
            // (using JAWS 17 at time of this writing).
            return this._ngZone.runOutsideAngular(function () {
                return new Promise(function (resolve) {
                    clearTimeout(_this._previousTimeout);
                    _this._previousTimeout = setTimeout(function () {
                        _this._liveElement.textContent = message;
                        resolve();
                        if (typeof duration === 'number') {
                            _this._previousTimeout = setTimeout(function () { return _this.clear(); }, duration);
                        }
                    }, 100);
                });
            });
        };
        /**
         * Clears the current text from the announcer element. Can be used to prevent
         * screen readers from reading the text out again while the user is going
         * through the page landmarks.
         */
        LiveAnnouncer.prototype.clear = function () {
            if (this._liveElement) {
                this._liveElement.textContent = '';
            }
        };
        LiveAnnouncer.prototype.ngOnDestroy = function () {
            clearTimeout(this._previousTimeout);
            if (this._liveElement && this._liveElement.parentNode) {
                this._liveElement.parentNode.removeChild(this._liveElement);
                this._liveElement = null;
            }
        };
        LiveAnnouncer.prototype._createLiveElement = function () {
            var elementClass = 'cdk-live-announcer-element';
            var previousElements = this._document.getElementsByClassName(elementClass);
            var liveEl = this._document.createElement('div');
            // Remove any old containers. This can happen when coming in from a server-side-rendered page.
            for (var i = 0; i < previousElements.length; i++) {
                previousElements[i].parentNode.removeChild(previousElements[i]);
            }
            liveEl.classList.add(elementClass);
            liveEl.classList.add('cdk-visually-hidden');
            liveEl.setAttribute('aria-atomic', 'true');
            liveEl.setAttribute('aria-live', 'polite');
            this._document.body.appendChild(liveEl);
            return liveEl;
        };
        return LiveAnnouncer;
    }());
    LiveAnnouncer.ɵprov = i0.ɵɵdefineInjectable({ factory: function LiveAnnouncer_Factory() { return new LiveAnnouncer(i0.ɵɵinject(LIVE_ANNOUNCER_ELEMENT_TOKEN, 8), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i2.DOCUMENT), i0.ɵɵinject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, 8)); }, token: LiveAnnouncer, providedIn: "root" });
    LiveAnnouncer.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    LiveAnnouncer.ctorParameters = function () { return [
        { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [LIVE_ANNOUNCER_ELEMENT_TOKEN,] }] },
        { type: i0.NgZone },
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] },
        { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [LIVE_ANNOUNCER_DEFAULT_OPTIONS,] }] }
    ]; };
    /**
     * A directive that works similarly to aria-live, but uses the LiveAnnouncer to ensure compatibility
     * with a wider range of browsers and screen readers.
     */
    var CdkAriaLive = /** @class */ (function () {
        function CdkAriaLive(_elementRef, _liveAnnouncer, _contentObserver, _ngZone) {
            this._elementRef = _elementRef;
            this._liveAnnouncer = _liveAnnouncer;
            this._contentObserver = _contentObserver;
            this._ngZone = _ngZone;
            this._politeness = 'polite';
        }
        Object.defineProperty(CdkAriaLive.prototype, "politeness", {
            /** The aria-live politeness level to use when announcing messages. */
            get: function () { return this._politeness; },
            set: function (value) {
                var _this = this;
                this._politeness = value === 'off' || value === 'assertive' ? value : 'polite';
                if (this._politeness === 'off') {
                    if (this._subscription) {
                        this._subscription.unsubscribe();
                        this._subscription = null;
                    }
                }
                else if (!this._subscription) {
                    this._subscription = this._ngZone.runOutsideAngular(function () {
                        return _this._contentObserver
                            .observe(_this._elementRef)
                            .subscribe(function () {
                            // Note that we use textContent here, rather than innerText, in order to avoid a reflow.
                            var elementText = _this._elementRef.nativeElement.textContent;
                            // The `MutationObserver` fires also for attribute
                            // changes which we don't want to announce.
                            if (elementText !== _this._previousAnnouncedText) {
                                _this._liveAnnouncer.announce(elementText, _this._politeness);
                                _this._previousAnnouncedText = elementText;
                            }
                        });
                    });
                }
            },
            enumerable: false,
            configurable: true
        });
        CdkAriaLive.prototype.ngOnDestroy = function () {
            if (this._subscription) {
                this._subscription.unsubscribe();
            }
        };
        return CdkAriaLive;
    }());
    CdkAriaLive.decorators = [
        { type: i0.Directive, args: [{
                    selector: '[cdkAriaLive]',
                    exportAs: 'cdkAriaLive',
                },] }
    ];
    CdkAriaLive.ctorParameters = function () { return [
        { type: i0.ElementRef },
        { type: LiveAnnouncer },
        { type: observers.ContentObserver },
        { type: i0.NgZone }
    ]; };
    CdkAriaLive.propDecorators = {
        politeness: [{ type: i0.Input, args: ['cdkAriaLive',] }]
    };

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** Gets whether an event could be a faked `mousedown` event dispatched by a screen reader. */
    function isFakeMousedownFromScreenReader(event) {
        // We can typically distinguish between these faked mousedown events and real mousedown events
        // using the "buttons" property. While real mousedowns will indicate the mouse button that was
        // pressed (e.g. "1" for the left mouse button), faked mousedowns will usually set the property
        // value to 0.
        return event.buttons === 0;
    }
    /** Gets whether an event could be a faked `touchstart` event dispatched by a screen reader. */
    function isFakeTouchstartFromScreenReader(event) {
        var touch = (event.touches && event.touches[0]) ||
            (event.changedTouches && event.changedTouches[0]);
        // A fake `touchstart` can be distinguished from a real one by looking at the `identifier`
        // which is typically >= 0 on a real device versus -1 from a screen reader. Just to be safe,
        // we can also look at `radiusX` and `radiusY`. This behavior was observed against a Windows 10
        // device with a touch screen running NVDA v2020.4 and Firefox 85 or Chrome 88.
        return !!touch && touch.identifier === -1 && (touch.radiusX == null || touch.radiusX === 1) &&
            (touch.radiusY == null || touch.radiusY === 1);
    }

    // This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
    // that a value of around 650ms seems appropriate.
    var TOUCH_BUFFER_MS = 650;
    /** InjectionToken for FocusMonitorOptions. */
    var FOCUS_MONITOR_DEFAULT_OPTIONS = new i0.InjectionToken('cdk-focus-monitor-default-options');
    /**
     * Event listener options that enable capturing and also
     * mark the listener as passive if the browser supports it.
     */
    var captureEventListenerOptions = i1.normalizePassiveListenerOptions({
        passive: true,
        capture: true
    });
    /** Monitors mouse and keyboard events to determine the cause of focus events. */
    var FocusMonitor = /** @class */ (function () {
        function FocusMonitor(_ngZone, _platform, 
        /** @breaking-change 11.0.0 make document required */
        document, options) {
            var _this = this;
            this._ngZone = _ngZone;
            this._platform = _platform;
            /** The focus origin that the next focus event is a result of. */
            this._origin = null;
            /** Whether the window has just been focused. */
            this._windowFocused = false;
            /** Map of elements being monitored to their info. */
            this._elementInfo = new Map();
            /** The number of elements currently being monitored. */
            this._monitoredElementCount = 0;
            /**
             * Keeps track of the root nodes to which we've currently bound a focus/blur handler,
             * as well as the number of monitored elements that they contain. We have to treat focus/blur
             * handlers differently from the rest of the events, because the browser won't emit events
             * to the document when focus moves inside of a shadow root.
             */
            this._rootNodeFocusListenerCount = new Map();
            /**
             * Event listener for `keydown` events on the document.
             * Needs to be an arrow function in order to preserve the context when it gets bound.
             */
            this._documentKeydownListener = function () {
                // On keydown record the origin and clear any touch event that may be in progress.
                _this._lastTouchTarget = null;
                _this._setOriginForCurrentEventQueue('keyboard');
            };
            /**
             * Event listener for `mousedown` events on the document.
             * Needs to be an arrow function in order to preserve the context when it gets bound.
             */
            this._documentMousedownListener = function (event) {
                // On mousedown record the origin only if there is not touch
                // target, since a mousedown can happen as a result of a touch event.
                if (!_this._lastTouchTarget) {
                    // In some cases screen readers fire fake `mousedown` events instead of `keydown`.
                    // Resolve the focus source to `keyboard` if we detect one of them.
                    var source = isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse';
                    _this._setOriginForCurrentEventQueue(source);
                }
            };
            /**
             * Event listener for `touchstart` events on the document.
             * Needs to be an arrow function in order to preserve the context when it gets bound.
             */
            this._documentTouchstartListener = function (event) {
                // Some screen readers will fire a fake `touchstart` event if an element is activated using
                // the keyboard while on a device with a touchsreen. Consider such events as keyboard focus.
                if (!isFakeTouchstartFromScreenReader(event)) {
                    // When the touchstart event fires the focus event is not yet in the event queue. This means
                    // we can't rely on the trick used above (setting timeout of 1ms). Instead we wait 650ms to
                    // see if a focus happens.
                    if (_this._touchTimeoutId != null) {
                        clearTimeout(_this._touchTimeoutId);
                    }
                    _this._lastTouchTarget = getTarget(event);
                    _this._touchTimeoutId = setTimeout(function () { return _this._lastTouchTarget = null; }, TOUCH_BUFFER_MS);
                }
                else if (!_this._lastTouchTarget) {
                    _this._setOriginForCurrentEventQueue('keyboard');
                }
            };
            /**
             * Event listener for `focus` events on the window.
             * Needs to be an arrow function in order to preserve the context when it gets bound.
             */
            this._windowFocusListener = function () {
                // Make a note of when the window regains focus, so we can
                // restore the origin info for the focused element.
                _this._windowFocused = true;
                _this._windowFocusTimeoutId = setTimeout(function () { return _this._windowFocused = false; });
            };
            /**
             * Event listener for `focus` and 'blur' events on the document.
             * Needs to be an arrow function in order to preserve the context when it gets bound.
             */
            this._rootNodeFocusAndBlurListener = function (event) {
                var target = getTarget(event);
                var handler = event.type === 'focus' ? _this._onFocus : _this._onBlur;
                // We need to walk up the ancestor chain in order to support `checkChildren`.
                for (var element = target; element; element = element.parentElement) {
                    handler.call(_this, event, element);
                }
            };
            this._document = document;
            this._detectionMode = (options === null || options === void 0 ? void 0 : options.detectionMode) || 0 /* IMMEDIATE */;
        }
        FocusMonitor.prototype.monitor = function (element, checkChildren) {
            if (checkChildren === void 0) { checkChildren = false; }
            var nativeElement = coercion.coerceElement(element);
            // Do nothing if we're not on the browser platform or the passed in node isn't an element.
            if (!this._platform.isBrowser || nativeElement.nodeType !== 1) {
                return rxjs.of(null);
            }
            // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to
            // the shadow root, rather than the `document`, because the browser won't emit focus events
            // to the `document`, if focus is moving within the same shadow root.
            var rootNode = i1._getShadowRoot(nativeElement) || this._getDocument();
            var cachedInfo = this._elementInfo.get(nativeElement);
            // Check if we're already monitoring this element.
            if (cachedInfo) {
                if (checkChildren) {
                    // TODO(COMP-318): this can be problematic, because it'll turn all non-checkChildren
                    // observers into ones that behave as if `checkChildren` was turned on. We need a more
                    // robust solution.
                    cachedInfo.checkChildren = true;
                }
                return cachedInfo.subject;
            }
            // Create monitored element info.
            var info = {
                checkChildren: checkChildren,
                subject: new rxjs.Subject(),
                rootNode: rootNode
            };
            this._elementInfo.set(nativeElement, info);
            this._registerGlobalListeners(info);
            return info.subject;
        };
        FocusMonitor.prototype.stopMonitoring = function (element) {
            var nativeElement = coercion.coerceElement(element);
            var elementInfo = this._elementInfo.get(nativeElement);
            if (elementInfo) {
                elementInfo.subject.complete();
                this._setClasses(nativeElement);
                this._elementInfo.delete(nativeElement);
                this._removeGlobalListeners(elementInfo);
            }
        };
        FocusMonitor.prototype.focusVia = function (element, origin, options) {
            var _this = this;
            var nativeElement = coercion.coerceElement(element);
            var focusedElement = this._getDocument().activeElement;
            // If the element is focused already, calling `focus` again won't trigger the event listener
            // which means that the focus classes won't be updated. If that's the case, update the classes
            // directly without waiting for an event.
            if (nativeElement === focusedElement) {
                this._getClosestElementsInfo(nativeElement)
                    .forEach(function (_a) {
                    var _b = __read(_a, 2), currentElement = _b[0], info = _b[1];
                    return _this._originChanged(currentElement, origin, info);
                });
            }
            else {
                this._setOriginForCurrentEventQueue(origin);
                // `focus` isn't available on the server
                if (typeof nativeElement.focus === 'function') {
                    nativeElement.focus(options);
                }
            }
        };
        FocusMonitor.prototype.ngOnDestroy = function () {
            var _this = this;
            this._elementInfo.forEach(function (_info, element) { return _this.stopMonitoring(element); });
        };
        /** Access injected document if available or fallback to global document reference */
        FocusMonitor.prototype._getDocument = function () {
            return this._document || document;
        };
        /** Use defaultView of injected document if available or fallback to global window reference */
        FocusMonitor.prototype._getWindow = function () {
            var doc = this._getDocument();
            return doc.defaultView || window;
        };
        FocusMonitor.prototype._toggleClass = function (element, className, shouldSet) {
            if (shouldSet) {
                element.classList.add(className);
            }
            else {
                element.classList.remove(className);
            }
        };
        FocusMonitor.prototype._getFocusOrigin = function (event) {
            // If we couldn't detect a cause for the focus event, it's due to one of three reasons:
            // 1) The window has just regained focus, in which case we want to restore the focused state of
            //    the element from before the window blurred.
            // 2) It was caused by a touch event, in which case we mark the origin as 'touch'.
            // 3) The element was programmatically focused, in which case we should mark the origin as
            //    'program'.
            if (this._origin) {
                return this._origin;
            }
            if (this._windowFocused && this._lastFocusOrigin) {
                return this._lastFocusOrigin;
            }
            else if (this._wasCausedByTouch(event)) {
                return 'touch';
            }
            else {
                return 'program';
            }
        };
        /**
         * Sets the focus classes on the element based on the given focus origin.
         * @param element The element to update the classes on.
         * @param origin The focus origin.
         */
        FocusMonitor.prototype._setClasses = function (element, origin) {
            this._toggleClass(element, 'cdk-focused', !!origin);
            this._toggleClass(element, 'cdk-touch-focused', origin === 'touch');
            this._toggleClass(element, 'cdk-keyboard-focused', origin === 'keyboard');
            this._toggleClass(element, 'cdk-mouse-focused', origin === 'mouse');
            this._toggleClass(element, 'cdk-program-focused', origin === 'program');
        };
        /**
         * Sets the origin and schedules an async function to clear it at the end of the event queue.
         * If the detection mode is 'eventual', the origin is never cleared.
         * @param origin The origin to set.
         */
        FocusMonitor.prototype._setOriginForCurrentEventQueue = function (origin) {
            var _this = this;
            this._ngZone.runOutsideAngular(function () {
                _this._origin = origin;
                if (_this._detectionMode === 0 /* IMMEDIATE */) {
                    // Sometimes the focus origin won't be valid in Firefox because Firefox seems to focus *one*
                    // tick after the interaction event fired. To ensure the focus origin is always correct,
                    // the focus origin will be determined at the beginning of the next tick.
                    _this._originTimeoutId = setTimeout(function () { return _this._origin = null; }, 1);
                }
            });
        };
        /**
         * Checks whether the given focus event was caused by a touchstart event.
         * @param event The focus event to check.
         * @returns Whether the event was caused by a touch.
         */
        FocusMonitor.prototype._wasCausedByTouch = function (event) {
            // Note(mmalerba): This implementation is not quite perfect, there is a small edge case.
            // Consider the following dom structure:
            //
            // <div #parent tabindex="0" cdkFocusClasses>
            //   <div #child (click)="#parent.focus()"></div>
            // </div>
            //
            // If the user touches the #child element and the #parent is programmatically focused as a
            // result, this code will still consider it to have been caused by the touch event and will
            // apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a
            // relatively small edge-case that can be worked around by using
            // focusVia(parentEl, 'program') to focus the parent element.
            //
            // If we decide that we absolutely must handle this case correctly, we can do so by listening
            // for the first focus event after the touchstart, and then the first blur event after that
            // focus event. When that blur event fires we know that whatever follows is not a result of the
            // touchstart.
            var focusTarget = getTarget(event);
            return this._lastTouchTarget instanceof Node && focusTarget instanceof Node &&
                (focusTarget === this._lastTouchTarget || focusTarget.contains(this._lastTouchTarget));
        };
        /**
         * Handles focus events on a registered element.
         * @param event The focus event.
         * @param element The monitored element.
         */
        FocusMonitor.prototype._onFocus = function (event, element) {
            // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
            // focus event affecting the monitored element. If we want to use the origin of the first event
            // instead we should check for the cdk-focused class here and return if the element already has
            // it. (This only matters for elements that have includesChildren = true).
            // If we are not counting child-element-focus as focused, make sure that the event target is the
            // monitored element itself.
            var elementInfo = this._elementInfo.get(element);
            if (!elementInfo || (!elementInfo.checkChildren && element !== getTarget(event))) {
                return;
            }
            this._originChanged(element, this._getFocusOrigin(event), elementInfo);
        };
        /**
         * Handles blur events on a registered element.
         * @param event The blur event.
         * @param element The monitored element.
         */
        FocusMonitor.prototype._onBlur = function (event, element) {
            // If we are counting child-element-focus as focused, make sure that we aren't just blurring in
            // order to focus another child of the monitored element.
            var elementInfo = this._elementInfo.get(element);
            if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
                element.contains(event.relatedTarget))) {
                return;
            }
            this._setClasses(element);
            this._emitOrigin(elementInfo.subject, null);
        };
        FocusMonitor.prototype._emitOrigin = function (subject, origin) {
            this._ngZone.run(function () { return subject.next(origin); });
        };
        FocusMonitor.prototype._registerGlobalListeners = function (elementInfo) {
            var _this = this;
            if (!this._platform.isBrowser) {
                return;
            }
            var rootNode = elementInfo.rootNode;
            var rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;
            if (!rootNodeFocusListeners) {
                this._ngZone.runOutsideAngular(function () {
                    rootNode.addEventListener('focus', _this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
                    rootNode.addEventListener('blur', _this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
                });
            }
            this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1);
            // Register global listeners when first element is monitored.
            if (++this._monitoredElementCount === 1) {
                // Note: we listen to events in the capture phase so we
                // can detect them even if the user stops propagation.
                this._ngZone.runOutsideAngular(function () {
                    var document = _this._getDocument();
                    var window = _this._getWindow();
                    document.addEventListener('keydown', _this._documentKeydownListener, captureEventListenerOptions);
                    document.addEventListener('mousedown', _this._documentMousedownListener, captureEventListenerOptions);
                    document.addEventListener('touchstart', _this._documentTouchstartListener, captureEventListenerOptions);
                    window.addEventListener('focus', _this._windowFocusListener);
                });
            }
        };
        FocusMonitor.prototype._removeGlobalListeners = function (elementInfo) {
            var rootNode = elementInfo.rootNode;
            if (this._rootNodeFocusListenerCount.has(rootNode)) {
                var rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode);
                if (rootNodeFocusListeners > 1) {
                    this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);
                }
                else {
                    rootNode.removeEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
                    rootNode.removeEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);
                    this._rootNodeFocusListenerCount.delete(rootNode);
                }
            }
            // Unregister global listeners when last element is unmonitored.
            if (!--this._monitoredElementCount) {
                var document = this._getDocument();
                var window = this._getWindow();
                document.removeEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
                document.removeEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
                document.removeEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
                window.removeEventListener('focus', this._windowFocusListener);
                // Clear timeouts for all potentially pending timeouts to prevent the leaks.
                clearTimeout(this._windowFocusTimeoutId);
                clearTimeout(this._touchTimeoutId);
                clearTimeout(this._originTimeoutId);
            }
        };
        /** Updates all the state on an element once its focus origin has changed. */
        FocusMonitor.prototype._originChanged = function (element, origin, elementInfo) {
            this._setClasses(element, origin);
            this._emitOrigin(elementInfo.subject, origin);
            this._lastFocusOrigin = origin;
        };
        /**
         * Collects the `MonitoredElementInfo` of a particular element and
         * all of its ancestors that have enabled `checkChildren`.
         * @param element Element from which to start the search.
         */
        FocusMonitor.prototype._getClosestElementsInfo = function (element) {
            var results = [];
            this._elementInfo.forEach(function (info, currentElement) {
                if (currentElement === element || (info.checkChildren && currentElement.contains(element))) {
                    results.push([currentElement, info]);
                }
            });
            return results;
        };
        return FocusMonitor;
    }());
    FocusMonitor.ɵprov = i0.ɵɵdefineInjectable({ factory: function FocusMonitor_Factory() { return new FocusMonitor(i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i1.Platform), i0.ɵɵinject(i2.DOCUMENT, 8), i0.ɵɵinject(FOCUS_MONITOR_DEFAULT_OPTIONS, 8)); }, token: FocusMonitor, providedIn: "root" });
    FocusMonitor.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    FocusMonitor.ctorParameters = function () { return [
        { type: i0.NgZone },
        { type: i1.Platform },
        { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [i2.DOCUMENT,] }] },
        { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [FOCUS_MONITOR_DEFAULT_OPTIONS,] }] }
    ]; };
    /** Gets the target of an event, accounting for Shadow DOM. */
    function getTarget(event) {
        // If an event is bound outside the Shadow DOM, the `event.target` will
        // point to the shadow root so we have to use `composedPath` instead.
        return (event.composedPath ? event.composedPath()[0] : event.target);
    }
    /**
     * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or
     * programmatically) and adds corresponding classes to the element.
     *
     * There are two variants of this directive:
     * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is
     *    focused.
     * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.
     */
    var CdkMonitorFocus = /** @class */ (function () {
        function CdkMonitorFocus(_elementRef, _focusMonitor) {
            this._elementRef = _elementRef;
            this._focusMonitor = _focusMonitor;
            this.cdkFocusChange = new i0.EventEmitter();
        }
        CdkMonitorFocus.prototype.ngAfterViewInit = function () {
            var _this = this;
            var element = this._elementRef.nativeElement;
            this._monitorSubscription = this._focusMonitor.monitor(element, element.nodeType === 1 && element.hasAttribute('cdkMonitorSubtreeFocus'))
                .subscribe(function (origin) { return _this.cdkFocusChange.emit(origin); });
        };
        CdkMonitorFocus.prototype.ngOnDestroy = function () {
            this._focusMonitor.stopMonitoring(this._elementRef);
            if (this._monitorSubscription) {
                this._monitorSubscription.unsubscribe();
            }
        };
        return CdkMonitorFocus;
    }());
    CdkMonitorFocus.decorators = [
        { type: i0.Directive, args: [{
                    selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]',
                },] }
    ];
    CdkMonitorFocus.ctorParameters = function () { return [
        { type: i0.ElementRef },
        { type: FocusMonitor }
    ]; };
    CdkMonitorFocus.propDecorators = {
        cdkFocusChange: [{ type: i0.Output }]
    };

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    /** CSS class applied to the document body when in black-on-white high-contrast mode. */
    var BLACK_ON_WHITE_CSS_CLASS = 'cdk-high-contrast-black-on-white';
    /** CSS class applied to the document body when in white-on-black high-contrast mode. */
    var WHITE_ON_BLACK_CSS_CLASS = 'cdk-high-contrast-white-on-black';
    /** CSS class applied to the document body when in high-contrast mode. */
    var HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';
    /**
     * Service to determine whether the browser is currently in a high-contrast-mode environment.
     *
     * Microsoft Windows supports an accessibility feature called "High Contrast Mode". This mode
     * changes the appearance of all applications, including web applications, to dramatically increase
     * contrast.
     *
     * IE, Edge, and Firefox currently support this mode. Chrome does not support Windows High Contrast
     * Mode. This service does not detect high-contrast mode as added by the Chrome "High Contrast"
     * browser extension.
     */
    var HighContrastModeDetector = /** @class */ (function () {
        function HighContrastModeDetector(_platform, document) {
            this._platform = _platform;
            this._document = document;
        }
        /** Gets the current high-contrast-mode for the page. */
        HighContrastModeDetector.prototype.getHighContrastMode = function () {
            if (!this._platform.isBrowser) {
                return 0 /* NONE */;
            }
            // Create a test element with an arbitrary background-color that is neither black nor
            // white; high-contrast mode will coerce the color to either black or white. Also ensure that
            // appending the test element to the DOM does not affect layout by absolutely positioning it
            var testElement = this._document.createElement('div');
            testElement.style.backgroundColor = 'rgb(1,2,3)';
            testElement.style.position = 'absolute';
            this._document.body.appendChild(testElement);
            // Get the computed style for the background color, collapsing spaces to normalize between
            // browsers. Once we get this color, we no longer need the test element. Access the `window`
            // via the document so we can fake it in tests. Note that we have extra null checks, because
            // this logic will likely run during app bootstrap and throwing can break the entire app.
            var documentWindow = this._document.defaultView || window;
            var computedStyle = (documentWindow && documentWindow.getComputedStyle) ?
                documentWindow.getComputedStyle(testElement) : null;
            var computedColor = (computedStyle && computedStyle.backgroundColor || '').replace(/ /g, '');
            this._document.body.removeChild(testElement);
            switch (computedColor) {
                case 'rgb(0,0,0)': return 2 /* WHITE_ON_BLACK */;
                case 'rgb(255,255,255)': return 1 /* BLACK_ON_WHITE */;
            }
            return 0 /* NONE */;
        };
        /** Applies CSS classes indicating high-contrast mode to document body (browser-only). */
        HighContrastModeDetector.prototype._applyBodyHighContrastModeCssClasses = function () {
            if (this._platform.isBrowser && this._document.body) {
                var bodyClasses = this._document.body.classList;
                // IE11 doesn't support `classList` operations with multiple arguments
                bodyClasses.remove(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
                bodyClasses.remove(BLACK_ON_WHITE_CSS_CLASS);
                bodyClasses.remove(WHITE_ON_BLACK_CSS_CLASS);
                var mode = this.getHighContrastMode();
                if (mode === 1 /* BLACK_ON_WHITE */) {
                    bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
                    bodyClasses.add(BLACK_ON_WHITE_CSS_CLASS);
                }
                else if (mode === 2 /* WHITE_ON_BLACK */) {
                    bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);
                    bodyClasses.add(WHITE_ON_BLACK_CSS_CLASS);
                }
            }
        };
        return HighContrastModeDetector;
    }());
    HighContrastModeDetector.ɵprov = i0.ɵɵdefineInjectable({ factory: function HighContrastModeDetector_Factory() { return new HighContrastModeDetector(i0.ɵɵinject(i1.Platform), i0.ɵɵinject(i2.DOCUMENT)); }, token: HighContrastModeDetector, providedIn: "root" });
    HighContrastModeDetector.decorators = [
        { type: i0.Injectable, args: [{ providedIn: 'root' },] }
    ];
    HighContrastModeDetector.ctorParameters = function () { return [
        { type: i1.Platform },
        { type: undefined, decorators: [{ type: i0.Inject, args: [i2.DOCUMENT,] }] }
    ]; };

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */
    var A11yModule = /** @class */ (function () {
        function A11yModule(highContrastModeDetector) {
            highContrastModeDetector._applyBodyHighContrastModeCssClasses();
        }
        return A11yModule;
    }());
    A11yModule.decorators = [
        { type: i0.NgModule, args: [{
                    imports: [i1.PlatformModule, observers.ObserversModule],
                    declarations: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
                    exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
                },] }
    ];
    A11yModule.ctorParameters = function () { return [
        { type: HighContrastModeDetector }
    ]; };

    /**
     * @license
     * Copyright Google LLC All Rights Reserved.
     *
     * Use of this source code is governed by an MIT-style license that can be
     * found in the LICENSE file at https://angular.io/license
     */

    /**
     * Generated bundle index. Do not edit.
     */

    exports.A11yModule = A11yModule;
    exports.ActiveDescendantKeyManager = ActiveDescendantKeyManager;
    exports.AriaDescriber = AriaDescriber;
    exports.CDK_DESCRIBEDBY_HOST_ATTRIBUTE = CDK_DESCRIBEDBY_HOST_ATTRIBUTE;
    exports.CDK_DESCRIBEDBY_ID_PREFIX = CDK_DESCRIBEDBY_ID_PREFIX;
    exports.CdkAriaLive = CdkAriaLive;
    exports.CdkMonitorFocus = CdkMonitorFocus;
    exports.CdkTrapFocus = CdkTrapFocus;
    exports.ConfigurableFocusTrap = ConfigurableFocusTrap;
    exports.ConfigurableFocusTrapFactory = ConfigurableFocusTrapFactory;
    exports.EventListenerFocusTrapInertStrategy = EventListenerFocusTrapInertStrategy;
    exports.FOCUS_MONITOR_DEFAULT_OPTIONS = FOCUS_MONITOR_DEFAULT_OPTIONS;
    exports.FOCUS_TRAP_INERT_STRATEGY = FOCUS_TRAP_INERT_STRATEGY;
    exports.FocusKeyManager = FocusKeyManager;
    exports.FocusMonitor = FocusMonitor;
    exports.FocusTrap = FocusTrap;
    exports.FocusTrapFactory = FocusTrapFactory;
    exports.HighContrastModeDetector = HighContrastModeDetector;
    exports.InteractivityChecker = InteractivityChecker;
    exports.IsFocusableConfig = IsFocusableConfig;
    exports.LIVE_ANNOUNCER_DEFAULT_OPTIONS = LIVE_ANNOUNCER_DEFAULT_OPTIONS;
    exports.LIVE_ANNOUNCER_ELEMENT_TOKEN = LIVE_ANNOUNCER_ELEMENT_TOKEN;
    exports.LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY = LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY;
    exports.ListKeyManager = ListKeyManager;
    exports.LiveAnnouncer = LiveAnnouncer;
    exports.MESSAGES_CONTAINER_ID = MESSAGES_CONTAINER_ID;
    exports.TOUCH_BUFFER_MS = TOUCH_BUFFER_MS;
    exports.isFakeMousedownFromScreenReader = isFakeMousedownFromScreenReader;
    exports.isFakeTouchstartFromScreenReader = isFakeTouchstartFromScreenReader;
    exports.ɵangular_material_src_cdk_a11y_a11y_a = FocusTrapManager;
    exports.ɵangular_material_src_cdk_a11y_a11y_b = ConfigurableFocusTrapConfig;

    Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=cdk-a11y.umd.js.map
