diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/0.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/0.pack
new file mode 100644
index 0000000..de397a5
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/0.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/1.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/1.pack
new file mode 100644
index 0000000..f9453d5
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/1.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/2.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/2.pack
new file mode 100644
index 0000000..8d79674
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/2.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/3.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/3.pack
new file mode 100644
index 0000000..6ce5177
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/3.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/4.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/4.pack
new file mode 100644
index 0000000..2044d05
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/4.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/5.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/5.pack
new file mode 100644
index 0000000..a920eca
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/5.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/6.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/6.pack
new file mode 100644
index 0000000..4b22174
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/6.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/7.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/7.pack
new file mode 100644
index 0000000..bb8939f
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/7.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack
new file mode 100644
index 0000000..89cd785
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack differ
diff --git a/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack.old b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack.old
new file mode 100644
index 0000000..76e0c88
Binary files /dev/null and b/.angular/cache/angular-webpack/abaea2daad04f175352255413d528437e2991d55/index.pack.old differ
diff --git a/.angular/cache/babel-webpack/021b3875dac392038afa4f167f278f3e.json b/.angular/cache/babel-webpack/021b3875dac392038afa4f167f278f3e.json
new file mode 100644
index 0000000..d1d489f
--- /dev/null
+++ b/.angular/cache/babel-webpack/021b3875dac392038afa4f167f278f3e.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\nexport function isIterable(input) {\n return isFunction(input === null || input === void 0 ? void 0 : input[Symbol_iterator]);\n} //# sourceMappingURL=isIterable.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/036b7ab6142c04bf4288e8dd6270e32a.json b/.angular/cache/babel-webpack/036b7ab6142c04bf4288e8dd6270e32a.json
new file mode 100644
index 0000000..f2e940f
--- /dev/null
+++ b/.angular/cache/babel-webpack/036b7ab6142c04bf4288e8dd6270e32a.json
@@ -0,0 +1 @@
+{"ast":null,"code":"// This file can be replaced during build by using the `fileReplacements` array.\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\n// The list of file replacements can be found in `angular.json`.\nexport const environment = {\n production: false\n};\n/*\n * For easier debugging in development mode, you can import the following file\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\n *\n * This import should be commented out in production mode because it will have a negative impact\n * on performance if an error is thrown.\n */\n// import 'zone.js/dist/zone-error'; // Included with Angular CLI.","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/05051ec7a3149bf36bd7e011662bb2ac.json b/.angular/cache/babel-webpack/05051ec7a3149bf36bd7e011662bb2ac.json
new file mode 100644
index 0000000..fef4b83
--- /dev/null
+++ b/.angular/cache/babel-webpack/05051ec7a3149bf36bd7e011662bb2ac.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { map } from \"../operators/map\";\nconst {\n isArray\n} = Array;\n\nfunction callOrApply(fn, args) {\n return isArray(args) ? fn(...args) : fn(args);\n}\n\nexport function mapOneOrManyArgs(fn) {\n return map(args => callOrApply(fn, args));\n} //# sourceMappingURL=mapOneOrManyArgs.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/072811d0b56c1dde6cf01c87a40a68cd.json b/.angular/cache/babel-webpack/072811d0b56c1dde6cf01c87a40a68cd.json
new file mode 100644
index 0000000..5fc7050
--- /dev/null
+++ b/.angular/cache/babel-webpack/072811d0b56c1dde6cf01c87a40a68cd.json
@@ -0,0 +1 @@
+{"ast":null,"code":"export const observable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')(); //# sourceMappingURL=observable.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0939bc6a6a9f12e9fb0eaf88899be418.json b/.angular/cache/babel-webpack/0939bc6a6a9f12e9fb0eaf88899be418.json
new file mode 100644
index 0000000..acbe50f
--- /dev/null
+++ b/.angular/cache/babel-webpack/0939bc6a6a9f12e9fb0eaf88899be418.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { DOCUMENT } from '@angular/common';\nimport * as i0 from '@angular/core';\nimport { Injectable, Inject, QueryList, Directive, Input, InjectionToken, Optional, EventEmitter, Output, NgModule } from '@angular/core';\nimport { Subject, Subscription, BehaviorSubject, of } from 'rxjs';\nimport { hasModifierKey, A, Z, ZERO, NINE, END, HOME, LEFT_ARROW, RIGHT_ARROW, UP_ARROW, DOWN_ARROW, TAB, ALT, CONTROL, MAC_META, META, SHIFT } from '@angular/cdk/keycodes';\nimport { tap, debounceTime, filter, map, take, skip, distinctUntilChanged, takeUntil } from 'rxjs/operators';\nimport { coerceBooleanProperty, coerceElement } from '@angular/cdk/coercion';\nimport * as i1 from '@angular/cdk/platform';\nimport { _getFocusedElementPierceShadowDom, normalizePassiveListenerOptions, _getEventTarget, _getShadowRoot, PlatformModule } from '@angular/cdk/platform';\nimport * as i1$1 from '@angular/cdk/observers';\nimport { ObserversModule } from '@angular/cdk/observers';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** IDs are delimited by an empty space, as per the spec. */\n\nconst ID_DELIMITER = ' ';\n/**\n * Adds the given ID to the specified ARIA attribute on an element.\n * Used for attributes such as aria-labelledby, aria-owns, etc.\n */\n\nfunction addAriaReferencedId(el, attr, id) {\n const ids = getAriaReferenceIds(el, attr);\n\n if (ids.some(existingId => existingId.trim() == id.trim())) {\n return;\n }\n\n ids.push(id.trim());\n el.setAttribute(attr, ids.join(ID_DELIMITER));\n}\n/**\n * Removes the given ID from the specified ARIA attribute on an element.\n * Used for attributes such as aria-labelledby, aria-owns, etc.\n */\n\n\nfunction removeAriaReferencedId(el, attr, id) {\n const ids = getAriaReferenceIds(el, attr);\n const filteredIds = ids.filter(val => val != id.trim());\n\n if (filteredIds.length) {\n el.setAttribute(attr, filteredIds.join(ID_DELIMITER));\n } else {\n el.removeAttribute(attr);\n }\n}\n/**\n * Gets the list of IDs referenced by the given ARIA attribute on an element.\n * Used for attributes such as aria-labelledby, aria-owns, etc.\n */\n\n\nfunction getAriaReferenceIds(el, attr) {\n // Get string array of all individual ids (whitespace delimited) in the attribute value\n return (el.getAttribute(attr) || '').match(/\\S+/g) || [];\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** ID used for the body container where all messages are appended. */\n\n\nconst MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';\n/** ID prefix used for each created message element. */\n\nconst CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';\n/** Attribute given to each host element that is described by a message element. */\n\nconst CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';\n/** Global incremental identifier for each registered message element. */\n\nlet nextId = 0;\n/** Global map of all registered message elements that have been placed into the document. */\n\nconst messageRegistry = /*#__PURE__*/new Map();\n/** Container for all registered messages. */\n\nlet messagesContainer = null;\n/**\n * Utility that creates visually hidden elements with a message content. Useful for elements that\n * want to use aria-describedby to further describe themselves without adding additional visual\n * content.\n */\n\nlet AriaDescriber = /*#__PURE__*/(() => {\n class AriaDescriber {\n constructor(_document) {\n this._document = _document;\n }\n\n describe(hostElement, message, role) {\n if (!this._canBeDescribed(hostElement, message)) {\n return;\n }\n\n const key = getKey(message, role);\n\n if (typeof message !== 'string') {\n // We need to ensure that the element has an ID.\n setMessageId(message);\n messageRegistry.set(key, {\n messageElement: message,\n referenceCount: 0\n });\n } else if (!messageRegistry.has(key)) {\n this._createMessageElement(message, role);\n }\n\n if (!this._isElementDescribedByMessage(hostElement, key)) {\n this._addMessageReference(hostElement, key);\n }\n }\n\n removeDescription(hostElement, message, role) {\n if (!message || !this._isElementNode(hostElement)) {\n return;\n }\n\n const key = getKey(message, role);\n\n if (this._isElementDescribedByMessage(hostElement, key)) {\n this._removeMessageReference(hostElement, key);\n } // If the message is a string, it means that it's one that we created for the\n // consumer so we can remove it safely, otherwise we should leave it in place.\n\n\n if (typeof message === 'string') {\n const registeredMessage = messageRegistry.get(key);\n\n if (registeredMessage && registeredMessage.referenceCount === 0) {\n this._deleteMessageElement(key);\n }\n }\n\n if (messagesContainer && messagesContainer.childNodes.length === 0) {\n this._deleteMessagesContainer();\n }\n }\n /** Unregisters all created message elements and removes the message container. */\n\n\n ngOnDestroy() {\n const describedElements = this._document.querySelectorAll(`[${CDK_DESCRIBEDBY_HOST_ATTRIBUTE}]`);\n\n for (let i = 0; i < describedElements.length; i++) {\n this._removeCdkDescribedByReferenceIds(describedElements[i]);\n\n describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);\n }\n\n if (messagesContainer) {\n this._deleteMessagesContainer();\n }\n\n messageRegistry.clear();\n }\n /**\n * Creates a new element in the visually hidden message container element with the message\n * as its content and adds it to the message registry.\n */\n\n\n _createMessageElement(message, role) {\n const messageElement = this._document.createElement('div');\n\n setMessageId(messageElement);\n messageElement.textContent = message;\n\n if (role) {\n messageElement.setAttribute('role', role);\n }\n\n this._createMessagesContainer();\n\n messagesContainer.appendChild(messageElement);\n messageRegistry.set(getKey(message, role), {\n messageElement,\n referenceCount: 0\n });\n }\n /** Deletes the message element from the global messages container. */\n\n\n _deleteMessageElement(key) {\n const registeredMessage = messageRegistry.get(key);\n registeredMessage?.messageElement?.remove();\n messageRegistry.delete(key);\n }\n /** Creates the global container for all aria-describedby messages. */\n\n\n _createMessagesContainer() {\n if (!messagesContainer) {\n const 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\n // already a container on the page, but we don't have a reference to it. Clear the\n // old container so we don't get duplicates. Doing this, instead of emptying the previous\n // container, should be slightly faster.\n\n\n preExistingContainer?.remove();\n messagesContainer = this._document.createElement('div');\n messagesContainer.id = MESSAGES_CONTAINER_ID; // We add `visibility: hidden` in order to prevent text in this container from\n // being searchable by the browser's Ctrl + F functionality.\n // Screen-readers will still read the description for elements with aria-describedby even\n // when the description element is not visible.\n\n messagesContainer.style.visibility = 'hidden'; // Even though we use `visibility: hidden`, we still apply `cdk-visually-hidden` so that\n // the description element doesn't impact page layout.\n\n messagesContainer.classList.add('cdk-visually-hidden');\n\n this._document.body.appendChild(messagesContainer);\n }\n }\n /** Deletes the global messages container. */\n\n\n _deleteMessagesContainer() {\n if (messagesContainer) {\n messagesContainer.remove();\n messagesContainer = null;\n }\n }\n /** Removes all cdk-describedby messages that are hosted through the element. */\n\n\n _removeCdkDescribedByReferenceIds(element) {\n // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX\n const originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby').filter(id => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0);\n element.setAttribute('aria-describedby', originalReferenceIds.join(' '));\n }\n /**\n * Adds a message reference to the element using aria-describedby and increments the registered\n * message's reference count.\n */\n\n\n _addMessageReference(element, key) {\n const registeredMessage = messageRegistry.get(key); // Add the aria-describedby reference and set the\n // describedby_host attribute to mark the element.\n\n addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);\n element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, '');\n registeredMessage.referenceCount++;\n }\n /**\n * Removes a message reference from the element using aria-describedby\n * and decrements the registered message's reference count.\n */\n\n\n _removeMessageReference(element, key) {\n const registeredMessage = messageRegistry.get(key);\n registeredMessage.referenceCount--;\n removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);\n element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);\n }\n /** Returns true if the element has been described by the provided message ID. */\n\n\n _isElementDescribedByMessage(element, key) {\n const referenceIds = getAriaReferenceIds(element, 'aria-describedby');\n const registeredMessage = messageRegistry.get(key);\n const messageId = registeredMessage && registeredMessage.messageElement.id;\n return !!messageId && referenceIds.indexOf(messageId) != -1;\n }\n /** Determines whether a message can be described on a particular element. */\n\n\n _canBeDescribed(element, message) {\n if (!this._isElementNode(element)) {\n return false;\n }\n\n if (message && typeof message === 'object') {\n // We'd have to make some assumptions about the description element's text, if the consumer\n // passed in an element. Assume that if an element is passed in, the consumer has verified\n // that it can be used as a description.\n return true;\n }\n\n const trimmedMessage = message == null ? '' : `${message}`.trim();\n const ariaLabel = element.getAttribute('aria-label'); // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the\n // element, because screen readers will end up reading out the same text twice in a row.\n\n return trimmedMessage ? !ariaLabel || ariaLabel.trim() !== trimmedMessage : false;\n }\n /** Checks whether a node is an Element node. */\n\n\n _isElementNode(element) {\n return element.nodeType === this._document.ELEMENT_NODE;\n }\n\n }\n\n AriaDescriber.ɵfac = function AriaDescriber_Factory(t) {\n return new (t || AriaDescriber)(i0.ɵɵinject(DOCUMENT));\n };\n\n AriaDescriber.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: AriaDescriber,\n factory: AriaDescriber.ɵfac,\n providedIn: 'root'\n });\n return AriaDescriber;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Gets a key that can be used to look messages up in the registry. */\n\n\nfunction getKey(message, role) {\n return typeof message === 'string' ? `${role || ''}/${message}` : message;\n}\n/** Assigns a unique ID to an element, if it doesn't have one already. */\n\n\nfunction setMessageId(element) {\n if (!element.id) {\n element.id = `${CDK_DESCRIBEDBY_ID_PREFIX}-${nextId++}`;\n }\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * This class manages keyboard events for selectable lists. If you pass it a query list\n * of items, it will set the active item correctly when arrow events occur.\n */\n\n\nclass ListKeyManager {\n constructor(_items) {\n this._items = _items;\n this._activeItemIndex = -1;\n this._activeItem = null;\n this._wrap = false;\n this._letterKeyStream = new Subject();\n this._typeaheadSubscription = Subscription.EMPTY;\n this._vertical = true;\n this._allowedModifierKeys = [];\n this._homeAndEnd = false;\n /**\n * Predicate function that can be used to check whether an item should be skipped\n * by the key manager. By default, disabled items are skipped.\n */\n\n this._skipPredicateFn = item => item.disabled; // Buffer for the letters that the user has pressed when the typeahead option is turned on.\n\n\n this._pressedLetters = [];\n /**\n * Stream that emits any time the TAB key is pressed, so components can react\n * when focus is shifted off of the list.\n */\n\n this.tabOut = new Subject();\n /** Stream that emits whenever the active item of the list manager changes. */\n\n this.change = new Subject(); // We allow for the items to be an array because, in some cases, the consumer may\n // not have access to a QueryList of the items they want to manage (e.g. when the\n // items aren't being collected via `ViewChildren` or `ContentChildren`).\n\n if (_items instanceof QueryList) {\n _items.changes.subscribe(newItems => {\n if (this._activeItem) {\n const itemArray = newItems.toArray();\n const newIndex = itemArray.indexOf(this._activeItem);\n\n if (newIndex > -1 && newIndex !== this._activeItemIndex) {\n this._activeItemIndex = newIndex;\n }\n }\n });\n }\n }\n /**\n * Sets the predicate function that determines which items should be skipped by the\n * list key manager.\n * @param predicate Function that determines whether the given item should be skipped.\n */\n\n\n skipPredicate(predicate) {\n this._skipPredicateFn = predicate;\n return this;\n }\n /**\n * Configures wrapping mode, which determines whether the active item will wrap to\n * the other end of list when there are no more items in the given direction.\n * @param shouldWrap Whether the list should wrap when reaching the end.\n */\n\n\n withWrap(shouldWrap = true) {\n this._wrap = shouldWrap;\n return this;\n }\n /**\n * Configures whether the key manager should be able to move the selection vertically.\n * @param enabled Whether vertical selection should be enabled.\n */\n\n\n withVerticalOrientation(enabled = true) {\n this._vertical = enabled;\n return this;\n }\n /**\n * Configures the key manager to move the selection horizontally.\n * Passing in `null` will disable horizontal movement.\n * @param direction Direction in which the selection can be moved.\n */\n\n\n withHorizontalOrientation(direction) {\n this._horizontal = direction;\n return this;\n }\n /**\n * Modifier keys which are allowed to be held down and whose default actions will be prevented\n * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.\n */\n\n\n withAllowedModifierKeys(keys) {\n this._allowedModifierKeys = keys;\n return this;\n }\n /**\n * Turns on typeahead mode which allows users to set the active item by typing.\n * @param debounceInterval Time to wait after the last keystroke before setting the active item.\n */\n\n\n withTypeAhead(debounceInterval = 200) {\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && this._items.length && this._items.some(item => typeof item.getLabel !== 'function')) {\n throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');\n }\n\n this._typeaheadSubscription.unsubscribe(); // Debounce the presses of non-navigational keys, collect the ones that correspond to letters\n // and convert those letters back into a string. Afterwards find the first item that starts\n // with that string and select it.\n\n\n this._typeaheadSubscription = this._letterKeyStream.pipe(tap(letter => this._pressedLetters.push(letter)), debounceTime(debounceInterval), filter(() => this._pressedLetters.length > 0), map(() => this._pressedLetters.join(''))).subscribe(inputString => {\n const items = this._getItemsArray(); // Start at 1 because we want to start searching at the item immediately\n // following the current active item.\n\n\n for (let i = 1; i < items.length + 1; i++) {\n const index = (this._activeItemIndex + i) % items.length;\n const item = items[index];\n\n if (!this._skipPredicateFn(item) && item.getLabel().toUpperCase().trim().indexOf(inputString) === 0) {\n this.setActiveItem(index);\n break;\n }\n }\n\n this._pressedLetters = [];\n });\n return this;\n }\n /**\n * Configures the key manager to activate the first and last items\n * respectively when the Home or End key is pressed.\n * @param enabled Whether pressing the Home or End key activates the first/last item.\n */\n\n\n withHomeAndEnd(enabled = true) {\n this._homeAndEnd = enabled;\n return this;\n }\n\n setActiveItem(item) {\n const previousActiveItem = this._activeItem;\n this.updateActiveItem(item);\n\n if (this._activeItem !== previousActiveItem) {\n this.change.next(this._activeItemIndex);\n }\n }\n /**\n * Sets the active item depending on the key event passed in.\n * @param event Keyboard event to be used for determining which element should be active.\n */\n\n\n onKeydown(event) {\n const keyCode = event.keyCode;\n const modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];\n const isModifierAllowed = modifiers.every(modifier => {\n return !event[modifier] || this._allowedModifierKeys.indexOf(modifier) > -1;\n });\n\n switch (keyCode) {\n case TAB:\n this.tabOut.next();\n return;\n\n case DOWN_ARROW:\n if (this._vertical && isModifierAllowed) {\n this.setNextItemActive();\n break;\n } else {\n return;\n }\n\n case UP_ARROW:\n if (this._vertical && isModifierAllowed) {\n this.setPreviousItemActive();\n break;\n } else {\n return;\n }\n\n case RIGHT_ARROW:\n if (this._horizontal && isModifierAllowed) {\n this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();\n break;\n } else {\n return;\n }\n\n case LEFT_ARROW:\n if (this._horizontal && isModifierAllowed) {\n this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();\n break;\n } else {\n return;\n }\n\n case HOME:\n if (this._homeAndEnd && isModifierAllowed) {\n this.setFirstItemActive();\n break;\n } else {\n return;\n }\n\n case END:\n if (this._homeAndEnd && isModifierAllowed) {\n this.setLastItemActive();\n break;\n } else {\n return;\n }\n\n default:\n if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {\n // Attempt to use the `event.key` which also maps it to the user's keyboard language,\n // otherwise fall back to resolving alphanumeric characters via the keyCode.\n if (event.key && event.key.length === 1) {\n this._letterKeyStream.next(event.key.toLocaleUpperCase());\n } else if (keyCode >= A && keyCode <= Z || keyCode >= ZERO && keyCode <= NINE) {\n this._letterKeyStream.next(String.fromCharCode(keyCode));\n }\n } // Note that we return here, in order to avoid preventing\n // the default action of non-navigational keys.\n\n\n return;\n }\n\n this._pressedLetters = [];\n event.preventDefault();\n }\n /** Index of the currently active item. */\n\n\n get activeItemIndex() {\n return this._activeItemIndex;\n }\n /** The active item. */\n\n\n get activeItem() {\n return this._activeItem;\n }\n /** Gets whether the user is currently typing into the manager using the typeahead feature. */\n\n\n isTyping() {\n return this._pressedLetters.length > 0;\n }\n /** Sets the active item to the first enabled item in the list. */\n\n\n setFirstItemActive() {\n this._setActiveItemByIndex(0, 1);\n }\n /** Sets the active item to the last enabled item in the list. */\n\n\n setLastItemActive() {\n this._setActiveItemByIndex(this._items.length - 1, -1);\n }\n /** Sets the active item to the next enabled item in the list. */\n\n\n setNextItemActive() {\n this._activeItemIndex < 0 ? this.setFirstItemActive() : this._setActiveItemByDelta(1);\n }\n /** Sets the active item to a previous enabled item in the list. */\n\n\n setPreviousItemActive() {\n this._activeItemIndex < 0 && this._wrap ? this.setLastItemActive() : this._setActiveItemByDelta(-1);\n }\n\n updateActiveItem(item) {\n const itemArray = this._getItemsArray();\n\n const index = typeof item === 'number' ? item : itemArray.indexOf(item);\n const activeItem = itemArray[index]; // Explicitly check for `null` and `undefined` because other falsy values are valid.\n\n this._activeItem = activeItem == null ? null : activeItem;\n this._activeItemIndex = index;\n }\n /**\n * This method sets the active item, given a list of items and the delta between the\n * currently active item and the new active item. It will calculate differently\n * depending on whether wrap mode is turned on.\n */\n\n\n _setActiveItemByDelta(delta) {\n this._wrap ? this._setActiveInWrapMode(delta) : this._setActiveInDefaultMode(delta);\n }\n /**\n * Sets the active item properly given \"wrap\" mode. In other words, it will continue to move\n * down the list until it finds an item that is not disabled, and it will wrap if it\n * encounters either end of the list.\n */\n\n\n _setActiveInWrapMode(delta) {\n const items = this._getItemsArray();\n\n for (let i = 1; i <= items.length; i++) {\n const index = (this._activeItemIndex + delta * i + items.length) % items.length;\n const item = items[index];\n\n if (!this._skipPredicateFn(item)) {\n this.setActiveItem(index);\n return;\n }\n }\n }\n /**\n * Sets the active item properly given the default mode. In other words, it will\n * continue to move down the list until it finds an item that is not disabled. If\n * it encounters either end of the list, it will stop and not wrap.\n */\n\n\n _setActiveInDefaultMode(delta) {\n this._setActiveItemByIndex(this._activeItemIndex + delta, delta);\n }\n /**\n * Sets the active item to the first enabled item starting at the index specified. If the\n * item is disabled, it will move in the fallbackDelta direction until it either\n * finds an enabled item or encounters the end of the list.\n */\n\n\n _setActiveItemByIndex(index, fallbackDelta) {\n const items = this._getItemsArray();\n\n if (!items[index]) {\n return;\n }\n\n while (this._skipPredicateFn(items[index])) {\n index += fallbackDelta;\n\n if (!items[index]) {\n return;\n }\n }\n\n this.setActiveItem(index);\n }\n /** Returns the items as an array. */\n\n\n _getItemsArray() {\n return this._items instanceof QueryList ? this._items.toArray() : this._items;\n }\n\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nclass ActiveDescendantKeyManager extends ListKeyManager {\n setActiveItem(index) {\n if (this.activeItem) {\n this.activeItem.setInactiveStyles();\n }\n\n super.setActiveItem(index);\n\n if (this.activeItem) {\n this.activeItem.setActiveStyles();\n }\n }\n\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nclass FocusKeyManager extends ListKeyManager {\n constructor() {\n super(...arguments);\n this._origin = 'program';\n }\n /**\n * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.\n * @param origin Focus origin to be used when focusing items.\n */\n\n\n setFocusOrigin(origin) {\n this._origin = origin;\n return this;\n }\n\n setActiveItem(item) {\n super.setActiveItem(item);\n\n if (this.activeItem) {\n this.activeItem.focus(this._origin);\n }\n }\n\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Configuration for the isFocusable method.\n */\n\n\nclass IsFocusableConfig {\n constructor() {\n /**\n * Whether to count an element as focusable even if it is not currently visible.\n */\n this.ignoreVisibility = false;\n }\n\n} // The InteractivityChecker leans heavily on the ally.js accessibility utilities.\n// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are\n// supported.\n\n/**\n * Utility for checking the interactivity of an element, such as whether is is focusable or\n * tabbable.\n */\n\n\nlet InteractivityChecker = /*#__PURE__*/(() => {\n class InteractivityChecker {\n constructor(_platform) {\n this._platform = _platform;\n }\n /**\n * Gets whether an element is disabled.\n *\n * @param element Element to be checked.\n * @returns Whether the element is disabled.\n */\n\n\n isDisabled(element) {\n // This does not capture some cases, such as a non-form control with a disabled attribute or\n // a form control inside of a disabled form, but should capture the most common cases.\n return element.hasAttribute('disabled');\n }\n /**\n * Gets whether an element is visible for the purposes of interactivity.\n *\n * This will capture states like `display: none` and `visibility: hidden`, but not things like\n * being clipped by an `overflow: hidden` parent or being outside the viewport.\n *\n * @returns Whether the element is visible.\n */\n\n\n isVisible(element) {\n return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';\n }\n /**\n * Gets whether an element can be reached via Tab key.\n * Assumes that the element has already been checked with isFocusable.\n *\n * @param element Element to be checked.\n * @returns Whether the element is tabbable.\n */\n\n\n isTabbable(element) {\n // Nothing is tabbable on the server 😎\n if (!this._platform.isBrowser) {\n return false;\n }\n\n const frameElement = getFrameElement(getWindow(element));\n\n if (frameElement) {\n // Frame elements inherit their tabindex onto all child elements.\n if (getTabIndexValue(frameElement) === -1) {\n return false;\n } // Browsers disable tabbing to an element inside of an invisible frame.\n\n\n if (!this.isVisible(frameElement)) {\n return false;\n }\n }\n\n let nodeName = element.nodeName.toLowerCase();\n let tabIndexValue = getTabIndexValue(element);\n\n if (element.hasAttribute('contenteditable')) {\n return tabIndexValue !== -1;\n }\n\n if (nodeName === 'iframe' || nodeName === 'object') {\n // The frame or object's content may be tabbable depending on the content, but it's\n // not possibly to reliably detect the content of the frames. We always consider such\n // elements as non-tabbable.\n return false;\n } // In iOS, the browser only considers some specific elements as tabbable.\n\n\n if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {\n return false;\n }\n\n if (nodeName === 'audio') {\n // Audio elements without controls enabled are never tabbable, regardless\n // of the tabindex attribute explicitly being set.\n if (!element.hasAttribute('controls')) {\n return false;\n } // Audio elements with controls are by default tabbable unless the\n // tabindex attribute is set to `-1` explicitly.\n\n\n return tabIndexValue !== -1;\n }\n\n if (nodeName === 'video') {\n // For all video elements, if the tabindex attribute is set to `-1`, the video\n // is not tabbable. Note: We cannot rely on the default `HTMLElement.tabIndex`\n // property as that one is set to `-1` in Chrome, Edge and Safari v13.1. The\n // tabindex attribute is the source of truth here.\n if (tabIndexValue === -1) {\n return false;\n } // If the tabindex is explicitly set, and not `-1` (as per check before), the\n // video element is always tabbable (regardless of whether it has controls or not).\n\n\n if (tabIndexValue !== null) {\n return true;\n } // Otherwise (when no explicit tabindex is set), a video is only tabbable if it\n // has controls enabled. Firefox is special as videos are always tabbable regardless\n // of whether there are controls or not.\n\n\n return this._platform.FIREFOX || element.hasAttribute('controls');\n }\n\n return element.tabIndex >= 0;\n }\n /**\n * Gets whether an element can be focused by the user.\n *\n * @param element Element to be checked.\n * @param config The config object with options to customize this method's behavior\n * @returns Whether the element is focusable.\n */\n\n\n isFocusable(element, config) {\n // Perform checks in order of left to most expensive.\n // Again, naive approach that does not capture many edge cases and browser quirks.\n return isPotentiallyFocusable(element) && !this.isDisabled(element) && (config?.ignoreVisibility || this.isVisible(element));\n }\n\n }\n\n InteractivityChecker.ɵfac = function InteractivityChecker_Factory(t) {\n return new (t || InteractivityChecker)(i0.ɵɵinject(i1.Platform));\n };\n\n InteractivityChecker.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: InteractivityChecker,\n factory: InteractivityChecker.ɵfac,\n providedIn: 'root'\n });\n return InteractivityChecker;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Returns the frame element from a window object. Since browsers like MS Edge throw errors if\n * the frameElement property is being accessed from a different host address, this property\n * should be accessed carefully.\n */\n\n\nfunction getFrameElement(window) {\n try {\n return window.frameElement;\n } catch {\n return null;\n }\n}\n/** Checks whether the specified element has any geometry / rectangles. */\n\n\nfunction hasGeometry(element) {\n // Use logic from jQuery to check for an invisible element.\n // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12\n return !!(element.offsetWidth || element.offsetHeight || typeof element.getClientRects === 'function' && element.getClientRects().length);\n}\n/** Gets whether an element's */\n\n\nfunction isNativeFormElement(element) {\n let nodeName = element.nodeName.toLowerCase();\n return nodeName === 'input' || nodeName === 'select' || nodeName === 'button' || nodeName === 'textarea';\n}\n/** Gets whether an element is an ``. */\n\n\nfunction isHiddenInput(element) {\n return isInputElement(element) && element.type == 'hidden';\n}\n/** Gets whether an element is an anchor that has an href attribute. */\n\n\nfunction isAnchorWithHref(element) {\n return isAnchorElement(element) && element.hasAttribute('href');\n}\n/** Gets whether an element is an input element. */\n\n\nfunction isInputElement(element) {\n return element.nodeName.toLowerCase() == 'input';\n}\n/** Gets whether an element is an anchor element. */\n\n\nfunction isAnchorElement(element) {\n return element.nodeName.toLowerCase() == 'a';\n}\n/** Gets whether an element has a valid tabindex. */\n\n\nfunction hasValidTabIndex(element) {\n if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {\n return false;\n }\n\n let tabIndex = element.getAttribute('tabindex');\n return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));\n}\n/**\n * Returns the parsed tabindex from the element attributes instead of returning the\n * evaluated tabindex from the browsers defaults.\n */\n\n\nfunction getTabIndexValue(element) {\n if (!hasValidTabIndex(element)) {\n return null;\n } // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054\n\n\n const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);\n return isNaN(tabIndex) ? -1 : tabIndex;\n}\n/** Checks whether the specified element is potentially tabbable on iOS */\n\n\nfunction isPotentiallyTabbableIOS(element) {\n let nodeName = element.nodeName.toLowerCase();\n let inputType = nodeName === 'input' && element.type;\n return inputType === 'text' || inputType === 'password' || nodeName === 'select' || nodeName === 'textarea';\n}\n/**\n * Gets whether an element is potentially focusable without taking current visible/disabled state\n * into account.\n */\n\n\nfunction isPotentiallyFocusable(element) {\n // Inputs are potentially focusable *unless* they're type=\"hidden\".\n if (isHiddenInput(element)) {\n return false;\n }\n\n return isNativeFormElement(element) || isAnchorWithHref(element) || element.hasAttribute('contenteditable') || hasValidTabIndex(element);\n}\n/** Gets the parent window of a DOM node with regards of being inside of an iframe. */\n\n\nfunction getWindow(node) {\n // ownerDocument is null if `node` itself *is* a document.\n return node.ownerDocument && node.ownerDocument.defaultView || window;\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Class that allows for trapping focus within a DOM element.\n *\n * This class currently uses a relatively simple approach to focus trapping.\n * It assumes that the tab order is the same as DOM order, which is not necessarily true.\n * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause the two to be misaligned.\n *\n * @deprecated Use `ConfigurableFocusTrap` instead.\n * @breaking-change 11.0.0\n */\n\n\nclass FocusTrap {\n constructor(_element, _checker, _ngZone, _document, deferAnchors = false) {\n this._element = _element;\n this._checker = _checker;\n this._ngZone = _ngZone;\n this._document = _document;\n this._hasAttached = false; // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.\n\n this.startAnchorListener = () => this.focusLastTabbableElement();\n\n this.endAnchorListener = () => this.focusFirstTabbableElement();\n\n this._enabled = true;\n\n if (!deferAnchors) {\n this.attachAnchors();\n }\n }\n /** Whether the focus trap is active. */\n\n\n get enabled() {\n return this._enabled;\n }\n\n set enabled(value) {\n this._enabled = value;\n\n if (this._startAnchor && this._endAnchor) {\n this._toggleAnchorTabIndex(value, this._startAnchor);\n\n this._toggleAnchorTabIndex(value, this._endAnchor);\n }\n }\n /** Destroys the focus trap by cleaning up the anchors. */\n\n\n destroy() {\n const startAnchor = this._startAnchor;\n const endAnchor = this._endAnchor;\n\n if (startAnchor) {\n startAnchor.removeEventListener('focus', this.startAnchorListener);\n startAnchor.remove();\n }\n\n if (endAnchor) {\n endAnchor.removeEventListener('focus', this.endAnchorListener);\n endAnchor.remove();\n }\n\n this._startAnchor = this._endAnchor = null;\n this._hasAttached = false;\n }\n /**\n * Inserts the anchors into the DOM. This is usually done automatically\n * in the constructor, but can be deferred for cases like directives with `*ngIf`.\n * @returns Whether the focus trap managed to attach successfully. This may not be the case\n * if the target element isn't currently in the DOM.\n */\n\n\n attachAnchors() {\n // If we're not on the browser, there can be no focus to trap.\n if (this._hasAttached) {\n return true;\n }\n\n this._ngZone.runOutsideAngular(() => {\n if (!this._startAnchor) {\n this._startAnchor = this._createAnchor();\n\n this._startAnchor.addEventListener('focus', this.startAnchorListener);\n }\n\n if (!this._endAnchor) {\n this._endAnchor = this._createAnchor();\n\n this._endAnchor.addEventListener('focus', this.endAnchorListener);\n }\n });\n\n if (this._element.parentNode) {\n this._element.parentNode.insertBefore(this._startAnchor, this._element);\n\n this._element.parentNode.insertBefore(this._endAnchor, this._element.nextSibling);\n\n this._hasAttached = true;\n }\n\n return this._hasAttached;\n }\n /**\n * Waits for the zone to stabilize, then focuses the first tabbable element.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n\n\n focusInitialElementWhenReady(options) {\n return new Promise(resolve => {\n this._executeOnStable(() => resolve(this.focusInitialElement(options)));\n });\n }\n /**\n * Waits for the zone to stabilize, then focuses\n * the first tabbable element within the focus trap region.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n\n\n focusFirstTabbableElementWhenReady(options) {\n return new Promise(resolve => {\n this._executeOnStable(() => resolve(this.focusFirstTabbableElement(options)));\n });\n }\n /**\n * Waits for the zone to stabilize, then focuses\n * the last tabbable element within the focus trap region.\n * @returns Returns a promise that resolves with a boolean, depending\n * on whether focus was moved successfully.\n */\n\n\n focusLastTabbableElementWhenReady(options) {\n return new Promise(resolve => {\n this._executeOnStable(() => resolve(this.focusLastTabbableElement(options)));\n });\n }\n /**\n * Get the specified boundary element of the trapped region.\n * @param bound The boundary to get (start or end of trapped region).\n * @returns The boundary element.\n */\n\n\n _getRegionBoundary(bound) {\n // Contains the deprecated version of selector, for temporary backwards comparability.\n const markers = this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` + `[cdkFocusRegion${bound}], ` + `[cdk-focus-${bound}]`);\n\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n for (let i = 0; i < markers.length; i++) {\n // @breaking-change 8.0.0\n if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {\n 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]);\n } else if (markers[i].hasAttribute(`cdk-focus-region-${bound}`)) {\n 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]);\n }\n }\n }\n\n if (bound == 'start') {\n return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);\n }\n\n return markers.length ? markers[markers.length - 1] : this._getLastTabbableElement(this._element);\n }\n /**\n * Focuses the element that should be focused when the focus trap is initialized.\n * @returns Whether focus was moved successfully.\n */\n\n\n focusInitialElement(options) {\n // Contains the deprecated version of selector, for temporary backwards comparability.\n const redirectToElement = this._element.querySelector(`[cdk-focus-initial], ` + `[cdkFocusInitial]`);\n\n if (redirectToElement) {\n // @breaking-change 8.0.0\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && redirectToElement.hasAttribute(`cdk-focus-initial`)) {\n console.warn(`Found use of deprecated attribute 'cdk-focus-initial', ` + `use 'cdkFocusInitial' instead. The deprecated attribute ` + `will be removed in 8.0.0`, redirectToElement);\n } // Warn the consumer if the element they've pointed to\n // isn't focusable, when not in production mode.\n\n\n if ((typeof ngDevMode === 'undefined' || ngDevMode) && !this._checker.isFocusable(redirectToElement)) {\n console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);\n }\n\n if (!this._checker.isFocusable(redirectToElement)) {\n const focusableChild = this._getFirstTabbableElement(redirectToElement);\n\n focusableChild?.focus(options);\n return !!focusableChild;\n }\n\n redirectToElement.focus(options);\n return true;\n }\n\n return this.focusFirstTabbableElement(options);\n }\n /**\n * Focuses the first tabbable element within the focus trap region.\n * @returns Whether focus was moved successfully.\n */\n\n\n focusFirstTabbableElement(options) {\n const redirectToElement = this._getRegionBoundary('start');\n\n if (redirectToElement) {\n redirectToElement.focus(options);\n }\n\n return !!redirectToElement;\n }\n /**\n * Focuses the last tabbable element within the focus trap region.\n * @returns Whether focus was moved successfully.\n */\n\n\n focusLastTabbableElement(options) {\n const redirectToElement = this._getRegionBoundary('end');\n\n if (redirectToElement) {\n redirectToElement.focus(options);\n }\n\n return !!redirectToElement;\n }\n /**\n * Checks whether the focus trap has successfully been attached.\n */\n\n\n hasAttached() {\n return this._hasAttached;\n }\n /** Get the first tabbable element from a DOM subtree (inclusive). */\n\n\n _getFirstTabbableElement(root) {\n if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {\n return root;\n }\n\n const children = root.children;\n\n for (let i = 0; i < children.length; i++) {\n const tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getFirstTabbableElement(children[i]) : null;\n\n if (tabbableChild) {\n return tabbableChild;\n }\n }\n\n return null;\n }\n /** Get the last tabbable element from a DOM subtree (inclusive). */\n\n\n _getLastTabbableElement(root) {\n if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {\n return root;\n } // Iterate in reverse DOM order.\n\n\n const children = root.children;\n\n for (let i = children.length - 1; i >= 0; i--) {\n const tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? this._getLastTabbableElement(children[i]) : null;\n\n if (tabbableChild) {\n return tabbableChild;\n }\n }\n\n return null;\n }\n /** Creates an anchor element. */\n\n\n _createAnchor() {\n const anchor = this._document.createElement('div');\n\n this._toggleAnchorTabIndex(this._enabled, anchor);\n\n anchor.classList.add('cdk-visually-hidden');\n anchor.classList.add('cdk-focus-trap-anchor');\n anchor.setAttribute('aria-hidden', 'true');\n return anchor;\n }\n /**\n * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.\n * @param isEnabled Whether the focus trap is enabled.\n * @param anchor Anchor on which to toggle the tabindex.\n */\n\n\n _toggleAnchorTabIndex(isEnabled, anchor) {\n // Remove the tabindex completely, rather than setting it to -1, because if the\n // element has a tabindex, the user might still hit it when navigating with the arrow keys.\n isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');\n }\n /**\n * Toggles the`tabindex` of both anchors to either trap Tab focus or allow it to escape.\n * @param enabled: Whether the anchors should trap Tab.\n */\n\n\n toggleAnchors(enabled) {\n if (this._startAnchor && this._endAnchor) {\n this._toggleAnchorTabIndex(enabled, this._startAnchor);\n\n this._toggleAnchorTabIndex(enabled, this._endAnchor);\n }\n }\n /** Executes a function when the zone is stable. */\n\n\n _executeOnStable(fn) {\n if (this._ngZone.isStable) {\n fn();\n } else {\n this._ngZone.onStable.pipe(take(1)).subscribe(fn);\n }\n }\n\n}\n/**\n * Factory that allows easy instantiation of focus traps.\n * @deprecated Use `ConfigurableFocusTrapFactory` instead.\n * @breaking-change 11.0.0\n */\n\n\nlet FocusTrapFactory = /*#__PURE__*/(() => {\n class FocusTrapFactory {\n constructor(_checker, _ngZone, _document) {\n this._checker = _checker;\n this._ngZone = _ngZone;\n this._document = _document;\n }\n /**\n * Creates a focus-trapped region around the given element.\n * @param element The element around which focus will be trapped.\n * @param deferCaptureElements Defers the creation of focus-capturing elements to be done\n * manually by the user.\n * @returns The created focus trap instance.\n */\n\n\n create(element, deferCaptureElements = false) {\n return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements);\n }\n\n }\n\n FocusTrapFactory.ɵfac = function FocusTrapFactory_Factory(t) {\n return new (t || FocusTrapFactory)(i0.ɵɵinject(InteractivityChecker), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(DOCUMENT));\n };\n\n FocusTrapFactory.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: FocusTrapFactory,\n factory: FocusTrapFactory.ɵfac,\n providedIn: 'root'\n });\n return FocusTrapFactory;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Directive for trapping focus within a region. */\n\n\nlet CdkTrapFocus = /*#__PURE__*/(() => {\n class CdkTrapFocus {\n constructor(_elementRef, _focusTrapFactory,\n /**\n * @deprecated No longer being used. To be removed.\n * @breaking-change 13.0.0\n */\n _document) {\n this._elementRef = _elementRef;\n this._focusTrapFactory = _focusTrapFactory;\n /** Previously focused element to restore focus to upon destroy when using autoCapture. */\n\n this._previouslyFocusedElement = null;\n this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);\n }\n /** Whether the focus trap is active. */\n\n\n get enabled() {\n return this.focusTrap.enabled;\n }\n\n set enabled(value) {\n this.focusTrap.enabled = coerceBooleanProperty(value);\n }\n /**\n * Whether the directive should automatically move focus into the trapped region upon\n * initialization and return focus to the previous activeElement upon destruction.\n */\n\n\n get autoCapture() {\n return this._autoCapture;\n }\n\n set autoCapture(value) {\n this._autoCapture = coerceBooleanProperty(value);\n }\n\n ngOnDestroy() {\n this.focusTrap.destroy(); // If we stored a previously focused element when using autoCapture, return focus to that\n // element now that the trapped region is being destroyed.\n\n if (this._previouslyFocusedElement) {\n this._previouslyFocusedElement.focus();\n\n this._previouslyFocusedElement = null;\n }\n }\n\n ngAfterContentInit() {\n this.focusTrap.attachAnchors();\n\n if (this.autoCapture) {\n this._captureFocus();\n }\n }\n\n ngDoCheck() {\n if (!this.focusTrap.hasAttached()) {\n this.focusTrap.attachAnchors();\n }\n }\n\n ngOnChanges(changes) {\n const autoCaptureChange = changes['autoCapture'];\n\n if (autoCaptureChange && !autoCaptureChange.firstChange && this.autoCapture && this.focusTrap.hasAttached()) {\n this._captureFocus();\n }\n }\n\n _captureFocus() {\n this._previouslyFocusedElement = _getFocusedElementPierceShadowDom();\n this.focusTrap.focusInitialElementWhenReady();\n }\n\n }\n\n CdkTrapFocus.ɵfac = function CdkTrapFocus_Factory(t) {\n return new (t || CdkTrapFocus)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(FocusTrapFactory), i0.ɵɵdirectiveInject(DOCUMENT));\n };\n\n CdkTrapFocus.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkTrapFocus,\n selectors: [[\"\", \"cdkTrapFocus\", \"\"]],\n inputs: {\n enabled: [\"cdkTrapFocus\", \"enabled\"],\n autoCapture: [\"cdkTrapFocusAutoCapture\", \"autoCapture\"]\n },\n exportAs: [\"cdkTrapFocus\"],\n features: [i0.ɵɵNgOnChangesFeature]\n });\n return CdkTrapFocus;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Class that allows for trapping focus within a DOM element.\n *\n * This class uses a strategy pattern that determines how it traps focus.\n * See FocusTrapInertStrategy.\n */\n\n\nclass ConfigurableFocusTrap extends FocusTrap {\n constructor(_element, _checker, _ngZone, _document, _focusTrapManager, _inertStrategy, config) {\n super(_element, _checker, _ngZone, _document, config.defer);\n this._focusTrapManager = _focusTrapManager;\n this._inertStrategy = _inertStrategy;\n\n this._focusTrapManager.register(this);\n }\n /** Whether the FocusTrap is enabled. */\n\n\n get enabled() {\n return this._enabled;\n }\n\n set enabled(value) {\n this._enabled = value;\n\n if (this._enabled) {\n this._focusTrapManager.register(this);\n } else {\n this._focusTrapManager.deregister(this);\n }\n }\n /** Notifies the FocusTrapManager that this FocusTrap will be destroyed. */\n\n\n destroy() {\n this._focusTrapManager.deregister(this);\n\n super.destroy();\n }\n /** @docs-private Implemented as part of ManagedFocusTrap. */\n\n\n _enable() {\n this._inertStrategy.preventFocus(this);\n\n this.toggleAnchors(true);\n }\n /** @docs-private Implemented as part of ManagedFocusTrap. */\n\n\n _disable() {\n this._inertStrategy.allowFocus(this);\n\n this.toggleAnchors(false);\n }\n\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** The injection token used to specify the inert strategy. */\n\n\nconst FOCUS_TRAP_INERT_STRATEGY = /*#__PURE__*/new InjectionToken('FOCUS_TRAP_INERT_STRATEGY');\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Lightweight FocusTrapInertStrategy that adds a document focus event\n * listener to redirect focus back inside the FocusTrap.\n */\n\nclass EventListenerFocusTrapInertStrategy {\n constructor() {\n /** Focus event handler. */\n this._listener = null;\n }\n /** Adds a document event listener that keeps focus inside the FocusTrap. */\n\n\n preventFocus(focusTrap) {\n // Ensure there's only one listener per document\n if (this._listener) {\n focusTrap._document.removeEventListener('focus', this._listener, true);\n }\n\n this._listener = e => this._trapFocus(focusTrap, e);\n\n focusTrap._ngZone.runOutsideAngular(() => {\n focusTrap._document.addEventListener('focus', this._listener, true);\n });\n }\n /** Removes the event listener added in preventFocus. */\n\n\n allowFocus(focusTrap) {\n if (!this._listener) {\n return;\n }\n\n focusTrap._document.removeEventListener('focus', this._listener, true);\n\n this._listener = null;\n }\n /**\n * Refocuses the first element in the FocusTrap if the focus event target was outside\n * the FocusTrap.\n *\n * This is an event listener callback. The event listener is added in runOutsideAngular,\n * so all this code runs outside Angular as well.\n */\n\n\n _trapFocus(focusTrap, event) {\n const target = event.target;\n const focusTrapRoot = focusTrap._element; // Don't refocus if target was in an overlay, because the overlay might be associated\n // with an element inside the FocusTrap, ex. mat-select.\n\n if (target && !focusTrapRoot.contains(target) && !target.closest?.('div.cdk-overlay-pane')) {\n // Some legacy FocusTrap usages have logic that focuses some element on the page\n // just before FocusTrap is destroyed. For backwards compatibility, wait\n // to be sure FocusTrap is still enabled before refocusing.\n setTimeout(() => {\n // Check whether focus wasn't put back into the focus trap while the timeout was pending.\n if (focusTrap.enabled && !focusTrapRoot.contains(focusTrap._document.activeElement)) {\n focusTrap.focusFirstTabbableElement();\n }\n });\n }\n }\n\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Injectable that ensures only the most recently enabled FocusTrap is active. */\n\n\nlet FocusTrapManager = /*#__PURE__*/(() => {\n class FocusTrapManager {\n constructor() {\n // A stack of the FocusTraps on the page. Only the FocusTrap at the\n // top of the stack is active.\n this._focusTrapStack = [];\n }\n /**\n * Disables the FocusTrap at the top of the stack, and then pushes\n * the new FocusTrap onto the stack.\n */\n\n\n register(focusTrap) {\n // Dedupe focusTraps that register multiple times.\n this._focusTrapStack = this._focusTrapStack.filter(ft => ft !== focusTrap);\n let stack = this._focusTrapStack;\n\n if (stack.length) {\n stack[stack.length - 1]._disable();\n }\n\n stack.push(focusTrap);\n\n focusTrap._enable();\n }\n /**\n * Removes the FocusTrap from the stack, and activates the\n * FocusTrap that is the new top of the stack.\n */\n\n\n deregister(focusTrap) {\n focusTrap._disable();\n\n const stack = this._focusTrapStack;\n const i = stack.indexOf(focusTrap);\n\n if (i !== -1) {\n stack.splice(i, 1);\n\n if (stack.length) {\n stack[stack.length - 1]._enable();\n }\n }\n }\n\n }\n\n FocusTrapManager.ɵfac = function FocusTrapManager_Factory(t) {\n return new (t || FocusTrapManager)();\n };\n\n FocusTrapManager.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: FocusTrapManager,\n factory: FocusTrapManager.ɵfac,\n providedIn: 'root'\n });\n return FocusTrapManager;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Factory that allows easy instantiation of configurable focus traps. */\n\n\nlet ConfigurableFocusTrapFactory = /*#__PURE__*/(() => {\n class ConfigurableFocusTrapFactory {\n constructor(_checker, _ngZone, _focusTrapManager, _document, _inertStrategy) {\n this._checker = _checker;\n this._ngZone = _ngZone;\n this._focusTrapManager = _focusTrapManager;\n this._document = _document; // TODO split up the strategies into different modules, similar to DateAdapter.\n\n this._inertStrategy = _inertStrategy || new EventListenerFocusTrapInertStrategy();\n }\n\n create(element, config = {\n defer: false\n }) {\n let configObject;\n\n if (typeof config === 'boolean') {\n configObject = {\n defer: config\n };\n } else {\n configObject = config;\n }\n\n return new ConfigurableFocusTrap(element, this._checker, this._ngZone, this._document, this._focusTrapManager, this._inertStrategy, configObject);\n }\n\n }\n\n ConfigurableFocusTrapFactory.ɵfac = function ConfigurableFocusTrapFactory_Factory(t) {\n return new (t || ConfigurableFocusTrapFactory)(i0.ɵɵinject(InteractivityChecker), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(FocusTrapManager), i0.ɵɵinject(DOCUMENT), i0.ɵɵinject(FOCUS_TRAP_INERT_STRATEGY, 8));\n };\n\n ConfigurableFocusTrapFactory.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: ConfigurableFocusTrapFactory,\n factory: ConfigurableFocusTrapFactory.ɵfac,\n providedIn: 'root'\n });\n return ConfigurableFocusTrapFactory;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Gets whether an event could be a faked `mousedown` event dispatched by a screen reader. */\n\n\nfunction isFakeMousedownFromScreenReader(event) {\n // Some screen readers will dispatch a fake `mousedown` event when pressing enter or space on\n // a clickable element. We can distinguish these events when both `offsetX` and `offsetY` are\n // zero. Note that there's an edge case where the user could click the 0x0 spot of the screen\n // themselves, but that is unlikely to contain interaction elements. Historically we used to\n // check `event.buttons === 0`, however that no longer works on recent versions of NVDA.\n return event.offsetX === 0 && event.offsetY === 0;\n}\n/** Gets whether an event could be a faked `touchstart` event dispatched by a screen reader. */\n\n\nfunction isFakeTouchstartFromScreenReader(event) {\n const 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`\n // which is typically >= 0 on a real device versus -1 from a screen reader. Just to be safe,\n // we can also look at `radiusX` and `radiusY`. This behavior was observed against a Windows 10\n // device with a touch screen running NVDA v2020.4 and Firefox 85 or Chrome 88.\n\n return !!touch && touch.identifier === -1 && (touch.radiusX == null || touch.radiusX === 1) && (touch.radiusY == null || touch.radiusY === 1);\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Injectable options for the InputModalityDetector. These are shallowly merged with the default\n * options.\n */\n\n\nconst INPUT_MODALITY_DETECTOR_OPTIONS = /*#__PURE__*/new InjectionToken('cdk-input-modality-detector-options');\n/**\n * Default options for the InputModalityDetector.\n *\n * Modifier keys are ignored by default (i.e. when pressed won't cause the service to detect\n * keyboard input modality) for two reasons:\n *\n * 1. Modifier keys are commonly used with mouse to perform actions such as 'right click' or 'open\n * in new tab', and are thus less representative of actual keyboard interaction.\n * 2. VoiceOver triggers some keyboard events when linearly navigating with Control + Option (but\n * confusingly not with Caps Lock). Thus, to have parity with other screen readers, we ignore\n * these keys so as to not update the input modality.\n *\n * Note that we do not by default ignore the right Meta key on Safari because it has the same key\n * code as the ContextMenu key on other browsers. When we switch to using event.key, we can\n * distinguish between the two.\n */\n\nconst INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS = {\n ignoreKeys: [ALT, CONTROL, MAC_META, META, SHIFT]\n};\n/**\n * The amount of time needed to pass after a touchstart event in order for a subsequent mousedown\n * event to be attributed as mouse and not touch.\n *\n * This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found\n * that a value of around 650ms seems appropriate.\n */\n\nconst TOUCH_BUFFER_MS = 650;\n/**\n * Event listener options that enable capturing and also mark the listener as passive if the browser\n * supports it.\n */\n\nconst modalityEventListenerOptions = /*#__PURE__*/normalizePassiveListenerOptions({\n passive: true,\n capture: true\n});\n/**\n * Service that detects the user's input modality.\n *\n * This service does not update the input modality when a user navigates with a screen reader\n * (e.g. linear navigation with VoiceOver, object navigation / browse mode with NVDA, virtual PC\n * cursor mode with JAWS). This is in part due to technical limitations (i.e. keyboard events do not\n * fire as expected in these modes) but is also arguably the correct behavior. Navigating with a\n * screen reader is akin to visually scanning a page, and should not be interpreted as actual user\n * input interaction.\n *\n * When a user is not navigating but *interacting* with a screen reader, this service attempts to\n * update the input modality to keyboard, but in general this service's behavior is largely\n * undefined.\n */\n\nlet InputModalityDetector = /*#__PURE__*/(() => {\n class InputModalityDetector {\n constructor(_platform, ngZone, document, options) {\n this._platform = _platform;\n /**\n * The most recently detected input modality event target. Is null if no input modality has been\n * detected or if the associated event target is null for some unknown reason.\n */\n\n this._mostRecentTarget = null;\n /** The underlying BehaviorSubject that emits whenever an input modality is detected. */\n\n this._modality = new BehaviorSubject(null);\n /**\n * The timestamp of the last touch input modality. Used to determine whether mousedown events\n * should be attributed to mouse or touch.\n */\n\n this._lastTouchMs = 0;\n /**\n * Handles keydown events. Must be an arrow function in order to preserve the context when it gets\n * bound.\n */\n\n this._onKeydown = event => {\n // If this is one of the keys we should ignore, then ignore it and don't update the input\n // modality to keyboard.\n if (this._options?.ignoreKeys?.some(keyCode => keyCode === event.keyCode)) {\n return;\n }\n\n this._modality.next('keyboard');\n\n this._mostRecentTarget = _getEventTarget(event);\n };\n /**\n * Handles mousedown events. Must be an arrow function in order to preserve the context when it\n * gets bound.\n */\n\n\n this._onMousedown = event => {\n // Touches trigger both touch and mouse events, so we need to distinguish between mouse events\n // that were triggered via mouse vs touch. To do so, check if the mouse event occurs closely\n // after the previous touch event.\n if (Date.now() - this._lastTouchMs < TOUCH_BUFFER_MS) {\n return;\n } // Fake mousedown events are fired by some screen readers when controls are activated by the\n // screen reader. Attribute them to keyboard input modality.\n\n\n this._modality.next(isFakeMousedownFromScreenReader(event) ? 'keyboard' : 'mouse');\n\n this._mostRecentTarget = _getEventTarget(event);\n };\n /**\n * Handles touchstart events. Must be an arrow function in order to preserve the context when it\n * gets bound.\n */\n\n\n this._onTouchstart = event => {\n // Same scenario as mentioned in _onMousedown, but on touch screen devices, fake touchstart\n // events are fired. Again, attribute to keyboard input modality.\n if (isFakeTouchstartFromScreenReader(event)) {\n this._modality.next('keyboard');\n\n return;\n } // Store the timestamp of this touch event, as it's used to distinguish between mouse events\n // triggered via mouse vs touch.\n\n\n this._lastTouchMs = Date.now();\n\n this._modality.next('touch');\n\n this._mostRecentTarget = _getEventTarget(event);\n };\n\n this._options = { ...INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS,\n ...options\n }; // Skip the first emission as it's null.\n\n this.modalityDetected = this._modality.pipe(skip(1));\n this.modalityChanged = this.modalityDetected.pipe(distinctUntilChanged()); // If we're not in a browser, this service should do nothing, as there's no relevant input\n // modality to detect.\n\n if (_platform.isBrowser) {\n ngZone.runOutsideAngular(() => {\n document.addEventListener('keydown', this._onKeydown, modalityEventListenerOptions);\n document.addEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);\n document.addEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);\n });\n }\n }\n /** The most recently detected input modality. */\n\n\n get mostRecentModality() {\n return this._modality.value;\n }\n\n ngOnDestroy() {\n this._modality.complete();\n\n if (this._platform.isBrowser) {\n document.removeEventListener('keydown', this._onKeydown, modalityEventListenerOptions);\n document.removeEventListener('mousedown', this._onMousedown, modalityEventListenerOptions);\n document.removeEventListener('touchstart', this._onTouchstart, modalityEventListenerOptions);\n }\n }\n\n }\n\n InputModalityDetector.ɵfac = function InputModalityDetector_Factory(t) {\n return new (t || InputModalityDetector)(i0.ɵɵinject(i1.Platform), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(DOCUMENT), i0.ɵɵinject(INPUT_MODALITY_DETECTOR_OPTIONS, 8));\n };\n\n InputModalityDetector.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: InputModalityDetector,\n factory: InputModalityDetector.ɵfac,\n providedIn: 'root'\n });\n return InputModalityDetector;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nconst LIVE_ANNOUNCER_ELEMENT_TOKEN = /*#__PURE__*/new InjectionToken('liveAnnouncerElement', {\n providedIn: 'root',\n factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY\n});\n/** @docs-private */\n\nfunction LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {\n return null;\n}\n/** Injection token that can be used to configure the default options for the LiveAnnouncer. */\n\n\nconst LIVE_ANNOUNCER_DEFAULT_OPTIONS = /*#__PURE__*/new InjectionToken('LIVE_ANNOUNCER_DEFAULT_OPTIONS');\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nlet LiveAnnouncer = /*#__PURE__*/(() => {\n class LiveAnnouncer {\n constructor(elementToken, _ngZone, _document, _defaultOptions) {\n this._ngZone = _ngZone;\n this._defaultOptions = _defaultOptions; // We inject the live element and document as `any` because the constructor signature cannot\n // reference browser globals (HTMLElement, Document) on non-browser environments, since having\n // a class decorator causes TypeScript to preserve the constructor signature types.\n\n this._document = _document;\n this._liveElement = elementToken || this._createLiveElement();\n }\n\n announce(message, ...args) {\n const defaultOptions = this._defaultOptions;\n let politeness;\n let duration;\n\n if (args.length === 1 && typeof args[0] === 'number') {\n duration = args[0];\n } else {\n [politeness, duration] = args;\n }\n\n this.clear();\n clearTimeout(this._previousTimeout);\n\n if (!politeness) {\n politeness = defaultOptions && defaultOptions.politeness ? defaultOptions.politeness : 'polite';\n }\n\n if (duration == null && defaultOptions) {\n duration = defaultOptions.duration;\n } // TODO: ensure changing the politeness works on all environments we support.\n\n\n this._liveElement.setAttribute('aria-live', politeness); // This 100ms timeout is necessary for some browser + screen-reader combinations:\n // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.\n // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a\n // second time without clearing and then using a non-zero delay.\n // (using JAWS 17 at time of this writing).\n\n\n return this._ngZone.runOutsideAngular(() => {\n return new Promise(resolve => {\n clearTimeout(this._previousTimeout);\n this._previousTimeout = setTimeout(() => {\n this._liveElement.textContent = message;\n resolve();\n\n if (typeof duration === 'number') {\n this._previousTimeout = setTimeout(() => this.clear(), duration);\n }\n }, 100);\n });\n });\n }\n /**\n * Clears the current text from the announcer element. Can be used to prevent\n * screen readers from reading the text out again while the user is going\n * through the page landmarks.\n */\n\n\n clear() {\n if (this._liveElement) {\n this._liveElement.textContent = '';\n }\n }\n\n ngOnDestroy() {\n clearTimeout(this._previousTimeout);\n this._liveElement?.remove();\n this._liveElement = null;\n }\n\n _createLiveElement() {\n const elementClass = 'cdk-live-announcer-element';\n\n const previousElements = this._document.getElementsByClassName(elementClass);\n\n const liveEl = this._document.createElement('div'); // Remove any old containers. This can happen when coming in from a server-side-rendered page.\n\n\n for (let i = 0; i < previousElements.length; i++) {\n previousElements[i].remove();\n }\n\n liveEl.classList.add(elementClass);\n liveEl.classList.add('cdk-visually-hidden');\n liveEl.setAttribute('aria-atomic', 'true');\n liveEl.setAttribute('aria-live', 'polite');\n\n this._document.body.appendChild(liveEl);\n\n return liveEl;\n }\n\n }\n\n LiveAnnouncer.ɵfac = function LiveAnnouncer_Factory(t) {\n return new (t || LiveAnnouncer)(i0.ɵɵinject(LIVE_ANNOUNCER_ELEMENT_TOKEN, 8), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(DOCUMENT), i0.ɵɵinject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, 8));\n };\n\n LiveAnnouncer.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: LiveAnnouncer,\n factory: LiveAnnouncer.ɵfac,\n providedIn: 'root'\n });\n return LiveAnnouncer;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * A directive that works similarly to aria-live, but uses the LiveAnnouncer to ensure compatibility\n * with a wider range of browsers and screen readers.\n */\n\n\nlet CdkAriaLive = /*#__PURE__*/(() => {\n class CdkAriaLive {\n constructor(_elementRef, _liveAnnouncer, _contentObserver, _ngZone) {\n this._elementRef = _elementRef;\n this._liveAnnouncer = _liveAnnouncer;\n this._contentObserver = _contentObserver;\n this._ngZone = _ngZone;\n this._politeness = 'polite';\n }\n /** The aria-live politeness level to use when announcing messages. */\n\n\n get politeness() {\n return this._politeness;\n }\n\n set politeness(value) {\n this._politeness = value === 'off' || value === 'assertive' ? value : 'polite';\n\n if (this._politeness === 'off') {\n if (this._subscription) {\n this._subscription.unsubscribe();\n\n this._subscription = null;\n }\n } else if (!this._subscription) {\n this._subscription = this._ngZone.runOutsideAngular(() => {\n return this._contentObserver.observe(this._elementRef).subscribe(() => {\n // Note that we use textContent here, rather than innerText, in order to avoid a reflow.\n const elementText = this._elementRef.nativeElement.textContent; // The `MutationObserver` fires also for attribute\n // changes which we don't want to announce.\n\n if (elementText !== this._previousAnnouncedText) {\n this._liveAnnouncer.announce(elementText, this._politeness);\n\n this._previousAnnouncedText = elementText;\n }\n });\n });\n }\n }\n\n ngOnDestroy() {\n if (this._subscription) {\n this._subscription.unsubscribe();\n }\n }\n\n }\n\n CdkAriaLive.ɵfac = function CdkAriaLive_Factory(t) {\n return new (t || CdkAriaLive)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(LiveAnnouncer), i0.ɵɵdirectiveInject(i1$1.ContentObserver), i0.ɵɵdirectiveInject(i0.NgZone));\n };\n\n CdkAriaLive.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkAriaLive,\n selectors: [[\"\", \"cdkAriaLive\", \"\"]],\n inputs: {\n politeness: [\"cdkAriaLive\", \"politeness\"]\n },\n exportAs: [\"cdkAriaLive\"]\n });\n return CdkAriaLive;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** InjectionToken for FocusMonitorOptions. */\n\n\nconst FOCUS_MONITOR_DEFAULT_OPTIONS = /*#__PURE__*/new InjectionToken('cdk-focus-monitor-default-options');\n/**\n * Event listener options that enable capturing and also\n * mark the listener as passive if the browser supports it.\n */\n\nconst captureEventListenerOptions = /*#__PURE__*/normalizePassiveListenerOptions({\n passive: true,\n capture: true\n});\n/** Monitors mouse and keyboard events to determine the cause of focus events. */\n\nlet FocusMonitor = /*#__PURE__*/(() => {\n class FocusMonitor {\n constructor(_ngZone, _platform, _inputModalityDetector,\n /** @breaking-change 11.0.0 make document required */\n document, options) {\n this._ngZone = _ngZone;\n this._platform = _platform;\n this._inputModalityDetector = _inputModalityDetector;\n /** The focus origin that the next focus event is a result of. */\n\n this._origin = null;\n /** Whether the window has just been focused. */\n\n this._windowFocused = false;\n /**\n * Whether the origin was determined via a touch interaction. Necessary as properly attributing\n * focus events to touch interactions requires special logic.\n */\n\n this._originFromTouchInteraction = false;\n /** Map of elements being monitored to their info. */\n\n this._elementInfo = new Map();\n /** The number of elements currently being monitored. */\n\n this._monitoredElementCount = 0;\n /**\n * Keeps track of the root nodes to which we've currently bound a focus/blur handler,\n * as well as the number of monitored elements that they contain. We have to treat focus/blur\n * handlers differently from the rest of the events, because the browser won't emit events\n * to the document when focus moves inside of a shadow root.\n */\n\n this._rootNodeFocusListenerCount = new Map();\n /**\n * Event listener for `focus` events on the window.\n * Needs to be an arrow function in order to preserve the context when it gets bound.\n */\n\n this._windowFocusListener = () => {\n // Make a note of when the window regains focus, so we can\n // restore the origin info for the focused element.\n this._windowFocused = true;\n this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);\n };\n /** Subject for stopping our InputModalityDetector subscription. */\n\n\n this._stopInputModalityDetector = new Subject();\n /**\n * Event listener for `focus` and 'blur' events on the document.\n * Needs to be an arrow function in order to preserve the context when it gets bound.\n */\n\n this._rootNodeFocusAndBlurListener = event => {\n const target = _getEventTarget(event);\n\n const handler = event.type === 'focus' ? this._onFocus : this._onBlur; // We need to walk up the ancestor chain in order to support `checkChildren`.\n\n for (let element = target; element; element = element.parentElement) {\n handler.call(this, event, element);\n }\n };\n\n this._document = document;\n this._detectionMode = options?.detectionMode || 0\n /* IMMEDIATE */\n ;\n }\n\n monitor(element, checkChildren = false) {\n const nativeElement = coerceElement(element); // Do nothing if we're not on the browser platform or the passed in node isn't an element.\n\n if (!this._platform.isBrowser || nativeElement.nodeType !== 1) {\n return of(null);\n } // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to\n // the shadow root, rather than the `document`, because the browser won't emit focus events\n // to the `document`, if focus is moving within the same shadow root.\n\n\n const rootNode = _getShadowRoot(nativeElement) || this._getDocument();\n\n const cachedInfo = this._elementInfo.get(nativeElement); // Check if we're already monitoring this element.\n\n\n if (cachedInfo) {\n if (checkChildren) {\n // TODO(COMP-318): this can be problematic, because it'll turn all non-checkChildren\n // observers into ones that behave as if `checkChildren` was turned on. We need a more\n // robust solution.\n cachedInfo.checkChildren = true;\n }\n\n return cachedInfo.subject;\n } // Create monitored element info.\n\n\n const info = {\n checkChildren: checkChildren,\n subject: new Subject(),\n rootNode\n };\n\n this._elementInfo.set(nativeElement, info);\n\n this._registerGlobalListeners(info);\n\n return info.subject;\n }\n\n stopMonitoring(element) {\n const nativeElement = coerceElement(element);\n\n const elementInfo = this._elementInfo.get(nativeElement);\n\n if (elementInfo) {\n elementInfo.subject.complete();\n\n this._setClasses(nativeElement);\n\n this._elementInfo.delete(nativeElement);\n\n this._removeGlobalListeners(elementInfo);\n }\n }\n\n focusVia(element, origin, options) {\n const nativeElement = coerceElement(element);\n\n const focusedElement = this._getDocument().activeElement; // If the element is focused already, calling `focus` again won't trigger the event listener\n // which means that the focus classes won't be updated. If that's the case, update the classes\n // directly without waiting for an event.\n\n\n if (nativeElement === focusedElement) {\n this._getClosestElementsInfo(nativeElement).forEach(([currentElement, info]) => this._originChanged(currentElement, origin, info));\n } else {\n this._setOrigin(origin); // `focus` isn't available on the server\n\n\n if (typeof nativeElement.focus === 'function') {\n nativeElement.focus(options);\n }\n }\n }\n\n ngOnDestroy() {\n this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));\n }\n /** Access injected document if available or fallback to global document reference */\n\n\n _getDocument() {\n return this._document || document;\n }\n /** Use defaultView of injected document if available or fallback to global window reference */\n\n\n _getWindow() {\n const doc = this._getDocument();\n\n return doc.defaultView || window;\n }\n\n _getFocusOrigin(focusEventTarget) {\n if (this._origin) {\n // If the origin was realized via a touch interaction, we need to perform additional checks\n // to determine whether the focus origin should be attributed to touch or program.\n if (this._originFromTouchInteraction) {\n return this._shouldBeAttributedToTouch(focusEventTarget) ? 'touch' : 'program';\n } else {\n return this._origin;\n }\n } // If the window has just regained focus, we can restore the most recent origin from before the\n // window blurred. Otherwise, we've reached the point where we can't identify the source of the\n // focus. This typically means one of two things happened:\n //\n // 1) The element was programmatically focused, or\n // 2) The element was focused via screen reader navigation (which generally doesn't fire\n // events).\n //\n // Because we can't distinguish between these two cases, we default to setting `program`.\n\n\n return this._windowFocused && this._lastFocusOrigin ? this._lastFocusOrigin : 'program';\n }\n /**\n * Returns whether the focus event should be attributed to touch. Recall that in IMMEDIATE mode, a\n * touch origin isn't immediately reset at the next tick (see _setOrigin). This means that when we\n * handle a focus event following a touch interaction, we need to determine whether (1) the focus\n * event was directly caused by the touch interaction or (2) the focus event was caused by a\n * subsequent programmatic focus call triggered by the touch interaction.\n * @param focusEventTarget The target of the focus event under examination.\n */\n\n\n _shouldBeAttributedToTouch(focusEventTarget) {\n // Please note that this check is not perfect. Consider the following edge case:\n //\n //
\n // \n //
\n //\n // Suppose there is a FocusMonitor in IMMEDIATE mode attached to #parent. When the user touches\n // #child, #parent is programmatically focused. This code will attribute the focus to touch\n // instead of program. This is a relatively minor edge-case that can be worked around by using\n // focusVia(parent, 'program') to focus #parent.\n return this._detectionMode === 1\n /* EVENTUAL */\n || !!focusEventTarget?.contains(this._inputModalityDetector._mostRecentTarget);\n }\n /**\n * Sets the focus classes on the element based on the given focus origin.\n * @param element The element to update the classes on.\n * @param origin The focus origin.\n */\n\n\n _setClasses(element, origin) {\n element.classList.toggle('cdk-focused', !!origin);\n element.classList.toggle('cdk-touch-focused', origin === 'touch');\n element.classList.toggle('cdk-keyboard-focused', origin === 'keyboard');\n element.classList.toggle('cdk-mouse-focused', origin === 'mouse');\n element.classList.toggle('cdk-program-focused', origin === 'program');\n }\n /**\n * Updates the focus origin. If we're using immediate detection mode, we schedule an async\n * function to clear the origin at the end of a timeout. The duration of the timeout depends on\n * the origin being set.\n * @param origin The origin to set.\n * @param isFromInteraction Whether we are setting the origin from an interaction event.\n */\n\n\n _setOrigin(origin, isFromInteraction = false) {\n this._ngZone.runOutsideAngular(() => {\n this._origin = origin;\n this._originFromTouchInteraction = origin === 'touch' && isFromInteraction; // If we're in IMMEDIATE mode, reset the origin at the next tick (or in `TOUCH_BUFFER_MS` ms\n // for a touch event). We reset the origin at the next tick because Firefox focuses one tick\n // after the interaction event. We wait `TOUCH_BUFFER_MS` ms before resetting the origin for\n // a touch event because when a touch event is fired, the associated focus event isn't yet in\n // the event queue. Before doing so, clear any pending timeouts.\n\n if (this._detectionMode === 0\n /* IMMEDIATE */\n ) {\n clearTimeout(this._originTimeoutId);\n const ms = this._originFromTouchInteraction ? TOUCH_BUFFER_MS : 1;\n this._originTimeoutId = setTimeout(() => this._origin = null, ms);\n }\n });\n }\n /**\n * Handles focus events on a registered element.\n * @param event The focus event.\n * @param element The monitored element.\n */\n\n\n _onFocus(event, element) {\n // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent\n // focus event affecting the monitored element. If we want to use the origin of the first event\n // instead we should check for the cdk-focused class here and return if the element already has\n // it. (This only matters for elements that have includesChildren = true).\n // If we are not counting child-element-focus as focused, make sure that the event target is the\n // monitored element itself.\n const elementInfo = this._elementInfo.get(element);\n\n const focusEventTarget = _getEventTarget(event);\n\n if (!elementInfo || !elementInfo.checkChildren && element !== focusEventTarget) {\n return;\n }\n\n this._originChanged(element, this._getFocusOrigin(focusEventTarget), elementInfo);\n }\n /**\n * Handles blur events on a registered element.\n * @param event The blur event.\n * @param element The monitored element.\n */\n\n\n _onBlur(event, element) {\n // If we are counting child-element-focus as focused, make sure that we aren't just blurring in\n // order to focus another child of the monitored element.\n const elementInfo = this._elementInfo.get(element);\n\n if (!elementInfo || elementInfo.checkChildren && event.relatedTarget instanceof Node && element.contains(event.relatedTarget)) {\n return;\n }\n\n this._setClasses(element);\n\n this._emitOrigin(elementInfo.subject, null);\n }\n\n _emitOrigin(subject, origin) {\n this._ngZone.run(() => subject.next(origin));\n }\n\n _registerGlobalListeners(elementInfo) {\n if (!this._platform.isBrowser) {\n return;\n }\n\n const rootNode = elementInfo.rootNode;\n const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode) || 0;\n\n if (!rootNodeFocusListeners) {\n this._ngZone.runOutsideAngular(() => {\n rootNode.addEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);\n rootNode.addEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);\n });\n }\n\n this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners + 1); // Register global listeners when first element is monitored.\n\n\n if (++this._monitoredElementCount === 1) {\n // Note: we listen to events in the capture phase so we\n // can detect them even if the user stops propagation.\n this._ngZone.runOutsideAngular(() => {\n const window = this._getWindow();\n\n window.addEventListener('focus', this._windowFocusListener);\n }); // The InputModalityDetector is also just a collection of global listeners.\n\n\n this._inputModalityDetector.modalityDetected.pipe(takeUntil(this._stopInputModalityDetector)).subscribe(modality => {\n this._setOrigin(modality, true\n /* isFromInteraction */\n );\n });\n }\n }\n\n _removeGlobalListeners(elementInfo) {\n const rootNode = elementInfo.rootNode;\n\n if (this._rootNodeFocusListenerCount.has(rootNode)) {\n const rootNodeFocusListeners = this._rootNodeFocusListenerCount.get(rootNode);\n\n if (rootNodeFocusListeners > 1) {\n this._rootNodeFocusListenerCount.set(rootNode, rootNodeFocusListeners - 1);\n } else {\n rootNode.removeEventListener('focus', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);\n rootNode.removeEventListener('blur', this._rootNodeFocusAndBlurListener, captureEventListenerOptions);\n\n this._rootNodeFocusListenerCount.delete(rootNode);\n }\n } // Unregister global listeners when last element is unmonitored.\n\n\n if (! --this._monitoredElementCount) {\n const window = this._getWindow();\n\n window.removeEventListener('focus', this._windowFocusListener); // Equivalently, stop our InputModalityDetector subscription.\n\n this._stopInputModalityDetector.next(); // Clear timeouts for all potentially pending timeouts to prevent the leaks.\n\n\n clearTimeout(this._windowFocusTimeoutId);\n clearTimeout(this._originTimeoutId);\n }\n }\n /** Updates all the state on an element once its focus origin has changed. */\n\n\n _originChanged(element, origin, elementInfo) {\n this._setClasses(element, origin);\n\n this._emitOrigin(elementInfo.subject, origin);\n\n this._lastFocusOrigin = origin;\n }\n /**\n * Collects the `MonitoredElementInfo` of a particular element and\n * all of its ancestors that have enabled `checkChildren`.\n * @param element Element from which to start the search.\n */\n\n\n _getClosestElementsInfo(element) {\n const results = [];\n\n this._elementInfo.forEach((info, currentElement) => {\n if (currentElement === element || info.checkChildren && currentElement.contains(element)) {\n results.push([currentElement, info]);\n }\n });\n\n return results;\n }\n\n }\n\n FocusMonitor.ɵfac = function FocusMonitor_Factory(t) {\n return new (t || FocusMonitor)(i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i1.Platform), i0.ɵɵinject(InputModalityDetector), i0.ɵɵinject(DOCUMENT, 8), i0.ɵɵinject(FOCUS_MONITOR_DEFAULT_OPTIONS, 8));\n };\n\n FocusMonitor.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: FocusMonitor,\n factory: FocusMonitor.ɵfac,\n providedIn: 'root'\n });\n return FocusMonitor;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or\n * programmatically) and adds corresponding classes to the element.\n *\n * There are two variants of this directive:\n * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is\n * focused.\n * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.\n */\n\n\nlet CdkMonitorFocus = /*#__PURE__*/(() => {\n class CdkMonitorFocus {\n constructor(_elementRef, _focusMonitor) {\n this._elementRef = _elementRef;\n this._focusMonitor = _focusMonitor;\n this.cdkFocusChange = new EventEmitter();\n }\n\n ngAfterViewInit() {\n const element = this._elementRef.nativeElement;\n this._monitorSubscription = this._focusMonitor.monitor(element, element.nodeType === 1 && element.hasAttribute('cdkMonitorSubtreeFocus')).subscribe(origin => this.cdkFocusChange.emit(origin));\n }\n\n ngOnDestroy() {\n this._focusMonitor.stopMonitoring(this._elementRef);\n\n if (this._monitorSubscription) {\n this._monitorSubscription.unsubscribe();\n }\n }\n\n }\n\n CdkMonitorFocus.ɵfac = function CdkMonitorFocus_Factory(t) {\n return new (t || CdkMonitorFocus)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(FocusMonitor));\n };\n\n CdkMonitorFocus.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkMonitorFocus,\n selectors: [[\"\", \"cdkMonitorElementFocus\", \"\"], [\"\", \"cdkMonitorSubtreeFocus\", \"\"]],\n outputs: {\n cdkFocusChange: \"cdkFocusChange\"\n }\n });\n return CdkMonitorFocus;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** CSS class applied to the document body when in black-on-white high-contrast mode. */\n\n\nconst BLACK_ON_WHITE_CSS_CLASS = 'cdk-high-contrast-black-on-white';\n/** CSS class applied to the document body when in white-on-black high-contrast mode. */\n\nconst WHITE_ON_BLACK_CSS_CLASS = 'cdk-high-contrast-white-on-black';\n/** CSS class applied to the document body when in high-contrast mode. */\n\nconst HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';\n/**\n * Service to determine whether the browser is currently in a high-contrast-mode environment.\n *\n * Microsoft Windows supports an accessibility feature called \"High Contrast Mode\". This mode\n * changes the appearance of all applications, including web applications, to dramatically increase\n * contrast.\n *\n * IE, Edge, and Firefox currently support this mode. Chrome does not support Windows High Contrast\n * Mode. This service does not detect high-contrast mode as added by the Chrome \"High Contrast\"\n * browser extension.\n */\n\nlet HighContrastModeDetector = /*#__PURE__*/(() => {\n class HighContrastModeDetector {\n constructor(_platform, document) {\n this._platform = _platform;\n this._document = document;\n }\n /** Gets the current high-contrast-mode for the page. */\n\n\n getHighContrastMode() {\n if (!this._platform.isBrowser) {\n return 0\n /* NONE */\n ;\n } // Create a test element with an arbitrary background-color that is neither black nor\n // white; high-contrast mode will coerce the color to either black or white. Also ensure that\n // appending the test element to the DOM does not affect layout by absolutely positioning it\n\n\n const testElement = this._document.createElement('div');\n\n testElement.style.backgroundColor = 'rgb(1,2,3)';\n testElement.style.position = 'absolute';\n\n this._document.body.appendChild(testElement); // Get the computed style for the background color, collapsing spaces to normalize between\n // browsers. Once we get this color, we no longer need the test element. Access the `window`\n // via the document so we can fake it in tests. Note that we have extra null checks, because\n // this logic will likely run during app bootstrap and throwing can break the entire app.\n\n\n const documentWindow = this._document.defaultView || window;\n const computedStyle = documentWindow && documentWindow.getComputedStyle ? documentWindow.getComputedStyle(testElement) : null;\n const computedColor = (computedStyle && computedStyle.backgroundColor || '').replace(/ /g, '');\n testElement.remove();\n\n switch (computedColor) {\n case 'rgb(0,0,0)':\n return 2\n /* WHITE_ON_BLACK */\n ;\n\n case 'rgb(255,255,255)':\n return 1\n /* BLACK_ON_WHITE */\n ;\n }\n\n return 0\n /* NONE */\n ;\n }\n /** Applies CSS classes indicating high-contrast mode to document body (browser-only). */\n\n\n _applyBodyHighContrastModeCssClasses() {\n if (!this._hasCheckedHighContrastMode && this._platform.isBrowser && this._document.body) {\n const bodyClasses = this._document.body.classList; // IE11 doesn't support `classList` operations with multiple arguments\n\n bodyClasses.remove(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);\n bodyClasses.remove(BLACK_ON_WHITE_CSS_CLASS);\n bodyClasses.remove(WHITE_ON_BLACK_CSS_CLASS);\n this._hasCheckedHighContrastMode = true;\n const mode = this.getHighContrastMode();\n\n if (mode === 1\n /* BLACK_ON_WHITE */\n ) {\n bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);\n bodyClasses.add(BLACK_ON_WHITE_CSS_CLASS);\n } else if (mode === 2\n /* WHITE_ON_BLACK */\n ) {\n bodyClasses.add(HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS);\n bodyClasses.add(WHITE_ON_BLACK_CSS_CLASS);\n }\n }\n }\n\n }\n\n HighContrastModeDetector.ɵfac = function HighContrastModeDetector_Factory(t) {\n return new (t || HighContrastModeDetector)(i0.ɵɵinject(i1.Platform), i0.ɵɵinject(DOCUMENT));\n };\n\n HighContrastModeDetector.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: HighContrastModeDetector,\n factory: HighContrastModeDetector.ɵfac,\n providedIn: 'root'\n });\n return HighContrastModeDetector;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nlet A11yModule = /*#__PURE__*/(() => {\n class A11yModule {\n constructor(highContrastModeDetector) {\n highContrastModeDetector._applyBodyHighContrastModeCssClasses();\n }\n\n }\n\n A11yModule.ɵfac = function A11yModule_Factory(t) {\n return new (t || A11yModule)(i0.ɵɵinject(HighContrastModeDetector));\n };\n\n A11yModule.ɵmod = /* @__PURE__ */i0.ɵɵdefineNgModule({\n type: A11yModule\n });\n A11yModule.ɵinj = /* @__PURE__ */i0.ɵɵdefineInjector({\n imports: [[PlatformModule, ObserversModule]]\n });\n return A11yModule;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Generated bundle index. Do not edit.\n */\n\n\nexport { A11yModule, ActiveDescendantKeyManager, AriaDescriber, CDK_DESCRIBEDBY_HOST_ATTRIBUTE, CDK_DESCRIBEDBY_ID_PREFIX, CdkAriaLive, CdkMonitorFocus, CdkTrapFocus, ConfigurableFocusTrap, ConfigurableFocusTrapFactory, EventListenerFocusTrapInertStrategy, FOCUS_MONITOR_DEFAULT_OPTIONS, FOCUS_TRAP_INERT_STRATEGY, FocusKeyManager, FocusMonitor, FocusTrap, FocusTrapFactory, HighContrastModeDetector, INPUT_MODALITY_DETECTOR_DEFAULT_OPTIONS, INPUT_MODALITY_DETECTOR_OPTIONS, InputModalityDetector, InteractivityChecker, IsFocusableConfig, LIVE_ANNOUNCER_DEFAULT_OPTIONS, LIVE_ANNOUNCER_ELEMENT_TOKEN, LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY, ListKeyManager, LiveAnnouncer, MESSAGES_CONTAINER_ID, isFakeMousedownFromScreenReader, isFakeTouchstartFromScreenReader }; //# sourceMappingURL=a11y.mjs.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0965e197328eb1486d49b3bb471d6802.json b/.angular/cache/babel-webpack/0965e197328eb1486d49b3bb471d6802.json
new file mode 100644
index 0000000..ac4dcf1
--- /dev/null
+++ b/.angular/cache/babel-webpack/0965e197328eb1486d49b3bb471d6802.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { Observable } from '../Observable';\nimport { innerFrom } from './innerFrom';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { EMPTY } from './empty';\nimport { OperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { popResultSelector } from '../util/args';\nexport function zip(...args) {\n const resultSelector = popResultSelector(args);\n const sources = argsOrArgArray(args);\n return sources.length ? new Observable(subscriber => {\n let buffers = sources.map(() => []);\n let completed = sources.map(() => false);\n subscriber.add(() => {\n buffers = completed = null;\n });\n\n for (let sourceIndex = 0; !subscriber.closed && sourceIndex < sources.length; sourceIndex++) {\n innerFrom(sources[sourceIndex]).subscribe(new OperatorSubscriber(subscriber, value => {\n buffers[sourceIndex].push(value);\n\n if (buffers.every(buffer => buffer.length)) {\n const result = buffers.map(buffer => buffer.shift());\n subscriber.next(resultSelector ? resultSelector(...result) : result);\n\n if (buffers.some((buffer, i) => !buffer.length && completed[i])) {\n subscriber.complete();\n }\n }\n }, () => {\n completed[sourceIndex] = true;\n !buffers[sourceIndex].length && subscriber.complete();\n }));\n }\n\n return () => {\n buffers = completed = null;\n };\n }) : EMPTY;\n} //# sourceMappingURL=zip.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/09b3360795fac0061c9f09a816f6a3ef.json b/.angular/cache/babel-webpack/09b3360795fac0061c9f09a816f6a3ef.json
new file mode 100644
index 0000000..817d804
--- /dev/null
+++ b/.angular/cache/babel-webpack/09b3360795fac0061c9f09a816f6a3ef.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { isFunction } from \"./isFunction\";\nexport function isPromise(value) {\n return isFunction(value === null || value === void 0 ? void 0 : value.then);\n} //# sourceMappingURL=isPromise.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/09fd17992ad76aac3e03608302861e48.json b/.angular/cache/babel-webpack/09fd17992ad76aac3e03608302861e48.json
new file mode 100644
index 0000000..3dbf5ac
--- /dev/null
+++ b/.angular/cache/babel-webpack/09fd17992ad76aac3e03608302861e48.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import * as i0 from '@angular/core';\nimport { InjectionToken, Component, ChangeDetectionStrategy, ViewEncapsulation, Optional, Inject, Input, NgModule } from '@angular/core';\nimport * as i2 from '@angular/common';\nimport { DOCUMENT, CommonModule } from '@angular/common';\nimport { mixinColor, MatCommonModule } from '@angular/material/core';\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport * as i1 from '@angular/cdk/platform';\nimport { _getShadowRoot } from '@angular/cdk/platform';\nimport { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Base reference size of the spinner.\n * @docs-private\n */\n\nfunction MatProgressSpinner__svg_circle_1_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelement(0, \"circle\", 3);\n }\n\n if (rf & 2) {\n const ctx_r0 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"animation-name\", \"mat-progress-spinner-stroke-rotate-\" + ctx_r0._spinnerAnimationLabel)(\"stroke-dashoffset\", ctx_r0._getStrokeDashOffset(), \"px\")(\"stroke-dasharray\", ctx_r0._getStrokeCircumference(), \"px\")(\"stroke-width\", ctx_r0._getCircleStrokeWidth(), \"%\");\n i0.ɵɵattribute(\"r\", ctx_r0._getCircleRadius());\n }\n}\n\nfunction MatProgressSpinner__svg_circle_2_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelement(0, \"circle\", 3);\n }\n\n if (rf & 2) {\n const ctx_r1 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"stroke-dashoffset\", ctx_r1._getStrokeDashOffset(), \"px\")(\"stroke-dasharray\", ctx_r1._getStrokeCircumference(), \"px\")(\"stroke-width\", ctx_r1._getCircleStrokeWidth(), \"%\");\n i0.ɵɵattribute(\"r\", ctx_r1._getCircleRadius());\n }\n}\n\nfunction MatSpinner__svg_circle_1_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelement(0, \"circle\", 3);\n }\n\n if (rf & 2) {\n const ctx_r0 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"animation-name\", \"mat-progress-spinner-stroke-rotate-\" + ctx_r0._spinnerAnimationLabel)(\"stroke-dashoffset\", ctx_r0._getStrokeDashOffset(), \"px\")(\"stroke-dasharray\", ctx_r0._getStrokeCircumference(), \"px\")(\"stroke-width\", ctx_r0._getCircleStrokeWidth(), \"%\");\n i0.ɵɵattribute(\"r\", ctx_r0._getCircleRadius());\n }\n}\n\nfunction MatSpinner__svg_circle_2_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelement(0, \"circle\", 3);\n }\n\n if (rf & 2) {\n const ctx_r1 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"stroke-dashoffset\", ctx_r1._getStrokeDashOffset(), \"px\")(\"stroke-dasharray\", ctx_r1._getStrokeCircumference(), \"px\")(\"stroke-width\", ctx_r1._getCircleStrokeWidth(), \"%\");\n i0.ɵɵattribute(\"r\", ctx_r1._getCircleRadius());\n }\n}\n\nconst _c0 = \".mat-progress-spinner{display:block;position:relative;overflow:hidden}.mat-progress-spinner svg{position:absolute;transform:rotate(-90deg);top:0;left:0;transform-origin:center;overflow:visible}.mat-progress-spinner circle{fill:transparent;transform-origin:center;transition:stroke-dashoffset 225ms linear}._mat-animation-noopable.mat-progress-spinner circle{transition:none;animation:none}.cdk-high-contrast-active .mat-progress-spinner circle{stroke:CanvasText}.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] svg{animation:mat-progress-spinner-linear-rotate 2000ms linear infinite}._mat-animation-noopable.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] svg{transition:none;animation:none}.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] circle{transition-property:stroke;animation-duration:4000ms;animation-timing-function:cubic-bezier(0.35, 0, 0.25, 1);animation-iteration-count:infinite}._mat-animation-noopable.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] circle{transition:none;animation:none}@keyframes mat-progress-spinner-linear-rotate{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes mat-progress-spinner-stroke-rotate-100{0%{stroke-dashoffset:268.606171575px;transform:rotate(0)}12.5%{stroke-dashoffset:56.5486677px;transform:rotate(0)}12.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(72.5deg)}25%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(72.5deg)}25.0001%{stroke-dashoffset:268.606171575px;transform:rotate(270deg)}37.5%{stroke-dashoffset:56.5486677px;transform:rotate(270deg)}37.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(161.5deg)}50%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(161.5deg)}50.0001%{stroke-dashoffset:268.606171575px;transform:rotate(180deg)}62.5%{stroke-dashoffset:56.5486677px;transform:rotate(180deg)}62.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(251.5deg)}75%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(251.5deg)}75.0001%{stroke-dashoffset:268.606171575px;transform:rotate(90deg)}87.5%{stroke-dashoffset:56.5486677px;transform:rotate(90deg)}87.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(341.5deg)}100%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(341.5deg)}}\\n\";\nconst BASE_SIZE = 100;\n/**\n * Base reference stroke width of the spinner.\n * @docs-private\n */\n\nconst BASE_STROKE_WIDTH = 10; // Boilerplate for applying mixins to MatProgressSpinner.\n\n/** @docs-private */\n\nconst _MatProgressSpinnerBase = /*#__PURE__*/mixinColor(class {\n constructor(_elementRef) {\n this._elementRef = _elementRef;\n }\n\n}, 'primary');\n/** Injection token to be used to override the default options for `mat-progress-spinner`. */\n\n\nconst MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS = /*#__PURE__*/new InjectionToken('mat-progress-spinner-default-options', {\n providedIn: 'root',\n factory: MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS_FACTORY\n});\n/** @docs-private */\n\nfunction MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS_FACTORY() {\n return {\n diameter: BASE_SIZE\n };\n} // .0001 percentage difference is necessary in order to avoid unwanted animation frames\n// for example because the animation duration is 4 seconds, .1% accounts to 4ms\n// which are enough to see the flicker described in\n// https://github.com/angular/components/issues/8984\n\n\nconst INDETERMINATE_ANIMATION_TEMPLATE = `\n @keyframes mat-progress-spinner-stroke-rotate-DIAMETER {\n 0% { stroke-dashoffset: START_VALUE; transform: rotate(0); }\n 12.5% { stroke-dashoffset: END_VALUE; transform: rotate(0); }\n 12.5001% { stroke-dashoffset: END_VALUE; transform: rotateX(180deg) rotate(72.5deg); }\n 25% { stroke-dashoffset: START_VALUE; transform: rotateX(180deg) rotate(72.5deg); }\n\n 25.0001% { stroke-dashoffset: START_VALUE; transform: rotate(270deg); }\n 37.5% { stroke-dashoffset: END_VALUE; transform: rotate(270deg); }\n 37.5001% { stroke-dashoffset: END_VALUE; transform: rotateX(180deg) rotate(161.5deg); }\n 50% { stroke-dashoffset: START_VALUE; transform: rotateX(180deg) rotate(161.5deg); }\n\n 50.0001% { stroke-dashoffset: START_VALUE; transform: rotate(180deg); }\n 62.5% { stroke-dashoffset: END_VALUE; transform: rotate(180deg); }\n 62.5001% { stroke-dashoffset: END_VALUE; transform: rotateX(180deg) rotate(251.5deg); }\n 75% { stroke-dashoffset: START_VALUE; transform: rotateX(180deg) rotate(251.5deg); }\n\n 75.0001% { stroke-dashoffset: START_VALUE; transform: rotate(90deg); }\n 87.5% { stroke-dashoffset: END_VALUE; transform: rotate(90deg); }\n 87.5001% { stroke-dashoffset: END_VALUE; transform: rotateX(180deg) rotate(341.5deg); }\n 100% { stroke-dashoffset: START_VALUE; transform: rotateX(180deg) rotate(341.5deg); }\n }\n`;\n/**\n * `` component.\n */\n\nclass MatProgressSpinner extends _MatProgressSpinnerBase {\n constructor(elementRef,\n /**\n * @deprecated `_platform` parameter no longer being used.\n * @breaking-change 14.0.0\n */\n _platform, _document, animationMode, defaults) {\n super(elementRef);\n this._document = _document;\n this._diameter = BASE_SIZE;\n this._value = 0;\n /** Mode of the progress circle */\n\n this.mode = 'determinate';\n const trackedDiameters = MatProgressSpinner._diameters;\n this._spinnerAnimationLabel = this._getSpinnerAnimationLabel(); // The base size is already inserted via the component's structural styles. We still\n // need to track it so we don't end up adding the same styles again.\n\n if (!trackedDiameters.has(_document.head)) {\n trackedDiameters.set(_document.head, new Set([BASE_SIZE]));\n }\n\n this._noopAnimations = animationMode === 'NoopAnimations' && !!defaults && !defaults._forceAnimations;\n\n if (defaults) {\n if (defaults.diameter) {\n this.diameter = defaults.diameter;\n }\n\n if (defaults.strokeWidth) {\n this.strokeWidth = defaults.strokeWidth;\n }\n }\n }\n /** The diameter of the progress spinner (will set width and height of svg). */\n\n\n get diameter() {\n return this._diameter;\n }\n\n set diameter(size) {\n this._diameter = coerceNumberProperty(size);\n this._spinnerAnimationLabel = this._getSpinnerAnimationLabel(); // If this is set before `ngOnInit`, the style root may not have been resolved yet.\n\n if (this._styleRoot) {\n this._attachStyleNode();\n }\n }\n /** Stroke width of the progress spinner. */\n\n\n get strokeWidth() {\n return this._strokeWidth || this.diameter / 10;\n }\n\n set strokeWidth(value) {\n this._strokeWidth = coerceNumberProperty(value);\n }\n /** Value of the progress circle. */\n\n\n get value() {\n return this.mode === 'determinate' ? this._value : 0;\n }\n\n set value(newValue) {\n this._value = Math.max(0, Math.min(100, coerceNumberProperty(newValue)));\n }\n\n ngOnInit() {\n const element = this._elementRef.nativeElement; // Note that we need to look up the root node in ngOnInit, rather than the constructor, because\n // Angular seems to create the element outside the shadow root and then moves it inside, if the\n // node is inside an `ngIf` and a ShadowDom-encapsulated component.\n\n this._styleRoot = _getShadowRoot(element) || this._document.head;\n\n this._attachStyleNode();\n\n element.classList.add('mat-progress-spinner-indeterminate-animation');\n }\n /** The radius of the spinner, adjusted for stroke width. */\n\n\n _getCircleRadius() {\n return (this.diameter - BASE_STROKE_WIDTH) / 2;\n }\n /** The view box of the spinner's svg element. */\n\n\n _getViewBox() {\n const viewBox = this._getCircleRadius() * 2 + this.strokeWidth;\n return `0 0 ${viewBox} ${viewBox}`;\n }\n /** The stroke circumference of the svg circle. */\n\n\n _getStrokeCircumference() {\n return 2 * Math.PI * this._getCircleRadius();\n }\n /** The dash offset of the svg circle. */\n\n\n _getStrokeDashOffset() {\n if (this.mode === 'determinate') {\n return this._getStrokeCircumference() * (100 - this._value) / 100;\n }\n\n return null;\n }\n /** Stroke width of the circle in percent. */\n\n\n _getCircleStrokeWidth() {\n return this.strokeWidth / this.diameter * 100;\n }\n /** Dynamically generates a style tag containing the correct animation for this diameter. */\n\n\n _attachStyleNode() {\n const styleRoot = this._styleRoot;\n const currentDiameter = this._diameter;\n const diameters = MatProgressSpinner._diameters;\n let diametersForElement = diameters.get(styleRoot);\n\n if (!diametersForElement || !diametersForElement.has(currentDiameter)) {\n const styleTag = this._document.createElement('style');\n\n styleTag.setAttribute('mat-spinner-animation', this._spinnerAnimationLabel);\n styleTag.textContent = this._getAnimationText();\n styleRoot.appendChild(styleTag);\n\n if (!diametersForElement) {\n diametersForElement = new Set();\n diameters.set(styleRoot, diametersForElement);\n }\n\n diametersForElement.add(currentDiameter);\n }\n }\n /** Generates animation styles adjusted for the spinner's diameter. */\n\n\n _getAnimationText() {\n const strokeCircumference = this._getStrokeCircumference();\n\n return INDETERMINATE_ANIMATION_TEMPLATE // Animation should begin at 5% and end at 80%\n .replace(/START_VALUE/g, `${0.95 * strokeCircumference}`).replace(/END_VALUE/g, `${0.2 * strokeCircumference}`).replace(/DIAMETER/g, `${this._spinnerAnimationLabel}`);\n }\n /** Returns the circle diameter formatted for use with the animation-name CSS property. */\n\n\n _getSpinnerAnimationLabel() {\n // The string of a float point number will include a period ‘.’ character,\n // which is not valid for a CSS animation-name.\n return this.diameter.toString().replace('.', '_');\n }\n\n}\n/**\n * Tracks diameters of existing instances to de-dupe generated styles (default d = 100).\n * We need to keep track of which elements the diameters were attached to, because for\n * elements in the Shadow DOM the style tags are attached to the shadow root, rather\n * than the document head.\n */\n\n\nMatProgressSpinner._diameters = /*#__PURE__*/new WeakMap();\n\nMatProgressSpinner.ɵfac = function MatProgressSpinner_Factory(t) {\n return new (t || MatProgressSpinner)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.Platform), i0.ɵɵdirectiveInject(DOCUMENT, 8), i0.ɵɵdirectiveInject(ANIMATION_MODULE_TYPE, 8), i0.ɵɵdirectiveInject(MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS));\n};\n\nMatProgressSpinner.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatProgressSpinner,\n selectors: [[\"mat-progress-spinner\"]],\n hostAttrs: [\"role\", \"progressbar\", \"tabindex\", \"-1\", 1, \"mat-progress-spinner\"],\n hostVars: 10,\n hostBindings: function MatProgressSpinner_HostBindings(rf, ctx) {\n if (rf & 2) {\n i0.ɵɵattribute(\"aria-valuemin\", ctx.mode === \"determinate\" ? 0 : null)(\"aria-valuemax\", ctx.mode === \"determinate\" ? 100 : null)(\"aria-valuenow\", ctx.mode === \"determinate\" ? ctx.value : null)(\"mode\", ctx.mode);\n i0.ɵɵstyleProp(\"width\", ctx.diameter, \"px\")(\"height\", ctx.diameter, \"px\");\n i0.ɵɵclassProp(\"_mat-animation-noopable\", ctx._noopAnimations);\n }\n },\n inputs: {\n color: \"color\",\n diameter: \"diameter\",\n strokeWidth: \"strokeWidth\",\n mode: \"mode\",\n value: \"value\"\n },\n exportAs: [\"matProgressSpinner\"],\n features: [i0.ɵɵInheritDefinitionFeature],\n decls: 3,\n vars: 8,\n consts: [[\"preserveAspectRatio\", \"xMidYMid meet\", \"focusable\", \"false\", \"aria-hidden\", \"true\", 3, \"ngSwitch\"], [\"cx\", \"50%\", \"cy\", \"50%\", 3, \"animation-name\", \"stroke-dashoffset\", \"stroke-dasharray\", \"stroke-width\", 4, \"ngSwitchCase\"], [\"cx\", \"50%\", \"cy\", \"50%\", 3, \"stroke-dashoffset\", \"stroke-dasharray\", \"stroke-width\", 4, \"ngSwitchCase\"], [\"cx\", \"50%\", \"cy\", \"50%\"]],\n template: function MatProgressSpinner_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelementStart(0, \"svg\", 0);\n i0.ɵɵtemplate(1, MatProgressSpinner__svg_circle_1_Template, 1, 9, \"circle\", 1);\n i0.ɵɵtemplate(2, MatProgressSpinner__svg_circle_2_Template, 1, 7, \"circle\", 2);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n i0.ɵɵstyleProp(\"width\", ctx.diameter, \"px\")(\"height\", ctx.diameter, \"px\");\n i0.ɵɵproperty(\"ngSwitch\", ctx.mode === \"indeterminate\");\n i0.ɵɵattribute(\"viewBox\", ctx._getViewBox());\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngSwitchCase\", true);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngSwitchCase\", false);\n }\n },\n directives: [i2.NgSwitch, i2.NgSwitchCase],\n styles: [\".mat-progress-spinner{display:block;position:relative;overflow:hidden}.mat-progress-spinner svg{position:absolute;transform:rotate(-90deg);top:0;left:0;transform-origin:center;overflow:visible}.mat-progress-spinner circle{fill:transparent;transform-origin:center;transition:stroke-dashoffset 225ms linear}._mat-animation-noopable.mat-progress-spinner circle{transition:none;animation:none}.cdk-high-contrast-active .mat-progress-spinner circle{stroke:CanvasText}.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] svg{animation:mat-progress-spinner-linear-rotate 2000ms linear infinite}._mat-animation-noopable.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] svg{transition:none;animation:none}.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] circle{transition-property:stroke;animation-duration:4000ms;animation-timing-function:cubic-bezier(0.35, 0, 0.25, 1);animation-iteration-count:infinite}._mat-animation-noopable.mat-progress-spinner.mat-progress-spinner-indeterminate-animation[mode=indeterminate] circle{transition:none;animation:none}@keyframes mat-progress-spinner-linear-rotate{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@keyframes mat-progress-spinner-stroke-rotate-100{0%{stroke-dashoffset:268.606171575px;transform:rotate(0)}12.5%{stroke-dashoffset:56.5486677px;transform:rotate(0)}12.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(72.5deg)}25%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(72.5deg)}25.0001%{stroke-dashoffset:268.606171575px;transform:rotate(270deg)}37.5%{stroke-dashoffset:56.5486677px;transform:rotate(270deg)}37.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(161.5deg)}50%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(161.5deg)}50.0001%{stroke-dashoffset:268.606171575px;transform:rotate(180deg)}62.5%{stroke-dashoffset:56.5486677px;transform:rotate(180deg)}62.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(251.5deg)}75%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(251.5deg)}75.0001%{stroke-dashoffset:268.606171575px;transform:rotate(90deg)}87.5%{stroke-dashoffset:56.5486677px;transform:rotate(90deg)}87.5001%{stroke-dashoffset:56.5486677px;transform:rotateX(180deg) rotate(341.5deg)}100%{stroke-dashoffset:268.606171575px;transform:rotateX(180deg) rotate(341.5deg)}}\\n\"],\n encapsulation: 2,\n changeDetection: 0\n});\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * `` component.\n *\n * This is a component definition to be used as a convenience reference to create an\n * indeterminate `` instance.\n */\n\n\nlet MatSpinner = /*#__PURE__*/(() => {\n class MatSpinner extends MatProgressSpinner {\n constructor(elementRef, platform, document, animationMode, defaults) {\n super(elementRef, platform, document, animationMode, defaults);\n this.mode = 'indeterminate';\n }\n\n }\n\n MatSpinner.ɵfac = function MatSpinner_Factory(t) {\n return new (t || MatSpinner)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.Platform), i0.ɵɵdirectiveInject(DOCUMENT, 8), i0.ɵɵdirectiveInject(ANIMATION_MODULE_TYPE, 8), i0.ɵɵdirectiveInject(MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS));\n };\n\n MatSpinner.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatSpinner,\n selectors: [[\"mat-spinner\"]],\n hostAttrs: [\"role\", \"progressbar\", \"mode\", \"indeterminate\", 1, \"mat-spinner\", \"mat-progress-spinner\"],\n hostVars: 6,\n hostBindings: function MatSpinner_HostBindings(rf, ctx) {\n if (rf & 2) {\n i0.ɵɵstyleProp(\"width\", ctx.diameter, \"px\")(\"height\", ctx.diameter, \"px\");\n i0.ɵɵclassProp(\"_mat-animation-noopable\", ctx._noopAnimations);\n }\n },\n inputs: {\n color: \"color\"\n },\n features: [i0.ɵɵInheritDefinitionFeature],\n decls: 3,\n vars: 8,\n consts: [[\"preserveAspectRatio\", \"xMidYMid meet\", \"focusable\", \"false\", \"aria-hidden\", \"true\", 3, \"ngSwitch\"], [\"cx\", \"50%\", \"cy\", \"50%\", 3, \"animation-name\", \"stroke-dashoffset\", \"stroke-dasharray\", \"stroke-width\", 4, \"ngSwitchCase\"], [\"cx\", \"50%\", \"cy\", \"50%\", 3, \"stroke-dashoffset\", \"stroke-dasharray\", \"stroke-width\", 4, \"ngSwitchCase\"], [\"cx\", \"50%\", \"cy\", \"50%\"]],\n template: function MatSpinner_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵnamespaceSVG();\n i0.ɵɵelementStart(0, \"svg\", 0);\n i0.ɵɵtemplate(1, MatSpinner__svg_circle_1_Template, 1, 9, \"circle\", 1);\n i0.ɵɵtemplate(2, MatSpinner__svg_circle_2_Template, 1, 7, \"circle\", 2);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n i0.ɵɵstyleProp(\"width\", ctx.diameter, \"px\")(\"height\", ctx.diameter, \"px\");\n i0.ɵɵproperty(\"ngSwitch\", ctx.mode === \"indeterminate\");\n i0.ɵɵattribute(\"viewBox\", ctx._getViewBox());\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngSwitchCase\", true);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngSwitchCase\", false);\n }\n },\n directives: [i2.NgSwitch, i2.NgSwitchCase],\n styles: [_c0],\n encapsulation: 2,\n changeDetection: 0\n });\n return MatSpinner;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nlet MatProgressSpinnerModule = /*#__PURE__*/(() => {\n class MatProgressSpinnerModule {}\n\n MatProgressSpinnerModule.ɵfac = function MatProgressSpinnerModule_Factory(t) {\n return new (t || MatProgressSpinnerModule)();\n };\n\n MatProgressSpinnerModule.ɵmod = /* @__PURE__ */i0.ɵɵdefineNgModule({\n type: MatProgressSpinnerModule\n });\n MatProgressSpinnerModule.ɵinj = /* @__PURE__ */i0.ɵɵdefineInjector({\n imports: [[MatCommonModule, CommonModule], MatCommonModule]\n });\n return MatProgressSpinnerModule;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Generated bundle index. Do not edit.\n */\n\n\nexport { MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS, MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS_FACTORY, MatProgressSpinner, MatProgressSpinnerModule, MatSpinner }; //# sourceMappingURL=progress-spinner.mjs.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0b6e69f115b277106670a9b64e2c0fb0.json b/.angular/cache/babel-webpack/0b6e69f115b277106670a9b64e2c0fb0.json
new file mode 100644
index 0000000..6d33ba3
--- /dev/null
+++ b/.angular/cache/babel-webpack/0b6e69f115b277106670a9b64e2c0fb0.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { coerceNumberProperty, coerceElement, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport * as i0 from '@angular/core';\nimport { InjectionToken, forwardRef, Directive, Input, Injectable, Optional, Inject, Component, ViewEncapsulation, ChangeDetectionStrategy, Output, ViewChild, SkipSelf, NgModule } from '@angular/core';\nimport { Subject, of, Observable, fromEvent, animationFrameScheduler, asapScheduler, Subscription, isObservable } from 'rxjs';\nimport { distinctUntilChanged, auditTime, filter, takeUntil, startWith, pairwise, switchMap, shareReplay } from 'rxjs/operators';\nimport * as i1 from '@angular/cdk/platform';\nimport { getRtlScrollAxisType, supportsScrollBehavior, PlatformModule } from '@angular/cdk/platform';\nimport { DOCUMENT } from '@angular/common';\nimport * as i2 from '@angular/cdk/bidi';\nimport { BidiModule } from '@angular/cdk/bidi';\nimport * as i2$1 from '@angular/cdk/collections';\nimport { isDataSource, ArrayDataSource, _VIEW_REPEATER_STRATEGY, _RecycleViewRepeaterStrategy } from '@angular/cdk/collections';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** The injection token used to specify the virtual scrolling strategy. */\n\nconst _c0 = [\"contentWrapper\"];\nconst _c1 = [\"*\"];\nconst VIRTUAL_SCROLL_STRATEGY = /*#__PURE__*/new InjectionToken('VIRTUAL_SCROLL_STRATEGY');\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Virtual scrolling strategy for lists with items of known fixed size. */\n\nclass FixedSizeVirtualScrollStrategy {\n /**\n * @param itemSize The size of the items in the virtually scrolling list.\n * @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more\n * @param maxBufferPx The amount of buffer (in pixels) to render when rendering more.\n */\n constructor(itemSize, minBufferPx, maxBufferPx) {\n this._scrolledIndexChange = new Subject();\n /** @docs-private Implemented as part of VirtualScrollStrategy. */\n\n this.scrolledIndexChange = this._scrolledIndexChange.pipe(distinctUntilChanged());\n /** The attached viewport. */\n\n this._viewport = null;\n this._itemSize = itemSize;\n this._minBufferPx = minBufferPx;\n this._maxBufferPx = maxBufferPx;\n }\n /**\n * Attaches this scroll strategy to a viewport.\n * @param viewport The viewport to attach this strategy to.\n */\n\n\n attach(viewport) {\n this._viewport = viewport;\n\n this._updateTotalContentSize();\n\n this._updateRenderedRange();\n }\n /** Detaches this scroll strategy from the currently attached viewport. */\n\n\n detach() {\n this._scrolledIndexChange.complete();\n\n this._viewport = null;\n }\n /**\n * Update the item size and buffer size.\n * @param itemSize The size of the items in the virtually scrolling list.\n * @param minBufferPx The minimum amount of buffer (in pixels) before needing to render more\n * @param maxBufferPx The amount of buffer (in pixels) to render when rendering more.\n */\n\n\n updateItemAndBufferSize(itemSize, minBufferPx, maxBufferPx) {\n if (maxBufferPx < minBufferPx && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('CDK virtual scroll: maxBufferPx must be greater than or equal to minBufferPx');\n }\n\n this._itemSize = itemSize;\n this._minBufferPx = minBufferPx;\n this._maxBufferPx = maxBufferPx;\n\n this._updateTotalContentSize();\n\n this._updateRenderedRange();\n }\n /** @docs-private Implemented as part of VirtualScrollStrategy. */\n\n\n onContentScrolled() {\n this._updateRenderedRange();\n }\n /** @docs-private Implemented as part of VirtualScrollStrategy. */\n\n\n onDataLengthChanged() {\n this._updateTotalContentSize();\n\n this._updateRenderedRange();\n }\n /** @docs-private Implemented as part of VirtualScrollStrategy. */\n\n\n onContentRendered() {\n /* no-op */\n }\n /** @docs-private Implemented as part of VirtualScrollStrategy. */\n\n\n onRenderedOffsetChanged() {\n /* no-op */\n }\n /**\n * Scroll to the offset for the given index.\n * @param index The index of the element to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling.\n */\n\n\n scrollToIndex(index, behavior) {\n if (this._viewport) {\n this._viewport.scrollToOffset(index * this._itemSize, behavior);\n }\n }\n /** Update the viewport's total content size. */\n\n\n _updateTotalContentSize() {\n if (!this._viewport) {\n return;\n }\n\n this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSize);\n }\n /** Update the viewport's rendered range. */\n\n\n _updateRenderedRange() {\n if (!this._viewport) {\n return;\n }\n\n const renderedRange = this._viewport.getRenderedRange();\n\n const newRange = {\n start: renderedRange.start,\n end: renderedRange.end\n };\n\n const viewportSize = this._viewport.getViewportSize();\n\n const dataLength = this._viewport.getDataLength();\n\n let scrollOffset = this._viewport.measureScrollOffset(); // Prevent NaN as result when dividing by zero.\n\n\n let firstVisibleIndex = this._itemSize > 0 ? scrollOffset / this._itemSize : 0; // If user scrolls to the bottom of the list and data changes to a smaller list\n\n if (newRange.end > dataLength) {\n // We have to recalculate the first visible index based on new data length and viewport size.\n const maxVisibleItems = Math.ceil(viewportSize / this._itemSize);\n const newVisibleIndex = Math.max(0, Math.min(firstVisibleIndex, dataLength - maxVisibleItems)); // If first visible index changed we must update scroll offset to handle start/end buffers\n // Current range must also be adjusted to cover the new position (bottom of new list).\n\n if (firstVisibleIndex != newVisibleIndex) {\n firstVisibleIndex = newVisibleIndex;\n scrollOffset = newVisibleIndex * this._itemSize;\n newRange.start = Math.floor(firstVisibleIndex);\n }\n\n newRange.end = Math.max(0, Math.min(dataLength, newRange.start + maxVisibleItems));\n }\n\n const startBuffer = scrollOffset - newRange.start * this._itemSize;\n\n if (startBuffer < this._minBufferPx && newRange.start != 0) {\n const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSize);\n newRange.start = Math.max(0, newRange.start - expandStart);\n newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSize));\n } else {\n const endBuffer = newRange.end * this._itemSize - (scrollOffset + viewportSize);\n\n if (endBuffer < this._minBufferPx && newRange.end != dataLength) {\n const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSize);\n\n if (expandEnd > 0) {\n newRange.end = Math.min(dataLength, newRange.end + expandEnd);\n newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSize));\n }\n }\n }\n\n this._viewport.setRenderedRange(newRange);\n\n this._viewport.setRenderedContentOffset(this._itemSize * newRange.start);\n\n this._scrolledIndexChange.next(Math.floor(firstVisibleIndex));\n }\n\n}\n/**\n * Provider factory for `FixedSizeVirtualScrollStrategy` that simply extracts the already created\n * `FixedSizeVirtualScrollStrategy` from the given directive.\n * @param fixedSizeDir The instance of `CdkFixedSizeVirtualScroll` to extract the\n * `FixedSizeVirtualScrollStrategy` from.\n */\n\n\nfunction _fixedSizeVirtualScrollStrategyFactory(fixedSizeDir) {\n return fixedSizeDir._scrollStrategy;\n}\n/** A virtual scroll strategy that supports fixed-size items. */\n\n\nlet CdkFixedSizeVirtualScroll = /*#__PURE__*/(() => {\n class CdkFixedSizeVirtualScroll {\n constructor() {\n this._itemSize = 20;\n this._minBufferPx = 100;\n this._maxBufferPx = 200;\n /** The scroll strategy used by this directive. */\n\n this._scrollStrategy = new FixedSizeVirtualScrollStrategy(this.itemSize, this.minBufferPx, this.maxBufferPx);\n }\n /** The size of the items in the list (in pixels). */\n\n\n get itemSize() {\n return this._itemSize;\n }\n\n set itemSize(value) {\n this._itemSize = coerceNumberProperty(value);\n }\n /**\n * The minimum amount of buffer rendered beyond the viewport (in pixels).\n * If the amount of buffer dips below this number, more items will be rendered. Defaults to 100px.\n */\n\n\n get minBufferPx() {\n return this._minBufferPx;\n }\n\n set minBufferPx(value) {\n this._minBufferPx = coerceNumberProperty(value);\n }\n /**\n * The number of pixels worth of buffer to render for when rendering new items. Defaults to 200px.\n */\n\n\n get maxBufferPx() {\n return this._maxBufferPx;\n }\n\n set maxBufferPx(value) {\n this._maxBufferPx = coerceNumberProperty(value);\n }\n\n ngOnChanges() {\n this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.minBufferPx, this.maxBufferPx);\n }\n\n }\n\n CdkFixedSizeVirtualScroll.ɵfac = function CdkFixedSizeVirtualScroll_Factory(t) {\n return new (t || CdkFixedSizeVirtualScroll)();\n };\n\n CdkFixedSizeVirtualScroll.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkFixedSizeVirtualScroll,\n selectors: [[\"cdk-virtual-scroll-viewport\", \"itemSize\", \"\"]],\n inputs: {\n itemSize: \"itemSize\",\n minBufferPx: \"minBufferPx\",\n maxBufferPx: \"maxBufferPx\"\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: VIRTUAL_SCROLL_STRATEGY,\n useFactory: _fixedSizeVirtualScrollStrategyFactory,\n deps: [forwardRef(() => CdkFixedSizeVirtualScroll)]\n }]), i0.ɵɵNgOnChangesFeature]\n });\n return CdkFixedSizeVirtualScroll;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Time in ms to throttle the scrolling events by default. */\n\n\nconst DEFAULT_SCROLL_TIME = 20;\n/**\n * Service contained all registered Scrollable references and emits an event when any one of the\n * Scrollable references emit a scrolled event.\n */\n\nlet ScrollDispatcher = /*#__PURE__*/(() => {\n class ScrollDispatcher {\n constructor(_ngZone, _platform, document) {\n this._ngZone = _ngZone;\n this._platform = _platform;\n /** Subject for notifying that a registered scrollable reference element has been scrolled. */\n\n this._scrolled = new Subject();\n /** Keeps track of the global `scroll` and `resize` subscriptions. */\n\n this._globalSubscription = null;\n /** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */\n\n this._scrolledCount = 0;\n /**\n * Map of all the scrollable references that are registered with the service and their\n * scroll event subscriptions.\n */\n\n this.scrollContainers = new Map();\n this._document = document;\n }\n /**\n * Registers a scrollable instance with the service and listens for its scrolled events. When the\n * scrollable is scrolled, the service emits the event to its scrolled observable.\n * @param scrollable Scrollable instance to be registered.\n */\n\n\n register(scrollable) {\n if (!this.scrollContainers.has(scrollable)) {\n this.scrollContainers.set(scrollable, scrollable.elementScrolled().subscribe(() => this._scrolled.next(scrollable)));\n }\n }\n /**\n * Deregisters a Scrollable reference and unsubscribes from its scroll event observable.\n * @param scrollable Scrollable instance to be deregistered.\n */\n\n\n deregister(scrollable) {\n const scrollableReference = this.scrollContainers.get(scrollable);\n\n if (scrollableReference) {\n scrollableReference.unsubscribe();\n this.scrollContainers.delete(scrollable);\n }\n }\n /**\n * Returns an observable that emits an event whenever any of the registered Scrollable\n * references (or window, document, or body) fire a scrolled event. Can provide a time in ms\n * to override the default \"throttle\" time.\n *\n * **Note:** in order to avoid hitting change detection for every scroll event,\n * all of the events emitted from this stream will be run outside the Angular zone.\n * If you need to update any data bindings as a result of a scroll event, you have\n * to run the callback using `NgZone.run`.\n */\n\n\n scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) {\n if (!this._platform.isBrowser) {\n return of();\n }\n\n return new Observable(observer => {\n if (!this._globalSubscription) {\n this._addGlobalListener();\n } // In the case of a 0ms delay, use an observable without auditTime\n // since it does add a perceptible delay in processing overhead.\n\n\n const subscription = auditTimeInMs > 0 ? this._scrolled.pipe(auditTime(auditTimeInMs)).subscribe(observer) : this._scrolled.subscribe(observer);\n this._scrolledCount++;\n return () => {\n subscription.unsubscribe();\n this._scrolledCount--;\n\n if (!this._scrolledCount) {\n this._removeGlobalListener();\n }\n };\n });\n }\n\n ngOnDestroy() {\n this._removeGlobalListener();\n\n this.scrollContainers.forEach((_, container) => this.deregister(container));\n\n this._scrolled.complete();\n }\n /**\n * Returns an observable that emits whenever any of the\n * scrollable ancestors of an element are scrolled.\n * @param elementOrElementRef Element whose ancestors to listen for.\n * @param auditTimeInMs Time to throttle the scroll events.\n */\n\n\n ancestorScrolled(elementOrElementRef, auditTimeInMs) {\n const ancestors = this.getAncestorScrollContainers(elementOrElementRef);\n return this.scrolled(auditTimeInMs).pipe(filter(target => {\n return !target || ancestors.indexOf(target) > -1;\n }));\n }\n /** Returns all registered Scrollables that contain the provided element. */\n\n\n getAncestorScrollContainers(elementOrElementRef) {\n const scrollingContainers = [];\n this.scrollContainers.forEach((_subscription, scrollable) => {\n if (this._scrollableContainsElement(scrollable, elementOrElementRef)) {\n scrollingContainers.push(scrollable);\n }\n });\n return scrollingContainers;\n }\n /** Use defaultView of injected document if available or fallback to global window reference */\n\n\n _getWindow() {\n return this._document.defaultView || window;\n }\n /** Returns true if the element is contained within the provided Scrollable. */\n\n\n _scrollableContainsElement(scrollable, elementOrElementRef) {\n let element = coerceElement(elementOrElementRef);\n let scrollableElement = scrollable.getElementRef().nativeElement; // Traverse through the element parents until we reach null, checking if any of the elements\n // are the scrollable's element.\n\n do {\n if (element == scrollableElement) {\n return true;\n }\n } while (element = element.parentElement);\n\n return false;\n }\n /** Sets up the global scroll listeners. */\n\n\n _addGlobalListener() {\n this._globalSubscription = this._ngZone.runOutsideAngular(() => {\n const window = this._getWindow();\n\n return fromEvent(window.document, 'scroll').subscribe(() => this._scrolled.next());\n });\n }\n /** Cleans up the global scroll listener. */\n\n\n _removeGlobalListener() {\n if (this._globalSubscription) {\n this._globalSubscription.unsubscribe();\n\n this._globalSubscription = null;\n }\n }\n\n }\n\n ScrollDispatcher.ɵfac = function ScrollDispatcher_Factory(t) {\n return new (t || ScrollDispatcher)(i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i1.Platform), i0.ɵɵinject(DOCUMENT, 8));\n };\n\n ScrollDispatcher.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: ScrollDispatcher,\n factory: ScrollDispatcher.ɵfac,\n providedIn: 'root'\n });\n return ScrollDispatcher;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Sends an event when the directive's element is scrolled. Registers itself with the\n * ScrollDispatcher service to include itself as part of its collection of scrolling events that it\n * can be listened to through the service.\n */\n\n\nlet CdkScrollable = /*#__PURE__*/(() => {\n class CdkScrollable {\n constructor(elementRef, scrollDispatcher, ngZone, dir) {\n this.elementRef = elementRef;\n this.scrollDispatcher = scrollDispatcher;\n this.ngZone = ngZone;\n this.dir = dir;\n this._destroyed = new Subject();\n this._elementScrolled = new Observable(observer => this.ngZone.runOutsideAngular(() => fromEvent(this.elementRef.nativeElement, 'scroll').pipe(takeUntil(this._destroyed)).subscribe(observer)));\n }\n\n ngOnInit() {\n this.scrollDispatcher.register(this);\n }\n\n ngOnDestroy() {\n this.scrollDispatcher.deregister(this);\n\n this._destroyed.next();\n\n this._destroyed.complete();\n }\n /** Returns observable that emits when a scroll event is fired on the host element. */\n\n\n elementScrolled() {\n return this._elementScrolled;\n }\n /** Gets the ElementRef for the viewport. */\n\n\n getElementRef() {\n return this.elementRef;\n }\n /**\n * Scrolls to the specified offsets. This is a normalized version of the browser's native scrollTo\n * method, since browsers are not consistent about what scrollLeft means in RTL. For this method\n * left and right always refer to the left and right side of the scrolling container irrespective\n * of the layout direction. start and end refer to left and right in an LTR context and vice-versa\n * in an RTL context.\n * @param options specified the offsets to scroll to.\n */\n\n\n scrollTo(options) {\n const el = this.elementRef.nativeElement;\n const isRtl = this.dir && this.dir.value == 'rtl'; // Rewrite start & end offsets as right or left offsets.\n\n if (options.left == null) {\n options.left = isRtl ? options.end : options.start;\n }\n\n if (options.right == null) {\n options.right = isRtl ? options.start : options.end;\n } // Rewrite the bottom offset as a top offset.\n\n\n if (options.bottom != null) {\n options.top = el.scrollHeight - el.clientHeight - options.bottom;\n } // Rewrite the right offset as a left offset.\n\n\n if (isRtl && getRtlScrollAxisType() != 0\n /* NORMAL */\n ) {\n if (options.left != null) {\n options.right = el.scrollWidth - el.clientWidth - options.left;\n }\n\n if (getRtlScrollAxisType() == 2\n /* INVERTED */\n ) {\n options.left = options.right;\n } else if (getRtlScrollAxisType() == 1\n /* NEGATED */\n ) {\n options.left = options.right ? -options.right : options.right;\n }\n } else {\n if (options.right != null) {\n options.left = el.scrollWidth - el.clientWidth - options.right;\n }\n }\n\n this._applyScrollToOptions(options);\n }\n\n _applyScrollToOptions(options) {\n const el = this.elementRef.nativeElement;\n\n if (supportsScrollBehavior()) {\n el.scrollTo(options);\n } else {\n if (options.top != null) {\n el.scrollTop = options.top;\n }\n\n if (options.left != null) {\n el.scrollLeft = options.left;\n }\n }\n }\n /**\n * Measures the scroll offset relative to the specified edge of the viewport. This method can be\n * used instead of directly checking scrollLeft or scrollTop, since browsers are not consistent\n * about what scrollLeft means in RTL. The values returned by this method are normalized such that\n * left and right always refer to the left and right side of the scrolling container irrespective\n * of the layout direction. start and end refer to left and right in an LTR context and vice-versa\n * in an RTL context.\n * @param from The edge to measure from.\n */\n\n\n measureScrollOffset(from) {\n const LEFT = 'left';\n const RIGHT = 'right';\n const el = this.elementRef.nativeElement;\n\n if (from == 'top') {\n return el.scrollTop;\n }\n\n if (from == 'bottom') {\n return el.scrollHeight - el.clientHeight - el.scrollTop;\n } // Rewrite start & end as left or right offsets.\n\n\n const isRtl = this.dir && this.dir.value == 'rtl';\n\n if (from == 'start') {\n from = isRtl ? RIGHT : LEFT;\n } else if (from == 'end') {\n from = isRtl ? LEFT : RIGHT;\n }\n\n if (isRtl && getRtlScrollAxisType() == 2\n /* INVERTED */\n ) {\n // For INVERTED, scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and\n // 0 when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollWidth - el.clientWidth - el.scrollLeft;\n } else {\n return el.scrollLeft;\n }\n } else if (isRtl && getRtlScrollAxisType() == 1\n /* NEGATED */\n ) {\n // For NEGATED, scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and\n // 0 when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollLeft + el.scrollWidth - el.clientWidth;\n } else {\n return -el.scrollLeft;\n }\n } else {\n // For NORMAL, as well as non-RTL contexts, scrollLeft is 0 when scrolled all the way left and\n // (scrollWidth - clientWidth) when scrolled all the way right.\n if (from == LEFT) {\n return el.scrollLeft;\n } else {\n return el.scrollWidth - el.clientWidth - el.scrollLeft;\n }\n }\n }\n\n }\n\n CdkScrollable.ɵfac = function CdkScrollable_Factory(t) {\n return new (t || CdkScrollable)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(ScrollDispatcher), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i2.Directionality, 8));\n };\n\n CdkScrollable.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkScrollable,\n selectors: [[\"\", \"cdk-scrollable\", \"\"], [\"\", \"cdkScrollable\", \"\"]]\n });\n return CdkScrollable;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Time in ms to throttle the resize events by default. */\n\n\nconst DEFAULT_RESIZE_TIME = 20;\n/**\n * Simple utility for getting the bounds of the browser viewport.\n * @docs-private\n */\n\nlet ViewportRuler = /*#__PURE__*/(() => {\n class ViewportRuler {\n constructor(_platform, ngZone, document) {\n this._platform = _platform;\n /** Stream of viewport change events. */\n\n this._change = new Subject();\n /** Event listener that will be used to handle the viewport change events. */\n\n this._changeListener = event => {\n this._change.next(event);\n };\n\n this._document = document;\n ngZone.runOutsideAngular(() => {\n if (_platform.isBrowser) {\n const window = this._getWindow(); // Note that bind the events ourselves, rather than going through something like RxJS's\n // `fromEvent` so that we can ensure that they're bound outside of the NgZone.\n\n\n window.addEventListener('resize', this._changeListener);\n window.addEventListener('orientationchange', this._changeListener);\n } // Clear the cached position so that the viewport is re-measured next time it is required.\n // We don't need to keep track of the subscription, because it is completed on destroy.\n\n\n this.change().subscribe(() => this._viewportSize = null);\n });\n }\n\n ngOnDestroy() {\n if (this._platform.isBrowser) {\n const window = this._getWindow();\n\n window.removeEventListener('resize', this._changeListener);\n window.removeEventListener('orientationchange', this._changeListener);\n }\n\n this._change.complete();\n }\n /** Returns the viewport's width and height. */\n\n\n getViewportSize() {\n if (!this._viewportSize) {\n this._updateViewportSize();\n }\n\n const output = {\n width: this._viewportSize.width,\n height: this._viewportSize.height\n }; // If we're not on a browser, don't cache the size since it'll be mocked out anyway.\n\n if (!this._platform.isBrowser) {\n this._viewportSize = null;\n }\n\n return output;\n }\n /** Gets a ClientRect for the viewport's bounds. */\n\n\n getViewportRect() {\n // Use the document element's bounding rect rather than the window scroll properties\n // (e.g. pageYOffset, scrollY) due to in issue in Chrome and IE where window scroll\n // properties and client coordinates (boundingClientRect, clientX/Y, etc.) are in different\n // conceptual viewports. Under most circumstances these viewports are equivalent, but they\n // can disagree when the page is pinch-zoomed (on devices that support touch).\n // See https://bugs.chromium.org/p/chromium/issues/detail?id=489206#c4\n // We use the documentElement instead of the body because, by default (without a css reset)\n // browsers typically give the document body an 8px margin, which is not included in\n // getBoundingClientRect().\n const scrollPosition = this.getViewportScrollPosition();\n const {\n width,\n height\n } = this.getViewportSize();\n return {\n top: scrollPosition.top,\n left: scrollPosition.left,\n bottom: scrollPosition.top + height,\n right: scrollPosition.left + width,\n height,\n width\n };\n }\n /** Gets the (top, left) scroll position of the viewport. */\n\n\n getViewportScrollPosition() {\n // While we can get a reference to the fake document\n // during SSR, it doesn't have getBoundingClientRect.\n if (!this._platform.isBrowser) {\n return {\n top: 0,\n left: 0\n };\n } // The top-left-corner of the viewport is determined by the scroll position of the document\n // body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about\n // whether `document.body` or `document.documentElement` is the scrolled element, so reading\n // `scrollTop` and `scrollLeft` is inconsistent. However, using the bounding rect of\n // `document.documentElement` works consistently, where the `top` and `left` values will\n // equal negative the scroll position.\n\n\n const document = this._document;\n\n const window = this._getWindow();\n\n const documentElement = document.documentElement;\n const documentRect = documentElement.getBoundingClientRect();\n const top = -documentRect.top || document.body.scrollTop || window.scrollY || documentElement.scrollTop || 0;\n const left = -documentRect.left || document.body.scrollLeft || window.scrollX || documentElement.scrollLeft || 0;\n return {\n top,\n left\n };\n }\n /**\n * Returns a stream that emits whenever the size of the viewport changes.\n * This stream emits outside of the Angular zone.\n * @param throttleTime Time in milliseconds to throttle the stream.\n */\n\n\n change(throttleTime = DEFAULT_RESIZE_TIME) {\n return throttleTime > 0 ? this._change.pipe(auditTime(throttleTime)) : this._change;\n }\n /** Use defaultView of injected document if available or fallback to global window reference */\n\n\n _getWindow() {\n return this._document.defaultView || window;\n }\n /** Updates the cached viewport size. */\n\n\n _updateViewportSize() {\n const window = this._getWindow();\n\n this._viewportSize = this._platform.isBrowser ? {\n width: window.innerWidth,\n height: window.innerHeight\n } : {\n width: 0,\n height: 0\n };\n }\n\n }\n\n ViewportRuler.ɵfac = function ViewportRuler_Factory(t) {\n return new (t || ViewportRuler)(i0.ɵɵinject(i1.Platform), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(DOCUMENT, 8));\n };\n\n ViewportRuler.ɵprov = /* @__PURE__ */i0.ɵɵdefineInjectable({\n token: ViewportRuler,\n factory: ViewportRuler.ɵfac,\n providedIn: 'root'\n });\n return ViewportRuler;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Checks if the given ranges are equal. */\n\n\nfunction rangesEqual(r1, r2) {\n return r1.start == r2.start && r1.end == r2.end;\n}\n/**\n * Scheduler to be used for scroll events. Needs to fall back to\n * something that doesn't rely on requestAnimationFrame on environments\n * that don't support it (e.g. server-side rendering).\n */\n\n\nconst SCROLL_SCHEDULER = typeof requestAnimationFrame !== 'undefined' ? animationFrameScheduler : asapScheduler;\n/** A viewport that virtualizes its scrolling with the help of `CdkVirtualForOf`. */\n\nlet CdkVirtualScrollViewport = /*#__PURE__*/(() => {\n class CdkVirtualScrollViewport extends CdkScrollable {\n constructor(elementRef, _changeDetectorRef, ngZone, _scrollStrategy, dir, scrollDispatcher, viewportRuler) {\n super(elementRef, scrollDispatcher, ngZone, dir);\n this.elementRef = elementRef;\n this._changeDetectorRef = _changeDetectorRef;\n this._scrollStrategy = _scrollStrategy;\n /** Emits when the viewport is detached from a CdkVirtualForOf. */\n\n this._detachedSubject = new Subject();\n /** Emits when the rendered range changes. */\n\n this._renderedRangeSubject = new Subject();\n this._orientation = 'vertical';\n this._appendOnly = false; // Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll\n // strategy lazily (i.e. only if the user is actually listening to the events). We do this because\n // depending on how the strategy calculates the scrolled index, it may come at a cost to\n // performance.\n\n /** Emits when the index of the first element visible in the viewport changes. */\n\n this.scrolledIndexChange = new Observable(observer => this._scrollStrategy.scrolledIndexChange.subscribe(index => Promise.resolve().then(() => this.ngZone.run(() => observer.next(index)))));\n /** A stream that emits whenever the rendered range changes. */\n\n this.renderedRangeStream = this._renderedRangeSubject;\n /**\n * The total size of all content (in pixels), including content that is not currently rendered.\n */\n\n this._totalContentSize = 0;\n /** A string representing the `style.width` property value to be used for the spacer element. */\n\n this._totalContentWidth = '';\n /** A string representing the `style.height` property value to be used for the spacer element. */\n\n this._totalContentHeight = '';\n /** The currently rendered range of indices. */\n\n this._renderedRange = {\n start: 0,\n end: 0\n };\n /** The length of the data bound to this viewport (in number of items). */\n\n this._dataLength = 0;\n /** The size of the viewport (in pixels). */\n\n this._viewportSize = 0;\n /** The last rendered content offset that was set. */\n\n this._renderedContentOffset = 0;\n /**\n * Whether the last rendered content offset was to the end of the content (and therefore needs to\n * be rewritten as an offset to the start of the content).\n */\n\n this._renderedContentOffsetNeedsRewrite = false;\n /** Whether there is a pending change detection cycle. */\n\n this._isChangeDetectionPending = false;\n /** A list of functions to run after the next change detection cycle. */\n\n this._runAfterChangeDetection = [];\n /** Subscription to changes in the viewport size. */\n\n this._viewportChanges = Subscription.EMPTY;\n\n if (!_scrollStrategy && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('Error: cdk-virtual-scroll-viewport requires the \"itemSize\" property to be set.');\n }\n\n this._viewportChanges = viewportRuler.change().subscribe(() => {\n this.checkViewportSize();\n });\n }\n /** The direction the viewport scrolls. */\n\n\n get orientation() {\n return this._orientation;\n }\n\n set orientation(orientation) {\n if (this._orientation !== orientation) {\n this._orientation = orientation;\n\n this._calculateSpacerSize();\n }\n }\n /**\n * Whether rendered items should persist in the DOM after scrolling out of view. By default, items\n * will be removed.\n */\n\n\n get appendOnly() {\n return this._appendOnly;\n }\n\n set appendOnly(value) {\n this._appendOnly = coerceBooleanProperty(value);\n }\n\n ngOnInit() {\n super.ngOnInit(); // It's still too early to measure the viewport at this point. Deferring with a promise allows\n // the Viewport to be rendered with the correct size before we measure. We run this outside the\n // zone to avoid causing more change detection cycles. We handle the change detection loop\n // ourselves instead.\n\n this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {\n this._measureViewportSize();\n\n this._scrollStrategy.attach(this);\n\n this.elementScrolled().pipe( // Start off with a fake scroll event so we properly detect our initial position.\n startWith(null), // Collect multiple events into one until the next animation frame. This way if\n // there are multiple scroll events in the same frame we only need to recheck\n // our layout once.\n auditTime(0, SCROLL_SCHEDULER)).subscribe(() => this._scrollStrategy.onContentScrolled());\n\n this._markChangeDetectionNeeded();\n }));\n }\n\n ngOnDestroy() {\n this.detach();\n\n this._scrollStrategy.detach(); // Complete all subjects\n\n\n this._renderedRangeSubject.complete();\n\n this._detachedSubject.complete();\n\n this._viewportChanges.unsubscribe();\n\n super.ngOnDestroy();\n }\n /** Attaches a `CdkVirtualScrollRepeater` to this viewport. */\n\n\n attach(forOf) {\n if (this._forOf && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error('CdkVirtualScrollViewport is already attached.');\n } // Subscribe to the data stream of the CdkVirtualForOf to keep track of when the data length\n // changes. Run outside the zone to avoid triggering change detection, since we're managing the\n // change detection loop ourselves.\n\n\n this.ngZone.runOutsideAngular(() => {\n this._forOf = forOf;\n\n this._forOf.dataStream.pipe(takeUntil(this._detachedSubject)).subscribe(data => {\n const newLength = data.length;\n\n if (newLength !== this._dataLength) {\n this._dataLength = newLength;\n\n this._scrollStrategy.onDataLengthChanged();\n }\n\n this._doChangeDetection();\n });\n });\n }\n /** Detaches the current `CdkVirtualForOf`. */\n\n\n detach() {\n this._forOf = null;\n\n this._detachedSubject.next();\n }\n /** Gets the length of the data bound to this viewport (in number of items). */\n\n\n getDataLength() {\n return this._dataLength;\n }\n /** Gets the size of the viewport (in pixels). */\n\n\n getViewportSize() {\n return this._viewportSize;\n } // TODO(mmalerba): This is technically out of sync with what's really rendered until a render\n // cycle happens. I'm being careful to only call it after the render cycle is complete and before\n // setting it to something else, but its error prone and should probably be split into\n // `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM.\n\n /** Get the current rendered range of items. */\n\n\n getRenderedRange() {\n return this._renderedRange;\n }\n /**\n * Sets the total size of all content (in pixels), including content that is not currently\n * rendered.\n */\n\n\n setTotalContentSize(size) {\n if (this._totalContentSize !== size) {\n this._totalContentSize = size;\n\n this._calculateSpacerSize();\n\n this._markChangeDetectionNeeded();\n }\n }\n /** Sets the currently rendered range of indices. */\n\n\n setRenderedRange(range) {\n if (!rangesEqual(this._renderedRange, range)) {\n if (this.appendOnly) {\n range = {\n start: 0,\n end: Math.max(this._renderedRange.end, range.end)\n };\n }\n\n this._renderedRangeSubject.next(this._renderedRange = range);\n\n this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered());\n }\n }\n /**\n * Gets the offset from the start of the viewport to the start of the rendered data (in pixels).\n */\n\n\n getOffsetToRenderedContentStart() {\n return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset;\n }\n /**\n * Sets the offset from the start of the viewport to either the start or end of the rendered data\n * (in pixels).\n */\n\n\n setRenderedContentOffset(offset, to = 'to-start') {\n // For a horizontal viewport in a right-to-left language we need to translate along the x-axis\n // in the negative direction.\n const isRtl = this.dir && this.dir.value == 'rtl';\n const isHorizontal = this.orientation == 'horizontal';\n const axis = isHorizontal ? 'X' : 'Y';\n const axisDirection = isHorizontal && isRtl ? -1 : 1;\n let transform = `translate${axis}(${Number(axisDirection * offset)}px)`;\n this._renderedContentOffset = offset;\n\n if (to === 'to-end') {\n transform += ` translate${axis}(-100%)`; // The viewport should rewrite this as a `to-start` offset on the next render cycle. Otherwise\n // elements will appear to expand in the wrong direction (e.g. `mat-expansion-panel` would\n // expand upward).\n\n this._renderedContentOffsetNeedsRewrite = true;\n }\n\n if (this._renderedContentTransform != transform) {\n // We know this value is safe because we parse `offset` with `Number()` before passing it\n // into the string.\n this._renderedContentTransform = transform;\n\n this._markChangeDetectionNeeded(() => {\n if (this._renderedContentOffsetNeedsRewrite) {\n this._renderedContentOffset -= this.measureRenderedContentSize();\n this._renderedContentOffsetNeedsRewrite = false;\n this.setRenderedContentOffset(this._renderedContentOffset);\n } else {\n this._scrollStrategy.onRenderedOffsetChanged();\n }\n });\n }\n }\n /**\n * Scrolls to the given offset from the start of the viewport. Please note that this is not always\n * the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left\n * direction, this would be the equivalent of setting a fictional `scrollRight` property.\n * @param offset The offset to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.\n */\n\n\n scrollToOffset(offset, behavior = 'auto') {\n const options = {\n behavior\n };\n\n if (this.orientation === 'horizontal') {\n options.start = offset;\n } else {\n options.top = offset;\n }\n\n this.scrollTo(options);\n }\n /**\n * Scrolls to the offset for the given index.\n * @param index The index of the element to scroll to.\n * @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.\n */\n\n\n scrollToIndex(index, behavior = 'auto') {\n this._scrollStrategy.scrollToIndex(index, behavior);\n }\n /**\n * Gets the current scroll offset from the start of the viewport (in pixels).\n * @param from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start'\n * in horizontal mode.\n */\n\n\n measureScrollOffset(from) {\n return from ? super.measureScrollOffset(from) : super.measureScrollOffset(this.orientation === 'horizontal' ? 'start' : 'top');\n }\n /** Measure the combined size of all of the rendered items. */\n\n\n measureRenderedContentSize() {\n const contentEl = this._contentWrapper.nativeElement;\n return this.orientation === 'horizontal' ? contentEl.offsetWidth : contentEl.offsetHeight;\n }\n /**\n * Measure the total combined size of the given range. Throws if the range includes items that are\n * not rendered.\n */\n\n\n measureRangeSize(range) {\n if (!this._forOf) {\n return 0;\n }\n\n return this._forOf.measureRangeSize(range, this.orientation);\n }\n /** Update the viewport dimensions and re-render. */\n\n\n checkViewportSize() {\n // TODO: Cleanup later when add logic for handling content resize\n this._measureViewportSize();\n\n this._scrollStrategy.onDataLengthChanged();\n }\n /** Measure the viewport size. */\n\n\n _measureViewportSize() {\n const viewportEl = this.elementRef.nativeElement;\n this._viewportSize = this.orientation === 'horizontal' ? viewportEl.clientWidth : viewportEl.clientHeight;\n }\n /** Queue up change detection to run. */\n\n\n _markChangeDetectionNeeded(runAfter) {\n if (runAfter) {\n this._runAfterChangeDetection.push(runAfter);\n } // Use a Promise to batch together calls to `_doChangeDetection`. This way if we set a bunch of\n // properties sequentially we only have to run `_doChangeDetection` once at the end.\n\n\n if (!this._isChangeDetectionPending) {\n this._isChangeDetectionPending = true;\n this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {\n this._doChangeDetection();\n }));\n }\n }\n /** Run change detection. */\n\n\n _doChangeDetection() {\n this._isChangeDetectionPending = false; // Apply the content transform. The transform can't be set via an Angular binding because\n // bypassSecurityTrustStyle is banned in Google. However the value is safe, it's composed of\n // string literals, a variable that can only be 'X' or 'Y', and user input that is run through\n // the `Number` function first to coerce it to a numeric value.\n\n this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform; // Apply changes to Angular bindings. Note: We must call `markForCheck` to run change detection\n // from the root, since the repeated items are content projected in. Calling `detectChanges`\n // instead does not properly check the projected content.\n\n this.ngZone.run(() => this._changeDetectorRef.markForCheck());\n const runAfterChangeDetection = this._runAfterChangeDetection;\n this._runAfterChangeDetection = [];\n\n for (const fn of runAfterChangeDetection) {\n fn();\n }\n }\n /** Calculates the `style.width` and `style.height` for the spacer element. */\n\n\n _calculateSpacerSize() {\n this._totalContentHeight = this.orientation === 'horizontal' ? '' : `${this._totalContentSize}px`;\n this._totalContentWidth = this.orientation === 'horizontal' ? `${this._totalContentSize}px` : '';\n }\n\n }\n\n CdkVirtualScrollViewport.ɵfac = function CdkVirtualScrollViewport_Factory(t) {\n return new (t || CdkVirtualScrollViewport)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(VIRTUAL_SCROLL_STRATEGY, 8), i0.ɵɵdirectiveInject(i2.Directionality, 8), i0.ɵɵdirectiveInject(ScrollDispatcher), i0.ɵɵdirectiveInject(ViewportRuler));\n };\n\n CdkVirtualScrollViewport.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: CdkVirtualScrollViewport,\n selectors: [[\"cdk-virtual-scroll-viewport\"]],\n viewQuery: function CdkVirtualScrollViewport_Query(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵviewQuery(_c0, 7);\n }\n\n if (rf & 2) {\n let _t;\n\n i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx._contentWrapper = _t.first);\n }\n },\n hostAttrs: [1, \"cdk-virtual-scroll-viewport\"],\n hostVars: 4,\n hostBindings: function CdkVirtualScrollViewport_HostBindings(rf, ctx) {\n if (rf & 2) {\n i0.ɵɵclassProp(\"cdk-virtual-scroll-orientation-horizontal\", ctx.orientation === \"horizontal\")(\"cdk-virtual-scroll-orientation-vertical\", ctx.orientation !== \"horizontal\");\n }\n },\n inputs: {\n orientation: \"orientation\",\n appendOnly: \"appendOnly\"\n },\n outputs: {\n scrolledIndexChange: \"scrolledIndexChange\"\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkScrollable,\n useExisting: CdkVirtualScrollViewport\n }]), i0.ɵɵInheritDefinitionFeature],\n ngContentSelectors: _c1,\n decls: 4,\n vars: 4,\n consts: [[1, \"cdk-virtual-scroll-content-wrapper\"], [\"contentWrapper\", \"\"], [1, \"cdk-virtual-scroll-spacer\"]],\n template: function CdkVirtualScrollViewport_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵprojectionDef();\n i0.ɵɵelementStart(0, \"div\", 0, 1);\n i0.ɵɵprojection(2);\n i0.ɵɵelementEnd();\n i0.ɵɵelement(3, \"div\", 2);\n }\n\n if (rf & 2) {\n i0.ɵɵadvance(3);\n i0.ɵɵstyleProp(\"width\", ctx._totalContentWidth)(\"height\", ctx._totalContentHeight);\n }\n },\n styles: [\"cdk-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict;transform:translateZ(0);will-change:scroll-position;-webkit-overflow-scrolling:touch}.cdk-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .cdk-virtual-scroll-content-wrapper{right:0;left:auto}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper{min-height:100%}.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-horizontal .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper{min-width:100%}.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.cdk-virtual-scroll-spacer{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0}[dir=rtl] .cdk-virtual-scroll-spacer{right:0;left:auto;transform-origin:100% 0}\\n\"],\n encapsulation: 2,\n changeDetection: 0\n });\n return CdkVirtualScrollViewport;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Helper to extract the offset of a DOM Node in a certain direction. */\n\n\nfunction getOffset(orientation, direction, node) {\n const el = node;\n\n if (!el.getBoundingClientRect) {\n return 0;\n }\n\n const rect = el.getBoundingClientRect();\n\n if (orientation === 'horizontal') {\n return direction === 'start' ? rect.left : rect.right;\n }\n\n return direction === 'start' ? rect.top : rect.bottom;\n}\n/**\n * A directive similar to `ngForOf` to be used for rendering data inside a virtual scrolling\n * container.\n */\n\n\nlet CdkVirtualForOf = /*#__PURE__*/(() => {\n class CdkVirtualForOf {\n constructor(\n /** The view container to add items to. */\n _viewContainerRef,\n /** The template to use when stamping out new items. */\n _template,\n /** The set of available differs. */\n _differs,\n /** The strategy used to render items in the virtual scroll viewport. */\n _viewRepeater,\n /** The virtual scrolling viewport that these items are being rendered in. */\n _viewport, ngZone) {\n this._viewContainerRef = _viewContainerRef;\n this._template = _template;\n this._differs = _differs;\n this._viewRepeater = _viewRepeater;\n this._viewport = _viewport;\n /** Emits when the rendered view of the data changes. */\n\n this.viewChange = new Subject();\n /** Subject that emits when a new DataSource instance is given. */\n\n this._dataSourceChanges = new Subject();\n /** Emits whenever the data in the current DataSource changes. */\n\n this.dataStream = this._dataSourceChanges.pipe( // Start off with null `DataSource`.\n startWith(null), // Bundle up the previous and current data sources so we can work with both.\n pairwise(), // Use `_changeDataSource` to disconnect from the previous data source and connect to the\n // new one, passing back a stream of data changes which we run through `switchMap` to give\n // us a data stream that emits the latest data from whatever the current `DataSource` is.\n switchMap(([prev, cur]) => this._changeDataSource(prev, cur)), // Replay the last emitted data when someone subscribes.\n shareReplay(1));\n /** The differ used to calculate changes to the data. */\n\n this._differ = null;\n /** Whether the rendered data should be updated during the next ngDoCheck cycle. */\n\n this._needsUpdate = false;\n this._destroyed = new Subject();\n this.dataStream.subscribe(data => {\n this._data = data;\n\n this._onRenderedDataChange();\n });\n\n this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => {\n this._renderedRange = range;\n ngZone.run(() => this.viewChange.next(this._renderedRange));\n\n this._onRenderedDataChange();\n });\n\n this._viewport.attach(this);\n }\n /** The DataSource to display. */\n\n\n get cdkVirtualForOf() {\n return this._cdkVirtualForOf;\n }\n\n set cdkVirtualForOf(value) {\n this._cdkVirtualForOf = value;\n\n if (isDataSource(value)) {\n this._dataSourceChanges.next(value);\n } else {\n // If value is an an NgIterable, convert it to an array.\n this._dataSourceChanges.next(new ArrayDataSource(isObservable(value) ? value : Array.from(value || [])));\n }\n }\n /**\n * The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and\n * the item and produces a value to be used as the item's identity when tracking changes.\n */\n\n\n get cdkVirtualForTrackBy() {\n return this._cdkVirtualForTrackBy;\n }\n\n set cdkVirtualForTrackBy(fn) {\n this._needsUpdate = true;\n this._cdkVirtualForTrackBy = fn ? (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item) : undefined;\n }\n /** The template used to stamp out new elements. */\n\n\n set cdkVirtualForTemplate(value) {\n if (value) {\n this._needsUpdate = true;\n this._template = value;\n }\n }\n /**\n * The size of the cache used to store templates that are not being used for re-use later.\n * Setting the cache size to `0` will disable caching. Defaults to 20 templates.\n */\n\n\n get cdkVirtualForTemplateCacheSize() {\n return this._viewRepeater.viewCacheSize;\n }\n\n set cdkVirtualForTemplateCacheSize(size) {\n this._viewRepeater.viewCacheSize = coerceNumberProperty(size);\n }\n /**\n * Measures the combined size (width for horizontal orientation, height for vertical) of all items\n * in the specified range. Throws an error if the range includes items that are not currently\n * rendered.\n */\n\n\n measureRangeSize(range, orientation) {\n if (range.start >= range.end) {\n return 0;\n }\n\n if ((range.start < this._renderedRange.start || range.end > this._renderedRange.end) && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw Error(`Error: attempted to measure an item that isn't rendered.`);\n } // The index into the list of rendered views for the first item in the range.\n\n\n const renderedStartIndex = range.start - this._renderedRange.start; // The length of the range we're measuring.\n\n const rangeLen = range.end - range.start; // Loop over all the views, find the first and land node and compute the size by subtracting\n // the top of the first node from the bottom of the last one.\n\n let firstNode;\n let lastNode; // Find the first node by starting from the beginning and going forwards.\n\n for (let i = 0; i < rangeLen; i++) {\n const view = this._viewContainerRef.get(i + renderedStartIndex);\n\n if (view && view.rootNodes.length) {\n firstNode = lastNode = view.rootNodes[0];\n break;\n }\n } // Find the last node by starting from the end and going backwards.\n\n\n for (let i = rangeLen - 1; i > -1; i--) {\n const view = this._viewContainerRef.get(i + renderedStartIndex);\n\n if (view && view.rootNodes.length) {\n lastNode = view.rootNodes[view.rootNodes.length - 1];\n break;\n }\n }\n\n return firstNode && lastNode ? getOffset(orientation, 'end', lastNode) - getOffset(orientation, 'start', firstNode) : 0;\n }\n\n ngDoCheck() {\n if (this._differ && this._needsUpdate) {\n // TODO(mmalerba): We should differentiate needs update due to scrolling and a new portion of\n // this list being rendered (can use simpler algorithm) vs needs update due to data actually\n // changing (need to do this diff).\n const changes = this._differ.diff(this._renderedItems);\n\n if (!changes) {\n this._updateContext();\n } else {\n this._applyChanges(changes);\n }\n\n this._needsUpdate = false;\n }\n }\n\n ngOnDestroy() {\n this._viewport.detach();\n\n this._dataSourceChanges.next(undefined);\n\n this._dataSourceChanges.complete();\n\n this.viewChange.complete();\n\n this._destroyed.next();\n\n this._destroyed.complete();\n\n this._viewRepeater.detach();\n }\n /** React to scroll state changes in the viewport. */\n\n\n _onRenderedDataChange() {\n if (!this._renderedRange) {\n return;\n }\n\n this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end);\n\n if (!this._differ) {\n // Use a wrapper function for the `trackBy` so any new values are\n // picked up automatically without having to recreate the differ.\n this._differ = this._differs.find(this._renderedItems).create((index, item) => {\n return this.cdkVirtualForTrackBy ? this.cdkVirtualForTrackBy(index, item) : item;\n });\n }\n\n this._needsUpdate = true;\n }\n /** Swap out one `DataSource` for another. */\n\n\n _changeDataSource(oldDs, newDs) {\n if (oldDs) {\n oldDs.disconnect(this);\n }\n\n this._needsUpdate = true;\n return newDs ? newDs.connect(this) : of();\n }\n /** Update the `CdkVirtualForOfContext` for all views. */\n\n\n _updateContext() {\n const count = this._data.length;\n let i = this._viewContainerRef.length;\n\n while (i--) {\n const view = this._viewContainerRef.get(i);\n\n view.context.index = this._renderedRange.start + i;\n view.context.count = count;\n\n this._updateComputedContextProperties(view.context);\n\n view.detectChanges();\n }\n }\n /** Apply changes to the DOM. */\n\n\n _applyChanges(changes) {\n this._viewRepeater.applyChanges(changes, this._viewContainerRef, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record, currentIndex), record => record.item); // Update $implicit for any items that had an identity change.\n\n\n changes.forEachIdentityChange(record => {\n const view = this._viewContainerRef.get(record.currentIndex);\n\n view.context.$implicit = record.item;\n }); // Update the context variables on all items.\n\n const count = this._data.length;\n let i = this._viewContainerRef.length;\n\n while (i--) {\n const view = this._viewContainerRef.get(i);\n\n view.context.index = this._renderedRange.start + i;\n view.context.count = count;\n\n this._updateComputedContextProperties(view.context);\n }\n }\n /** Update the computed properties on the `CdkVirtualForOfContext`. */\n\n\n _updateComputedContextProperties(context) {\n context.first = context.index === 0;\n context.last = context.index === context.count - 1;\n context.even = context.index % 2 === 0;\n context.odd = !context.even;\n }\n\n _getEmbeddedViewArgs(record, index) {\n // Note that it's important that we insert the item directly at the proper index,\n // rather than inserting it and the moving it in place, because if there's a directive\n // on the same node that injects the `ViewContainerRef`, Angular will insert another\n // comment node which can throw off the move when it's being repeated for all items.\n return {\n templateRef: this._template,\n context: {\n $implicit: record.item,\n // It's guaranteed that the iterable is not \"undefined\" or \"null\" because we only\n // generate views for elements if the \"cdkVirtualForOf\" iterable has elements.\n cdkVirtualForOf: this._cdkVirtualForOf,\n index: -1,\n count: -1,\n first: false,\n last: false,\n odd: false,\n even: false\n },\n index\n };\n }\n\n }\n\n CdkVirtualForOf.ɵfac = function CdkVirtualForOf_Factory(t) {\n return new (t || CdkVirtualForOf)(i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(i0.IterableDiffers), i0.ɵɵdirectiveInject(_VIEW_REPEATER_STRATEGY), i0.ɵɵdirectiveInject(CdkVirtualScrollViewport, 4), i0.ɵɵdirectiveInject(i0.NgZone));\n };\n\n CdkVirtualForOf.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: CdkVirtualForOf,\n selectors: [[\"\", \"cdkVirtualFor\", \"\", \"cdkVirtualForOf\", \"\"]],\n inputs: {\n cdkVirtualForOf: \"cdkVirtualForOf\",\n cdkVirtualForTrackBy: \"cdkVirtualForTrackBy\",\n cdkVirtualForTemplate: \"cdkVirtualForTemplate\",\n cdkVirtualForTemplateCacheSize: \"cdkVirtualForTemplateCacheSize\"\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: _VIEW_REPEATER_STRATEGY,\n useClass: _RecycleViewRepeaterStrategy\n }])]\n });\n return CdkVirtualForOf;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nlet CdkScrollableModule = /*#__PURE__*/(() => {\n class CdkScrollableModule {}\n\n CdkScrollableModule.ɵfac = function CdkScrollableModule_Factory(t) {\n return new (t || CdkScrollableModule)();\n };\n\n CdkScrollableModule.ɵmod = /* @__PURE__ */i0.ɵɵdefineNgModule({\n type: CdkScrollableModule\n });\n CdkScrollableModule.ɵinj = /* @__PURE__ */i0.ɵɵdefineInjector({});\n return CdkScrollableModule;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @docs-primary-export\n */\n\n\nlet ScrollingModule = /*#__PURE__*/(() => {\n class ScrollingModule {}\n\n ScrollingModule.ɵfac = function ScrollingModule_Factory(t) {\n return new (t || ScrollingModule)();\n };\n\n ScrollingModule.ɵmod = /* @__PURE__ */i0.ɵɵdefineNgModule({\n type: ScrollingModule\n });\n ScrollingModule.ɵinj = /* @__PURE__ */i0.ɵɵdefineInjector({\n imports: [[BidiModule, PlatformModule, CdkScrollableModule], BidiModule, CdkScrollableModule]\n });\n return ScrollingModule;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Generated bundle index. Do not edit.\n */\n\n\nexport { CdkFixedSizeVirtualScroll, CdkScrollable, CdkScrollableModule, CdkVirtualForOf, CdkVirtualScrollViewport, DEFAULT_RESIZE_TIME, DEFAULT_SCROLL_TIME, FixedSizeVirtualScrollStrategy, ScrollDispatcher, ScrollingModule, VIRTUAL_SCROLL_STRATEGY, ViewportRuler, _fixedSizeVirtualScrollStrategyFactory }; //# sourceMappingURL=scrolling.mjs.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0ce3ebb7d9da9e1e1f0f685a4a0eb25b.json b/.angular/cache/babel-webpack/0ce3ebb7d9da9e1e1f0f685a4a0eb25b.json
new file mode 100644
index 0000000..a3cc711
--- /dev/null
+++ b/.angular/cache/babel-webpack/0ce3ebb7d9da9e1e1f0f685a4a0eb25b.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { Version } from '@angular/core';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/** Current version of the Angular Component Development Kit. */\n\nconst VERSION = /*#__PURE__*/new Version('13.0.3');\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport { VERSION }; //# sourceMappingURL=cdk.mjs.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0dfc853ea4fcba85d32a05367c92de1b.json b/.angular/cache/babel-webpack/0dfc853ea4fcba85d32a05367c92de1b.json
new file mode 100644
index 0000000..74b08e5
--- /dev/null
+++ b/.angular/cache/babel-webpack/0dfc853ea4fcba85d32a05367c92de1b.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { identity } from './identity';\nexport function pipe(...fns) {\n return pipeFromArray(fns);\n}\nexport function pipeFromArray(fns) {\n if (fns.length === 0) {\n return identity;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input) {\n return fns.reduce((prev, fn) => fn(prev), input);\n };\n} //# sourceMappingURL=pipe.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/0f3a10fbbedc9ffb1b810169d831f48e.json b/.angular/cache/babel-webpack/0f3a10fbbedc9ffb1b810169d831f48e.json
new file mode 100644
index 0000000..0a0c37d
--- /dev/null
+++ b/.angular/cache/babel-webpack/0f3a10fbbedc9ffb1b810169d831f48e.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { createErrorClass } from './createErrorClass';\nexport const SequenceError = createErrorClass(_super => function SequenceErrorImpl(message) {\n _super(this);\n\n this.name = 'SequenceError';\n this.message = message;\n}); //# sourceMappingURL=SequenceError.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1091db21e752c4d2f54f01f22d5c4f87.json b/.angular/cache/babel-webpack/1091db21e752c4d2f54f01f22d5c4f87.json
new file mode 100644
index 0000000..3033843
--- /dev/null
+++ b/.angular/cache/babel-webpack/1091db21e752c4d2f54f01f22d5c4f87.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { arrRemove } from '../util/arrRemove';\nexport function bufferCount(bufferSize, startBufferEvery = null) {\n startBufferEvery = startBufferEvery !== null && startBufferEvery !== void 0 ? startBufferEvery : bufferSize;\n return operate((source, subscriber) => {\n let buffers = [];\n let count = 0;\n source.subscribe(new OperatorSubscriber(subscriber, value => {\n let toEmit = null;\n\n if (count++ % startBufferEvery === 0) {\n buffers.push([]);\n }\n\n for (const buffer of buffers) {\n buffer.push(value);\n\n if (bufferSize <= buffer.length) {\n toEmit = toEmit !== null && toEmit !== void 0 ? toEmit : [];\n toEmit.push(buffer);\n }\n }\n\n if (toEmit) {\n for (const buffer of toEmit) {\n arrRemove(buffers, buffer);\n subscriber.next(buffer);\n }\n }\n }, () => {\n for (const buffer of buffers) {\n subscriber.next(buffer);\n }\n\n subscriber.complete();\n }, undefined, () => {\n buffers = null;\n }));\n });\n} //# sourceMappingURL=bufferCount.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/10dce8f2467d4c1c0bd120460e261e39.json b/.angular/cache/babel-webpack/10dce8f2467d4c1c0bd120460e261e39.json
new file mode 100644
index 0000000..ef578b7
--- /dev/null
+++ b/.angular/cache/babel-webpack/10dce8f2467d4c1c0bd120460e261e39.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { EmptyError } from './util/EmptyError';\nexport function lastValueFrom(source, config) {\n const hasConfig = typeof config === 'object';\n return new Promise((resolve, reject) => {\n let _hasValue = false;\n\n let _value;\n\n source.subscribe({\n next: value => {\n _value = value;\n _hasValue = true;\n },\n error: reject,\n complete: () => {\n if (_hasValue) {\n resolve(_value);\n } else if (hasConfig) {\n resolve(config.defaultValue);\n } else {\n reject(new EmptyError());\n }\n }\n });\n });\n} //# sourceMappingURL=lastValueFrom.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1185a99f63a0b7fd413fa6b361f6b7b5.json b/.angular/cache/babel-webpack/1185a99f63a0b7fd413fa6b361f6b7b5.json
new file mode 100644
index 0000000..7853caa
--- /dev/null
+++ b/.angular/cache/babel-webpack/1185a99f63a0b7fd413fa6b361f6b7b5.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { concat } from '../observable/concat';\nimport { of } from '../observable/of';\nexport function endWith(...values) {\n return source => concat(source, of(...values));\n} //# sourceMappingURL=endWith.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/11e800cecdd2fcebb179bd288a038e21.json b/.angular/cache/babel-webpack/11e800cecdd2fcebb179bd288a038e21.json
new file mode 100644
index 0000000..0698e24
--- /dev/null
+++ b/.angular/cache/babel-webpack/11e800cecdd2fcebb179bd288a038e21.json
@@ -0,0 +1 @@
+{"ast":null,"code":"const {\n isArray\n} = Array;\nconst {\n getPrototypeOf,\n prototype: objectProto,\n keys: getKeys\n} = Object;\nexport function argsArgArrayOrObject(args) {\n if (args.length === 1) {\n const first = args[0];\n\n if (isArray(first)) {\n return {\n args: first,\n keys: null\n };\n }\n\n if (isPOJO(first)) {\n const keys = getKeys(first);\n return {\n args: keys.map(key => first[key]),\n keys\n };\n }\n }\n\n return {\n args: args,\n keys: null\n };\n}\n\nfunction isPOJO(obj) {\n return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n} //# sourceMappingURL=argsArgArrayOrObject.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/12599f24dcc01ddf8b28fce405f8c884.json b/.angular/cache/babel-webpack/12599f24dcc01ddf8b28fce405f8c884.json
new file mode 100644
index 0000000..2928d10
--- /dev/null
+++ b/.angular/cache/babel-webpack/12599f24dcc01ddf8b28fce405f8c884.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function debounceTime(dueTime, scheduler = asyncScheduler) {\n return operate((source, subscriber) => {\n let activeTask = null;\n let lastValue = null;\n let lastTime = null;\n\n const emit = () => {\n if (activeTask) {\n activeTask.unsubscribe();\n activeTask = null;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n\n function emitWhenIdle() {\n const targetTime = lastTime + dueTime;\n const now = scheduler.now();\n\n if (now < targetTime) {\n activeTask = this.schedule(undefined, targetTime - now);\n subscriber.add(activeTask);\n return;\n }\n\n emit();\n }\n\n source.subscribe(new OperatorSubscriber(subscriber, value => {\n lastValue = value;\n lastTime = scheduler.now();\n\n if (!activeTask) {\n activeTask = scheduler.schedule(emitWhenIdle, dueTime);\n subscriber.add(activeTask);\n }\n }, () => {\n emit();\n subscriber.complete();\n }, undefined, () => {\n lastValue = activeTask = null;\n }));\n });\n} //# sourceMappingURL=debounceTime.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/12a4d432fd6eae5147cbb073c8edc6e1.json b/.angular/cache/babel-webpack/12a4d432fd6eae5147cbb073c8edc6e1.json
new file mode 100644
index 0000000..cf79843
--- /dev/null
+++ b/.angular/cache/babel-webpack/12a4d432fd6eae5147cbb073c8edc6e1.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function sequenceEqual(compareTo, comparator = (a, b) => a === b) {\n return operate((source, subscriber) => {\n const aState = createState();\n const bState = createState();\n\n const emit = isEqual => {\n subscriber.next(isEqual);\n subscriber.complete();\n };\n\n const createSubscriber = (selfState, otherState) => {\n const sequenceEqualSubscriber = new OperatorSubscriber(subscriber, a => {\n const {\n buffer,\n complete\n } = otherState;\n\n if (buffer.length === 0) {\n complete ? emit(false) : selfState.buffer.push(a);\n } else {\n !comparator(a, buffer.shift()) && emit(false);\n }\n }, () => {\n selfState.complete = true;\n const {\n complete,\n buffer\n } = otherState;\n complete && emit(buffer.length === 0);\n sequenceEqualSubscriber === null || sequenceEqualSubscriber === void 0 ? void 0 : sequenceEqualSubscriber.unsubscribe();\n });\n return sequenceEqualSubscriber;\n };\n\n source.subscribe(createSubscriber(aState, bState));\n compareTo.subscribe(createSubscriber(bState, aState));\n });\n}\n\nfunction createState() {\n return {\n buffer: [],\n complete: false\n };\n} //# sourceMappingURL=sequenceEqual.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/12efd2ada375266e320ccf243973d851.json b/.angular/cache/babel-webpack/12efd2ada375266e320ccf243973d851.json
new file mode 100644
index 0000000..f20a34b
--- /dev/null
+++ b/.angular/cache/babel-webpack/12efd2ada375266e320ccf243973d851.json
@@ -0,0 +1 @@
+{"ast":null,"code":"export const intervalProvider = {\n setInterval(...args) {\n const {\n delegate\n } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) || setInterval)(...args);\n },\n\n clearInterval(handle) {\n const {\n delegate\n } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);\n },\n\n delegate: undefined\n}; //# sourceMappingURL=intervalProvider.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/149ffc33a76d11fb77fe2c5b21d4c358.json b/.angular/cache/babel-webpack/149ffc33a76d11fb77fe2c5b21d4c358.json
new file mode 100644
index 0000000..acc499c
--- /dev/null
+++ b/.angular/cache/babel-webpack/149ffc33a76d11fb77fe2c5b21d4c358.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { sample } from './sample';\nimport { interval } from '../observable/interval';\nexport function sampleTime(period, scheduler = asyncScheduler) {\n return sample(interval(period, scheduler));\n} //# sourceMappingURL=sampleTime.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/153ade4180fc695060020bc9321c6372.json b/.angular/cache/babel-webpack/153ade4180fc695060020bc9321c6372.json
new file mode 100644
index 0000000..6688796
--- /dev/null
+++ b/.angular/cache/babel-webpack/153ade4180fc695060020bc9321c6372.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { argsOrArgArray } from '../util/argsOrArgArray';\nimport { raceWith } from './raceWith';\nexport function race(...args) {\n return raceWith(...argsOrArgArray(args));\n} //# sourceMappingURL=race.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/157c46a8ddd7157b605d9eb355cb3277.json b/.angular/cache/babel-webpack/157c46a8ddd7157b605d9eb355cb3277.json
new file mode 100644
index 0000000..2e2484f
--- /dev/null
+++ b/.angular/cache/babel-webpack/157c46a8ddd7157b605d9eb355cb3277.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { innerFrom } from '../observable/innerFrom';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function switchMap(project, resultSelector) {\n return operate((source, subscriber) => {\n let innerSubscriber = null;\n let index = 0;\n let isComplete = false;\n\n const checkComplete = () => isComplete && !innerSubscriber && subscriber.complete();\n\n source.subscribe(new OperatorSubscriber(subscriber, value => {\n innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();\n let innerIndex = 0;\n const outerIndex = index++;\n innerFrom(project(value, outerIndex)).subscribe(innerSubscriber = new OperatorSubscriber(subscriber, innerValue => subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue), () => {\n innerSubscriber = null;\n checkComplete();\n }));\n }, () => {\n isComplete = true;\n checkComplete();\n }));\n });\n} //# sourceMappingURL=switchMap.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/15dcf5202cc3a22011ac7162fda15a5c.json b/.angular/cache/babel-webpack/15dcf5202cc3a22011ac7162fda15a5c.json
new file mode 100644
index 0000000..a31bb6f
--- /dev/null
+++ b/.angular/cache/babel-webpack/15dcf5202cc3a22011ac7162fda15a5c.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import '@pwabuilder/pwainstall';\nimport { animate, state, style, transition, trigger } from '@angular/animations';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"./bowl.service\";\nimport * as i2 from \"@angular/service-worker\";\nimport * as i3 from \"@angular/material/snack-bar\";\nimport * as i4 from \"@angular/material/toolbar\";\nimport * as i5 from \"@angular/common\";\nimport * as i6 from \"@angular/material/progress-spinner\";\nimport * as i7 from \"@angular/material/form-field\";\nimport * as i8 from \"@angular/material/select\";\nimport * as i9 from \"@angular/material/core\";\nimport * as i10 from \"@angular/material/table\";\nimport * as i11 from \"@angular/material/icon\";\n\nfunction AppComponent_div_6_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"div\", 7);\n i0.ɵɵelementStart(1, \"h4\", 8);\n i0.ɵɵtext(2, \"Loading Scoreboard\");\n i0.ɵɵelementEnd();\n i0.ɵɵelement(3, \"mat-spinner\", 9);\n i0.ɵɵelementEnd();\n }\n}\n\nfunction AppComponent_mat_form_field_7_mat_option_4_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"mat-option\", 13);\n i0.ɵɵtext(1);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const userPick_r4 = ctx.$implicit;\n i0.ɵɵproperty(\"value\", userPick_r4);\n i0.ɵɵadvance(1);\n i0.ɵɵtextInterpolate1(\" \", userPick_r4.name, \" \");\n }\n}\n\nfunction AppComponent_mat_form_field_7_Template(rf, ctx) {\n if (rf & 1) {\n const _r6 = i0.ɵɵgetCurrentView();\n\n i0.ɵɵelementStart(0, \"mat-form-field\", 10);\n i0.ɵɵelementStart(1, \"mat-label\");\n i0.ɵɵtext(2, \"See Differences Between\");\n i0.ɵɵelementEnd();\n i0.ɵɵelementStart(3, \"mat-select\", 11);\n i0.ɵɵlistener(\"selectionChange\", function AppComponent_mat_form_field_7_Template_mat_select_selectionChange_3_listener($event) {\n i0.ɵɵrestoreView(_r6);\n const ctx_r5 = i0.ɵɵnextContext();\n return ctx_r5.selectUser($event.value);\n });\n i0.ɵɵtemplate(4, AppComponent_mat_form_field_7_mat_option_4_Template, 2, 2, \"mat-option\", 12);\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const ctx_r1 = i0.ɵɵnextContext();\n i0.ɵɵadvance(4);\n i0.ɵɵproperty(\"ngForOf\", ctx_r1.userPicks);\n }\n}\n\nfunction AppComponent_table_8_ng_container_1_th_1_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"th\", 23);\n i0.ɵɵtext(1);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const column_r12 = i0.ɵɵnextContext().$implicit;\n i0.ɵɵadvance(1);\n i0.ɵɵtextInterpolate1(\" \", column_r12, \" \");\n }\n}\n\nfunction AppComponent_table_8_ng_container_1_td_2_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"td\", 24);\n i0.ɵɵtext(1);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const element_r16 = ctx.$implicit;\n const column_r12 = i0.ɵɵnextContext().$implicit;\n i0.ɵɵadvance(1);\n i0.ɵɵtextInterpolate1(\" \", element_r16[column_r12], \" \");\n }\n}\n\nfunction AppComponent_table_8_ng_container_1_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementContainerStart(0, 21);\n i0.ɵɵtemplate(1, AppComponent_table_8_ng_container_1_th_1_Template, 2, 1, \"th\", 22);\n i0.ɵɵtemplate(2, AppComponent_table_8_ng_container_1_td_2_Template, 2, 1, \"td\", 17);\n i0.ɵɵelementContainerEnd();\n }\n\n if (rf & 2) {\n const column_r12 = ctx.$implicit;\n i0.ɵɵpropertyInterpolate(\"matColumnDef\", column_r12);\n }\n}\n\nfunction AppComponent_table_8_td_3_div_3_mat_icon_4_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"mat-icon\", 31);\n i0.ɵɵtext(1, \"check\");\n i0.ɵɵelementEnd();\n }\n}\n\nfunction AppComponent_table_8_td_3_div_3_mat_icon_5_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"mat-icon\", 32);\n i0.ɵɵtext(1, \"close\");\n i0.ɵɵelementEnd();\n }\n}\n\nfunction AppComponent_table_8_td_3_div_3_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"div\");\n i0.ɵɵelementStart(1, \"div\", 28);\n i0.ɵɵelementStart(2, \"h6\", 2);\n i0.ɵɵtext(3);\n i0.ɵɵelementEnd();\n i0.ɵɵtemplate(4, AppComponent_table_8_td_3_div_3_mat_icon_4_Template, 2, 0, \"mat-icon\", 29);\n i0.ɵɵtemplate(5, AppComponent_table_8_td_3_div_3_mat_icon_5_Template, 2, 0, \"mat-icon\", 30);\n i0.ɵɵelementEnd();\n i0.ɵɵelementStart(6, \"p\");\n i0.ɵɵtext(7);\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const pick_r20 = ctx.$implicit;\n i0.ɵɵadvance(3);\n i0.ɵɵtextInterpolate1(\" \", pick_r20.bowl, \" \");\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngIf\", pick_r20.win);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngIf\", pick_r20.loss);\n i0.ɵɵadvance(2);\n i0.ɵɵtextInterpolate(pick_r20.pick);\n }\n}\n\nfunction AppComponent_table_8_td_3_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"td\", 24);\n i0.ɵɵelementStart(1, \"div\", 25);\n i0.ɵɵelementStart(2, \"div\", 26);\n i0.ɵɵtemplate(3, AppComponent_table_8_td_3_div_3_Template, 8, 4, \"div\", 27);\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const element_r18 = ctx.$implicit;\n const ctx_r8 = i0.ɵɵnextContext(2);\n i0.ɵɵattribute(\"colspan\", ctx_r8.columnsToDisplay.length);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"@detailExpand\", element_r18 == ctx_r8.expandedElement ? \"expanded\" : \"collapsed\");\n i0.ɵɵadvance(2);\n i0.ɵɵproperty(\"ngForOf\", element_r18.picks);\n }\n}\n\nfunction AppComponent_table_8_tr_4_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelement(0, \"tr\", 33);\n }\n}\n\nfunction AppComponent_table_8_tr_5_Template(rf, ctx) {\n if (rf & 1) {\n const _r25 = i0.ɵɵgetCurrentView();\n\n i0.ɵɵelementStart(0, \"tr\", 34);\n i0.ɵɵlistener(\"click\", function AppComponent_table_8_tr_5_Template_tr_click_0_listener() {\n const restoredCtx = i0.ɵɵrestoreView(_r25);\n const element_r23 = restoredCtx.$implicit;\n const ctx_r24 = i0.ɵɵnextContext(2);\n return ctx_r24.expandedElement = ctx_r24.expandedElement === element_r23 ? null : element_r23;\n });\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const element_r23 = ctx.$implicit;\n const ctx_r10 = i0.ɵɵnextContext(2);\n i0.ɵɵclassProp(\"example-expanded-row\", ctx_r10.expandedElement === element_r23);\n }\n}\n\nfunction AppComponent_table_8_tr_6_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelement(0, \"tr\", 35);\n }\n}\n\nconst _c0 = function () {\n return [\"expandedDetail\"];\n};\n\nfunction AppComponent_table_8_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"table\", 14);\n i0.ɵɵtemplate(1, AppComponent_table_8_ng_container_1_Template, 3, 1, \"ng-container\", 15);\n i0.ɵɵelementContainerStart(2, 16);\n i0.ɵɵtemplate(3, AppComponent_table_8_td_3_Template, 4, 3, \"td\", 17);\n i0.ɵɵelementContainerEnd();\n i0.ɵɵtemplate(4, AppComponent_table_8_tr_4_Template, 1, 0, \"tr\", 18);\n i0.ɵɵtemplate(5, AppComponent_table_8_tr_5_Template, 1, 2, \"tr\", 19);\n i0.ɵɵtemplate(6, AppComponent_table_8_tr_6_Template, 1, 0, \"tr\", 20);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const ctx_r2 = i0.ɵɵnextContext();\n i0.ɵɵproperty(\"dataSource\", ctx_r2.userPicks);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngForOf\", ctx_r2.columnsToDisplay);\n i0.ɵɵadvance(3);\n i0.ɵɵproperty(\"matHeaderRowDef\", ctx_r2.columnsToDisplay);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"matRowDefColumns\", ctx_r2.columnsToDisplay);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"matRowDefColumns\", i0.ɵɵpureFunction0(5, _c0));\n }\n}\n\nexport let AppComponent = /*#__PURE__*/(() => {\n class AppComponent {\n constructor(bowlService, swUpdate, snackBar) {\n this.bowlService = bowlService;\n this.swUpdate = swUpdate;\n this.snackBar = snackBar;\n this.loading = false;\n this.columnsToDisplay = ['name', 'wins', 'losses', 'differences'];\n }\n\n visibilityChange() {\n if (!document.hidden) {\n this.loadPicks();\n }\n }\n\n ngOnInit() {\n this.loadPicks();\n this.swUpdate.versionUpdates.subscribe(event => {\n console.log('[App] Update available');\n const snackBarRef = this.snackBar.open('Newer version of the app is available', 'Refresh');\n snackBarRef.onAction().subscribe(() => {\n location.reload();\n });\n });\n }\n\n loadPicks() {\n this.loading = true;\n this.bowlService.getPicks().subscribe(picks => {\n this.loading = false;\n this.userPicks = picks.sort((pick1, pick2) => {\n return pick1.wins > pick2.wins ? -1 : 1;\n });\n });\n }\n\n selectUser(selectedUserPicks) {\n this.selectedUserPicks = selectedUserPicks;\n this.userPicks.forEach(up => {\n up.differences = 0;\n up.picks.forEach(p => {\n const selectedUserPick = selectedUserPicks.picks.find(suPicks => suPicks.bowl === p.bowl).pick;\n const isSameUser = selectedUserPicks.name === up.name;\n const undecidedGame = !p.win && !p.loss;\n const isNotTiebreaker = !p.bowl.includes('Tiebreaker');\n\n if (p.pick !== selectedUserPick && !isSameUser && undecidedGame && isNotTiebreaker) {\n up.differences++;\n }\n });\n });\n }\n\n }\n\n AppComponent.ɵfac = function AppComponent_Factory(t) {\n return new (t || AppComponent)(i0.ɵɵdirectiveInject(i1.BowlService), i0.ɵɵdirectiveInject(i2.SwUpdate), i0.ɵɵdirectiveInject(i3.MatSnackBar));\n };\n\n AppComponent.ɵcmp = /*@__PURE__*/i0.ɵɵdefineComponent({\n type: AppComponent,\n selectors: [[\"app-root\"]],\n hostBindings: function AppComponent_HostBindings(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵlistener(\"visibilitychange\", function AppComponent_visibilitychange_HostBindingHandler() {\n return ctx.visibilityChange();\n }, false, i0.ɵɵresolveDocument);\n }\n },\n decls: 9,\n vars: 3,\n consts: [[\"color\", \"primary\"], [1, \"d-flex\", \"align-items-center\", \"justify-content-between\", \"w-100\"], [1, \"mb-0\"], [\"manifestpath\", \"manifest.webmanifest\"], [\"class\", \"d-flex align-items-center justify-content-center w-100 mt-4\", 4, \"ngIf\"], [\"class\", \"w-100 p-2\", 4, \"ngIf\"], [\"mat-table\", \"\", \"multiTemplateDataRows\", \"\", \"class\", \"mat-elevation-z8\", 3, \"dataSource\", 4, \"ngIf\"], [1, \"d-flex\", \"align-items-center\", \"justify-content-center\", \"w-100\", \"mt-4\"], [1, \"mb-0\", \"mr-3\"], [\"diameter\", \"30\"], [1, \"w-100\", \"p-2\"], [3, \"selectionChange\"], [3, \"value\", 4, \"ngFor\", \"ngForOf\"], [3, \"value\"], [\"mat-table\", \"\", \"multiTemplateDataRows\", \"\", 1, \"mat-elevation-z8\", 3, \"dataSource\"], [3, \"matColumnDef\", 4, \"ngFor\", \"ngForOf\"], [\"matColumnDef\", \"expandedDetail\"], [\"mat-cell\", \"\", 4, \"matCellDef\"], [\"mat-header-row\", \"\", 4, \"matHeaderRowDef\"], [\"mat-row\", \"\", \"class\", \"example-element-row\", 3, \"example-expanded-row\", \"click\", 4, \"matRowDef\", \"matRowDefColumns\"], [\"mat-row\", \"\", \"class\", \"example-detail-row\", 4, \"matRowDef\", \"matRowDefColumns\"], [3, \"matColumnDef\"], [\"mat-header-cell\", \"\", 4, \"matHeaderCellDef\"], [\"mat-header-cell\", \"\"], [\"mat-cell\", \"\"], [1, \"example-element-detail\"], [1, \"example-element-description\"], [4, \"ngFor\", \"ngForOf\"], [1, \"d-flex\", \"align-items-center\", \"justify-content-start\"], [\"class\", \"text-success\", 4, \"ngIf\"], [\"class\", \"text-danger\", 4, \"ngIf\"], [1, \"text-success\"], [1, \"text-danger\"], [\"mat-header-row\", \"\"], [\"mat-row\", \"\", 1, \"example-element-row\", 3, \"click\"], [\"mat-row\", \"\", 1, \"example-detail-row\"]],\n template: function AppComponent_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"mat-toolbar\", 0);\n i0.ɵɵelementStart(1, \"div\", 1);\n i0.ɵɵelementStart(2, \"p\", 2);\n i0.ɵɵtext(3, \"Livingston Bowl\");\n i0.ɵɵelementEnd();\n i0.ɵɵelementStart(4, \"div\");\n i0.ɵɵelement(5, \"pwa-install\", 3);\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n i0.ɵɵelementEnd();\n i0.ɵɵtemplate(6, AppComponent_div_6_Template, 4, 0, \"div\", 4);\n i0.ɵɵtemplate(7, AppComponent_mat_form_field_7_Template, 5, 1, \"mat-form-field\", 5);\n i0.ɵɵtemplate(8, AppComponent_table_8_Template, 7, 6, \"table\", 6);\n }\n\n if (rf & 2) {\n i0.ɵɵadvance(6);\n i0.ɵɵproperty(\"ngIf\", ctx.loading);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngIf\", !ctx.loading);\n i0.ɵɵadvance(1);\n i0.ɵɵproperty(\"ngIf\", !ctx.loading);\n }\n },\n directives: [i4.MatToolbar, i5.NgIf, i6.MatSpinner, i7.MatFormField, i7.MatLabel, i8.MatSelect, i5.NgForOf, i9.MatOption, i10.MatTable, i10.MatColumnDef, i10.MatCellDef, i10.MatHeaderRowDef, i10.MatRowDef, i10.MatHeaderCellDef, i10.MatHeaderCell, i10.MatCell, i11.MatIcon, i10.MatHeaderRow, i10.MatRow],\n styles: [\"table[_ngcontent-%COMP%]{width:100%}tr.example-detail-row[_ngcontent-%COMP%]{height:0}tr.example-element-row[_ngcontent-%COMP%]:not(.example-expanded-row):hover{background:#777}tr.example-element-row[_ngcontent-%COMP%]:not(.example-expanded-row):active{background:#efefef}.example-element-row[_ngcontent-%COMP%] td[_ngcontent-%COMP%]{border-bottom-width:0}.example-element-detail[_ngcontent-%COMP%]{overflow:hidden;display:flex}.example-element-diagram[_ngcontent-%COMP%]{min-width:80px;border:2px solid black;padding:8px;font-weight:lighter;margin:8px 0;height:104px}.example-element-symbol[_ngcontent-%COMP%]{font-weight:bold;font-size:40px;line-height:normal}.example-element-description[_ngcontent-%COMP%]{padding:16px}.example-element-description-attribution[_ngcontent-%COMP%]{opacity:.5}\"],\n data: {\n animation: [trigger('detailExpand', [state('collapsed', style({\n height: '0px',\n minHeight: '0'\n })), state('expanded', style({\n height: '*'\n })), transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))])]\n }\n });\n return AppComponent;\n})();","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1615b40c1be8327ff87131e87400bbb6.json b/.angular/cache/babel-webpack/1615b40c1be8327ff87131e87400bbb6.json
new file mode 100644
index 0000000..97eb77a
--- /dev/null
+++ b/.angular/cache/babel-webpack/1615b40c1be8327ff87131e87400bbb6.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { switchMap } from './switchMap';\nimport { identity } from '../util/identity';\nexport function switchAll() {\n return switchMap(identity);\n} //# sourceMappingURL=switchAll.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/17beeae6034248df3b9cac6df76099be.json b/.angular/cache/babel-webpack/17beeae6034248df3b9cac6df76099be.json
new file mode 100644
index 0000000..909ec4d
--- /dev/null
+++ b/.angular/cache/babel-webpack/17beeae6034248df3b9cac6df76099be.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { exhaustAll } from './exhaustAll';\nexport const exhaust = exhaustAll; //# sourceMappingURL=exhaust.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/183de50554f4a1ac06243efc6b2ed875.json b/.angular/cache/babel-webpack/183de50554f4a1ac06243efc6b2ed875.json
new file mode 100644
index 0000000..e18961a
--- /dev/null
+++ b/.angular/cache/babel-webpack/183de50554f4a1ac06243efc6b2ed875.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { operate } from '../util/lift';\nexport function subscribeOn(scheduler, delay = 0) {\n return operate((source, subscriber) => {\n subscriber.add(scheduler.schedule(() => source.subscribe(subscriber), delay));\n });\n} //# sourceMappingURL=subscribeOn.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/19cfadb2ca4da2ee4e869fb4b2af0aa1.json b/.angular/cache/babel-webpack/19cfadb2ca4da2ee4e869fb4b2af0aa1.json
new file mode 100644
index 0000000..1c497e9
--- /dev/null
+++ b/.angular/cache/babel-webpack/19cfadb2ca4da2ee4e869fb4b2af0aa1.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { isFunction } from './util/isFunction';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\nexport class Subscriber extends Subscription {\n constructor(destination) {\n super();\n this.isStopped = false;\n\n if (destination) {\n this.destination = destination;\n\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n static create(next, error, complete) {\n return new SafeSubscriber(next, error, complete);\n }\n\n next(value) {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value);\n }\n }\n\n error(err) {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n\n this._error(err);\n }\n }\n\n complete() {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n\n this._complete();\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null;\n }\n }\n\n _next(value) {\n this.destination.next(value);\n }\n\n _error(err) {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n _complete() {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n\n}\nexport class SafeSubscriber extends Subscriber {\n constructor(observerOrNext, error, complete) {\n super();\n let next;\n\n if (isFunction(observerOrNext)) {\n next = observerOrNext;\n } else if (observerOrNext) {\n ({\n next,\n error,\n complete\n } = observerOrNext);\n let context;\n\n if (this && config.useDeprecatedNextContext) {\n context = Object.create(observerOrNext);\n\n context.unsubscribe = () => this.unsubscribe();\n } else {\n context = observerOrNext;\n }\n\n next = next === null || next === void 0 ? void 0 : next.bind(context);\n error = error === null || error === void 0 ? void 0 : error.bind(context);\n complete = complete === null || complete === void 0 ? void 0 : complete.bind(context);\n }\n\n this.destination = {\n next: next ? wrapForErrorHandling(next, this) : noop,\n error: wrapForErrorHandling(error !== null && error !== void 0 ? error : defaultErrorHandler, this),\n complete: complete ? wrapForErrorHandling(complete, this) : noop\n };\n }\n\n}\n\nfunction wrapForErrorHandling(handler, instance) {\n return (...args) => {\n try {\n handler(...args);\n } catch (err) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(err);\n } else {\n reportUnhandledError(err);\n }\n }\n };\n}\n\nfunction defaultErrorHandler(err) {\n throw err;\n}\n\nfunction handleStoppedNotification(notification, subscriber) {\n const {\n onStoppedNotification\n } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\nexport const EMPTY_OBSERVER = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop\n}; //# sourceMappingURL=Subscriber.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1a3b80c3f6f6f2147cc7f073ef1a3aef.json b/.angular/cache/babel-webpack/1a3b80c3f6f6f2147cc7f073ef1a3aef.json
new file mode 100644
index 0000000..04fc5c0
--- /dev/null
+++ b/.angular/cache/babel-webpack/1a3b80c3f6f6f2147cc7f073ef1a3aef.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { __decorate } from \"tslib\";\nimport { BrowserModule } from '@angular/platform-browser';\nimport { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';\nimport { AppComponent } from './app.component';\nimport { ServiceWorkerModule } from '@angular/service-worker';\nimport { environment } from '../environments/environment';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\nimport { HttpClientModule } from '@angular/common/http';\nlet AppModule = class AppModule {};\nAppModule = __decorate([NgModule({\n declarations: [AppComponent],\n imports: [HttpClientModule, MatIconModule, MatSnackBarModule, MatButtonModule, MatSelectModule, MatProgressSpinnerModule, MatIconModule, MatTableModule, MatToolbarModule, BrowserModule, ServiceWorkerModule.register('ngsw-worker.js', {\n enabled: environment.production\n }), BrowserAnimationsModule],\n providers: [],\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n bootstrap: [AppComponent]\n})], AppModule);\nexport { AppModule };","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1a509858e7d0fdf59df635b46b7ac28e.json b/.angular/cache/babel-webpack/1a509858e7d0fdf59df635b46b7ac28e.json
new file mode 100644
index 0000000..30fedcd
--- /dev/null
+++ b/.angular/cache/babel-webpack/1a509858e7d0fdf59df635b46b7ac28e.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { Scheduler } from '../Scheduler';\nexport class AsyncScheduler extends Scheduler {\n constructor(SchedulerAction, now = Scheduler.now) {\n super(SchedulerAction, now);\n this.actions = [];\n this._active = false;\n this._scheduled = undefined;\n }\n\n flush(action) {\n const {\n actions\n } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error;\n this._active = true;\n\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (action = actions.shift());\n\n this._active = false;\n\n if (error) {\n while (action = actions.shift()) {\n action.unsubscribe();\n }\n\n throw error;\n }\n }\n\n} //# sourceMappingURL=AsyncScheduler.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1c08ded61f8a4ad6e5f8adc1faf24ee4.json b/.angular/cache/babel-webpack/1c08ded61f8a4ad6e5f8adc1faf24ee4.json
new file mode 100644
index 0000000..d761c7c
--- /dev/null
+++ b/.angular/cache/babel-webpack/1c08ded61f8a4ad6e5f8adc1faf24ee4.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import * as i0 from '@angular/core';\nimport { Directive, Component, ViewEncapsulation, ChangeDetectionStrategy, Input, NgModule } from '@angular/core';\nimport * as i1 from '@angular/cdk/table';\nimport { CdkTable, CDK_TABLE, _COALESCED_STYLE_SCHEDULER, _CoalescedStyleScheduler, STICKY_POSITIONING_LISTENER, CDK_TABLE_TEMPLATE, CdkCellDef, CdkHeaderCellDef, CdkFooterCellDef, CdkColumnDef, CdkHeaderCell, CdkFooterCell, CdkCell, CdkHeaderRowDef, CdkFooterRowDef, CdkRowDef, CdkHeaderRow, CDK_ROW_TEMPLATE, CdkFooterRow, CdkRow, CdkNoDataRow, CdkTextColumn, CdkTableModule, DataSource } from '@angular/cdk/table';\nimport { _VIEW_REPEATER_STRATEGY, _RecycleViewRepeaterStrategy, _DisposeViewRepeaterStrategy } from '@angular/cdk/collections';\nimport { MatCommonModule } from '@angular/material/core';\nimport { _isNumberValue } from '@angular/cdk/coercion';\nimport { BehaviorSubject, Subject, merge, of, combineLatest } from 'rxjs';\nimport { map } from 'rxjs/operators';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with\n * tables that animate rows.\n */\n\nconst _c0 = [[[\"caption\"]], [[\"colgroup\"], [\"col\"]]];\nconst _c1 = [\"caption\", \"colgroup, col\"];\n\nfunction MatTextColumn_th_1_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"th\", 3);\n i0.ɵɵtext(1);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const ctx_r0 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"text-align\", ctx_r0.justify);\n i0.ɵɵadvance(1);\n i0.ɵɵtextInterpolate1(\" \", ctx_r0.headerText, \" \");\n }\n}\n\nfunction MatTextColumn_td_2_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementStart(0, \"td\", 4);\n i0.ɵɵtext(1);\n i0.ɵɵelementEnd();\n }\n\n if (rf & 2) {\n const data_r2 = ctx.$implicit;\n const ctx_r1 = i0.ɵɵnextContext();\n i0.ɵɵstyleProp(\"text-align\", ctx_r1.justify);\n i0.ɵɵadvance(1);\n i0.ɵɵtextInterpolate1(\" \", ctx_r1.dataAccessor(data_r2, ctx_r1.name), \" \");\n }\n}\n\nlet MatRecycleRows = /*#__PURE__*/(() => {\n class MatRecycleRows {}\n\n MatRecycleRows.ɵfac = function MatRecycleRows_Factory(t) {\n return new (t || MatRecycleRows)();\n };\n\n MatRecycleRows.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatRecycleRows,\n selectors: [[\"mat-table\", \"recycleRows\", \"\"], [\"table\", \"mat-table\", \"\", \"recycleRows\", \"\"]],\n features: [i0.ɵɵProvidersFeature([{\n provide: _VIEW_REPEATER_STRATEGY,\n useClass: _RecycleViewRepeaterStrategy\n }])]\n });\n return MatRecycleRows;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Wrapper for the CdkTable with Material design styles.\n */\n\n\nlet MatTable = /*#__PURE__*/(() => {\n class MatTable extends CdkTable {\n constructor() {\n super(...arguments);\n /** Overrides the sticky CSS class set by the `CdkTable`. */\n\n this.stickyCssClass = 'mat-table-sticky';\n /** Overrides the need to add position: sticky on every sticky cell element in `CdkTable`. */\n\n this.needsPositionStickyOnElement = false;\n }\n\n }\n\n MatTable.ɵfac = /* @__PURE__ */function () {\n let ɵMatTable_BaseFactory;\n return function MatTable_Factory(t) {\n return (ɵMatTable_BaseFactory || (ɵMatTable_BaseFactory = i0.ɵɵgetInheritedFactory(MatTable)))(t || MatTable);\n };\n }();\n\n MatTable.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatTable,\n selectors: [[\"mat-table\"], [\"table\", \"mat-table\", \"\"]],\n hostAttrs: [1, \"mat-table\"],\n hostVars: 2,\n hostBindings: function MatTable_HostBindings(rf, ctx) {\n if (rf & 2) {\n i0.ɵɵclassProp(\"mat-table-fixed-layout\", ctx.fixedLayout);\n }\n },\n exportAs: [\"matTable\"],\n features: [i0.ɵɵProvidersFeature([// TODO(michaeljamesparsons) Abstract the view repeater strategy to a directive API so this code\n // is only included in the build if used.\n {\n provide: _VIEW_REPEATER_STRATEGY,\n useClass: _DisposeViewRepeaterStrategy\n }, {\n provide: CdkTable,\n useExisting: MatTable\n }, {\n provide: CDK_TABLE,\n useExisting: MatTable\n }, {\n provide: _COALESCED_STYLE_SCHEDULER,\n useClass: _CoalescedStyleScheduler\n }, // Prevent nested tables from seeing this table's StickyPositioningListener.\n {\n provide: STICKY_POSITIONING_LISTENER,\n useValue: null\n }]), i0.ɵɵInheritDefinitionFeature],\n ngContentSelectors: _c1,\n decls: 6,\n vars: 0,\n consts: [[\"headerRowOutlet\", \"\"], [\"rowOutlet\", \"\"], [\"noDataRowOutlet\", \"\"], [\"footerRowOutlet\", \"\"]],\n template: function MatTable_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵprojectionDef(_c0);\n i0.ɵɵprojection(0);\n i0.ɵɵprojection(1, 1);\n i0.ɵɵelementContainer(2, 0);\n i0.ɵɵelementContainer(3, 1);\n i0.ɵɵelementContainer(4, 2);\n i0.ɵɵelementContainer(5, 3);\n }\n },\n directives: [i1.HeaderRowOutlet, i1.DataRowOutlet, i1.NoDataRowOutlet, i1.FooterRowOutlet],\n styles: [\"mat-table{display:block}mat-header-row{min-height:56px}mat-row,mat-footer-row{min-height:48px}mat-row,mat-header-row,mat-footer-row{display:flex;border-width:0;border-bottom-width:1px;border-style:solid;align-items:center;box-sizing:border-box}mat-row::after,mat-header-row::after,mat-footer-row::after{display:inline-block;min-height:inherit;content:\\\"\\\"}mat-cell:first-of-type,mat-header-cell:first-of-type,mat-footer-cell:first-of-type{padding-left:24px}[dir=rtl] mat-cell:first-of-type:not(:only-of-type),[dir=rtl] mat-header-cell:first-of-type:not(:only-of-type),[dir=rtl] mat-footer-cell:first-of-type:not(:only-of-type){padding-left:0;padding-right:24px}mat-cell:last-of-type,mat-header-cell:last-of-type,mat-footer-cell:last-of-type{padding-right:24px}[dir=rtl] mat-cell:last-of-type:not(:only-of-type),[dir=rtl] mat-header-cell:last-of-type:not(:only-of-type),[dir=rtl] mat-footer-cell:last-of-type:not(:only-of-type){padding-right:0;padding-left:24px}mat-cell,mat-header-cell,mat-footer-cell{flex:1;display:flex;align-items:center;overflow:hidden;word-wrap:break-word;min-height:inherit}table.mat-table{border-spacing:0}tr.mat-header-row{height:56px}tr.mat-row,tr.mat-footer-row{height:48px}th.mat-header-cell{text-align:left}[dir=rtl] th.mat-header-cell{text-align:right}th.mat-header-cell,td.mat-cell,td.mat-footer-cell{padding:0;border-bottom-width:1px;border-bottom-style:solid}th.mat-header-cell:first-of-type,td.mat-cell:first-of-type,td.mat-footer-cell:first-of-type{padding-left:24px}[dir=rtl] th.mat-header-cell:first-of-type:not(:only-of-type),[dir=rtl] td.mat-cell:first-of-type:not(:only-of-type),[dir=rtl] td.mat-footer-cell:first-of-type:not(:only-of-type){padding-left:0;padding-right:24px}th.mat-header-cell:last-of-type,td.mat-cell:last-of-type,td.mat-footer-cell:last-of-type{padding-right:24px}[dir=rtl] th.mat-header-cell:last-of-type:not(:only-of-type),[dir=rtl] td.mat-cell:last-of-type:not(:only-of-type),[dir=rtl] td.mat-footer-cell:last-of-type:not(:only-of-type){padding-right:0;padding-left:24px}.mat-table-sticky{position:-webkit-sticky !important;position:sticky !important}.mat-table-fixed-layout{table-layout:fixed}\\n\"],\n encapsulation: 2\n });\n return MatTable;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Cell definition for the mat-table.\n * Captures the template of a column's data row cell as well as cell-specific properties.\n */\n\n\nlet MatCellDef = /*#__PURE__*/(() => {\n class MatCellDef extends CdkCellDef {}\n\n MatCellDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatCellDef_BaseFactory;\n return function MatCellDef_Factory(t) {\n return (ɵMatCellDef_BaseFactory || (ɵMatCellDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatCellDef)))(t || MatCellDef);\n };\n }();\n\n MatCellDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatCellDef,\n selectors: [[\"\", \"matCellDef\", \"\"]],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkCellDef,\n useExisting: MatCellDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatCellDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Header cell definition for the mat-table.\n * Captures the template of a column's header cell and as well as cell-specific properties.\n */\n\n\nlet MatHeaderCellDef = /*#__PURE__*/(() => {\n class MatHeaderCellDef extends CdkHeaderCellDef {}\n\n MatHeaderCellDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatHeaderCellDef_BaseFactory;\n return function MatHeaderCellDef_Factory(t) {\n return (ɵMatHeaderCellDef_BaseFactory || (ɵMatHeaderCellDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatHeaderCellDef)))(t || MatHeaderCellDef);\n };\n }();\n\n MatHeaderCellDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatHeaderCellDef,\n selectors: [[\"\", \"matHeaderCellDef\", \"\"]],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkHeaderCellDef,\n useExisting: MatHeaderCellDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatHeaderCellDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Footer cell definition for the mat-table.\n * Captures the template of a column's footer cell and as well as cell-specific properties.\n */\n\n\nlet MatFooterCellDef = /*#__PURE__*/(() => {\n class MatFooterCellDef extends CdkFooterCellDef {}\n\n MatFooterCellDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatFooterCellDef_BaseFactory;\n return function MatFooterCellDef_Factory(t) {\n return (ɵMatFooterCellDef_BaseFactory || (ɵMatFooterCellDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatFooterCellDef)))(t || MatFooterCellDef);\n };\n }();\n\n MatFooterCellDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatFooterCellDef,\n selectors: [[\"\", \"matFooterCellDef\", \"\"]],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkFooterCellDef,\n useExisting: MatFooterCellDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatFooterCellDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Column definition for the mat-table.\n * Defines a set of cells available for a table column.\n */\n\n\nlet MatColumnDef = /*#__PURE__*/(() => {\n class MatColumnDef extends CdkColumnDef {\n /** Unique name for this column. */\n get name() {\n return this._name;\n }\n\n set name(name) {\n this._setNameInput(name);\n }\n /**\n * Add \"mat-column-\" prefix in addition to \"cdk-column-\" prefix.\n * In the future, this will only add \"mat-column-\" and columnCssClassName\n * will change from type string[] to string.\n * @docs-private\n */\n\n\n _updateColumnCssClassName() {\n super._updateColumnCssClassName();\n\n this._columnCssClassName.push(`mat-column-${this.cssClassFriendlyName}`);\n }\n\n }\n\n MatColumnDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatColumnDef_BaseFactory;\n return function MatColumnDef_Factory(t) {\n return (ɵMatColumnDef_BaseFactory || (ɵMatColumnDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatColumnDef)))(t || MatColumnDef);\n };\n }();\n\n MatColumnDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatColumnDef,\n selectors: [[\"\", \"matColumnDef\", \"\"]],\n inputs: {\n sticky: \"sticky\",\n name: [\"matColumnDef\", \"name\"]\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkColumnDef,\n useExisting: MatColumnDef\n }, {\n provide: 'MAT_SORT_HEADER_COLUMN_DEF',\n useExisting: MatColumnDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatColumnDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Header cell template container that adds the right classes and role. */\n\n\nlet MatHeaderCell = /*#__PURE__*/(() => {\n class MatHeaderCell extends CdkHeaderCell {}\n\n MatHeaderCell.ɵfac = /* @__PURE__ */function () {\n let ɵMatHeaderCell_BaseFactory;\n return function MatHeaderCell_Factory(t) {\n return (ɵMatHeaderCell_BaseFactory || (ɵMatHeaderCell_BaseFactory = i0.ɵɵgetInheritedFactory(MatHeaderCell)))(t || MatHeaderCell);\n };\n }();\n\n MatHeaderCell.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatHeaderCell,\n selectors: [[\"mat-header-cell\"], [\"th\", \"mat-header-cell\", \"\"]],\n hostAttrs: [\"role\", \"columnheader\", 1, \"mat-header-cell\"],\n features: [i0.ɵɵInheritDefinitionFeature]\n });\n return MatHeaderCell;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Footer cell template container that adds the right classes and role. */\n\n\nlet MatFooterCell = /*#__PURE__*/(() => {\n class MatFooterCell extends CdkFooterCell {}\n\n MatFooterCell.ɵfac = /* @__PURE__ */function () {\n let ɵMatFooterCell_BaseFactory;\n return function MatFooterCell_Factory(t) {\n return (ɵMatFooterCell_BaseFactory || (ɵMatFooterCell_BaseFactory = i0.ɵɵgetInheritedFactory(MatFooterCell)))(t || MatFooterCell);\n };\n }();\n\n MatFooterCell.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatFooterCell,\n selectors: [[\"mat-footer-cell\"], [\"td\", \"mat-footer-cell\", \"\"]],\n hostAttrs: [\"role\", \"gridcell\", 1, \"mat-footer-cell\"],\n features: [i0.ɵɵInheritDefinitionFeature]\n });\n return MatFooterCell;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Cell template container that adds the right classes and role. */\n\n\nlet MatCell = /*#__PURE__*/(() => {\n class MatCell extends CdkCell {}\n\n MatCell.ɵfac = /* @__PURE__ */function () {\n let ɵMatCell_BaseFactory;\n return function MatCell_Factory(t) {\n return (ɵMatCell_BaseFactory || (ɵMatCell_BaseFactory = i0.ɵɵgetInheritedFactory(MatCell)))(t || MatCell);\n };\n }();\n\n MatCell.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatCell,\n selectors: [[\"mat-cell\"], [\"td\", \"mat-cell\", \"\"]],\n hostAttrs: [\"role\", \"gridcell\", 1, \"mat-cell\"],\n features: [i0.ɵɵInheritDefinitionFeature]\n });\n return MatCell;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Header row definition for the mat-table.\n * Captures the header row's template and other header properties such as the columns to display.\n */\n\n\nlet MatHeaderRowDef = /*#__PURE__*/(() => {\n class MatHeaderRowDef extends CdkHeaderRowDef {}\n\n MatHeaderRowDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatHeaderRowDef_BaseFactory;\n return function MatHeaderRowDef_Factory(t) {\n return (ɵMatHeaderRowDef_BaseFactory || (ɵMatHeaderRowDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatHeaderRowDef)))(t || MatHeaderRowDef);\n };\n }();\n\n MatHeaderRowDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatHeaderRowDef,\n selectors: [[\"\", \"matHeaderRowDef\", \"\"]],\n inputs: {\n columns: [\"matHeaderRowDef\", \"columns\"],\n sticky: [\"matHeaderRowDefSticky\", \"sticky\"]\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkHeaderRowDef,\n useExisting: MatHeaderRowDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatHeaderRowDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Footer row definition for the mat-table.\n * Captures the footer row's template and other footer properties such as the columns to display.\n */\n\n\nlet MatFooterRowDef = /*#__PURE__*/(() => {\n class MatFooterRowDef extends CdkFooterRowDef {}\n\n MatFooterRowDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatFooterRowDef_BaseFactory;\n return function MatFooterRowDef_Factory(t) {\n return (ɵMatFooterRowDef_BaseFactory || (ɵMatFooterRowDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatFooterRowDef)))(t || MatFooterRowDef);\n };\n }();\n\n MatFooterRowDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatFooterRowDef,\n selectors: [[\"\", \"matFooterRowDef\", \"\"]],\n inputs: {\n columns: [\"matFooterRowDef\", \"columns\"],\n sticky: [\"matFooterRowDefSticky\", \"sticky\"]\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkFooterRowDef,\n useExisting: MatFooterRowDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatFooterRowDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * Data row definition for the mat-table.\n * Captures the data row's template and other properties such as the columns to display and\n * a when predicate that describes when this row should be used.\n */\n\n\nlet MatRowDef = /*#__PURE__*/(() => {\n class MatRowDef extends CdkRowDef {}\n\n MatRowDef.ɵfac = /* @__PURE__ */function () {\n let ɵMatRowDef_BaseFactory;\n return function MatRowDef_Factory(t) {\n return (ɵMatRowDef_BaseFactory || (ɵMatRowDef_BaseFactory = i0.ɵɵgetInheritedFactory(MatRowDef)))(t || MatRowDef);\n };\n }();\n\n MatRowDef.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatRowDef,\n selectors: [[\"\", \"matRowDef\", \"\"]],\n inputs: {\n columns: [\"matRowDefColumns\", \"columns\"],\n when: [\"matRowDefWhen\", \"when\"]\n },\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkRowDef,\n useExisting: MatRowDef\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatRowDef;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Header template container that contains the cell outlet. Adds the right class and role. */\n\n\nlet MatHeaderRow = /*#__PURE__*/(() => {\n class MatHeaderRow extends CdkHeaderRow {}\n\n MatHeaderRow.ɵfac = /* @__PURE__ */function () {\n let ɵMatHeaderRow_BaseFactory;\n return function MatHeaderRow_Factory(t) {\n return (ɵMatHeaderRow_BaseFactory || (ɵMatHeaderRow_BaseFactory = i0.ɵɵgetInheritedFactory(MatHeaderRow)))(t || MatHeaderRow);\n };\n }();\n\n MatHeaderRow.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatHeaderRow,\n selectors: [[\"mat-header-row\"], [\"tr\", \"mat-header-row\", \"\"]],\n hostAttrs: [\"role\", \"row\", 1, \"mat-header-row\"],\n exportAs: [\"matHeaderRow\"],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkHeaderRow,\n useExisting: MatHeaderRow\n }]), i0.ɵɵInheritDefinitionFeature],\n decls: 1,\n vars: 0,\n consts: [[\"cdkCellOutlet\", \"\"]],\n template: function MatHeaderRow_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementContainer(0, 0);\n }\n },\n directives: [i1.CdkCellOutlet],\n encapsulation: 2\n });\n return MatHeaderRow;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Footer template container that contains the cell outlet. Adds the right class and role. */\n\n\nlet MatFooterRow = /*#__PURE__*/(() => {\n class MatFooterRow extends CdkFooterRow {}\n\n MatFooterRow.ɵfac = /* @__PURE__ */function () {\n let ɵMatFooterRow_BaseFactory;\n return function MatFooterRow_Factory(t) {\n return (ɵMatFooterRow_BaseFactory || (ɵMatFooterRow_BaseFactory = i0.ɵɵgetInheritedFactory(MatFooterRow)))(t || MatFooterRow);\n };\n }();\n\n MatFooterRow.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatFooterRow,\n selectors: [[\"mat-footer-row\"], [\"tr\", \"mat-footer-row\", \"\"]],\n hostAttrs: [\"role\", \"row\", 1, \"mat-footer-row\"],\n exportAs: [\"matFooterRow\"],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkFooterRow,\n useExisting: MatFooterRow\n }]), i0.ɵɵInheritDefinitionFeature],\n decls: 1,\n vars: 0,\n consts: [[\"cdkCellOutlet\", \"\"]],\n template: function MatFooterRow_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementContainer(0, 0);\n }\n },\n directives: [i1.CdkCellOutlet],\n encapsulation: 2\n });\n return MatFooterRow;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Data row template container that contains the cell outlet. Adds the right class and role. */\n\n\nlet MatRow = /*#__PURE__*/(() => {\n class MatRow extends CdkRow {}\n\n MatRow.ɵfac = /* @__PURE__ */function () {\n let ɵMatRow_BaseFactory;\n return function MatRow_Factory(t) {\n return (ɵMatRow_BaseFactory || (ɵMatRow_BaseFactory = i0.ɵɵgetInheritedFactory(MatRow)))(t || MatRow);\n };\n }();\n\n MatRow.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatRow,\n selectors: [[\"mat-row\"], [\"tr\", \"mat-row\", \"\"]],\n hostAttrs: [\"role\", \"row\", 1, \"mat-row\"],\n exportAs: [\"matRow\"],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkRow,\n useExisting: MatRow\n }]), i0.ɵɵInheritDefinitionFeature],\n decls: 1,\n vars: 0,\n consts: [[\"cdkCellOutlet\", \"\"]],\n template: function MatRow_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementContainer(0, 0);\n }\n },\n directives: [i1.CdkCellOutlet],\n encapsulation: 2\n });\n return MatRow;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/** Row that can be used to display a message when no data is shown in the table. */\n\n\nlet MatNoDataRow = /*#__PURE__*/(() => {\n class MatNoDataRow extends CdkNoDataRow {}\n\n MatNoDataRow.ɵfac = /* @__PURE__ */function () {\n let ɵMatNoDataRow_BaseFactory;\n return function MatNoDataRow_Factory(t) {\n return (ɵMatNoDataRow_BaseFactory || (ɵMatNoDataRow_BaseFactory = i0.ɵɵgetInheritedFactory(MatNoDataRow)))(t || MatNoDataRow);\n };\n }();\n\n MatNoDataRow.ɵdir = /* @__PURE__ */i0.ɵɵdefineDirective({\n type: MatNoDataRow,\n selectors: [[\"ng-template\", \"matNoDataRow\", \"\"]],\n features: [i0.ɵɵProvidersFeature([{\n provide: CdkNoDataRow,\n useExisting: MatNoDataRow\n }]), i0.ɵɵInheritDefinitionFeature]\n });\n return MatNoDataRow;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Column that simply shows text content for the header and row cells. Assumes that the table\n * is using the native table implementation (`
`).\n *\n * By default, the name of this column will be the header text and data property accessor.\n * The header text can be overridden with the `headerText` input. Cell values can be overridden with\n * the `dataAccessor` input. Change the text justification to the start or end using the `justify`\n * input.\n */\n\n\nlet MatTextColumn = /*#__PURE__*/(() => {\n class MatTextColumn extends CdkTextColumn {}\n\n MatTextColumn.ɵfac = /* @__PURE__ */function () {\n let ɵMatTextColumn_BaseFactory;\n return function MatTextColumn_Factory(t) {\n return (ɵMatTextColumn_BaseFactory || (ɵMatTextColumn_BaseFactory = i0.ɵɵgetInheritedFactory(MatTextColumn)))(t || MatTextColumn);\n };\n }();\n\n MatTextColumn.ɵcmp = /* @__PURE__ */i0.ɵɵdefineComponent({\n type: MatTextColumn,\n selectors: [[\"mat-text-column\"]],\n features: [i0.ɵɵInheritDefinitionFeature],\n decls: 3,\n vars: 0,\n consts: [[\"matColumnDef\", \"\"], [\"mat-header-cell\", \"\", 3, \"text-align\", 4, \"matHeaderCellDef\"], [\"mat-cell\", \"\", 3, \"text-align\", 4, \"matCellDef\"], [\"mat-header-cell\", \"\"], [\"mat-cell\", \"\"]],\n template: function MatTextColumn_Template(rf, ctx) {\n if (rf & 1) {\n i0.ɵɵelementContainerStart(0, 0);\n i0.ɵɵtemplate(1, MatTextColumn_th_1_Template, 2, 3, \"th\", 1);\n i0.ɵɵtemplate(2, MatTextColumn_td_2_Template, 2, 3, \"td\", 2);\n i0.ɵɵelementContainerEnd();\n }\n },\n directives: [MatColumnDef, MatHeaderCellDef, MatCellDef, MatHeaderCell, MatCell],\n encapsulation: 2\n });\n return MatTextColumn;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nconst EXPORTED_DECLARATIONS = [// Table\nMatTable, MatRecycleRows, // Template defs\nMatHeaderCellDef, MatHeaderRowDef, MatColumnDef, MatCellDef, MatRowDef, MatFooterCellDef, MatFooterRowDef, // Cell directives\nMatHeaderCell, MatCell, MatFooterCell, // Row directives\nMatHeaderRow, MatRow, MatFooterRow, MatNoDataRow, MatTextColumn];\nlet MatTableModule = /*#__PURE__*/(() => {\n class MatTableModule {}\n\n MatTableModule.ɵfac = function MatTableModule_Factory(t) {\n return new (t || MatTableModule)();\n };\n\n MatTableModule.ɵmod = /* @__PURE__ */i0.ɵɵdefineNgModule({\n type: MatTableModule\n });\n MatTableModule.ɵinj = /* @__PURE__ */i0.ɵɵdefineInjector({\n imports: [[CdkTableModule, MatCommonModule], MatCommonModule]\n });\n return MatTableModule;\n})();\n\n/*#__PURE__*/\n(function () {\n (typeof ngDevMode === \"undefined\" || ngDevMode) && void 0;\n})();\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Corresponds to `Number.MAX_SAFE_INTEGER`. Moved out into a variable here due to\n * flaky browser support and the value not being defined in Closure's typings.\n */\n\n\nconst MAX_SAFE_INTEGER = 9007199254740991;\n/** Shared base class with MDC-based implementation. */\n\nclass _MatTableDataSource extends DataSource {\n constructor(initialData = []) {\n super();\n /** Stream emitting render data to the table (depends on ordered data changes). */\n\n this._renderData = new BehaviorSubject([]);\n /** Stream that emits when a new filter string is set on the data source. */\n\n this._filter = new BehaviorSubject('');\n /** Used to react to internal changes of the paginator that are made by the data source itself. */\n\n this._internalPageChanges = new Subject();\n /**\n * Subscription to the changes that should trigger an update to the table's rendered rows, such\n * as filtering, sorting, pagination, or base data changes.\n */\n\n this._renderChangesSubscription = null;\n /**\n * Data accessor function that is used for accessing data properties for sorting through\n * the default sortData function.\n * This default function assumes that the sort header IDs (which defaults to the column name)\n * matches the data's properties (e.g. column Xyz represents data['Xyz']).\n * May be set to a custom function for different behavior.\n * @param data Data object that is being accessed.\n * @param sortHeaderId The name of the column that represents the data.\n */\n\n this.sortingDataAccessor = (data, sortHeaderId) => {\n const value = data[sortHeaderId];\n\n if (_isNumberValue(value)) {\n const numberValue = Number(value); // Numbers beyond `MAX_SAFE_INTEGER` can't be compared reliably so we\n // leave them as strings. For more info: https://goo.gl/y5vbSg\n\n return numberValue < MAX_SAFE_INTEGER ? numberValue : value;\n }\n\n return value;\n };\n /**\n * Gets a sorted copy of the data array based on the state of the MatSort. Called\n * after changes are made to the filtered data or when sort changes are emitted from MatSort.\n * By default, the function retrieves the active sort and its direction and compares data\n * by retrieving data using the sortingDataAccessor. May be overridden for a custom implementation\n * of data ordering.\n * @param data The array of data that should be sorted.\n * @param sort The connected MatSort that holds the current sort state.\n */\n\n\n this.sortData = (data, sort) => {\n const active = sort.active;\n const direction = sort.direction;\n\n if (!active || direction == '') {\n return data;\n }\n\n return data.sort((a, b) => {\n let valueA = this.sortingDataAccessor(a, active);\n let valueB = this.sortingDataAccessor(b, active); // If there are data in the column that can be converted to a number,\n // it must be ensured that the rest of the data\n // is of the same type so as not to order incorrectly.\n\n const valueAType = typeof valueA;\n const valueBType = typeof valueB;\n\n if (valueAType !== valueBType) {\n if (valueAType === 'number') {\n valueA += '';\n }\n\n if (valueBType === 'number') {\n valueB += '';\n }\n } // If both valueA and valueB exist (truthy), then compare the two. Otherwise, check if\n // one value exists while the other doesn't. In this case, existing value should come last.\n // This avoids inconsistent results when comparing values to undefined/null.\n // If neither value exists, return 0 (equal).\n\n\n let comparatorResult = 0;\n\n if (valueA != null && valueB != null) {\n // Check if one value is greater than the other; if equal, comparatorResult should remain 0.\n if (valueA > valueB) {\n comparatorResult = 1;\n } else if (valueA < valueB) {\n comparatorResult = -1;\n }\n } else if (valueA != null) {\n comparatorResult = 1;\n } else if (valueB != null) {\n comparatorResult = -1;\n }\n\n return comparatorResult * (direction == 'asc' ? 1 : -1);\n });\n };\n /**\n * Checks if a data object matches the data source's filter string. By default, each data object\n * is converted to a string of its properties and returns true if the filter has\n * at least one occurrence in that string. By default, the filter string has its whitespace\n * trimmed and the match is case-insensitive. May be overridden for a custom implementation of\n * filter matching.\n * @param data Data object used to check against the filter.\n * @param filter Filter string that has been set on the data source.\n * @returns Whether the filter matches against the data\n */\n\n\n this.filterPredicate = (data, filter) => {\n // Transform the data into a lowercase string of all property values.\n const dataStr = Object.keys(data).reduce((currentTerm, key) => {\n // Use an obscure Unicode character to delimit the words in the concatenated string.\n // This avoids matches where the values of two columns combined will match the user's query\n // (e.g. `Flute` and `Stop` will match `Test`). The character is intended to be something\n // that has a very low chance of being typed in by somebody in a text field. This one in\n // particular is \"White up-pointing triangle with dot\" from\n // https://en.wikipedia.org/wiki/List_of_Unicode_characters\n return currentTerm + data[key] + '◬';\n }, '').toLowerCase(); // Transform the filter by converting it to lowercase and removing whitespace.\n\n const transformedFilter = filter.trim().toLowerCase();\n return dataStr.indexOf(transformedFilter) != -1;\n };\n\n this._data = new BehaviorSubject(initialData);\n\n this._updateChangeSubscription();\n }\n /** Array of data that should be rendered by the table, where each object represents one row. */\n\n\n get data() {\n return this._data.value;\n }\n\n set data(data) {\n this._data.next(data); // Normally the `filteredData` is updated by the re-render\n // subscription, but that won't happen if it's inactive.\n\n\n if (!this._renderChangesSubscription) {\n this._filterData(data);\n }\n }\n /**\n * Filter term that should be used to filter out objects from the data array. To override how\n * data objects match to this filter string, provide a custom function for filterPredicate.\n */\n\n\n get filter() {\n return this._filter.value;\n }\n\n set filter(filter) {\n this._filter.next(filter); // Normally the `filteredData` is updated by the re-render\n // subscription, but that won't happen if it's inactive.\n\n\n if (!this._renderChangesSubscription) {\n this._filterData(this.data);\n }\n }\n /**\n * Instance of the MatSort directive used by the table to control its sorting. Sort changes\n * emitted by the MatSort will trigger an update to the table's rendered data.\n */\n\n\n get sort() {\n return this._sort;\n }\n\n set sort(sort) {\n this._sort = sort;\n\n this._updateChangeSubscription();\n }\n /**\n * Instance of the MatPaginator component used by the table to control what page of the data is\n * displayed. Page changes emitted by the MatPaginator will trigger an update to the\n * table's rendered data.\n *\n * Note that the data source uses the paginator's properties to calculate which page of data\n * should be displayed. If the paginator receives its properties as template inputs,\n * e.g. `[pageLength]=100` or `[pageIndex]=1`, then be sure that the paginator's view has been\n * initialized before assigning it to this data source.\n */\n\n\n get paginator() {\n return this._paginator;\n }\n\n set paginator(paginator) {\n this._paginator = paginator;\n\n this._updateChangeSubscription();\n }\n /**\n * Subscribe to changes that should trigger an update to the table's rendered rows. When the\n * changes occur, process the current state of the filter, sort, and pagination along with\n * the provided base data and send it to the table for rendering.\n */\n\n\n _updateChangeSubscription() {\n // Sorting and/or pagination should be watched if MatSort and/or MatPaginator are provided.\n // The events should emit whenever the component emits a change or initializes, or if no\n // component is provided, a stream with just a null event should be provided.\n // The `sortChange` and `pageChange` acts as a signal to the combineLatests below so that the\n // pipeline can progress to the next step. Note that the value from these streams are not used,\n // they purely act as a signal to progress in the pipeline.\n const sortChange = this._sort ? merge(this._sort.sortChange, this._sort.initialized) : of(null);\n const pageChange = this._paginator ? merge(this._paginator.page, this._internalPageChanges, this._paginator.initialized) : of(null);\n const dataStream = this._data; // Watch for base data or filter changes to provide a filtered set of data.\n\n const filteredData = combineLatest([dataStream, this._filter]).pipe(map(([data]) => this._filterData(data))); // Watch for filtered data or sort changes to provide an ordered set of data.\n\n const orderedData = combineLatest([filteredData, sortChange]).pipe(map(([data]) => this._orderData(data))); // Watch for ordered data or page changes to provide a paged set of data.\n\n const paginatedData = combineLatest([orderedData, pageChange]).pipe(map(([data]) => this._pageData(data))); // Watched for paged data changes and send the result to the table to render.\n\n this._renderChangesSubscription?.unsubscribe();\n this._renderChangesSubscription = paginatedData.subscribe(data => this._renderData.next(data));\n }\n /**\n * Returns a filtered data array where each filter object contains the filter string within\n * the result of the filterTermAccessor function. If no filter is set, returns the data array\n * as provided.\n */\n\n\n _filterData(data) {\n // If there is a filter string, filter out data that does not contain it.\n // Each data object is converted to a string using the function defined by filterTermAccessor.\n // May be overridden for customization.\n this.filteredData = this.filter == null || this.filter === '' ? data : data.filter(obj => this.filterPredicate(obj, this.filter));\n\n if (this.paginator) {\n this._updatePaginator(this.filteredData.length);\n }\n\n return this.filteredData;\n }\n /**\n * Returns a sorted copy of the data if MatSort has a sort applied, otherwise just returns the\n * data array as provided. Uses the default data accessor for data lookup, unless a\n * sortDataAccessor function is defined.\n */\n\n\n _orderData(data) {\n // If there is no active sort or direction, return the data without trying to sort.\n if (!this.sort) {\n return data;\n }\n\n return this.sortData(data.slice(), this.sort);\n }\n /**\n * Returns a paged slice of the provided data array according to the provided MatPaginator's page\n * index and length. If there is no paginator provided, returns the data array as provided.\n */\n\n\n _pageData(data) {\n if (!this.paginator) {\n return data;\n }\n\n const startIndex = this.paginator.pageIndex * this.paginator.pageSize;\n return data.slice(startIndex, startIndex + this.paginator.pageSize);\n }\n /**\n * Updates the paginator to reflect the length of the filtered data, and makes sure that the page\n * index does not exceed the paginator's last page. Values are changed in a resolved promise to\n * guard against making property changes within a round of change detection.\n */\n\n\n _updatePaginator(filteredDataLength) {\n Promise.resolve().then(() => {\n const paginator = this.paginator;\n\n if (!paginator) {\n return;\n }\n\n paginator.length = filteredDataLength; // If the page index is set beyond the page, reduce it to the last page.\n\n if (paginator.pageIndex > 0) {\n const lastPageIndex = Math.ceil(paginator.length / paginator.pageSize) - 1 || 0;\n const newPageIndex = Math.min(paginator.pageIndex, lastPageIndex);\n\n if (newPageIndex !== paginator.pageIndex) {\n paginator.pageIndex = newPageIndex; // Since the paginator only emits after user-generated changes,\n // we need our own stream so we know to should re-render the data.\n\n this._internalPageChanges.next();\n }\n }\n });\n }\n /**\n * Used by the MatTable. Called when it connects to the data source.\n * @docs-private\n */\n\n\n connect() {\n if (!this._renderChangesSubscription) {\n this._updateChangeSubscription();\n }\n\n return this._renderData;\n }\n /**\n * Used by the MatTable. Called when it disconnects from the data source.\n * @docs-private\n */\n\n\n disconnect() {\n this._renderChangesSubscription?.unsubscribe();\n this._renderChangesSubscription = null;\n }\n\n}\n/**\n * Data source that accepts a client-side data array and includes native support of filtering,\n * sorting (using MatSort), and pagination (using MatPaginator).\n *\n * Allows for sort customization by overriding sortingDataAccessor, which defines how data\n * properties are accessed. Also allows for filter customization by overriding filterTermAccessor,\n * which defines how row data is converted to a string for filter matching.\n *\n * **Note:** This class is meant to be a simple data source to help you get started. As such\n * it isn't equipped to handle some more advanced cases like robust i18n support or server-side\n * interactions. If your app needs to support more advanced use cases, consider implementing your\n * own `DataSource`.\n */\n\n\nclass MatTableDataSource extends _MatTableDataSource {}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Generated bundle index. Do not edit.\n */\n\n\nexport { MatCell, MatCellDef, MatColumnDef, MatFooterCell, MatFooterCellDef, MatFooterRow, MatFooterRowDef, MatHeaderCell, MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatNoDataRow, MatRecycleRows, MatRow, MatRowDef, MatTable, MatTableDataSource, MatTableModule, MatTextColumn, _MatTableDataSource }; //# sourceMappingURL=table.mjs.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1e6c38159dcf4e77816e1731a37264c9.json b/.angular/cache/babel-webpack/1e6c38159dcf4e77816e1731a37264c9.json
new file mode 100644
index 0000000..cd0c305
--- /dev/null
+++ b/.angular/cache/babel-webpack/1e6c38159dcf4e77816e1731a37264c9.json
@@ -0,0 +1 @@
+{"ast":null,"code":"'use strict';\n\nmodule.exports = ansiHTML; // Reference to https://github.com/sindresorhus/ansi-regex\n\nvar _regANSI = /(?:(?:\\u001b\\[)|\\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\\u001b[A-M]/;\nvar _defColors = {\n reset: ['fff', '000'],\n // [FOREGROUD_COLOR, BACKGROUND_COLOR]\n black: '000',\n red: 'ff0000',\n green: '209805',\n yellow: 'e8bf03',\n blue: '0000ff',\n magenta: 'ff00ff',\n cyan: '00ffee',\n lightgrey: 'f0f0f0',\n darkgrey: '888'\n};\nvar _styles = {\n 30: 'black',\n 31: 'red',\n 32: 'green',\n 33: 'yellow',\n 34: 'blue',\n 35: 'magenta',\n 36: 'cyan',\n 37: 'lightgrey'\n};\nvar _openTags = {\n '1': 'font-weight:bold',\n // bold\n '2': 'opacity:0.5',\n // dim\n '3': '',\n // italic\n '4': '',\n // underscore\n '8': 'display:none',\n // hidden\n '9': '' // delete\n\n};\nvar _closeTags = {\n '23': '',\n // reset italic\n '24': '',\n // reset underscore\n '29': '' // reset delete\n\n};\n[0, 21, 22, 27, 28, 39, 49].forEach(function (n) {\n _closeTags[n] = '';\n});\n/**\n * Converts text with ANSI color codes to HTML markup.\n * @param {String} text\n * @returns {*}\n */\n\nfunction ansiHTML(text) {\n // Returns the text if the string has no ANSI escape code.\n if (!_regANSI.test(text)) {\n return text;\n } // Cache opened sequence.\n\n\n var ansiCodes = []; // Replace with markup.\n\n var ret = text.replace(/\\033\\[(\\d+)m/g, function (match, seq) {\n var ot = _openTags[seq];\n\n if (ot) {\n // If current sequence has been opened, close it.\n if (!!~ansiCodes.indexOf(seq)) {\n // eslint-disable-line no-extra-boolean-cast\n ansiCodes.pop();\n return '';\n } // Open tag.\n\n\n ansiCodes.push(seq);\n return ot[0] === '<' ? ot : '';\n }\n\n var ct = _closeTags[seq];\n\n if (ct) {\n // Pop sequence\n ansiCodes.pop();\n return ct;\n }\n\n return '';\n }); // Make sure tags are closed.\n\n var l = ansiCodes.length;\n l > 0 && (ret += Array(l + 1).join(''));\n return ret;\n}\n/**\n * Customize colors.\n * @param {Object} colors reference to _defColors\n */\n\n\nansiHTML.setColors = function (colors) {\n if (typeof colors !== 'object') {\n throw new Error('`colors` parameter must be an Object.');\n }\n\n var _finalColors = {};\n\n for (var key in _defColors) {\n var hex = colors.hasOwnProperty(key) ? colors[key] : null;\n\n if (!hex) {\n _finalColors[key] = _defColors[key];\n continue;\n }\n\n if ('reset' === key) {\n if (typeof hex === 'string') {\n hex = [hex];\n }\n\n if (!Array.isArray(hex) || hex.length === 0 || hex.some(function (h) {\n return typeof h !== 'string';\n })) {\n throw new Error('The value of `' + key + '` property must be an Array and each item could only be a hex string, e.g.: FF0000');\n }\n\n var defHexColor = _defColors[key];\n\n if (!hex[0]) {\n hex[0] = defHexColor[0];\n }\n\n if (hex.length === 1 || !hex[1]) {\n hex = [hex[0]];\n hex.push(defHexColor[1]);\n }\n\n hex = hex.slice(0, 2);\n } else if (typeof hex !== 'string') {\n throw new Error('The value of `' + key + '` property must be a hex string, e.g.: FF0000');\n }\n\n _finalColors[key] = hex;\n }\n\n _setTags(_finalColors);\n};\n/**\n * Reset colors.\n */\n\n\nansiHTML.reset = function () {\n _setTags(_defColors);\n};\n/**\n * Expose tags, including open and close.\n * @type {Object}\n */\n\n\nansiHTML.tags = {};\n\nif (Object.defineProperty) {\n Object.defineProperty(ansiHTML.tags, 'open', {\n get: function () {\n return _openTags;\n }\n });\n Object.defineProperty(ansiHTML.tags, 'close', {\n get: function () {\n return _closeTags;\n }\n });\n} else {\n ansiHTML.tags.open = _openTags;\n ansiHTML.tags.close = _closeTags;\n}\n\nfunction _setTags(colors) {\n // reset all\n _openTags['0'] = 'font-weight:normal;opacity:1;color:#' + colors.reset[0] + ';background:#' + colors.reset[1]; // inverse\n\n _openTags['7'] = 'color:#' + colors.reset[1] + ';background:#' + colors.reset[0]; // dark grey\n\n _openTags['90'] = 'color:#' + colors.darkgrey;\n\n for (var code in _styles) {\n var color = _styles[code];\n var oriColor = colors[color] || '000';\n _openTags[code] = 'color:#' + oriColor;\n code = parseInt(code);\n _openTags[(code + 10).toString()] = 'background:#' + oriColor;\n }\n}\n\nansiHTML.reset();","map":null,"metadata":{},"sourceType":"script"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1ed34d422e450680727df84bf16fc11d.json b/.angular/cache/babel-webpack/1ed34d422e450680727df84bf16fc11d.json
new file mode 100644
index 0000000..fa4a3d0
--- /dev/null
+++ b/.angular/cache/babel-webpack/1ed34d422e450680727df84bf16fc11d.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { AsyncScheduler } from './AsyncScheduler';\nexport class AnimationFrameScheduler extends AsyncScheduler {\n flush(action) {\n this._active = true;\n this._scheduled = undefined;\n const {\n actions\n } = this;\n let error;\n let index = -1;\n action = action || actions.shift();\n const count = actions.length;\n\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (++index < count && (action = actions.shift()));\n\n this._active = false;\n\n if (error) {\n while (++index < count && (action = actions.shift())) {\n action.unsubscribe();\n }\n\n throw error;\n }\n }\n\n} //# sourceMappingURL=AnimationFrameScheduler.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1f72217312c5fc44de2724f9c825b682.json b/.angular/cache/babel-webpack/1f72217312c5fc44de2724f9c825b682.json
new file mode 100644
index 0000000..b0d810f
--- /dev/null
+++ b/.angular/cache/babel-webpack/1f72217312c5fc44de2724f9c825b682.json
@@ -0,0 +1 @@
+{"ast":null,"code":"export const isArrayLike = x => x && typeof x.length === 'number' && typeof x !== 'function'; //# sourceMappingURL=isArrayLike.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/1fbf11ffacb013558af4ec93e593a094.json b/.angular/cache/babel-webpack/1fbf11ffacb013558af4ec93e593a094.json
new file mode 100644
index 0000000..22cdb10
--- /dev/null
+++ b/.angular/cache/babel-webpack/1fbf11ffacb013558af4ec93e593a094.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { BrowserModule } from '@angular/platform-browser';\nimport { AppComponent } from './app.component';\nimport { ServiceWorkerModule } from '@angular/service-worker';\nimport { environment } from '../environments/environment';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\nimport { HttpClientModule } from '@angular/common/http';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatSnackBarModule } from '@angular/material/snack-bar';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatTableModule } from '@angular/material/table';\nimport { MatToolbarModule } from '@angular/material/toolbar';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"@angular/service-worker\";\nexport let AppModule = /*#__PURE__*/(() => {\n class AppModule {}\n\n AppModule.ɵfac = function AppModule_Factory(t) {\n return new (t || AppModule)();\n };\n\n AppModule.ɵmod = /*@__PURE__*/i0.ɵɵdefineNgModule({\n type: AppModule,\n bootstrap: [AppComponent]\n });\n AppModule.ɵinj = /*@__PURE__*/i0.ɵɵdefineInjector({\n providers: [],\n imports: [[HttpClientModule, MatIconModule, MatSnackBarModule, MatButtonModule, MatSelectModule, MatProgressSpinnerModule, MatIconModule, MatTableModule, MatToolbarModule, BrowserModule, ServiceWorkerModule.register('ngsw-worker.js', {\n enabled: environment.production\n }), BrowserAnimationsModule]]\n });\n return AppModule;\n})();","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/21355e79c8c40b2969f707ff29505e08.json b/.angular/cache/babel-webpack/21355e79c8c40b2969f707ff29505e08.json
new file mode 100644
index 0000000..c4b17db
--- /dev/null
+++ b/.angular/cache/babel-webpack/21355e79c8c40b2969f707ff29505e08.json
@@ -0,0 +1 @@
+{"ast":null,"code":"const {\n isArray\n} = Array;\nexport function argsOrArgArray(args) {\n return args.length === 1 && isArray(args[0]) ? args[0] : args;\n} //# sourceMappingURL=argsOrArgArray.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/21f69dea07e65105816449641bbb0f6c.json b/.angular/cache/babel-webpack/21f69dea07e65105816449641bbb0f6c.json
new file mode 100644
index 0000000..51aef08
--- /dev/null
+++ b/.angular/cache/babel-webpack/21f69dea07e65105816449641bbb0f6c.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { isFunction } from './isFunction';\nexport function isScheduler(value) {\n return value && isFunction(value.schedule);\n} //# sourceMappingURL=isScheduler.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/22e959971f56bc09f9ab7fc19977f0a1.json b/.angular/cache/babel-webpack/22e959971f56bc09f9ab7fc19977f0a1.json
new file mode 100644
index 0000000..155d542
--- /dev/null
+++ b/.angular/cache/babel-webpack/22e959971f56bc09f9ab7fc19977f0a1.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { from } from './from';\nexport function pairs(obj, scheduler) {\n return from(Object.entries(obj), scheduler);\n} //# sourceMappingURL=pairs.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/27d644ef15d3c35f5e3731a2fee2ceb9.json b/.angular/cache/babel-webpack/27d644ef15d3c35f5e3731a2fee2ceb9.json
new file mode 100644
index 0000000..f922fff
--- /dev/null
+++ b/.angular/cache/babel-webpack/27d644ef15d3c35f5e3731a2fee2ceb9.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { ArgumentOutOfRangeError } from '../util/ArgumentOutOfRangeError';\nimport { filter } from './filter';\nimport { throwIfEmpty } from './throwIfEmpty';\nimport { defaultIfEmpty } from './defaultIfEmpty';\nimport { take } from './take';\nexport function elementAt(index, defaultValue) {\n if (index < 0) {\n throw new ArgumentOutOfRangeError();\n }\n\n const hasDefaultValue = arguments.length >= 2;\n return source => source.pipe(filter((v, i) => i === index), take(1), hasDefaultValue ? defaultIfEmpty(defaultValue) : throwIfEmpty(() => new ArgumentOutOfRangeError()));\n} //# sourceMappingURL=elementAt.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/27eaf82fe94ef15b5d5571f4f9d7ed0c.json b/.angular/cache/babel-webpack/27eaf82fe94ef15b5d5571f4f9d7ed0c.json
new file mode 100644
index 0000000..ed6c5bc
--- /dev/null
+++ b/.angular/cache/babel-webpack/27eaf82fe94ef15b5d5571f4f9d7ed0c.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { scheduleObservable } from './scheduleObservable';\nimport { schedulePromise } from './schedulePromise';\nimport { scheduleArray } from './scheduleArray';\nimport { scheduleIterable } from './scheduleIterable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isPromise } from '../util/isPromise';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isIterable } from '../util/isIterable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isReadableStreamLike } from '../util/isReadableStreamLike';\nimport { scheduleReadableStreamLike } from './scheduleReadableStreamLike';\nexport function scheduled(input, scheduler) {\n if (input != null) {\n if (isInteropObservable(input)) {\n return scheduleObservable(input, scheduler);\n }\n\n if (isArrayLike(input)) {\n return scheduleArray(input, scheduler);\n }\n\n if (isPromise(input)) {\n return schedulePromise(input, scheduler);\n }\n\n if (isAsyncIterable(input)) {\n return scheduleAsyncIterable(input, scheduler);\n }\n\n if (isIterable(input)) {\n return scheduleIterable(input, scheduler);\n }\n\n if (isReadableStreamLike(input)) {\n return scheduleReadableStreamLike(input, scheduler);\n }\n }\n\n throw createInvalidObservableTypeError(input);\n} //# sourceMappingURL=scheduled.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/27eb7e50d37382ac6e5a0f9d46efedab.json b/.angular/cache/babel-webpack/27eb7e50d37382ac6e5a0f9d46efedab.json
new file mode 100644
index 0000000..5ad4c22
--- /dev/null
+++ b/.angular/cache/babel-webpack/27eb7e50d37382ac6e5a0f9d46efedab.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import { Immediate } from '../util/Immediate';\nconst {\n setImmediate,\n clearImmediate\n} = Immediate;\nexport const immediateProvider = {\n setImmediate(...args) {\n const {\n delegate\n } = immediateProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setImmediate) || setImmediate)(...args);\n },\n\n clearImmediate(handle) {\n const {\n delegate\n } = immediateProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearImmediate) || clearImmediate)(handle);\n },\n\n delegate: undefined\n}; //# sourceMappingURL=immediateProvider.js.map","map":null,"metadata":{},"sourceType":"module"}
\ No newline at end of file
diff --git a/.angular/cache/babel-webpack/2874b153235c725387bd95ac9bcf01a4.json b/.angular/cache/babel-webpack/2874b153235c725387bd95ac9bcf01a4.json
new file mode 100644
index 0000000..561e98a
--- /dev/null
+++ b/.angular/cache/babel-webpack/2874b153235c725387bd95ac9bcf01a4.json
@@ -0,0 +1 @@
+{"ast":null,"code":"import * as i0 from '@angular/core';\nimport { SecurityContext, Injectable, Optional, Inject, SkipSelf, ErrorHandler, InjectionToken, inject, Component, ViewEncapsulation, ChangeDetectionStrategy, Attribute, Input, NgModule } from '@angular/core';\nimport { mixinColor, MatCommonModule } from '@angular/material/core';\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { DOCUMENT } from '@angular/common';\nimport { of, throwError, forkJoin, Subscription } from 'rxjs';\nimport { tap, map, catchError, finalize, share, take } from 'rxjs/operators';\nimport * as i1 from '@angular/common/http';\nimport { HttpClient } from '@angular/common/http';\nimport * as i2 from '@angular/platform-browser';\nimport { DomSanitizer } from '@angular/platform-browser';\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * The Trusted Types policy, or null if Trusted Types are not\n * enabled/supported, or undefined if the policy has not been created yet.\n */\n\nconst _c0 = [\"*\"];\nlet policy;\n/**\n * Returns the Trusted Types policy, or null if Trusted Types are not\n * enabled/supported. The first call to this function will create the policy.\n */\n\nfunction getPolicy() {\n if (policy === undefined) {\n policy = null;\n\n if (typeof window !== 'undefined') {\n const ttWindow = window;\n\n if (ttWindow.trustedTypes !== undefined) {\n policy = ttWindow.trustedTypes.createPolicy('angular#components', {\n createHTML: s => s\n });\n }\n }\n }\n\n return policy;\n}\n/**\n * Unsafely promote a string to a TrustedHTML, falling back to strings when\n * Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that the\n * provided string will never cause an XSS vulnerability if used in a context\n * that will be interpreted as HTML by a browser, e.g. when assigning to\n * element.innerHTML.\n */\n\n\nfunction trustedHTMLFromString(html) {\n return getPolicy()?.createHTML(html) || html;\n}\n/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * Returns an exception to be thrown in the case when attempting to\n * load an icon with a name that cannot be found.\n * @docs-private\n */\n\n\nfunction getMatIconNameNotFoundError(iconName) {\n return Error(`Unable to find icon with the name \"${iconName}\"`);\n}\n/**\n * Returns an exception to be thrown when the consumer attempts to use\n * `` without including @angular/common/http.\n * @docs-private\n */\n\n\nfunction getMatIconNoHttpProviderError() {\n return Error('Could not find HttpClient provider for use with Angular Material icons. ' + 'Please include the HttpClientModule from @angular/common/http in your ' + 'app imports.');\n}\n/**\n * Returns an exception to be thrown when a URL couldn't be sanitized.\n * @param url URL that was attempted to be sanitized.\n * @docs-private\n */\n\n\nfunction getMatIconFailedToSanitizeUrlError(url) {\n return Error(`The URL provided to MatIconRegistry was not trusted as a resource URL ` + `via Angular's DomSanitizer. Attempted URL was \"${url}\".`);\n}\n/**\n * Returns an exception to be thrown when a HTML string couldn't be sanitized.\n * @param literal HTML that was attempted to be sanitized.\n * @docs-private\n */\n\n\nfunction getMatIconFailedToSanitizeLiteralError(literal) {\n return Error(`The literal provided to MatIconRegistry was not trusted as safe HTML by ` + `Angular's DomSanitizer. Attempted literal was \"${literal}\".`);\n}\n/**\n * Configuration for an icon, including the URL and possibly the cached SVG element.\n * @docs-private\n */\n\n\nclass SvgIconConfig {\n constructor(url, svgText, options) {\n this.url = url;\n this.svgText = svgText;\n this.options = options;\n }\n\n}\n/**\n * Service to register and display icons used by the `` component.\n * - Registers icon URLs by namespace and name.\n * - Registers icon set URLs by namespace.\n * - Registers aliases for CSS classes, for use with icon fonts.\n * - Loads icons from URLs and extracts individual icons from icon sets.\n */\n\n\nlet MatIconRegistry = /*#__PURE__*/(() => {\n class MatIconRegistry {\n constructor(_httpClient, _sanitizer, document, _errorHandler) {\n this._httpClient = _httpClient;\n this._sanitizer = _sanitizer;\n this._errorHandler = _errorHandler;\n /**\n * URLs and cached SVG elements for individual icons. Keys are of the format \"[namespace]:[icon]\".\n */\n\n this._svgIconConfigs = new Map();\n /**\n * SvgIconConfig objects and cached SVG elements for icon sets, keyed by namespace.\n * Multiple icon sets can be registered under the same namespace.\n */\n\n this._iconSetConfigs = new Map();\n /** Cache for icons loaded by direct URLs. */\n\n this._cachedIconsByUrl = new Map();\n /** In-progress icon fetches. Used to coalesce multiple requests to the same URL. */\n\n this._inProgressUrlFetches = new Map();\n /** Map from font identifiers to their CSS class names. Used for icon fonts. */\n\n this._fontCssClassesByAlias = new Map();\n /** Registered icon resolver functions. */\n\n this._resolvers = [];\n /**\n * The CSS class to apply when an `` component has no icon name, url, or font specified.\n * The default 'material-icons' value assumes that the material icon font has been loaded as\n * described at http://google.github.io/material-design-icons/#icon-font-for-the-web\n */\n\n this._defaultFontSetClass = 'material-icons';\n this._document = document;\n }\n /**\n * Registers an icon by URL in the default namespace.\n * @param iconName Name under which the icon should be registered.\n * @param url\n */\n\n\n addSvgIcon(iconName, url, options) {\n return this.addSvgIconInNamespace('', iconName, url, options);\n }\n /**\n * Registers an icon using an HTML string in the default namespace.\n * @param iconName Name under which the icon should be registered.\n * @param literal SVG source of the icon.\n */\n\n\n addSvgIconLiteral(iconName, literal, options) {\n return this.addSvgIconLiteralInNamespace('', iconName, literal, options);\n }\n /**\n * Registers an icon by URL in the specified namespace.\n * @param namespace Namespace in which the icon should be registered.\n * @param iconName Name under which the icon should be registered.\n * @param url\n */\n\n\n addSvgIconInNamespace(namespace, iconName, url, options) {\n return this._addSvgIconConfig(namespace, iconName, new SvgIconConfig(url, null, options));\n }\n /**\n * Registers an icon resolver function with the registry. The function will be invoked with the\n * name and namespace of an icon when the registry tries to resolve the URL from which to fetch\n * the icon. The resolver is expected to return a `SafeResourceUrl` that points to the icon,\n * an object with the icon URL and icon options, or `null` if the icon is not supported. Resolvers\n * will be invoked in the order in which they have been registered.\n * @param resolver Resolver function to be registered.\n */\n\n\n addSvgIconResolver(resolver) {\n this._resolvers.push(resolver);\n\n return this;\n }\n /**\n * Registers an icon using an HTML string in the specified namespace.\n * @param namespace Namespace in which the icon should be registered.\n * @param iconName Name under which the icon should be registered.\n * @param literal SVG source of the icon.\n */\n\n\n addSvgIconLiteralInNamespace(namespace, iconName, literal, options) {\n const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal); // TODO: add an ngDevMode check\n\n\n if (!cleanLiteral) {\n throw getMatIconFailedToSanitizeLiteralError(literal);\n } // Security: The literal is passed in as SafeHtml, and is thus trusted.\n\n\n const trustedLiteral = trustedHTMLFromString(cleanLiteral);\n return this._addSvgIconConfig(namespace, iconName, new SvgIconConfig('', trustedLiteral, options));\n }\n /**\n * Registers an icon set by URL in the default namespace.\n * @param url\n */\n\n\n addSvgIconSet(url, options) {\n return this.addSvgIconSetInNamespace('', url, options);\n }\n /**\n * Registers an icon set using an HTML string in the default namespace.\n * @param literal SVG source of the icon set.\n */\n\n\n addSvgIconSetLiteral(literal, options) {\n return this.addSvgIconSetLiteralInNamespace('', literal, options);\n }\n /**\n * Registers an icon set by URL in the specified namespace.\n * @param namespace Namespace in which to register the icon set.\n * @param url\n */\n\n\n addSvgIconSetInNamespace(namespace, url, options) {\n return this._addSvgIconSetConfig(namespace, new SvgIconConfig(url, null, options));\n }\n /**\n * Registers an icon set using an HTML string in the specified namespace.\n * @param namespace Namespace in which to register the icon set.\n * @param literal SVG source of the icon set.\n */\n\n\n addSvgIconSetLiteralInNamespace(namespace, literal, options) {\n const cleanLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);\n\n if (!cleanLiteral) {\n throw getMatIconFailedToSanitizeLiteralError(literal);\n } // Security: The literal is passed in as SafeHtml, and is thus trusted.\n\n\n const trustedLiteral = trustedHTMLFromString(cleanLiteral);\n return this._addSvgIconSetConfig(namespace, new SvgIconConfig('', trustedLiteral, options));\n }\n /**\n * Defines an alias for a CSS class name to be used for icon fonts. Creating an matIcon\n * component with the alias as the fontSet input will cause the class name to be applied\n * to the `` element.\n *\n * @param alias Alias for the font.\n * @param className Class name override to be used instead of the alias.\n */\n\n\n registerFontClassAlias(alias, className = alias) {\n this._fontCssClassesByAlias.set(alias, className);\n\n return this;\n }\n /**\n * Returns the CSS class name associated with the alias by a previous call to\n * registerFontClassAlias. If no CSS class has been associated, returns the alias unmodified.\n */\n\n\n classNameForFontAlias(alias) {\n return this._fontCssClassesByAlias.get(alias) || alias;\n }\n /**\n * Sets the CSS class name to be used for icon fonts when an `` component does not\n * have a fontSet input value, and is not loading an icon by name or URL.\n *\n * @param className\n */\n\n\n setDefaultFontSetClass(className) {\n this._defaultFontSetClass = className;\n return this;\n }\n /**\n * Returns the CSS class name to be used for icon fonts when an `` component does not\n * have a fontSet input value, and is not loading an icon by name or URL.\n */\n\n\n getDefaultFontSetClass() {\n return this._defaultFontSetClass;\n }\n /**\n * Returns an Observable that produces the icon (as an `