commit a6bf178a7e99e444a0c9bd142bd073207f5b8db4 Author: BB Date: Tue Oct 10 09:15:19 2023 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30bc162 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f493af5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/oldtimer.iml b/.idea/oldtimer.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/oldtimer.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..84d1cb4 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `. + * @param {?} element + * @return {?} + */ +function isHiddenInput(element) { + return isInputElement(element) && element.type == 'hidden'; +} +/** + * Gets whether an element is an anchor that has an href attribute. + * @param {?} element + * @return {?} + */ +function isAnchorWithHref(element) { + return isAnchorElement(element) && element.hasAttribute('href'); +} +/** + * Gets whether an element is an input element. + * @param {?} element + * @return {?} + */ +function isInputElement(element) { + return element.nodeName.toLowerCase() == 'input'; +} +/** + * Gets whether an element is an anchor element. + * @param {?} element + * @return {?} + */ +function isAnchorElement(element) { + return element.nodeName.toLowerCase() == 'a'; +} +/** + * Gets whether an element has a valid tabindex. + * @param {?} element + * @return {?} + */ +function hasValidTabIndex(element) { + if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) { + return false; + } + /** @type {?} */ + let tabIndex = element.getAttribute('tabindex'); + // IE11 parses tabindex="" as the value "-32768" + if (tabIndex == '-32768') { + return false; + } + return !!(tabIndex && !isNaN(parseInt(tabIndex, 10))); +} +/** + * Returns the parsed tabindex from the element attributes instead of returning the + * evaluated tabindex from the browsers defaults. + * @param {?} element + * @return {?} + */ +function getTabIndexValue(element) { + if (!hasValidTabIndex(element)) { + return null; + } + // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054 + /** @type {?} */ + const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10); + return isNaN(tabIndex) ? -1 : tabIndex; +} +/** + * Checks whether the specified element is potentially tabbable on iOS + * @param {?} element + * @return {?} + */ +function isPotentiallyTabbableIOS(element) { + /** @type {?} */ + let nodeName = element.nodeName.toLowerCase(); + /** @type {?} */ + let inputType = nodeName === 'input' && ((/** @type {?} */ (element))).type; + return inputType === 'text' + || inputType === 'password' + || nodeName === 'select' + || nodeName === 'textarea'; +} +/** + * Gets whether an element is potentially focusable without taking current visible/disabled state + * into account. + * @param {?} element + * @return {?} + */ +function isPotentiallyFocusable(element) { + // Inputs are potentially focusable *unless* they're type="hidden". + if (isHiddenInput(element)) { + return false; + } + return isNativeFormElement(element) || + isAnchorWithHref(element) || + element.hasAttribute('contenteditable') || + hasValidTabIndex(element); +} +/** + * Gets the parent window of a DOM node with regards of being inside of an iframe. + * @param {?} node + * @return {?} + */ +function getWindow(node) { + // ownerDocument is null if `node` itself *is* a document. + return node.ownerDocument && node.ownerDocument.defaultView || window; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Class that allows for trapping focus within a DOM element. + * + * This class currently uses a relatively simple approach to focus trapping. + * It assumes that the tab order is the same as DOM order, which is not necessarily true. + * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause to two to misalign. + */ +class FocusTrap { + /** + * @param {?} _element + * @param {?} _checker + * @param {?} _ngZone + * @param {?} _document + * @param {?=} deferAnchors + */ + constructor(_element, _checker, _ngZone, _document, deferAnchors = false) { + this._element = _element; + this._checker = _checker; + this._ngZone = _ngZone; + this._document = _document; + this._hasAttached = false; + // Event listeners for the anchors. Need to be regular functions so that we can unbind them later. + this.startAnchorListener = (/** + * @return {?} + */ + () => this.focusLastTabbableElement()); + this.endAnchorListener = (/** + * @return {?} + */ + () => this.focusFirstTabbableElement()); + this._enabled = true; + if (!deferAnchors) { + this.attachAnchors(); + } + } + /** + * Whether the focus trap is active. + * @return {?} + */ + get enabled() { return this._enabled; } + /** + * @param {?} value + * @return {?} + */ + set enabled(value) { + this._enabled = value; + if (this._startAnchor && this._endAnchor) { + this._toggleAnchorTabIndex(value, this._startAnchor); + this._toggleAnchorTabIndex(value, this._endAnchor); + } + } + /** + * Destroys the focus trap by cleaning up the anchors. + * @return {?} + */ + destroy() { + /** @type {?} */ + const startAnchor = this._startAnchor; + /** @type {?} */ + const endAnchor = this._endAnchor; + if (startAnchor) { + startAnchor.removeEventListener('focus', this.startAnchorListener); + if (startAnchor.parentNode) { + startAnchor.parentNode.removeChild(startAnchor); + } + } + if (endAnchor) { + endAnchor.removeEventListener('focus', this.endAnchorListener); + if (endAnchor.parentNode) { + endAnchor.parentNode.removeChild(endAnchor); + } + } + this._startAnchor = this._endAnchor = null; + } + /** + * Inserts the anchors into the DOM. This is usually done automatically + * in the constructor, but can be deferred for cases like directives with `*ngIf`. + * @return {?} Whether the focus trap managed to attach successfuly. This may not be the case + * if the target element isn't currently in the DOM. + */ + attachAnchors() { + // If we're not on the browser, there can be no focus to trap. + if (this._hasAttached) { + return true; + } + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + if (!this._startAnchor) { + this._startAnchor = this._createAnchor(); + (/** @type {?} */ (this._startAnchor)).addEventListener('focus', this.startAnchorListener); + } + if (!this._endAnchor) { + this._endAnchor = this._createAnchor(); + (/** @type {?} */ (this._endAnchor)).addEventListener('focus', this.endAnchorListener); + } + })); + if (this._element.parentNode) { + this._element.parentNode.insertBefore((/** @type {?} */ (this._startAnchor)), this._element); + this._element.parentNode.insertBefore((/** @type {?} */ (this._endAnchor)), this._element.nextSibling); + this._hasAttached = true; + } + return this._hasAttached; + } + /** + * Waits for the zone to stabilize, then either focuses the first element that the + * user specified, or the first tabbable element. + * @return {?} Returns a promise that resolves with a boolean, depending + * on whether focus was moved successfuly. + */ + focusInitialElementWhenReady() { + return new Promise((/** + * @param {?} resolve + * @return {?} + */ + resolve => { + this._executeOnStable((/** + * @return {?} + */ + () => resolve(this.focusInitialElement()))); + })); + } + /** + * Waits for the zone to stabilize, then focuses + * the first tabbable element within the focus trap region. + * @return {?} Returns a promise that resolves with a boolean, depending + * on whether focus was moved successfuly. + */ + focusFirstTabbableElementWhenReady() { + return new Promise((/** + * @param {?} resolve + * @return {?} + */ + resolve => { + this._executeOnStable((/** + * @return {?} + */ + () => resolve(this.focusFirstTabbableElement()))); + })); + } + /** + * Waits for the zone to stabilize, then focuses + * the last tabbable element within the focus trap region. + * @return {?} Returns a promise that resolves with a boolean, depending + * on whether focus was moved successfuly. + */ + focusLastTabbableElementWhenReady() { + return new Promise((/** + * @param {?} resolve + * @return {?} + */ + resolve => { + this._executeOnStable((/** + * @return {?} + */ + () => resolve(this.focusLastTabbableElement()))); + })); + } + /** + * Get the specified boundary element of the trapped region. + * @private + * @param {?} bound The boundary to get (start or end of trapped region). + * @return {?} The boundary element. + */ + _getRegionBoundary(bound) { + // Contains the deprecated version of selector, for temporary backwards comparability. + /** @type {?} */ + let markers = (/** @type {?} */ (this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` + + `[cdkFocusRegion${bound}], ` + + `[cdk-focus-${bound}]`))); + for (let i = 0; i < markers.length; i++) { + // @breaking-change 8.0.0 + if (markers[i].hasAttribute(`cdk-focus-${bound}`)) { + console.warn(`Found use of deprecated attribute 'cdk-focus-${bound}', ` + + `use 'cdkFocusRegion${bound}' instead. The deprecated ` + + `attribute will be removed in 8.0.0.`, markers[i]); + } + else if (markers[i].hasAttribute(`cdk-focus-region-${bound}`)) { + console.warn(`Found use of deprecated attribute 'cdk-focus-region-${bound}', ` + + `use 'cdkFocusRegion${bound}' instead. The deprecated attribute ` + + `will be removed in 8.0.0.`, markers[i]); + } + } + if (bound == 'start') { + return markers.length ? markers[0] : this._getFirstTabbableElement(this._element); + } + return markers.length ? + markers[markers.length - 1] : this._getLastTabbableElement(this._element); + } + /** + * Focuses the element that should be focused when the focus trap is initialized. + * @return {?} Whether focus was moved successfuly. + */ + focusInitialElement() { + // Contains the deprecated version of selector, for temporary backwards comparability. + /** @type {?} */ + const redirectToElement = (/** @type {?} */ (this._element.querySelector(`[cdk-focus-initial], ` + + `[cdkFocusInitial]`))); + if (redirectToElement) { + // @breaking-change 8.0.0 + if (redirectToElement.hasAttribute(`cdk-focus-initial`)) { + console.warn(`Found use of deprecated attribute 'cdk-focus-initial', ` + + `use 'cdkFocusInitial' instead. The deprecated attribute ` + + `will be removed in 8.0.0`, redirectToElement); + } + // Warn the consumer if the element they've pointed to + // isn't focusable, when not in production mode. + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["isDevMode"])() && !this._checker.isFocusable(redirectToElement)) { + console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement); + } + redirectToElement.focus(); + return true; + } + return this.focusFirstTabbableElement(); + } + /** + * Focuses the first tabbable element within the focus trap region. + * @return {?} Whether focus was moved successfuly. + */ + focusFirstTabbableElement() { + /** @type {?} */ + const redirectToElement = this._getRegionBoundary('start'); + if (redirectToElement) { + redirectToElement.focus(); + } + return !!redirectToElement; + } + /** + * Focuses the last tabbable element within the focus trap region. + * @return {?} Whether focus was moved successfuly. + */ + focusLastTabbableElement() { + /** @type {?} */ + const redirectToElement = this._getRegionBoundary('end'); + if (redirectToElement) { + redirectToElement.focus(); + } + return !!redirectToElement; + } + /** + * Checks whether the focus trap has successfuly been attached. + * @return {?} + */ + hasAttached() { + return this._hasAttached; + } + /** + * Get the first tabbable element from a DOM subtree (inclusive). + * @private + * @param {?} root + * @return {?} + */ + _getFirstTabbableElement(root) { + if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) { + return root; + } + // Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall + // back to `childNodes` which includes text nodes, comments etc. + /** @type {?} */ + let children = root.children || root.childNodes; + for (let i = 0; i < children.length; i++) { + /** @type {?} */ + let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? + this._getFirstTabbableElement((/** @type {?} */ (children[i]))) : + null; + if (tabbableChild) { + return tabbableChild; + } + } + return null; + } + /** + * Get the last tabbable element from a DOM subtree (inclusive). + * @private + * @param {?} root + * @return {?} + */ + _getLastTabbableElement(root) { + if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) { + return root; + } + // Iterate in reverse DOM order. + /** @type {?} */ + let children = root.children || root.childNodes; + for (let i = children.length - 1; i >= 0; i--) { + /** @type {?} */ + let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ? + this._getLastTabbableElement((/** @type {?} */ (children[i]))) : + null; + if (tabbableChild) { + return tabbableChild; + } + } + return null; + } + /** + * Creates an anchor element. + * @private + * @return {?} + */ + _createAnchor() { + /** @type {?} */ + const anchor = this._document.createElement('div'); + this._toggleAnchorTabIndex(this._enabled, anchor); + anchor.classList.add('cdk-visually-hidden'); + anchor.classList.add('cdk-focus-trap-anchor'); + anchor.setAttribute('aria-hidden', 'true'); + return anchor; + } + /** + * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap. + * @private + * @param {?} isEnabled Whether the focus trap is enabled. + * @param {?} anchor Anchor on which to toggle the tabindex. + * @return {?} + */ + _toggleAnchorTabIndex(isEnabled, anchor) { + // Remove the tabindex completely, rather than setting it to -1, because if the + // element has a tabindex, the user might still hit it when navigating with the arrow keys. + isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex'); + } + /** + * Executes a function when the zone is stable. + * @private + * @param {?} fn + * @return {?} + */ + _executeOnStable(fn) { + if (this._ngZone.isStable) { + fn(); + } + else { + this._ngZone.onStable.asObservable().pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_4__["take"])(1)).subscribe(fn); + } + } +} +/** + * Factory that allows easy instantiation of focus traps. + */ +class FocusTrapFactory { + /** + * @param {?} _checker + * @param {?} _ngZone + * @param {?} _document + */ + constructor(_checker, _ngZone, _document) { + this._checker = _checker; + this._ngZone = _ngZone; + this._document = _document; + } + /** + * Creates a focus-trapped region around the given element. + * @param {?} element The element around which focus will be trapped. + * @param {?=} deferCaptureElements Defers the creation of focus-capturing elements to be done + * manually by the user. + * @return {?} The created focus trap instance. + */ + create(element, deferCaptureElements = false) { + return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements); + } +} +FocusTrapFactory.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +FocusTrapFactory.ctorParameters = () => [ + { type: InteractivityChecker }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"],] }] } +]; +/** @nocollapse */ FocusTrapFactory.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function FocusTrapFactory_Factory() { return new FocusTrapFactory(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(InteractivityChecker), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"])); }, token: FocusTrapFactory, providedIn: "root" }); +/** + * Directive for trapping focus within a region. + */ +class CdkTrapFocus { + /** + * @param {?} _elementRef + * @param {?} _focusTrapFactory + * @param {?} _document + */ + constructor(_elementRef, _focusTrapFactory, _document) { + this._elementRef = _elementRef; + this._focusTrapFactory = _focusTrapFactory; + /** + * Previously focused element to restore focus to upon destroy when using autoCapture. + */ + this._previouslyFocusedElement = null; + this._document = _document; + this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true); + } + /** + * Whether the focus trap is active. + * @return {?} + */ + get enabled() { return this.focusTrap.enabled; } + /** + * @param {?} value + * @return {?} + */ + set enabled(value) { this.focusTrap.enabled = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_6__["coerceBooleanProperty"])(value); } + /** + * Whether the directive should automatially move focus into the trapped region upon + * initialization and return focus to the previous activeElement upon destruction. + * @return {?} + */ + get autoCapture() { return this._autoCapture; } + /** + * @param {?} value + * @return {?} + */ + set autoCapture(value) { this._autoCapture = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_6__["coerceBooleanProperty"])(value); } + /** + * @return {?} + */ + ngOnDestroy() { + this.focusTrap.destroy(); + // If we stored a previously focused element when using autoCapture, return focus to that + // element now that the trapped region is being destroyed. + if (this._previouslyFocusedElement) { + this._previouslyFocusedElement.focus(); + this._previouslyFocusedElement = null; + } + } + /** + * @return {?} + */ + ngAfterContentInit() { + this.focusTrap.attachAnchors(); + if (this.autoCapture) { + this._previouslyFocusedElement = (/** @type {?} */ (this._document.activeElement)); + this.focusTrap.focusInitialElementWhenReady(); + } + } + /** + * @return {?} + */ + ngDoCheck() { + if (!this.focusTrap.hasAttached()) { + this.focusTrap.attachAnchors(); + } + } +} +CdkTrapFocus.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkTrapFocus]', + exportAs: 'cdkTrapFocus', + },] }, +]; +/** @nocollapse */ +CdkTrapFocus.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: FocusTrapFactory }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"],] }] } +]; +CdkTrapFocus.propDecorators = { + enabled: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkTrapFocus',] }], + autoCapture: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkTrapFocusAutoCapture',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const LIVE_ANNOUNCER_ELEMENT_TOKEN = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["InjectionToken"]('liveAnnouncerElement', { + providedIn: 'root', + factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY, +}); +/** + * \@docs-private + * @return {?} + */ +function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() { + return null; +} +/** + * Injection token that can be used to configure the default options for the LiveAnnouncer. + * @type {?} + */ +const LIVE_ANNOUNCER_DEFAULT_OPTIONS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["InjectionToken"]('LIVE_ANNOUNCER_DEFAULT_OPTIONS'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class LiveAnnouncer { + /** + * @param {?} elementToken + * @param {?} _ngZone + * @param {?} _document + * @param {?=} _defaultOptions + */ + constructor(elementToken, _ngZone, _document, _defaultOptions) { + this._ngZone = _ngZone; + this._defaultOptions = _defaultOptions; + // We inject the live element and document as `any` because the constructor signature cannot + // reference browser globals (HTMLElement, Document) on non-browser environments, since having + // a class decorator causes TypeScript to preserve the constructor signature types. + this._document = _document; + this._liveElement = elementToken || this._createLiveElement(); + } + /** + * @param {?} message + * @param {...?} args + * @return {?} + */ + announce(message, ...args) { + /** @type {?} */ + const defaultOptions = this._defaultOptions; + /** @type {?} */ + let politeness; + /** @type {?} */ + let duration; + if (args.length === 1 && typeof args[0] === 'number') { + duration = args[0]; + } + else { + [politeness, duration] = args; + } + this.clear(); + clearTimeout(this._previousTimeout); + if (!politeness) { + politeness = + (defaultOptions && defaultOptions.politeness) ? defaultOptions.politeness : 'polite'; + } + if (duration == null && defaultOptions) { + duration = defaultOptions.duration; + } + // TODO: ensure changing the politeness works on all environments we support. + this._liveElement.setAttribute('aria-live', politeness); + // This 100ms timeout is necessary for some browser + screen-reader combinations: + // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout. + // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a + // second time without clearing and then using a non-zero delay. + // (using JAWS 17 at time of this writing). + return this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + return new Promise((/** + * @param {?} resolve + * @return {?} + */ + resolve => { + clearTimeout(this._previousTimeout); + this._previousTimeout = setTimeout((/** + * @return {?} + */ + () => { + this._liveElement.textContent = message; + resolve(); + if (typeof duration === 'number') { + this._previousTimeout = setTimeout((/** + * @return {?} + */ + () => this.clear()), duration); + } + }), 100); + })); + })); + } + /** + * Clears the current text from the announcer element. Can be used to prevent + * screen readers from reading the text out again while the user is going + * through the page landmarks. + * @return {?} + */ + clear() { + if (this._liveElement) { + this._liveElement.textContent = ''; + } + } + /** + * @return {?} + */ + ngOnDestroy() { + clearTimeout(this._previousTimeout); + if (this._liveElement && this._liveElement.parentNode) { + this._liveElement.parentNode.removeChild(this._liveElement); + this._liveElement = (/** @type {?} */ (null)); + } + } + /** + * @private + * @return {?} + */ + _createLiveElement() { + /** @type {?} */ + const elementClass = 'cdk-live-announcer-element'; + /** @type {?} */ + const previousElements = this._document.getElementsByClassName(elementClass); + /** @type {?} */ + const liveEl = this._document.createElement('div'); + // Remove any old containers. This can happen when coming in from a server-side-rendered page. + for (let i = 0; i < previousElements.length; i++) { + (/** @type {?} */ (previousElements[i].parentNode)).removeChild(previousElements[i]); + } + liveEl.classList.add(elementClass); + liveEl.classList.add('cdk-visually-hidden'); + liveEl.setAttribute('aria-atomic', 'true'); + liveEl.setAttribute('aria-live', 'polite'); + this._document.body.appendChild(liveEl); + return liveEl; + } +} +LiveAnnouncer.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +LiveAnnouncer.ctorParameters = () => [ + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [LIVE_ANNOUNCER_ELEMENT_TOKEN,] }] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"],] }] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [LIVE_ANNOUNCER_DEFAULT_OPTIONS,] }] } +]; +/** @nocollapse */ LiveAnnouncer.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function LiveAnnouncer_Factory() { return new LiveAnnouncer(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(LIVE_ANNOUNCER_ELEMENT_TOKEN, 8), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(LIVE_ANNOUNCER_DEFAULT_OPTIONS, 8)); }, token: LiveAnnouncer, providedIn: "root" }); +/** + * A directive that works similarly to aria-live, but uses the LiveAnnouncer to ensure compatibility + * with a wider range of browsers and screen readers. + */ +class CdkAriaLive { + /** + * @param {?} _elementRef + * @param {?} _liveAnnouncer + * @param {?} _contentObserver + * @param {?} _ngZone + */ + constructor(_elementRef, _liveAnnouncer, _contentObserver, _ngZone) { + this._elementRef = _elementRef; + this._liveAnnouncer = _liveAnnouncer; + this._contentObserver = _contentObserver; + this._ngZone = _ngZone; + this._politeness = 'off'; + } + /** + * The aria-live politeness level to use when announcing messages. + * @return {?} + */ + get politeness() { return this._politeness; } + /** + * @param {?} value + * @return {?} + */ + set politeness(value) { + this._politeness = value === 'polite' || value === 'assertive' ? value : 'off'; + if (this._politeness === 'off') { + if (this._subscription) { + this._subscription.unsubscribe(); + this._subscription = null; + } + } + else if (!this._subscription) { + this._subscription = this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + return this._contentObserver + .observe(this._elementRef) + .subscribe((/** + * @return {?} + */ + () => { + // Note that we use textContent here, rather than innerText, in order to avoid a reflow. + /** @type {?} */ + const elementText = this._elementRef.nativeElement.textContent; + // The `MutationObserver` fires also for attribute + // changes which we don't want to announce. + if (elementText !== this._previousAnnouncedText) { + this._liveAnnouncer.announce(elementText, this._politeness); + this._previousAnnouncedText = elementText; + } + })); + })); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._subscription) { + this._subscription.unsubscribe(); + } + } +} +CdkAriaLive.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkAriaLive]', + exportAs: 'cdkAriaLive', + },] }, +]; +/** @nocollapse */ +CdkAriaLive.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: LiveAnnouncer }, + { type: _angular_cdk_observers__WEBPACK_IMPORTED_MODULE_7__["ContentObserver"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] } +]; +CdkAriaLive.propDecorators = { + politeness: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkAriaLive',] }] +}; +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} parentAnnouncer + * @param {?} liveElement + * @param {?} _document + * @param {?} ngZone + * @return {?} + */ +function LIVE_ANNOUNCER_PROVIDER_FACTORY(parentAnnouncer, liveElement, _document, ngZone) { + return parentAnnouncer || new LiveAnnouncer(liveElement, ngZone, _document); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const LIVE_ANNOUNCER_PROVIDER = { + // If there is already a LiveAnnouncer available, use that. Otherwise, provide a new one. + provide: LiveAnnouncer, + deps: [ + [new _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_1__["SkipSelf"](), LiveAnnouncer], + [new _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"](LIVE_ANNOUNCER_ELEMENT_TOKEN)], + _angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"], + _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"], + ], + useFactory: LIVE_ANNOUNCER_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found +// that a value of around 650ms seems appropriate. +/** @type {?} */ +const TOUCH_BUFFER_MS = 650; +/** + * Event listener options that enable capturing and also + * mark the listener as passive if the browser supports it. + * @type {?} + */ +const captureEventListenerOptions = Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_5__["normalizePassiveListenerOptions"])({ + passive: true, + capture: true +}); +/** + * Monitors mouse and keyboard events to determine the cause of focus events. + */ +class FocusMonitor { + /** + * @param {?} _ngZone + * @param {?} _platform + */ + constructor(_ngZone, _platform) { + this._ngZone = _ngZone; + this._platform = _platform; + /** + * The focus origin that the next focus event is a result of. + */ + this._origin = null; + /** + * Whether the window has just been focused. + */ + this._windowFocused = false; + /** + * Map of elements being monitored to their info. + */ + this._elementInfo = new Map(); + /** + * The number of elements currently being monitored. + */ + this._monitoredElementCount = 0; + /** + * Event listener for `keydown` events on the document. + * Needs to be an arrow function in order to preserve the context when it gets bound. + */ + this._documentKeydownListener = (/** + * @return {?} + */ + () => { + // On keydown record the origin and clear any touch event that may be in progress. + this._lastTouchTarget = null; + this._setOriginForCurrentEventQueue('keyboard'); + }); + /** + * Event listener for `mousedown` events on the document. + * Needs to be an arrow function in order to preserve the context when it gets bound. + */ + this._documentMousedownListener = (/** + * @return {?} + */ + () => { + // On mousedown record the origin only if there is not touch + // target, since a mousedown can happen as a result of a touch event. + if (!this._lastTouchTarget) { + this._setOriginForCurrentEventQueue('mouse'); + } + }); + /** + * Event listener for `touchstart` events on the document. + * Needs to be an arrow function in order to preserve the context when it gets bound. + */ + this._documentTouchstartListener = (/** + * @param {?} event + * @return {?} + */ + (event) => { + // When the touchstart event fires the focus event is not yet in the event queue. This means + // we can't rely on the trick used above (setting timeout of 1ms). Instead we wait 650ms to + // see if a focus happens. + if (this._touchTimeoutId != null) { + clearTimeout(this._touchTimeoutId); + } + this._lastTouchTarget = event.target; + this._touchTimeoutId = setTimeout((/** + * @return {?} + */ + () => this._lastTouchTarget = null), TOUCH_BUFFER_MS); + }); + /** + * Event listener for `focus` events on the window. + * Needs to be an arrow function in order to preserve the context when it gets bound. + */ + this._windowFocusListener = (/** + * @return {?} + */ + () => { + // Make a note of when the window regains focus, so we can + // restore the origin info for the focused element. + this._windowFocused = true; + this._windowFocusTimeoutId = setTimeout((/** + * @return {?} + */ + () => this._windowFocused = false)); + }); + } + /** + * @param {?} element + * @param {?=} checkChildren + * @return {?} + */ + monitor(element, checkChildren = false) { + // Do nothing if we're not on the browser platform. + if (!this._platform.isBrowser) { + return Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["of"])(null); + } + /** @type {?} */ + const nativeElement = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_6__["coerceElement"])(element); + // Check if we're already monitoring this element. + if (this._elementInfo.has(nativeElement)) { + /** @type {?} */ + let cachedInfo = this._elementInfo.get(nativeElement); + (/** @type {?} */ (cachedInfo)).checkChildren = checkChildren; + return (/** @type {?} */ (cachedInfo)).subject.asObservable(); + } + // Create monitored element info. + /** @type {?} */ + let info = { + unlisten: (/** + * @return {?} + */ + () => { }), + checkChildren: checkChildren, + subject: new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"]() + }; + this._elementInfo.set(nativeElement, info); + this._incrementMonitoredElementCount(); + // Start listening. We need to listen in capture phase since focus events don't bubble. + /** @type {?} */ + let focusListener = (/** + * @param {?} event + * @return {?} + */ + (event) => this._onFocus(event, nativeElement)); + /** @type {?} */ + let blurListener = (/** + * @param {?} event + * @return {?} + */ + (event) => this._onBlur(event, nativeElement)); + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + nativeElement.addEventListener('focus', focusListener, true); + nativeElement.addEventListener('blur', blurListener, true); + })); + // Create an unlisten function for later. + info.unlisten = (/** + * @return {?} + */ + () => { + nativeElement.removeEventListener('focus', focusListener, true); + nativeElement.removeEventListener('blur', blurListener, true); + }); + return info.subject.asObservable(); + } + /** + * @param {?} element + * @return {?} + */ + stopMonitoring(element) { + /** @type {?} */ + const nativeElement = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_6__["coerceElement"])(element); + /** @type {?} */ + const elementInfo = this._elementInfo.get(nativeElement); + if (elementInfo) { + elementInfo.unlisten(); + elementInfo.subject.complete(); + this._setClasses(nativeElement); + this._elementInfo.delete(nativeElement); + this._decrementMonitoredElementCount(); + } + } + /** + * @param {?} element + * @param {?} origin + * @param {?=} options + * @return {?} + */ + focusVia(element, origin, options) { + /** @type {?} */ + const nativeElement = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_6__["coerceElement"])(element); + this._setOriginForCurrentEventQueue(origin); + // `focus` isn't available on the server + if (typeof nativeElement.focus === 'function') { + // Cast the element to `any`, because the TS typings don't have the `options` parameter yet. + ((/** @type {?} */ (nativeElement))).focus(options); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._elementInfo.forEach((/** + * @param {?} _info + * @param {?} element + * @return {?} + */ + (_info, element) => this.stopMonitoring(element))); + } + /** + * @private + * @param {?} element + * @param {?} className + * @param {?} shouldSet + * @return {?} + */ + _toggleClass(element, className, shouldSet) { + if (shouldSet) { + element.classList.add(className); + } + else { + element.classList.remove(className); + } + } + /** + * Sets the focus classes on the element based on the given focus origin. + * @private + * @param {?} element The element to update the classes on. + * @param {?=} origin The focus origin. + * @return {?} + */ + _setClasses(element, origin) { + /** @type {?} */ + const elementInfo = this._elementInfo.get(element); + if (elementInfo) { + this._toggleClass(element, 'cdk-focused', !!origin); + this._toggleClass(element, 'cdk-touch-focused', origin === 'touch'); + this._toggleClass(element, 'cdk-keyboard-focused', origin === 'keyboard'); + this._toggleClass(element, 'cdk-mouse-focused', origin === 'mouse'); + this._toggleClass(element, 'cdk-program-focused', origin === 'program'); + } + } + /** + * Sets the origin and schedules an async function to clear it at the end of the event queue. + * @private + * @param {?} origin The origin to set. + * @return {?} + */ + _setOriginForCurrentEventQueue(origin) { + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + this._origin = origin; + // Sometimes the focus origin won't be valid in Firefox because Firefox seems to focus *one* + // tick after the interaction event fired. To ensure the focus origin is always correct, + // the focus origin will be determined at the beginning of the next tick. + this._originTimeoutId = setTimeout((/** + * @return {?} + */ + () => this._origin = null), 1); + })); + } + /** + * Checks whether the given focus event was caused by a touchstart event. + * @private + * @param {?} event The focus event to check. + * @return {?} Whether the event was caused by a touch. + */ + _wasCausedByTouch(event) { + // Note(mmalerba): This implementation is not quite perfect, there is a small edge case. + // Consider the following dom structure: + // + //
+ //
+ //
+ // + // If the user touches the #child element and the #parent is programmatically focused as a + // result, this code will still consider it to have been caused by the touch event and will + // apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a + // relatively small edge-case that can be worked around by using + // focusVia(parentEl, 'program') to focus the parent element. + // + // If we decide that we absolutely must handle this case correctly, we can do so by listening + // for the first focus event after the touchstart, and then the first blur event after that + // focus event. When that blur event fires we know that whatever follows is not a result of the + // touchstart. + /** @type {?} */ + let focusTarget = event.target; + return this._lastTouchTarget instanceof Node && focusTarget instanceof Node && + (focusTarget === this._lastTouchTarget || focusTarget.contains(this._lastTouchTarget)); + } + /** + * Handles focus events on a registered element. + * @private + * @param {?} event The focus event. + * @param {?} element The monitored element. + * @return {?} + */ + _onFocus(event, element) { + // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent + // focus event affecting the monitored element. If we want to use the origin of the first event + // instead we should check for the cdk-focused class here and return if the element already has + // it. (This only matters for elements that have includesChildren = true). + // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent + // focus event affecting the monitored element. If we want to use the origin of the first event + // instead we should check for the cdk-focused class here and return if the element already has + // it. (This only matters for elements that have includesChildren = true). + // If we are not counting child-element-focus as focused, make sure that the event target is the + // monitored element itself. + /** @type {?} */ + const elementInfo = this._elementInfo.get(element); + if (!elementInfo || (!elementInfo.checkChildren && element !== event.target)) { + return; + } + // If we couldn't detect a cause for the focus event, it's due to one of three reasons: + // 1) The window has just regained focus, in which case we want to restore the focused state of + // the element from before the window blurred. + // 2) It was caused by a touch event, in which case we mark the origin as 'touch'. + // 3) The element was programmatically focused, in which case we should mark the origin as + // 'program'. + /** @type {?} */ + let origin = this._origin; + if (!origin) { + if (this._windowFocused && this._lastFocusOrigin) { + origin = this._lastFocusOrigin; + } + else if (this._wasCausedByTouch(event)) { + origin = 'touch'; + } + else { + origin = 'program'; + } + } + this._setClasses(element, origin); + this._emitOrigin(elementInfo.subject, origin); + this._lastFocusOrigin = origin; + } + /** + * Handles blur events on a registered element. + * @param {?} event The blur event. + * @param {?} element The monitored element. + * @return {?} + */ + _onBlur(event, element) { + // If we are counting child-element-focus as focused, make sure that we aren't just blurring in + // order to focus another child of the monitored element. + /** @type {?} */ + const elementInfo = this._elementInfo.get(element); + if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node && + element.contains(event.relatedTarget))) { + return; + } + this._setClasses(element); + this._emitOrigin(elementInfo.subject, null); + } + /** + * @private + * @param {?} subject + * @param {?} origin + * @return {?} + */ + _emitOrigin(subject, origin) { + this._ngZone.run((/** + * @return {?} + */ + () => subject.next(origin))); + } + /** + * @private + * @return {?} + */ + _incrementMonitoredElementCount() { + // Register global listeners when first element is monitored. + if (++this._monitoredElementCount == 1 && this._platform.isBrowser) { + // Note: we listen to events in the capture phase so we + // can detect them even if the user stops propagation. + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + document.addEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions); + document.addEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions); + document.addEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions); + window.addEventListener('focus', this._windowFocusListener); + })); + } + } + /** + * @private + * @return {?} + */ + _decrementMonitoredElementCount() { + // Unregister global listeners when last element is unmonitored. + if (!--this._monitoredElementCount) { + document.removeEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions); + document.removeEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions); + document.removeEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions); + window.removeEventListener('focus', this._windowFocusListener); + // Clear timeouts for all potentially pending timeouts to prevent the leaks. + clearTimeout(this._windowFocusTimeoutId); + clearTimeout(this._touchTimeoutId); + clearTimeout(this._originTimeoutId); + } + } +} +FocusMonitor.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +FocusMonitor.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] }, + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_5__["Platform"] } +]; +/** @nocollapse */ FocusMonitor.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function FocusMonitor_Factory() { return new FocusMonitor(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_5__["Platform"])); }, token: FocusMonitor, providedIn: "root" }); +/** + * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or + * programmatically) and adds corresponding classes to the element. + * + * There are two variants of this directive: + * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is + * focused. + * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused. + */ +class CdkMonitorFocus { + /** + * @param {?} _elementRef + * @param {?} _focusMonitor + */ + constructor(_elementRef, _focusMonitor) { + this._elementRef = _elementRef; + this._focusMonitor = _focusMonitor; + this.cdkFocusChange = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + this._monitorSubscription = this._focusMonitor.monitor(this._elementRef, this._elementRef.nativeElement.hasAttribute('cdkMonitorSubtreeFocus')) + .subscribe((/** + * @param {?} origin + * @return {?} + */ + origin => this.cdkFocusChange.emit(origin))); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._focusMonitor.stopMonitoring(this._elementRef); + this._monitorSubscription.unsubscribe(); + } +} +CdkMonitorFocus.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]', + },] }, +]; +/** @nocollapse */ +CdkMonitorFocus.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: FocusMonitor } +]; +CdkMonitorFocus.propDecorators = { + cdkFocusChange: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }] +}; +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} parentDispatcher + * @param {?} ngZone + * @param {?} platform + * @return {?} + */ +function FOCUS_MONITOR_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) { + return parentDispatcher || new FocusMonitor(ngZone, platform); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const FOCUS_MONITOR_PROVIDER = { + // If there is already a FocusMonitor available, use that. Otherwise, provide a new one. + provide: FocusMonitor, + deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_1__["SkipSelf"](), FocusMonitor], _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"], _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_5__["Platform"]], + useFactory: FOCUS_MONITOR_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Screenreaders will often fire fake mousedown events when a focusable element + * is activated using the keyboard. We can typically distinguish between these faked + * mousedown events and real mousedown events using the "buttons" property. While + * real mousedowns will indicate the mouse button that was pressed (e.g. "1" for + * the left mouse button), faked mousedowns will usually set the property value to 0. + * @param {?} event + * @return {?} + */ +function isFakeMousedownFromScreenReader(event) { + return event.buttons === 0; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class A11yModule { +} +A11yModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + imports: [_angular_common__WEBPACK_IMPORTED_MODULE_0__["CommonModule"], _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_5__["PlatformModule"], _angular_cdk_observers__WEBPACK_IMPORTED_MODULE_7__["ObserversModule"]], + declarations: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus], + exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=a11y.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/accordion.js": +/*!********************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/accordion.js ***! + \********************************************************/ +/*! exports provided: CdkAccordionItem, CdkAccordion, CdkAccordionModule */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkAccordionItem", function() { return CdkAccordionItem; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkAccordion", function() { return CdkAccordion; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkAccordionModule", function() { return CdkAccordionModule; }); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/cdk/collections */ "./node_modules/@angular/cdk/esm2015/collections.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Used to generate unique ID for each accordion. + * @type {?} + */ +let nextId = 0; +/** + * Directive whose purpose is to manage the expanded state of CdkAccordionItem children. + */ +class CdkAccordion { + constructor() { + /** + * Emits when the state of the accordion changes + */ + this._stateChanges = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * Stream that emits true/false when openAll/closeAll is triggered. + */ + this._openCloseAllActions = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * A readonly id value to use for unique selection coordination. + */ + this.id = `cdk-accordion-${nextId++}`; + this._multi = false; + } + /** + * Whether the accordion should allow multiple expanded accordion items simultaneously. + * @return {?} + */ + get multi() { return this._multi; } + /** + * @param {?} multi + * @return {?} + */ + set multi(multi) { this._multi = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(multi); } + /** + * Opens all enabled accordion items in an accordion where multi is enabled. + * @return {?} + */ + openAll() { + this._openCloseAll(true); + } + /** + * Closes all enabled accordion items in an accordion where multi is enabled. + * @return {?} + */ + closeAll() { + this._openCloseAll(false); + } + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + this._stateChanges.next(changes); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._stateChanges.complete(); + } + /** + * @private + * @param {?} expanded + * @return {?} + */ + _openCloseAll(expanded) { + if (this.multi) { + this._openCloseAllActions.next(expanded); + } + } +} +CdkAccordion.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'cdk-accordion, [cdkAccordion]', + exportAs: 'cdkAccordion', + },] }, +]; +CdkAccordion.propDecorators = { + multi: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Used to generate unique ID for each accordion item. + * @type {?} + */ +let nextId$1 = 0; +const ɵ0 = undefined; +/** + * An basic directive expected to be extended and decorated as a component. Sets up all + * events and attributes needed to be managed by a CdkAccordion parent. + */ +class CdkAccordionItem { + /** + * @param {?} accordion + * @param {?} _changeDetectorRef + * @param {?} _expansionDispatcher + */ + constructor(accordion, _changeDetectorRef, _expansionDispatcher) { + this.accordion = accordion; + this._changeDetectorRef = _changeDetectorRef; + this._expansionDispatcher = _expansionDispatcher; + /** + * Subscription to openAll/closeAll events. + */ + this._openCloseAllSubscription = rxjs__WEBPACK_IMPORTED_MODULE_2__["Subscription"].EMPTY; + /** + * Event emitted every time the AccordionItem is closed. + */ + this.closed = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + /** + * Event emitted every time the AccordionItem is opened. + */ + this.opened = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + /** + * Event emitted when the AccordionItem is destroyed. + */ + this.destroyed = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + /** + * Emits whenever the expanded state of the accordion changes. + * Primarily used to facilitate two-way binding. + * \@docs-private + */ + this.expandedChange = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + /** + * The unique AccordionItem id. + */ + this.id = `cdk-accordion-child-${nextId$1++}`; + this._expanded = false; + this._disabled = false; + /** + * Unregister function for _expansionDispatcher. + */ + this._removeUniqueSelectionListener = (/** + * @return {?} + */ + () => { }); + this._removeUniqueSelectionListener = + _expansionDispatcher.listen((/** + * @param {?} id + * @param {?} accordionId + * @return {?} + */ + (id, accordionId) => { + if (this.accordion && !this.accordion.multi && + this.accordion.id === accordionId && this.id !== id) { + this.expanded = false; + } + })); + // When an accordion item is hosted in an accordion, subscribe to open/close events. + if (this.accordion) { + this._openCloseAllSubscription = this._subscribeToOpenCloseAllActions(); + } + } + /** + * Whether the AccordionItem is expanded. + * @return {?} + */ + get expanded() { return this._expanded; } + /** + * @param {?} expanded + * @return {?} + */ + set expanded(expanded) { + expanded = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(expanded); + // Only emit events and update the internal value if the value changes. + if (this._expanded !== expanded) { + this._expanded = expanded; + this.expandedChange.emit(expanded); + if (expanded) { + this.opened.emit(); + /** + * In the unique selection dispatcher, the id parameter is the id of the CdkAccordionItem, + * the name value is the id of the accordion. + * @type {?} + */ + const accordionId = this.accordion ? this.accordion.id : this.id; + this._expansionDispatcher.notify(this.id, accordionId); + } + else { + this.closed.emit(); + } + // Ensures that the animation will run when the value is set outside of an `@Input`. + // This includes cases like the open, close and toggle methods. + this._changeDetectorRef.markForCheck(); + } + } + /** + * Whether the AccordionItem is disabled. + * @return {?} + */ + get disabled() { return this._disabled; } + /** + * @param {?} disabled + * @return {?} + */ + set disabled(disabled) { this._disabled = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(disabled); } + /** + * Emits an event for the accordion item being destroyed. + * @return {?} + */ + ngOnDestroy() { + this.opened.complete(); + this.closed.complete(); + this.destroyed.emit(); + this.destroyed.complete(); + this._removeUniqueSelectionListener(); + this._openCloseAllSubscription.unsubscribe(); + } + /** + * Toggles the expanded state of the accordion item. + * @return {?} + */ + toggle() { + if (!this.disabled) { + this.expanded = !this.expanded; + } + } + /** + * Sets the expanded state of the accordion item to false. + * @return {?} + */ + close() { + if (!this.disabled) { + this.expanded = false; + } + } + /** + * Sets the expanded state of the accordion item to true. + * @return {?} + */ + open() { + if (!this.disabled) { + this.expanded = true; + } + } + /** + * @private + * @return {?} + */ + _subscribeToOpenCloseAllActions() { + return this.accordion._openCloseAllActions.subscribe((/** + * @param {?} expanded + * @return {?} + */ + expanded => { + // Only change expanded state if item is enabled + if (!this.disabled) { + this.expanded = expanded; + } + })); + } +} +CdkAccordionItem.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'cdk-accordion-item, [cdkAccordionItem]', + exportAs: 'cdkAccordionItem', + providers: [ + // Provide CdkAccordion as undefined to prevent nested accordion items from registering + // to the same accordion. + { provide: CdkAccordion, useValue: ɵ0 }, + ], + },] }, +]; +/** @nocollapse */ +CdkAccordionItem.ctorParameters = () => [ + { type: CdkAccordion, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["SkipSelf"] }] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectorRef"] }, + { type: _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__["UniqueSelectionDispatcher"] } +]; +CdkAccordionItem.propDecorators = { + closed: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }], + opened: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }], + destroyed: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }], + expandedChange: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }], + expanded: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + disabled: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class CdkAccordionModule { +} +CdkAccordionModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + exports: [CdkAccordion, CdkAccordionItem], + declarations: [CdkAccordion, CdkAccordionItem], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=accordion.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/bidi.js": +/*!***************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/bidi.js ***! + \***************************************************/ +/*! exports provided: Directionality, DIR_DOCUMENT, Dir, BidiModule, ɵa */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Directionality", function() { return Directionality; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DIR_DOCUMENT", function() { return DIR_DOCUMENT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Dir", function() { return Dir; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BidiModule", function() { return BidiModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵa", function() { return DIR_DOCUMENT_FACTORY; }); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Injection token used to inject the document into Directionality. + * This is used so that the value can be faked in tests. + * + * We can't use the real document in tests because changing the real `dir` causes geometry-based + * tests in Safari to fail. + * + * We also can't re-provide the DOCUMENT token from platform-brower because the unit tests + * themselves use things like `querySelector` in test code. + * + * This token is defined in a separate file from Directionality as a workaround for + * https://github.com/angular/angular/issues/22559 + * + * \@docs-private + * @type {?} + */ +const DIR_DOCUMENT = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["InjectionToken"]('cdk-dir-doc', { + providedIn: 'root', + factory: DIR_DOCUMENT_FACTORY, +}); +/** + * \@docs-private + * @return {?} + */ +function DIR_DOCUMENT_FACTORY() { + return Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["inject"])(_angular_common__WEBPACK_IMPORTED_MODULE_0__["DOCUMENT"]); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * The directionality (LTR / RTL) context for the application (or a subtree of it). + * Exposes the current direction and a stream of direction changes. + */ +class Directionality { + /** + * @param {?=} _document + */ + constructor(_document) { + /** + * The current 'ltr' or 'rtl' value. + */ + this.value = 'ltr'; + /** + * Stream that emits whenever the 'ltr' / 'rtl' state changes. + */ + this.change = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + if (_document) { + // TODO: handle 'auto' value - + // We still need to account for dir="auto". + // It looks like HTMLElemenet.dir is also "auto" when that's set to the attribute, + // but getComputedStyle return either "ltr" or "rtl". avoiding getComputedStyle for now + /** @type {?} */ + const bodyDir = _document.body ? _document.body.dir : null; + /** @type {?} */ + const htmlDir = _document.documentElement ? _document.documentElement.dir : null; + /** @type {?} */ + const value = bodyDir || htmlDir; + this.value = (value === 'ltr' || value === 'rtl') ? value : 'ltr'; + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this.change.complete(); + } +} +Directionality.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +Directionality.ctorParameters = () => [ + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [DIR_DOCUMENT,] }] } +]; +/** @nocollapse */ Directionality.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function Directionality_Factory() { return new Directionality(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(DIR_DOCUMENT, 8)); }, token: Directionality, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Directive to listen for changes of direction of part of the DOM. + * + * Provides itself as Directionality such that descendant directives only need to ever inject + * Directionality to get the closest direction. + */ +class Dir { + constructor() { + /** + * Normalized direction that accounts for invalid/unsupported values. + */ + this._dir = 'ltr'; + /** + * Whether the `value` has been set to its initial value. + */ + this._isInitialized = false; + /** + * Event emitted when the direction changes. + */ + this.change = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + } + /** + * \@docs-private + * @return {?} + */ + get dir() { return this._dir; } + /** + * @param {?} value + * @return {?} + */ + set dir(value) { + /** @type {?} */ + const old = this._dir; + /** @type {?} */ + const normalizedValue = value ? value.toLowerCase() : value; + this._rawDir = value; + this._dir = (normalizedValue === 'ltr' || normalizedValue === 'rtl') ? normalizedValue : 'ltr'; + if (old !== this._dir && this._isInitialized) { + this.change.emit(this._dir); + } + } + /** + * Current layout direction of the element. + * @return {?} + */ + get value() { return this.dir; } + /** + * Initialize once default value has been set. + * @return {?} + */ + ngAfterContentInit() { + this._isInitialized = true; + } + /** + * @return {?} + */ + ngOnDestroy() { + this.change.complete(); + } +} +Dir.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[dir]', + providers: [{ provide: Directionality, useExisting: Dir }], + host: { '[attr.dir]': '_rawDir' }, + exportAs: 'dir', + },] }, +]; +Dir.propDecorators = { + change: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"], args: ['dirChange',] }], + dir: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class BidiModule { +} +BidiModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + exports: [Dir], + declarations: [Dir], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=bidi.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/cdk.js": +/*!**************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/cdk.js ***! + \**************************************************/ +/*! exports provided: VERSION */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Current version of the Angular Component Development Kit. + * @type {?} + */ +const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Version"]('8.1.1'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=cdk.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/coercion.js": +/*!*******************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/coercion.js ***! + \*******************************************************/ +/*! exports provided: coerceBooleanProperty, coerceNumberProperty, _isNumberValue, coerceArray, coerceCssPixelValue, coerceElement */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "coerceBooleanProperty", function() { return coerceBooleanProperty; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "coerceNumberProperty", function() { return coerceNumberProperty; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_isNumberValue", function() { return _isNumberValue; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "coerceArray", function() { return coerceArray; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "coerceCssPixelValue", function() { return coerceCssPixelValue; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "coerceElement", function() { return coerceElement; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Coerces a data-bound value (typically a string) to a boolean. + * @param {?} value + * @return {?} + */ +function coerceBooleanProperty(value) { + return value != null && `${value}` !== 'false'; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @param {?} value + * @param {?=} fallbackValue + * @return {?} + */ +function coerceNumberProperty(value, fallbackValue = 0) { + return _isNumberValue(value) ? Number(value) : fallbackValue; +} +/** + * Whether the provided value is considered a number. + * \@docs-private + * @param {?} value + * @return {?} + */ +function _isNumberValue(value) { + // parseFloat(value) handles most of the cases we're interested in (it treats null, empty string, + // and other non-number values as NaN, where Number just uses 0) but it considers the string + // '123hello' to be a valid number. Therefore we also check if Number(value) is NaN. + return !isNaN(parseFloat((/** @type {?} */ (value)))) && !isNaN(Number(value)); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Wraps the provided value in an array, unless the provided value is an array. + * @template T + * @param {?} value + * @return {?} + */ +function coerceArray(value) { + return Array.isArray(value) ? value : [value]; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Coerces a value to a CSS pixel value. + * @param {?} value + * @return {?} + */ +function coerceCssPixelValue(value) { + if (value == null) { + return ''; + } + return typeof value === 'string' ? value : `${value}px`; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Coerces an ElementRef or an Element into an element. + * Useful for APIs that can accept either a ref or the native element itself. + * @template T + * @param {?} elementOrRef + * @return {?} + */ +function coerceElement(elementOrRef) { + return elementOrRef instanceof _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] ? elementOrRef.nativeElement : elementOrRef; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=coercion.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/collections.js": +/*!**********************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/collections.js ***! + \**********************************************************/ +/*! exports provided: UniqueSelectionDispatcher, ArrayDataSource, isDataSource, DataSource, getMultipleValuesInSingleSelectionError, SelectionModel */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UniqueSelectionDispatcher", function() { return UniqueSelectionDispatcher; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayDataSource", function() { return ArrayDataSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isDataSource", function() { return isDataSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DataSource", function() { return DataSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMultipleValuesInSingleSelectionError", function() { return getMultipleValuesInSingleSelectionError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectionModel", function() { return SelectionModel; }); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @abstract + * @template T + */ +class DataSource { +} +/** + * Checks whether an object is a data source. + * @param {?} value + * @return {?} + */ +function isDataSource(value) { + // Check if the value is a DataSource by observing if it has a connect function. Cannot + // be checked as an `instanceof DataSource` since people could create their own sources + // that match the interface, but don't extend DataSource. + return value && typeof value.connect === 'function'; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * DataSource wrapper for a native array. + * @template T + */ +class ArrayDataSource extends DataSource { + /** + * @param {?} _data + */ + constructor(_data) { + super(); + this._data = _data; + } + /** + * @return {?} + */ + connect() { + return this._data instanceof rxjs__WEBPACK_IMPORTED_MODULE_0__["Observable"] ? this._data : Object(rxjs__WEBPACK_IMPORTED_MODULE_0__["of"])(this._data); + } + /** + * @return {?} + */ + disconnect() { } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Class to be used to power selecting one or more options from a list. + * @template T + */ +class SelectionModel { + /** + * @param {?=} _multiple + * @param {?=} initiallySelectedValues + * @param {?=} _emitChanges + */ + constructor(_multiple = false, initiallySelectedValues, _emitChanges = true) { + this._multiple = _multiple; + this._emitChanges = _emitChanges; + /** + * Currently-selected values. + */ + this._selection = new Set(); + /** + * Keeps track of the deselected options that haven't been emitted by the change event. + */ + this._deselectedToEmit = []; + /** + * Keeps track of the selected options that haven't been emitted by the change event. + */ + this._selectedToEmit = []; + /** + * Event emitted when the value has changed. + */ + this.changed = new rxjs__WEBPACK_IMPORTED_MODULE_0__["Subject"](); + /** + * Event emitted when the value has changed. + * @deprecated Use `changed` instead. + * \@breaking-change 8.0.0 To be changed to `changed` + */ + this.onChange = this.changed; + if (initiallySelectedValues && initiallySelectedValues.length) { + if (_multiple) { + initiallySelectedValues.forEach((/** + * @param {?} value + * @return {?} + */ + value => this._markSelected(value))); + } + else { + this._markSelected(initiallySelectedValues[0]); + } + // Clear the array in order to avoid firing the change event for preselected values. + this._selectedToEmit.length = 0; + } + } + /** + * Selected values. + * @return {?} + */ + get selected() { + if (!this._selected) { + this._selected = Array.from(this._selection.values()); + } + return this._selected; + } + /** + * Selects a value or an array of values. + * @param {...?} values + * @return {?} + */ + select(...values) { + this._verifyValueAssignment(values); + values.forEach((/** + * @param {?} value + * @return {?} + */ + value => this._markSelected(value))); + this._emitChangeEvent(); + } + /** + * Deselects a value or an array of values. + * @param {...?} values + * @return {?} + */ + deselect(...values) { + this._verifyValueAssignment(values); + values.forEach((/** + * @param {?} value + * @return {?} + */ + value => this._unmarkSelected(value))); + this._emitChangeEvent(); + } + /** + * Toggles a value between selected and deselected. + * @param {?} value + * @return {?} + */ + toggle(value) { + this.isSelected(value) ? this.deselect(value) : this.select(value); + } + /** + * Clears all of the selected values. + * @return {?} + */ + clear() { + this._unmarkAll(); + this._emitChangeEvent(); + } + /** + * Determines whether a value is selected. + * @param {?} value + * @return {?} + */ + isSelected(value) { + return this._selection.has(value); + } + /** + * Determines whether the model does not have a value. + * @return {?} + */ + isEmpty() { + return this._selection.size === 0; + } + /** + * Determines whether the model has a value. + * @return {?} + */ + hasValue() { + return !this.isEmpty(); + } + /** + * Sorts the selected values based on a predicate function. + * @param {?=} predicate + * @return {?} + */ + sort(predicate) { + if (this._multiple && this.selected) { + (/** @type {?} */ (this._selected)).sort(predicate); + } + } + /** + * Gets whether multiple values can be selected. + * @return {?} + */ + isMultipleSelection() { + return this._multiple; + } + /** + * Emits a change event and clears the records of selected and deselected values. + * @private + * @return {?} + */ + _emitChangeEvent() { + // Clear the selected values so they can be re-cached. + this._selected = null; + if (this._selectedToEmit.length || this._deselectedToEmit.length) { + this.changed.next({ + source: this, + added: this._selectedToEmit, + removed: this._deselectedToEmit + }); + this._deselectedToEmit = []; + this._selectedToEmit = []; + } + } + /** + * Selects a value. + * @private + * @param {?} value + * @return {?} + */ + _markSelected(value) { + if (!this.isSelected(value)) { + if (!this._multiple) { + this._unmarkAll(); + } + this._selection.add(value); + if (this._emitChanges) { + this._selectedToEmit.push(value); + } + } + } + /** + * Deselects a value. + * @private + * @param {?} value + * @return {?} + */ + _unmarkSelected(value) { + if (this.isSelected(value)) { + this._selection.delete(value); + if (this._emitChanges) { + this._deselectedToEmit.push(value); + } + } + } + /** + * Clears out the selected values. + * @private + * @return {?} + */ + _unmarkAll() { + if (!this.isEmpty()) { + this._selection.forEach((/** + * @param {?} value + * @return {?} + */ + value => this._unmarkSelected(value))); + } + } + /** + * Verifies the value assignment and throws an error if the specified value array is + * including multiple values while the selection model is not supporting multiple values. + * @private + * @param {?} values + * @return {?} + */ + _verifyValueAssignment(values) { + if (values.length > 1 && !this._multiple) { + throw getMultipleValuesInSingleSelectionError(); + } + } +} +/** + * Returns an error that reports that multiple values are passed into a selection model + * with a single value. + * \@docs-private + * @return {?} + */ +function getMultipleValuesInSingleSelectionError() { + return Error('Cannot pass multiple values into SelectionModel with single-value mode.'); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Class to coordinate unique selection based on name. + * Intended to be consumed as an Angular service. + * This service is needed because native radio change events are only fired on the item currently + * being selected, and we still need to uncheck the previous selection. + * + * This service does not *store* any IDs and names because they may change at any time, so it is + * less error-prone if they are simply passed through when the events occur. + */ +class UniqueSelectionDispatcher { + constructor() { + this._listeners = []; + } + /** + * Notify other items that selection for the given name has been set. + * @param {?} id ID of the item. + * @param {?} name Name of the item. + * @return {?} + */ + notify(id, name) { + for (let listener of this._listeners) { + listener(id, name); + } + } + /** + * Listen for future changes to item selection. + * @param {?} listener + * @return {?} Function used to deregister listener + */ + listen(listener) { + this._listeners.push(listener); + return (/** + * @return {?} + */ + () => { + this._listeners = this._listeners.filter((/** + * @param {?} registered + * @return {?} + */ + (registered) => { + return listener !== registered; + })); + }); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._listeners = []; + } +} +UniqueSelectionDispatcher.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ UniqueSelectionDispatcher.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function UniqueSelectionDispatcher_Factory() { return new UniqueSelectionDispatcher(); }, token: UniqueSelectionDispatcher, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=collections.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/keycodes.js": +/*!*******************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/keycodes.js ***! + \*******************************************************/ +/*! exports provided: MAC_ENTER, BACKSPACE, TAB, NUM_CENTER, ENTER, SHIFT, CONTROL, ALT, PAUSE, CAPS_LOCK, ESCAPE, SPACE, PAGE_UP, PAGE_DOWN, END, HOME, LEFT_ARROW, UP_ARROW, RIGHT_ARROW, DOWN_ARROW, PLUS_SIGN, PRINT_SCREEN, INSERT, DELETE, ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, FF_SEMICOLON, FF_EQUALS, QUESTION_MARK, AT_SIGN, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, META, MAC_WK_CMD_LEFT, MAC_WK_CMD_RIGHT, CONTEXT_MENU, NUMPAD_ZERO, NUMPAD_ONE, NUMPAD_TWO, NUMPAD_THREE, NUMPAD_FOUR, NUMPAD_FIVE, NUMPAD_SIX, NUMPAD_SEVEN, NUMPAD_EIGHT, NUMPAD_NINE, NUMPAD_MULTIPLY, NUMPAD_PLUS, NUMPAD_MINUS, NUMPAD_PERIOD, NUMPAD_DIVIDE, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, NUM_LOCK, SCROLL_LOCK, FIRST_MEDIA, FF_MINUS, MUTE, VOLUME_DOWN, VOLUME_UP, FF_MUTE, FF_VOLUME_DOWN, LAST_MEDIA, FF_VOLUME_UP, SEMICOLON, EQUALS, COMMA, DASH, SLASH, APOSTROPHE, TILDE, OPEN_SQUARE_BRACKET, BACKSLASH, CLOSE_SQUARE_BRACKET, SINGLE_QUOTE, MAC_META, hasModifierKey */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MAC_ENTER", function() { return MAC_ENTER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BACKSPACE", function() { return BACKSPACE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TAB", function() { return TAB; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUM_CENTER", function() { return NUM_CENTER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ENTER", function() { return ENTER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SHIFT", function() { return SHIFT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CONTROL", function() { return CONTROL; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ALT", function() { return ALT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PAUSE", function() { return PAUSE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CAPS_LOCK", function() { return CAPS_LOCK; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ESCAPE", function() { return ESCAPE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SPACE", function() { return SPACE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PAGE_UP", function() { return PAGE_UP; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PAGE_DOWN", function() { return PAGE_DOWN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "END", function() { return END; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HOME", function() { return HOME; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LEFT_ARROW", function() { return LEFT_ARROW; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UP_ARROW", function() { return UP_ARROW; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RIGHT_ARROW", function() { return RIGHT_ARROW; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DOWN_ARROW", function() { return DOWN_ARROW; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PLUS_SIGN", function() { return PLUS_SIGN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PRINT_SCREEN", function() { return PRINT_SCREEN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "INSERT", function() { return INSERT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DELETE", function() { return DELETE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZERO", function() { return ZERO; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ONE", function() { return ONE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TWO", function() { return TWO; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "THREE", function() { return THREE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FOUR", function() { return FOUR; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FIVE", function() { return FIVE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SIX", function() { return SIX; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SEVEN", function() { return SEVEN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EIGHT", function() { return EIGHT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NINE", function() { return NINE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_SEMICOLON", function() { return FF_SEMICOLON; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_EQUALS", function() { return FF_EQUALS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QUESTION_MARK", function() { return QUESTION_MARK; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AT_SIGN", function() { return AT_SIGN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "A", function() { return A; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "B", function() { return B; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "C", function() { return C; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "D", function() { return D; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "E", function() { return E; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F", function() { return F; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "G", function() { return G; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "H", function() { return H; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I", function() { return I; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "J", function() { return J; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "K", function() { return K; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "L", function() { return L; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "M", function() { return M; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "N", function() { return N; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "O", function() { return O; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "P", function() { return P; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Q", function() { return Q; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R", function() { return R; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "S", function() { return S; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "T", function() { return T; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "U", function() { return U; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "V", function() { return V; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "W", function() { return W; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "X", function() { return X; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Y", function() { return Y; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Z", function() { return Z; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "META", function() { return META; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MAC_WK_CMD_LEFT", function() { return MAC_WK_CMD_LEFT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MAC_WK_CMD_RIGHT", function() { return MAC_WK_CMD_RIGHT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CONTEXT_MENU", function() { return CONTEXT_MENU; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_ZERO", function() { return NUMPAD_ZERO; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_ONE", function() { return NUMPAD_ONE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_TWO", function() { return NUMPAD_TWO; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_THREE", function() { return NUMPAD_THREE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_FOUR", function() { return NUMPAD_FOUR; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_FIVE", function() { return NUMPAD_FIVE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_SIX", function() { return NUMPAD_SIX; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_SEVEN", function() { return NUMPAD_SEVEN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_EIGHT", function() { return NUMPAD_EIGHT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_NINE", function() { return NUMPAD_NINE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_MULTIPLY", function() { return NUMPAD_MULTIPLY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_PLUS", function() { return NUMPAD_PLUS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_MINUS", function() { return NUMPAD_MINUS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_PERIOD", function() { return NUMPAD_PERIOD; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUMPAD_DIVIDE", function() { return NUMPAD_DIVIDE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F1", function() { return F1; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F2", function() { return F2; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F3", function() { return F3; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F4", function() { return F4; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F5", function() { return F5; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F6", function() { return F6; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F7", function() { return F7; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F8", function() { return F8; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F9", function() { return F9; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F10", function() { return F10; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F11", function() { return F11; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "F12", function() { return F12; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NUM_LOCK", function() { return NUM_LOCK; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SCROLL_LOCK", function() { return SCROLL_LOCK; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FIRST_MEDIA", function() { return FIRST_MEDIA; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_MINUS", function() { return FF_MINUS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MUTE", function() { return MUTE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VOLUME_DOWN", function() { return VOLUME_DOWN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VOLUME_UP", function() { return VOLUME_UP; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_MUTE", function() { return FF_MUTE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_VOLUME_DOWN", function() { return FF_VOLUME_DOWN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LAST_MEDIA", function() { return LAST_MEDIA; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FF_VOLUME_UP", function() { return FF_VOLUME_UP; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SEMICOLON", function() { return SEMICOLON; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EQUALS", function() { return EQUALS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "COMMA", function() { return COMMA; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DASH", function() { return DASH; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SLASH", function() { return SLASH; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "APOSTROPHE", function() { return APOSTROPHE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TILDE", function() { return TILDE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OPEN_SQUARE_BRACKET", function() { return OPEN_SQUARE_BRACKET; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BACKSLASH", function() { return BACKSLASH; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CLOSE_SQUARE_BRACKET", function() { return CLOSE_SQUARE_BRACKET; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SINGLE_QUOTE", function() { return SINGLE_QUOTE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MAC_META", function() { return MAC_META; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasModifierKey", function() { return hasModifierKey; }); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** @type {?} */ +const MAC_ENTER = 3; +/** @type {?} */ +const BACKSPACE = 8; +/** @type {?} */ +const TAB = 9; +/** @type {?} */ +const NUM_CENTER = 12; +/** @type {?} */ +const ENTER = 13; +/** @type {?} */ +const SHIFT = 16; +/** @type {?} */ +const CONTROL = 17; +/** @type {?} */ +const ALT = 18; +/** @type {?} */ +const PAUSE = 19; +/** @type {?} */ +const CAPS_LOCK = 20; +/** @type {?} */ +const ESCAPE = 27; +/** @type {?} */ +const SPACE = 32; +/** @type {?} */ +const PAGE_UP = 33; +/** @type {?} */ +const PAGE_DOWN = 34; +/** @type {?} */ +const END = 35; +/** @type {?} */ +const HOME = 36; +/** @type {?} */ +const LEFT_ARROW = 37; +/** @type {?} */ +const UP_ARROW = 38; +/** @type {?} */ +const RIGHT_ARROW = 39; +/** @type {?} */ +const DOWN_ARROW = 40; +/** @type {?} */ +const PLUS_SIGN = 43; +/** @type {?} */ +const PRINT_SCREEN = 44; +/** @type {?} */ +const INSERT = 45; +/** @type {?} */ +const DELETE = 46; +/** @type {?} */ +const ZERO = 48; +/** @type {?} */ +const ONE = 49; +/** @type {?} */ +const TWO = 50; +/** @type {?} */ +const THREE = 51; +/** @type {?} */ +const FOUR = 52; +/** @type {?} */ +const FIVE = 53; +/** @type {?} */ +const SIX = 54; +/** @type {?} */ +const SEVEN = 55; +/** @type {?} */ +const EIGHT = 56; +/** @type {?} */ +const NINE = 57; +/** @type {?} */ +const FF_SEMICOLON = 59; +// Firefox (Gecko) fires this for semicolon instead of 186 +/** @type {?} */ +const FF_EQUALS = 61; +// Firefox (Gecko) fires this for equals instead of 187 +/** @type {?} */ +const QUESTION_MARK = 63; +/** @type {?} */ +const AT_SIGN = 64; +/** @type {?} */ +const A = 65; +/** @type {?} */ +const B = 66; +/** @type {?} */ +const C = 67; +/** @type {?} */ +const D = 68; +/** @type {?} */ +const E = 69; +/** @type {?} */ +const F = 70; +/** @type {?} */ +const G = 71; +/** @type {?} */ +const H = 72; +/** @type {?} */ +const I = 73; +/** @type {?} */ +const J = 74; +/** @type {?} */ +const K = 75; +/** @type {?} */ +const L = 76; +/** @type {?} */ +const M = 77; +/** @type {?} */ +const N = 78; +/** @type {?} */ +const O = 79; +/** @type {?} */ +const P = 80; +/** @type {?} */ +const Q = 81; +/** @type {?} */ +const R = 82; +/** @type {?} */ +const S = 83; +/** @type {?} */ +const T = 84; +/** @type {?} */ +const U = 85; +/** @type {?} */ +const V = 86; +/** @type {?} */ +const W = 87; +/** @type {?} */ +const X = 88; +/** @type {?} */ +const Y = 89; +/** @type {?} */ +const Z = 90; +/** @type {?} */ +const META = 91; +// WIN_KEY_LEFT +/** @type {?} */ +const MAC_WK_CMD_LEFT = 91; +/** @type {?} */ +const MAC_WK_CMD_RIGHT = 93; +/** @type {?} */ +const CONTEXT_MENU = 93; +/** @type {?} */ +const NUMPAD_ZERO = 96; +/** @type {?} */ +const NUMPAD_ONE = 97; +/** @type {?} */ +const NUMPAD_TWO = 98; +/** @type {?} */ +const NUMPAD_THREE = 99; +/** @type {?} */ +const NUMPAD_FOUR = 100; +/** @type {?} */ +const NUMPAD_FIVE = 101; +/** @type {?} */ +const NUMPAD_SIX = 102; +/** @type {?} */ +const NUMPAD_SEVEN = 103; +/** @type {?} */ +const NUMPAD_EIGHT = 104; +/** @type {?} */ +const NUMPAD_NINE = 105; +/** @type {?} */ +const NUMPAD_MULTIPLY = 106; +/** @type {?} */ +const NUMPAD_PLUS = 107; +/** @type {?} */ +const NUMPAD_MINUS = 109; +/** @type {?} */ +const NUMPAD_PERIOD = 110; +/** @type {?} */ +const NUMPAD_DIVIDE = 111; +/** @type {?} */ +const F1 = 112; +/** @type {?} */ +const F2 = 113; +/** @type {?} */ +const F3 = 114; +/** @type {?} */ +const F4 = 115; +/** @type {?} */ +const F5 = 116; +/** @type {?} */ +const F6 = 117; +/** @type {?} */ +const F7 = 118; +/** @type {?} */ +const F8 = 119; +/** @type {?} */ +const F9 = 120; +/** @type {?} */ +const F10 = 121; +/** @type {?} */ +const F11 = 122; +/** @type {?} */ +const F12 = 123; +/** @type {?} */ +const NUM_LOCK = 144; +/** @type {?} */ +const SCROLL_LOCK = 145; +/** @type {?} */ +const FIRST_MEDIA = 166; +/** @type {?} */ +const FF_MINUS = 173; +/** @type {?} */ +const MUTE = 173; +// Firefox (Gecko) fires 181 for MUTE +/** @type {?} */ +const VOLUME_DOWN = 174; +// Firefox (Gecko) fires 182 for VOLUME_DOWN +/** @type {?} */ +const VOLUME_UP = 175; +// Firefox (Gecko) fires 183 for VOLUME_UP +/** @type {?} */ +const FF_MUTE = 181; +/** @type {?} */ +const FF_VOLUME_DOWN = 182; +/** @type {?} */ +const LAST_MEDIA = 183; +/** @type {?} */ +const FF_VOLUME_UP = 183; +/** @type {?} */ +const SEMICOLON = 186; +// Firefox (Gecko) fires 59 for SEMICOLON +/** @type {?} */ +const EQUALS = 187; +// Firefox (Gecko) fires 61 for EQUALS +/** @type {?} */ +const COMMA = 188; +/** @type {?} */ +const DASH = 189; +// Firefox (Gecko) fires 173 for DASH/MINUS +/** @type {?} */ +const SLASH = 191; +/** @type {?} */ +const APOSTROPHE = 192; +/** @type {?} */ +const TILDE = 192; +/** @type {?} */ +const OPEN_SQUARE_BRACKET = 219; +/** @type {?} */ +const BACKSLASH = 220; +/** @type {?} */ +const CLOSE_SQUARE_BRACKET = 221; +/** @type {?} */ +const SINGLE_QUOTE = 222; +/** @type {?} */ +const MAC_META = 224; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Checks whether a modifier key is pressed. + * @param {?} event Event to be checked. + * @param {...?} modifiers + * @return {?} + */ +function hasModifierKey(event, ...modifiers) { + if (modifiers.length) { + return modifiers.some((/** + * @param {?} modifier + * @return {?} + */ + modifier => event[modifier])); + } + return event.altKey || event.shiftKey || event.ctrlKey || event.metaKey; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=keycodes.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/layout.js": +/*!*****************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/layout.js ***! + \*****************************************************/ +/*! exports provided: LayoutModule, BreakpointObserver, Breakpoints, MediaMatcher */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LayoutModule", function() { return LayoutModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BreakpointObserver", function() { return BreakpointObserver; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Breakpoints", function() { return Breakpoints; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MediaMatcher", function() { return MediaMatcher; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/cdk/platform */ "./node_modules/@angular/cdk/esm2015/platform.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class LayoutModule { +} +LayoutModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{},] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Global registry for all dynamically-created, injected media queries. + * @type {?} + */ +const mediaQueriesForWebkitCompatibility = new Set(); +/** + * Style tag that holds all of the dynamically-created media queries. + * @type {?} + */ +let mediaQueryStyleNode; +/** + * A utility for calling matchMedia queries. + */ +class MediaMatcher { + /** + * @param {?} _platform + */ + constructor(_platform) { + this._platform = _platform; + this._matchMedia = this._platform.isBrowser && window.matchMedia ? + // matchMedia is bound to the window scope intentionally as it is an illegal invocation to + // call it from a different scope. + window.matchMedia.bind(window) : + noopMatchMedia; + } + /** + * Evaluates the given media query and returns the native MediaQueryList from which results + * can be retrieved. + * Confirms the layout engine will trigger for the selector query provided and returns the + * MediaQueryList for the query provided. + * @param {?} query + * @return {?} + */ + matchMedia(query) { + if (this._platform.WEBKIT) { + createEmptyStyleRule(query); + } + return this._matchMedia(query); + } +} +MediaMatcher.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +MediaMatcher.ctorParameters = () => [ + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_1__["Platform"] } +]; +/** @nocollapse */ MediaMatcher.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: function MediaMatcher_Factory() { return new MediaMatcher(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_1__["Platform"])); }, token: MediaMatcher, providedIn: "root" }); +/** + * For Webkit engines that only trigger the MediaQueryListListener when + * there is at least one CSS selector for the respective media query. + * @param {?} query + * @return {?} + */ +function createEmptyStyleRule(query) { + if (mediaQueriesForWebkitCompatibility.has(query)) { + return; + } + try { + if (!mediaQueryStyleNode) { + mediaQueryStyleNode = document.createElement('style'); + mediaQueryStyleNode.setAttribute('type', 'text/css'); + (/** @type {?} */ (document.head)).appendChild(mediaQueryStyleNode); + } + if (mediaQueryStyleNode.sheet) { + ((/** @type {?} */ (mediaQueryStyleNode.sheet))) + .insertRule(`@media ${query} {.fx-query-test{ }}`, 0); + mediaQueriesForWebkitCompatibility.add(query); + } + } + catch (e) { + console.error(e); + } +} +/** + * No-op matchMedia replacement for non-browser platforms. + * @param {?} query + * @return {?} + */ +function noopMatchMedia(query) { + // Use `as any` here to avoid adding additional necessary properties for + // the noop matcher. + return (/** @type {?} */ ({ + matches: query === 'all' || query === '', + media: query, + addListener: (/** + * @return {?} + */ + () => { }), + removeListener: (/** + * @return {?} + */ + () => { }) + })); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Utility for checking the matching state of \@media queries. + */ +class BreakpointObserver { + /** + * @param {?} _mediaMatcher + * @param {?} _zone + */ + constructor(_mediaMatcher, _zone) { + this._mediaMatcher = _mediaMatcher; + this._zone = _zone; + /** + * A map of all media queries currently being listened for. + */ + this._queries = new Map(); + /** + * A subject for all other observables to takeUntil based on. + */ + this._destroySubject = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + } + /** + * Completes the active subject, signalling to all other observables to complete. + * @return {?} + */ + ngOnDestroy() { + this._destroySubject.next(); + this._destroySubject.complete(); + } + /** + * Whether one or more media queries match the current viewport size. + * @param {?} value One or more media queries to check. + * @return {?} Whether any of the media queries match. + */ + isMatched(value) { + /** @type {?} */ + const queries = splitQueries(Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_4__["coerceArray"])(value)); + return queries.some((/** + * @param {?} mediaQuery + * @return {?} + */ + mediaQuery => this._registerQuery(mediaQuery).mql.matches)); + } + /** + * Gets an observable of results for the given queries that will emit new results for any changes + * in matching of the given queries. + * @param {?} value One or more media queries to check. + * @return {?} A stream of matches for the given queries. + */ + observe(value) { + /** @type {?} */ + const queries = splitQueries(Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_4__["coerceArray"])(value)); + /** @type {?} */ + const observables = queries.map((/** + * @param {?} query + * @return {?} + */ + query => this._registerQuery(query).observable)); + /** @type {?} */ + let stateObservable = Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["combineLatest"])(observables); + // Emit the first state immediately, and then debounce the subsequent emissions. + stateObservable = Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["concat"])(stateObservable.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["take"])(1)), stateObservable.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["skip"])(1), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["debounceTime"])(0))); + return stateObservable.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["map"])((/** + * @param {?} breakpointStates + * @return {?} + */ + (breakpointStates) => { + /** @type {?} */ + const response = { + matches: false, + breakpoints: {}, + }; + breakpointStates.forEach((/** + * @param {?} state + * @return {?} + */ + (state) => { + response.matches = response.matches || state.matches; + response.breakpoints[state.query] = state.matches; + })); + return response; + }))); + } + /** + * Registers a specific query to be listened for. + * @private + * @param {?} query + * @return {?} + */ + _registerQuery(query) { + // Only set up a new MediaQueryList if it is not already being listened for. + if (this._queries.has(query)) { + return (/** @type {?} */ (this._queries.get(query))); + } + /** @type {?} */ + const mql = this._mediaMatcher.matchMedia(query); + // Create callback for match changes and add it is as a listener. + /** @type {?} */ + const queryObservable = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => { + // Listener callback methods are wrapped to be placed back in ngZone. Callbacks must be placed + // back into the zone because matchMedia is only included in Zone.js by loading the + // webapis-media-query.js file alongside the zone.js file. Additionally, some browsers do not + // have MediaQueryList inherit from EventTarget, which causes inconsistencies in how Zone.js + // patches it. + /** @type {?} */ + const handler = (/** + * @param {?} e + * @return {?} + */ + (e) => this._zone.run((/** + * @return {?} + */ + () => observer.next(e)))); + mql.addListener(handler); + return (/** + * @return {?} + */ + () => { + mql.removeListener(handler); + }); + })).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["startWith"])(mql), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["map"])((/** + * @param {?} nextMql + * @return {?} + */ + (nextMql) => ({ query, matches: nextMql.matches }))), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["takeUntil"])(this._destroySubject)); + // Add the MediaQueryList to the set of queries. + /** @type {?} */ + const output = { observable: queryObservable, mql }; + this._queries.set(query, output); + return output; + } +} +BreakpointObserver.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +BreakpointObserver.ctorParameters = () => [ + { type: MediaMatcher }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] } +]; +/** @nocollapse */ BreakpointObserver.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: function BreakpointObserver_Factory() { return new BreakpointObserver(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(MediaMatcher), Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"])); }, token: BreakpointObserver, providedIn: "root" }); +/** + * Split each query string into separate query strings if two queries are provided as comma + * separated. + * @param {?} queries + * @return {?} + */ +function splitQueries(queries) { + return queries.map((/** + * @param {?} query + * @return {?} + */ + (query) => query.split(','))) + .reduce((/** + * @param {?} a1 + * @param {?} a2 + * @return {?} + */ + (a1, a2) => a1.concat(a2))) + .map((/** + * @param {?} query + * @return {?} + */ + query => query.trim())); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// PascalCase is being used as Breakpoints is used like an enum. +// tslint:disable-next-line:variable-name +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + * @type {?} + */ +const Breakpoints = { + XSmall: '(max-width: 599.99px)', + Small: '(min-width: 600px) and (max-width: 959.99px)', + Medium: '(min-width: 960px) and (max-width: 1279.99px)', + Large: '(min-width: 1280px) and (max-width: 1919.99px)', + XLarge: '(min-width: 1920px)', + Handset: '(max-width: 599.99px) and (orientation: portrait), ' + + '(max-width: 959.99px) and (orientation: landscape)', + Tablet: '(min-width: 600px) and (max-width: 839.99px) and (orientation: portrait), ' + + '(min-width: 960px) and (max-width: 1279.99px) and (orientation: landscape)', + Web: '(min-width: 840px) and (orientation: portrait), ' + + '(min-width: 1280px) and (orientation: landscape)', + HandsetPortrait: '(max-width: 599.99px) and (orientation: portrait)', + TabletPortrait: '(min-width: 600px) and (max-width: 839.99px) and (orientation: portrait)', + WebPortrait: '(min-width: 840px) and (orientation: portrait)', + HandsetLandscape: '(max-width: 959.99px) and (orientation: landscape)', + TabletLandscape: '(min-width: 960px) and (max-width: 1279.99px) and (orientation: landscape)', + WebLandscape: '(min-width: 1280px) and (orientation: landscape)', +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=layout.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/observers.js": +/*!********************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/observers.js ***! + \********************************************************/ +/*! exports provided: MutationObserverFactory, ContentObserver, CdkObserveContent, ObserversModule */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MutationObserverFactory", function() { return MutationObserverFactory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ContentObserver", function() { return ContentObserver; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkObserveContent", function() { return CdkObserveContent; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserversModule", function() { return ObserversModule; }); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Factory that creates a new MutationObserver and allows us to stub it out in unit tests. + * \@docs-private + */ +class MutationObserverFactory { + /** + * @param {?} callback + * @return {?} + */ + create(callback) { + return typeof MutationObserver === 'undefined' ? null : new MutationObserver(callback); + } +} +MutationObserverFactory.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ MutationObserverFactory.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function MutationObserverFactory_Factory() { return new MutationObserverFactory(); }, token: MutationObserverFactory, providedIn: "root" }); +/** + * An injectable service that allows watching elements for changes to their content. + */ +class ContentObserver { + /** + * @param {?} _mutationObserverFactory + */ + constructor(_mutationObserverFactory) { + this._mutationObserverFactory = _mutationObserverFactory; + /** + * Keeps track of the existing MutationObservers so they can be reused. + */ + this._observedElements = new Map(); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._observedElements.forEach((/** + * @param {?} _ + * @param {?} element + * @return {?} + */ + (_, element) => this._cleanupObserver(element))); + } + /** + * @param {?} elementOrRef + * @return {?} + */ + observe(elementOrRef) { + /** @type {?} */ + const element = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceElement"])(elementOrRef); + return new rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => { + /** @type {?} */ + const stream = this._observeElement(element); + /** @type {?} */ + const subscription = stream.subscribe(observer); + return (/** + * @return {?} + */ + () => { + subscription.unsubscribe(); + this._unobserveElement(element); + }); + })); + } + /** + * Observes the given element by using the existing MutationObserver if available, or creating a + * new one if not. + * @private + * @param {?} element + * @return {?} + */ + _observeElement(element) { + if (!this._observedElements.has(element)) { + /** @type {?} */ + const stream = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** @type {?} */ + const observer = this._mutationObserverFactory.create((/** + * @param {?} mutations + * @return {?} + */ + mutations => stream.next(mutations))); + if (observer) { + observer.observe(element, { + characterData: true, + childList: true, + subtree: true + }); + } + this._observedElements.set(element, { observer, stream, count: 1 }); + } + else { + (/** @type {?} */ (this._observedElements.get(element))).count++; + } + return (/** @type {?} */ (this._observedElements.get(element))).stream; + } + /** + * Un-observes the given element and cleans up the underlying MutationObserver if nobody else is + * observing this element. + * @private + * @param {?} element + * @return {?} + */ + _unobserveElement(element) { + if (this._observedElements.has(element)) { + (/** @type {?} */ (this._observedElements.get(element))).count--; + if (!(/** @type {?} */ (this._observedElements.get(element))).count) { + this._cleanupObserver(element); + } + } + } + /** + * Clean up the underlying MutationObserver for the specified element. + * @private + * @param {?} element + * @return {?} + */ + _cleanupObserver(element) { + if (this._observedElements.has(element)) { + const { observer, stream } = (/** @type {?} */ (this._observedElements.get(element))); + if (observer) { + observer.disconnect(); + } + stream.complete(); + this._observedElements.delete(element); + } + } +} +ContentObserver.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +ContentObserver.ctorParameters = () => [ + { type: MutationObserverFactory } +]; +/** @nocollapse */ ContentObserver.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function ContentObserver_Factory() { return new ContentObserver(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(MutationObserverFactory)); }, token: ContentObserver, providedIn: "root" }); +/** + * Directive that triggers a callback whenever the content of + * its associated element has changed. + */ +class CdkObserveContent { + /** + * @param {?} _contentObserver + * @param {?} _elementRef + * @param {?} _ngZone + */ + constructor(_contentObserver, _elementRef, _ngZone) { + this._contentObserver = _contentObserver; + this._elementRef = _elementRef; + this._ngZone = _ngZone; + /** + * Event emitted for each change in the element's content. + */ + this.event = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + this._disabled = false; + this._currentSubscription = null; + } + /** + * Whether observing content is disabled. This option can be used + * to disconnect the underlying MutationObserver until it is needed. + * @return {?} + */ + get disabled() { return this._disabled; } + /** + * @param {?} value + * @return {?} + */ + set disabled(value) { + this._disabled = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); + this._disabled ? this._unsubscribe() : this._subscribe(); + } + /** + * Debounce interval for emitting the changes. + * @return {?} + */ + get debounce() { return this._debounce; } + /** + * @param {?} value + * @return {?} + */ + set debounce(value) { + this._debounce = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceNumberProperty"])(value); + this._subscribe(); + } + /** + * @return {?} + */ + ngAfterContentInit() { + if (!this._currentSubscription && !this.disabled) { + this._subscribe(); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._unsubscribe(); + } + /** + * @private + * @return {?} + */ + _subscribe() { + this._unsubscribe(); + /** @type {?} */ + const stream = this._contentObserver.observe(this._elementRef); + // TODO(mmalerba): We shouldn't be emitting on this @Output() outside the zone. + // Consider brining it back inside the zone next time we're making breaking changes. + // Bringing it back inside can cause things like infinite change detection loops and changed + // after checked errors if people's code isn't handling it properly. + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + this._currentSubscription = + (this.debounce ? stream.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["debounceTime"])(this.debounce)) : stream).subscribe(this.event); + })); + } + /** + * @private + * @return {?} + */ + _unsubscribe() { + if (this._currentSubscription) { + this._currentSubscription.unsubscribe(); + } + } +} +CdkObserveContent.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkObserveContent]', + exportAs: 'cdkObserveContent', + },] }, +]; +/** @nocollapse */ +CdkObserveContent.ctorParameters = () => [ + { type: ContentObserver }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] } +]; +CdkObserveContent.propDecorators = { + event: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"], args: ['cdkObserveContent',] }], + disabled: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkObserveContentDisabled',] }], + debounce: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }] +}; +class ObserversModule { +} +ObserversModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + exports: [CdkObserveContent], + declarations: [CdkObserveContent], + providers: [MutationObserverFactory] + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=observers.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/overlay.js": +/*!******************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/overlay.js ***! + \******************************************************/ +/*! exports provided: ViewportRuler, VIEWPORT_RULER_PROVIDER, CdkScrollable, ScrollDispatcher, Overlay, OverlayContainer, CdkOverlayOrigin, CdkConnectedOverlay, FullscreenOverlayContainer, OverlayRef, OverlayKeyboardDispatcher, OverlayPositionBuilder, GlobalPositionStrategy, ConnectedPositionStrategy, FlexibleConnectedPositionStrategy, OverlayConfig, validateVerticalPosition, validateHorizontalPosition, ConnectionPositionPair, ScrollingVisibility, ConnectedOverlayPositionChange, ScrollStrategyOptions, RepositionScrollStrategy, CloseScrollStrategy, NoopScrollStrategy, BlockScrollStrategy, OverlayModule, OVERLAY_PROVIDERS, ɵg, ɵf, ɵb, ɵa, ɵc, ɵe, ɵd */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Overlay", function() { return Overlay; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayContainer", function() { return OverlayContainer; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkOverlayOrigin", function() { return CdkOverlayOrigin; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkConnectedOverlay", function() { return CdkConnectedOverlay; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FullscreenOverlayContainer", function() { return FullscreenOverlayContainer; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayRef", function() { return OverlayRef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayKeyboardDispatcher", function() { return OverlayKeyboardDispatcher; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayPositionBuilder", function() { return OverlayPositionBuilder; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GlobalPositionStrategy", function() { return GlobalPositionStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectedPositionStrategy", function() { return ConnectedPositionStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FlexibleConnectedPositionStrategy", function() { return FlexibleConnectedPositionStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayConfig", function() { return OverlayConfig; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateVerticalPosition", function() { return validateVerticalPosition; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateHorizontalPosition", function() { return validateHorizontalPosition; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectionPositionPair", function() { return ConnectionPositionPair; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollingVisibility", function() { return ScrollingVisibility; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectedOverlayPositionChange", function() { return ConnectedOverlayPositionChange; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollStrategyOptions", function() { return ScrollStrategyOptions; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RepositionScrollStrategy", function() { return RepositionScrollStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CloseScrollStrategy", function() { return CloseScrollStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NoopScrollStrategy", function() { return NoopScrollStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BlockScrollStrategy", function() { return BlockScrollStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OverlayModule", function() { return OverlayModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OVERLAY_PROVIDERS", function() { return OVERLAY_PROVIDERS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵg", function() { return OVERLAY_KEYBOARD_DISPATCHER_PROVIDER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵf", function() { return OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵb", function() { return OVERLAY_CONTAINER_PROVIDER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵa", function() { return OVERLAY_CONTAINER_PROVIDER_FACTORY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵc", function() { return CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵe", function() { return CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵd", function() { return CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY; }); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/cdk/scrolling */ "./node_modules/@angular/cdk/esm2015/scrolling.js"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ViewportRuler", function() { return _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ViewportRuler"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VIEWPORT_RULER_PROVIDER", function() { return _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["VIEWPORT_RULER_PROVIDER"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "CdkScrollable", function() { return _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["CdkScrollable"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ScrollDispatcher", function() { return _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ScrollDispatcher"]; }); + +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/* harmony import */ var _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/cdk/platform */ "./node_modules/@angular/cdk/esm2015/platform.js"); +/* harmony import */ var _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/cdk/bidi */ "./node_modules/@angular/cdk/esm2015/bidi.js"); +/* harmony import */ var _angular_cdk_portal__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/cdk/portal */ "./node_modules/@angular/cdk/esm2015/portal.js"); +/* harmony import */ var _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/cdk/keycodes */ "./node_modules/@angular/cdk/esm2015/keycodes.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Strategy that will prevent the user from scrolling while the overlay is visible. + */ +class BlockScrollStrategy { + /** + * @param {?} _viewportRuler + * @param {?} document + */ + constructor(_viewportRuler, document) { + this._viewportRuler = _viewportRuler; + this._previousHTMLStyles = { top: '', left: '' }; + this._isEnabled = false; + this._document = document; + } + /** + * Attaches this scroll strategy to an overlay. + * @return {?} + */ + attach() { } + /** + * Blocks page-level scroll while the attached overlay is open. + * @return {?} + */ + enable() { + if (this._canBeEnabled()) { + /** @type {?} */ + const root = (/** @type {?} */ (this._document.documentElement)); + this._previousScrollPosition = this._viewportRuler.getViewportScrollPosition(); + // Cache the previous inline styles in case the user had set them. + this._previousHTMLStyles.left = root.style.left || ''; + this._previousHTMLStyles.top = root.style.top || ''; + // Note: we're using the `html` node, instead of the `body`, because the `body` may + // have the user agent margin, whereas the `html` is guaranteed not to have one. + root.style.left = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(-this._previousScrollPosition.left); + root.style.top = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(-this._previousScrollPosition.top); + root.classList.add('cdk-global-scrollblock'); + this._isEnabled = true; + } + } + /** + * Unblocks page-level scroll while the attached overlay is open. + * @return {?} + */ + disable() { + if (this._isEnabled) { + /** @type {?} */ + const html = (/** @type {?} */ (this._document.documentElement)); + /** @type {?} */ + const body = (/** @type {?} */ (this._document.body)); + /** @type {?} */ + const htmlStyle = (/** @type {?} */ (html.style)); + /** @type {?} */ + const bodyStyle = (/** @type {?} */ (body.style)); + /** @type {?} */ + const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || ''; + /** @type {?} */ + const previousBodyScrollBehavior = bodyStyle.scrollBehavior || ''; + this._isEnabled = false; + htmlStyle.left = this._previousHTMLStyles.left; + htmlStyle.top = this._previousHTMLStyles.top; + html.classList.remove('cdk-global-scrollblock'); + // Disable user-defined smooth scrolling temporarily while we restore the scroll position. + // See https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior + htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto'; + window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top); + htmlStyle.scrollBehavior = previousHtmlScrollBehavior; + bodyStyle.scrollBehavior = previousBodyScrollBehavior; + } + } + /** + * @private + * @return {?} + */ + _canBeEnabled() { + // Since the scroll strategies can't be singletons, we have to use a global CSS class + // (`cdk-global-scrollblock`) to make sure that we don't try to disable global + // scrolling multiple times. + /** @type {?} */ + const html = (/** @type {?} */ (this._document.documentElement)); + if (html.classList.contains('cdk-global-scrollblock') || this._isEnabled) { + return false; + } + /** @type {?} */ + const body = this._document.body; + /** @type {?} */ + const viewport = this._viewportRuler.getViewportSize(); + return body.scrollHeight > viewport.height || body.scrollWidth > viewport.width; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Returns an error to be thrown when attempting to attach an already-attached scroll strategy. + * @return {?} + */ +function getMatScrollStrategyAlreadyAttachedError() { + return Error(`Scroll strategy has already been attached.`); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Strategy that will close the overlay as soon as the user starts scrolling. + */ +class CloseScrollStrategy { + /** + * @param {?} _scrollDispatcher + * @param {?} _ngZone + * @param {?} _viewportRuler + * @param {?=} _config + */ + constructor(_scrollDispatcher, _ngZone, _viewportRuler, _config) { + this._scrollDispatcher = _scrollDispatcher; + this._ngZone = _ngZone; + this._viewportRuler = _viewportRuler; + this._config = _config; + this._scrollSubscription = null; + /** + * Detaches the overlay ref and disables the scroll strategy. + */ + this._detach = (/** + * @return {?} + */ + () => { + this.disable(); + if (this._overlayRef.hasAttached()) { + this._ngZone.run((/** + * @return {?} + */ + () => this._overlayRef.detach())); + } + }); + } + /** + * Attaches this scroll strategy to an overlay. + * @param {?} overlayRef + * @return {?} + */ + attach(overlayRef) { + if (this._overlayRef) { + throw getMatScrollStrategyAlreadyAttachedError(); + } + this._overlayRef = overlayRef; + } + /** + * Enables the closing of the attached overlay on scroll. + * @return {?} + */ + enable() { + if (this._scrollSubscription) { + return; + } + /** @type {?} */ + const stream = this._scrollDispatcher.scrolled(0); + if (this._config && this._config.threshold && this._config.threshold > 1) { + this._initialScrollPosition = this._viewportRuler.getViewportScrollPosition().top; + this._scrollSubscription = stream.subscribe((/** + * @return {?} + */ + () => { + /** @type {?} */ + const scrollPosition = this._viewportRuler.getViewportScrollPosition().top; + if (Math.abs(scrollPosition - this._initialScrollPosition) > (/** @type {?} */ ((/** @type {?} */ (this._config)).threshold))) { + this._detach(); + } + else { + this._overlayRef.updatePosition(); + } + })); + } + else { + this._scrollSubscription = stream.subscribe(this._detach); + } + } + /** + * Disables the closing the attached overlay on scroll. + * @return {?} + */ + disable() { + if (this._scrollSubscription) { + this._scrollSubscription.unsubscribe(); + this._scrollSubscription = null; + } + } + /** + * @return {?} + */ + detach() { + this.disable(); + this._overlayRef = (/** @type {?} */ (null)); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Scroll strategy that doesn't do anything. + */ +class NoopScrollStrategy { + /** + * Does nothing, as this scroll strategy is a no-op. + * @return {?} + */ + enable() { } + /** + * Does nothing, as this scroll strategy is a no-op. + * @return {?} + */ + disable() { } + /** + * Does nothing, as this scroll strategy is a no-op. + * @return {?} + */ + attach() { } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +// TODO(jelbourn): move this to live with the rest of the scrolling code +// TODO(jelbourn): someday replace this with IntersectionObservers +/** + * Gets whether an element is scrolled outside of view by any of its parent scrolling containers. + * \@docs-private + * @param {?} element Dimensions of the element (from getBoundingClientRect) + * @param {?} scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect) + * @return {?} Whether the element is scrolled out of view + */ +function isElementScrolledOutsideView(element, scrollContainers) { + return scrollContainers.some((/** + * @param {?} containerBounds + * @return {?} + */ + containerBounds => { + /** @type {?} */ + const outsideAbove = element.bottom < containerBounds.top; + /** @type {?} */ + const outsideBelow = element.top > containerBounds.bottom; + /** @type {?} */ + const outsideLeft = element.right < containerBounds.left; + /** @type {?} */ + const outsideRight = element.left > containerBounds.right; + return outsideAbove || outsideBelow || outsideLeft || outsideRight; + })); +} +/** + * Gets whether an element is clipped by any of its scrolling containers. + * \@docs-private + * @param {?} element Dimensions of the element (from getBoundingClientRect) + * @param {?} scrollContainers Dimensions of element's scrolling containers (from getBoundingClientRect) + * @return {?} Whether the element is clipped + */ +function isElementClippedByScrolling(element, scrollContainers) { + return scrollContainers.some((/** + * @param {?} scrollContainerRect + * @return {?} + */ + scrollContainerRect => { + /** @type {?} */ + const clippedAbove = element.top < scrollContainerRect.top; + /** @type {?} */ + const clippedBelow = element.bottom > scrollContainerRect.bottom; + /** @type {?} */ + const clippedLeft = element.left < scrollContainerRect.left; + /** @type {?} */ + const clippedRight = element.right > scrollContainerRect.right; + return clippedAbove || clippedBelow || clippedLeft || clippedRight; + })); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Strategy that will update the element position as the user is scrolling. + */ +class RepositionScrollStrategy { + /** + * @param {?} _scrollDispatcher + * @param {?} _viewportRuler + * @param {?} _ngZone + * @param {?=} _config + */ + constructor(_scrollDispatcher, _viewportRuler, _ngZone, _config) { + this._scrollDispatcher = _scrollDispatcher; + this._viewportRuler = _viewportRuler; + this._ngZone = _ngZone; + this._config = _config; + this._scrollSubscription = null; + } + /** + * Attaches this scroll strategy to an overlay. + * @param {?} overlayRef + * @return {?} + */ + attach(overlayRef) { + if (this._overlayRef) { + throw getMatScrollStrategyAlreadyAttachedError(); + } + this._overlayRef = overlayRef; + } + /** + * Enables repositioning of the attached overlay on scroll. + * @return {?} + */ + enable() { + if (!this._scrollSubscription) { + /** @type {?} */ + const throttle = this._config ? this._config.scrollThrottle : 0; + this._scrollSubscription = this._scrollDispatcher.scrolled(throttle).subscribe((/** + * @return {?} + */ + () => { + this._overlayRef.updatePosition(); + // TODO(crisbeto): make `close` on by default once all components can handle it. + if (this._config && this._config.autoClose) { + /** @type {?} */ + const overlayRect = this._overlayRef.overlayElement.getBoundingClientRect(); + const { width, height } = this._viewportRuler.getViewportSize(); + // TODO(crisbeto): include all ancestor scroll containers here once + // we have a way of exposing the trigger element to the scroll strategy. + /** @type {?} */ + const parentRects = [{ width, height, bottom: height, right: width, top: 0, left: 0 }]; + if (isElementScrolledOutsideView(overlayRect, parentRects)) { + this.disable(); + this._ngZone.run((/** + * @return {?} + */ + () => this._overlayRef.detach())); + } + } + })); + } + } + /** + * Disables repositioning of the attached overlay on scroll. + * @return {?} + */ + disable() { + if (this._scrollSubscription) { + this._scrollSubscription.unsubscribe(); + this._scrollSubscription = null; + } + } + /** + * @return {?} + */ + detach() { + this.disable(); + this._overlayRef = (/** @type {?} */ (null)); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Options for how an overlay will handle scrolling. + * + * Users can provide a custom value for `ScrollStrategyOptions` to replace the default + * behaviors. This class primarily acts as a factory for ScrollStrategy instances. + */ +class ScrollStrategyOptions { + /** + * @param {?} _scrollDispatcher + * @param {?} _viewportRuler + * @param {?} _ngZone + * @param {?} document + */ + constructor(_scrollDispatcher, _viewportRuler, _ngZone, document) { + this._scrollDispatcher = _scrollDispatcher; + this._viewportRuler = _viewportRuler; + this._ngZone = _ngZone; + /** + * Do nothing on scroll. + */ + this.noop = (/** + * @return {?} + */ + () => new NoopScrollStrategy()); + /** + * Close the overlay as soon as the user scrolls. + * @param config Configuration to be used inside the scroll strategy. + */ + this.close = (/** + * @param {?=} config + * @return {?} + */ + (config) => new CloseScrollStrategy(this._scrollDispatcher, this._ngZone, this._viewportRuler, config)); + /** + * Block scrolling. + */ + this.block = (/** + * @return {?} + */ + () => new BlockScrollStrategy(this._viewportRuler, this._document)); + /** + * Update the overlay's position on scroll. + * @param config Configuration to be used inside the scroll strategy. + * Allows debouncing the reposition calls. + */ + this.reposition = (/** + * @param {?=} config + * @return {?} + */ + (config) => new RepositionScrollStrategy(this._scrollDispatcher, this._viewportRuler, this._ngZone, config)); + this._document = document; + } +} +ScrollStrategyOptions.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +ScrollStrategyOptions.ctorParameters = () => [ + { type: _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ScrollDispatcher"] }, + { type: _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ViewportRuler"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["NgZone"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] } +]; +/** @nocollapse */ ScrollStrategyOptions.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"])({ factory: function ScrollStrategyOptions_Factory() { return new ScrollStrategyOptions(Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ScrollDispatcher"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ViewportRuler"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_3__["NgZone"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])); }, token: ScrollStrategyOptions, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Initial configuration used when creating an overlay. + */ +class OverlayConfig { + /** + * @param {?=} config + */ + constructor(config) { + /** + * Strategy to be used when handling scroll events while the overlay is open. + */ + this.scrollStrategy = new NoopScrollStrategy(); + /** + * Custom class to add to the overlay pane. + */ + this.panelClass = ''; + /** + * Whether the overlay has a backdrop. + */ + this.hasBackdrop = false; + /** + * Custom class to add to the backdrop + */ + this.backdropClass = 'cdk-overlay-dark-backdrop'; + /** + * Whether the overlay should be disposed of when the user goes backwards/forwards in history. + * Note that this usually doesn't include clicking on links (unless the user is using + * the `HashLocationStrategy`). + */ + this.disposeOnNavigation = false; + if (config) { + /** @type {?} */ + const configKeys = (/** @type {?} */ (Object.keys(config))); + for (const key of configKeys) { + if (config[key] !== undefined) { + // TypeScript, as of version 3.5, sees the left-hand-side of this expression + // as "I don't know *which* key this is, so the only valid value is the intersection + // of all the posible values." In this case, that happens to be `undefined`. TypeScript + // is not smart enough to see that the right-hand-side is actually an access of the same + // exact type with the same exact key, meaning that the value type must be identical. + // So we use `any` to work around this. + this[key] = (/** @type {?} */ (config[key])); + } + } + } + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * The points of the origin element and the overlay element to connect. + */ +class ConnectionPositionPair { + /** + * @param {?} origin + * @param {?} overlay + * @param {?=} offsetX + * @param {?=} offsetY + * @param {?=} panelClass + */ + constructor(origin, overlay, offsetX, offsetY, panelClass) { + this.offsetX = offsetX; + this.offsetY = offsetY; + this.panelClass = panelClass; + this.originX = origin.originX; + this.originY = origin.originY; + this.overlayX = overlay.overlayX; + this.overlayY = overlay.overlayY; + } +} +/** + * Set of properties regarding the position of the origin and overlay relative to the viewport + * with respect to the containing Scrollable elements. + * + * The overlay and origin are clipped if any part of their bounding client rectangle exceeds the + * bounds of any one of the strategy's Scrollable's bounding client rectangle. + * + * The overlay and origin are outside view if there is no overlap between their bounding client + * rectangle and any one of the strategy's Scrollable's bounding client rectangle. + * + * ----------- ----------- + * | outside | | clipped | + * | view | -------------------------- + * | | | | | | + * ---------- | ----------- | + * -------------------------- | | + * | | | Scrollable | + * | | | | + * | | -------------------------- + * | Scrollable | + * | | + * -------------------------- + * + * \@docs-private + */ +class ScrollingVisibility { +} +/** + * The change event emitted by the strategy when a fallback position is used. + */ +class ConnectedOverlayPositionChange { + /** + * @param {?} connectionPair + * @param {?} scrollableViewProperties + */ + constructor(connectionPair, scrollableViewProperties) { + this.connectionPair = connectionPair; + this.scrollableViewProperties = scrollableViewProperties; + } +} +/** @nocollapse */ +ConnectedOverlayPositionChange.ctorParameters = () => [ + { type: ConnectionPositionPair }, + { type: ScrollingVisibility, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"] }] } +]; +/** + * Validates whether a vertical position property matches the expected values. + * \@docs-private + * @param {?} property Name of the property being validated. + * @param {?} value Value of the property being validated. + * @return {?} + */ +function validateVerticalPosition(property, value) { + if (value !== 'top' && value !== 'bottom' && value !== 'center') { + throw Error(`ConnectedPosition: Invalid ${property} "${value}". ` + + `Expected "top", "bottom" or "center".`); + } +} +/** + * Validates whether a horizontal position property matches the expected values. + * \@docs-private + * @param {?} property Name of the property being validated. + * @param {?} value Value of the property being validated. + * @return {?} + */ +function validateHorizontalPosition(property, value) { + if (value !== 'start' && value !== 'end' && value !== 'center') { + throw Error(`ConnectedPosition: Invalid ${property} "${value}". ` + + `Expected "start", "end" or "center".`); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Service for dispatching keyboard events that land on the body to appropriate overlay ref, + * if any. It maintains a list of attached overlays to determine best suited overlay based + * on event target and order of overlay opens. + */ +class OverlayKeyboardDispatcher { + /** + * @param {?} document + */ + constructor(document) { + /** + * Currently attached overlays in the order they were attached. + */ + this._attachedOverlays = []; + /** + * Keyboard event listener that will be attached to the body. + */ + this._keydownListener = (/** + * @param {?} event + * @return {?} + */ + (event) => { + /** @type {?} */ + const overlays = this._attachedOverlays; + for (let i = overlays.length - 1; i > -1; i--) { + // Dispatch the keydown event to the top overlay which has subscribers to its keydown events. + // We want to target the most recent overlay, rather than trying to match where the event came + // from, because some components might open an overlay, but keep focus on a trigger element + // (e.g. for select and autocomplete). We skip overlays without keydown event subscriptions, + // because we don't want overlays that don't handle keyboard events to block the ones below + // them that do. + if (overlays[i]._keydownEventSubscriptions > 0) { + overlays[i]._keydownEvents.next(event); + break; + } + } + }); + this._document = document; + } + /** + * @return {?} + */ + ngOnDestroy() { + this._detach(); + } + /** + * Add a new overlay to the list of attached overlay refs. + * @param {?} overlayRef + * @return {?} + */ + add(overlayRef) { + // Ensure that we don't get the same overlay multiple times. + this.remove(overlayRef); + // Lazily start dispatcher once first overlay is added + if (!this._isAttached) { + this._document.body.addEventListener('keydown', this._keydownListener); + this._isAttached = true; + } + this._attachedOverlays.push(overlayRef); + } + /** + * Remove an overlay from the list of attached overlay refs. + * @param {?} overlayRef + * @return {?} + */ + remove(overlayRef) { + /** @type {?} */ + const index = this._attachedOverlays.indexOf(overlayRef); + if (index > -1) { + this._attachedOverlays.splice(index, 1); + } + // Remove the global listener once there are no more overlays. + if (this._attachedOverlays.length === 0) { + this._detach(); + } + } + /** + * Detaches the global keyboard event listener. + * @private + * @return {?} + */ + _detach() { + if (this._isAttached) { + this._document.body.removeEventListener('keydown', this._keydownListener); + this._isAttached = false; + } + } +} +OverlayKeyboardDispatcher.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +OverlayKeyboardDispatcher.ctorParameters = () => [ + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] } +]; +/** @nocollapse */ OverlayKeyboardDispatcher.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"])({ factory: function OverlayKeyboardDispatcher_Factory() { return new OverlayKeyboardDispatcher(Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])); }, token: OverlayKeyboardDispatcher, providedIn: "root" }); +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} dispatcher + * @param {?} _document + * @return {?} + */ +function OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY(dispatcher, _document) { + return dispatcher || new OverlayKeyboardDispatcher(_document); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const OVERLAY_KEYBOARD_DISPATCHER_PROVIDER = { + // If there is already an OverlayKeyboardDispatcher available, use that. + // Otherwise, provide a new one. + provide: OverlayKeyboardDispatcher, + deps: [ + [new _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_3__["SkipSelf"](), OverlayKeyboardDispatcher], + (/** @type {?} */ ( + // Coerce to `InjectionToken` so that the `deps` match the "shape" + // of the type expected by Angular + _angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])) + ], + useFactory: OVERLAY_KEYBOARD_DISPATCHER_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Container inside which all overlays will render. + */ +class OverlayContainer { + /** + * @param {?} _document + */ + constructor(_document) { + this._document = _document; + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._containerElement && this._containerElement.parentNode) { + this._containerElement.parentNode.removeChild(this._containerElement); + } + } + /** + * This method returns the overlay container element. It will lazily + * create the element the first time it is called to facilitate using + * the container in non-browser environments. + * @return {?} the container element + */ + getContainerElement() { + if (!this._containerElement) { + this._createContainer(); + } + return this._containerElement; + } + /** + * Create the overlay container element, which is simply a div + * with the 'cdk-overlay-container' class on the document body. + * @protected + * @return {?} + */ + _createContainer() { + /** @type {?} */ + const container = this._document.createElement('div'); + container.classList.add('cdk-overlay-container'); + this._document.body.appendChild(container); + this._containerElement = container; + } +} +OverlayContainer.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +OverlayContainer.ctorParameters = () => [ + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] } +]; +/** @nocollapse */ OverlayContainer.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"])({ factory: function OverlayContainer_Factory() { return new OverlayContainer(Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])); }, token: OverlayContainer, providedIn: "root" }); +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} parentContainer + * @param {?} _document + * @return {?} + */ +function OVERLAY_CONTAINER_PROVIDER_FACTORY(parentContainer, _document) { + return parentContainer || new OverlayContainer(_document); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const OVERLAY_CONTAINER_PROVIDER = { + // If there is already an OverlayContainer available, use that. Otherwise, provide a new one. + provide: OverlayContainer, + deps: [ + [new _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_3__["SkipSelf"](), OverlayContainer], + (/** @type {?} */ (_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])) + ], + useFactory: OVERLAY_CONTAINER_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Reference to an overlay that has been created with the Overlay service. + * Used to manipulate or dispose of said overlay. + */ +class OverlayRef { + /** + * @param {?} _portalOutlet + * @param {?} _host + * @param {?} _pane + * @param {?} _config + * @param {?} _ngZone + * @param {?} _keyboardDispatcher + * @param {?} _document + * @param {?=} _location + */ + constructor(_portalOutlet, _host, _pane, _config, _ngZone, _keyboardDispatcher, _document, _location) { + this._portalOutlet = _portalOutlet; + this._host = _host; + this._pane = _pane; + this._config = _config; + this._ngZone = _ngZone; + this._keyboardDispatcher = _keyboardDispatcher; + this._document = _document; + this._location = _location; + this._backdropElement = null; + this._backdropClick = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Subject"](); + this._attachments = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Subject"](); + this._detachments = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Subject"](); + this._locationChanges = rxjs__WEBPACK_IMPORTED_MODULE_4__["Subscription"].EMPTY; + this._backdropClickHandler = (/** + * @param {?} event + * @return {?} + */ + (event) => this._backdropClick.next(event)); + this._keydownEventsObservable = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => { + /** @type {?} */ + const subscription = this._keydownEvents.subscribe(observer); + this._keydownEventSubscriptions++; + return (/** + * @return {?} + */ + () => { + subscription.unsubscribe(); + this._keydownEventSubscriptions--; + }); + })); + /** + * Stream of keydown events dispatched to this overlay. + */ + this._keydownEvents = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Subject"](); + /** + * Amount of subscriptions to the keydown events. + */ + this._keydownEventSubscriptions = 0; + if (_config.scrollStrategy) { + this._scrollStrategy = _config.scrollStrategy; + this._scrollStrategy.attach(this); + } + this._positionStrategy = _config.positionStrategy; + } + /** + * The overlay's HTML element + * @return {?} + */ + get overlayElement() { + return this._pane; + } + /** + * The overlay's backdrop HTML element. + * @return {?} + */ + get backdropElement() { + return this._backdropElement; + } + /** + * Wrapper around the panel element. Can be used for advanced + * positioning where a wrapper with specific styling is + * required around the overlay pane. + * @return {?} + */ + get hostElement() { + return this._host; + } + /** + * Attaches content, given via a Portal, to the overlay. + * If the overlay is configured to have a backdrop, it will be created. + * + * @param {?} portal Portal instance to which to attach the overlay. + * @return {?} The portal attachment result. + */ + attach(portal) { + /** @type {?} */ + let attachResult = this._portalOutlet.attach(portal); + if (this._positionStrategy) { + this._positionStrategy.attach(this); + } + // Update the pane element with the given configuration. + if (!this._host.parentElement && this._previousHostParent) { + this._previousHostParent.appendChild(this._host); + } + this._updateStackingOrder(); + this._updateElementSize(); + this._updateElementDirection(); + if (this._scrollStrategy) { + this._scrollStrategy.enable(); + } + // Update the position once the zone is stable so that the overlay will be fully rendered + // before attempting to position it, as the position may depend on the size of the rendered + // content. + this._ngZone.onStable + .asObservable() + .pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_5__["take"])(1)) + .subscribe((/** + * @return {?} + */ + () => { + // The overlay could've been detached before the zone has stabilized. + if (this.hasAttached()) { + this.updatePosition(); + } + })); + // Enable pointer events for the overlay pane element. + this._togglePointerEvents(true); + if (this._config.hasBackdrop) { + this._attachBackdrop(); + } + if (this._config.panelClass) { + this._toggleClasses(this._pane, this._config.panelClass, true); + } + // Only emit the `attachments` event once all other setup is done. + this._attachments.next(); + // Track this overlay by the keyboard dispatcher + this._keyboardDispatcher.add(this); + // @breaking-change 8.0.0 remove the null check for `_location` + // once the constructor parameter is made required. + if (this._config.disposeOnNavigation && this._location) { + this._locationChanges = this._location.subscribe((/** + * @return {?} + */ + () => this.dispose())); + } + return attachResult; + } + /** + * Detaches an overlay from a portal. + * @return {?} The portal detachment result. + */ + detach() { + if (!this.hasAttached()) { + return; + } + this.detachBackdrop(); + // When the overlay is detached, the pane element should disable pointer events. + // This is necessary because otherwise the pane element will cover the page and disable + // pointer events therefore. Depends on the position strategy and the applied pane boundaries. + this._togglePointerEvents(false); + if (this._positionStrategy && this._positionStrategy.detach) { + this._positionStrategy.detach(); + } + if (this._scrollStrategy) { + this._scrollStrategy.disable(); + } + /** @type {?} */ + const detachmentResult = this._portalOutlet.detach(); + // Only emit after everything is detached. + this._detachments.next(); + // Remove this overlay from keyboard dispatcher tracking. + this._keyboardDispatcher.remove(this); + // Keeping the host element in DOM the can cause scroll jank, because it still gets + // rendered, even though it's transparent and unclickable which is why we remove it. + this._detachContentWhenStable(); + // Stop listening for location changes. + this._locationChanges.unsubscribe(); + return detachmentResult; + } + /** + * Cleans up the overlay from the DOM. + * @return {?} + */ + dispose() { + /** @type {?} */ + const isAttached = this.hasAttached(); + if (this._positionStrategy) { + this._positionStrategy.dispose(); + } + this._disposeScrollStrategy(); + this.detachBackdrop(); + this._locationChanges.unsubscribe(); + this._keyboardDispatcher.remove(this); + this._portalOutlet.dispose(); + this._attachments.complete(); + this._backdropClick.complete(); + this._keydownEvents.complete(); + if (this._host && this._host.parentNode) { + this._host.parentNode.removeChild(this._host); + this._host = (/** @type {?} */ (null)); + } + this._previousHostParent = this._pane = (/** @type {?} */ (null)); + if (isAttached) { + this._detachments.next(); + } + this._detachments.complete(); + } + /** + * Whether the overlay has attached content. + * @return {?} + */ + hasAttached() { + return this._portalOutlet.hasAttached(); + } + /** + * Gets an observable that emits when the backdrop has been clicked. + * @return {?} + */ + backdropClick() { + return this._backdropClick.asObservable(); + } + /** + * Gets an observable that emits when the overlay has been attached. + * @return {?} + */ + attachments() { + return this._attachments.asObservable(); + } + /** + * Gets an observable that emits when the overlay has been detached. + * @return {?} + */ + detachments() { + return this._detachments.asObservable(); + } + /** + * Gets an observable of keydown events targeted to this overlay. + * @return {?} + */ + keydownEvents() { + return this._keydownEventsObservable; + } + /** + * Gets the current overlay configuration, which is immutable. + * @return {?} + */ + getConfig() { + return this._config; + } + /** + * Updates the position of the overlay based on the position strategy. + * @return {?} + */ + updatePosition() { + if (this._positionStrategy) { + this._positionStrategy.apply(); + } + } + /** + * Switches to a new position strategy and updates the overlay position. + * @param {?} strategy + * @return {?} + */ + updatePositionStrategy(strategy) { + if (strategy === this._positionStrategy) { + return; + } + if (this._positionStrategy) { + this._positionStrategy.dispose(); + } + this._positionStrategy = strategy; + if (this.hasAttached()) { + strategy.attach(this); + this.updatePosition(); + } + } + /** + * Update the size properties of the overlay. + * @param {?} sizeConfig + * @return {?} + */ + updateSize(sizeConfig) { + this._config = Object.assign({}, this._config, sizeConfig); + this._updateElementSize(); + } + /** + * Sets the LTR/RTL direction for the overlay. + * @param {?} dir + * @return {?} + */ + setDirection(dir) { + this._config = Object.assign({}, this._config, { direction: dir }); + this._updateElementDirection(); + } + /** + * Add a CSS class or an array of classes to the overlay pane. + * @param {?} classes + * @return {?} + */ + addPanelClass(classes) { + if (this._pane) { + this._toggleClasses(this._pane, classes, true); + } + } + /** + * Remove a CSS class or an array of classes from the overlay pane. + * @param {?} classes + * @return {?} + */ + removePanelClass(classes) { + if (this._pane) { + this._toggleClasses(this._pane, classes, false); + } + } + /** + * Returns the layout direction of the overlay panel. + * @return {?} + */ + getDirection() { + /** @type {?} */ + const direction = this._config.direction; + if (!direction) { + return 'ltr'; + } + return typeof direction === 'string' ? direction : direction.value; + } + /** + * Switches to a new scroll strategy. + * @param {?} strategy + * @return {?} + */ + updateScrollStrategy(strategy) { + if (strategy === this._scrollStrategy) { + return; + } + this._disposeScrollStrategy(); + this._scrollStrategy = strategy; + if (this.hasAttached()) { + strategy.attach(this); + strategy.enable(); + } + } + /** + * Updates the text direction of the overlay panel. + * @private + * @return {?} + */ + _updateElementDirection() { + this._host.setAttribute('dir', this.getDirection()); + } + /** + * Updates the size of the overlay element based on the overlay config. + * @private + * @return {?} + */ + _updateElementSize() { + /** @type {?} */ + const style = this._pane.style; + style.width = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.width); + style.height = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.height); + style.minWidth = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.minWidth); + style.minHeight = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.minHeight); + style.maxWidth = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.maxWidth); + style.maxHeight = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(this._config.maxHeight); + } + /** + * Toggles the pointer events for the overlay pane element. + * @private + * @param {?} enablePointer + * @return {?} + */ + _togglePointerEvents(enablePointer) { + this._pane.style.pointerEvents = enablePointer ? 'auto' : 'none'; + } + /** + * Attaches a backdrop for this overlay. + * @private + * @return {?} + */ + _attachBackdrop() { + /** @type {?} */ + const showingClass = 'cdk-overlay-backdrop-showing'; + this._backdropElement = this._document.createElement('div'); + this._backdropElement.classList.add('cdk-overlay-backdrop'); + if (this._config.backdropClass) { + this._toggleClasses(this._backdropElement, this._config.backdropClass, true); + } + // Insert the backdrop before the pane in the DOM order, + // in order to handle stacked overlays properly. + (/** @type {?} */ (this._host.parentElement)).insertBefore(this._backdropElement, this._host); + // Forward backdrop clicks such that the consumer of the overlay can perform whatever + // action desired when such a click occurs (usually closing the overlay). + this._backdropElement.addEventListener('click', this._backdropClickHandler); + // Add class to fade-in the backdrop after one frame. + if (typeof requestAnimationFrame !== 'undefined') { + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + requestAnimationFrame((/** + * @return {?} + */ + () => { + if (this._backdropElement) { + this._backdropElement.classList.add(showingClass); + } + })); + })); + } + else { + this._backdropElement.classList.add(showingClass); + } + } + /** + * Updates the stacking order of the element, moving it to the top if necessary. + * This is required in cases where one overlay was detached, while another one, + * that should be behind it, was destroyed. The next time both of them are opened, + * the stacking will be wrong, because the detached element's pane will still be + * in its original DOM position. + * @private + * @return {?} + */ + _updateStackingOrder() { + if (this._host.nextSibling) { + (/** @type {?} */ (this._host.parentNode)).appendChild(this._host); + } + } + /** + * Detaches the backdrop (if any) associated with the overlay. + * @return {?} + */ + detachBackdrop() { + /** @type {?} */ + let backdropToDetach = this._backdropElement; + if (!backdropToDetach) { + return; + } + /** @type {?} */ + let timeoutId; + /** @type {?} */ + let finishDetach = (/** + * @return {?} + */ + () => { + // It may not be attached to anything in certain cases (e.g. unit tests). + if (backdropToDetach) { + backdropToDetach.removeEventListener('click', this._backdropClickHandler); + backdropToDetach.removeEventListener('transitionend', finishDetach); + if (backdropToDetach.parentNode) { + backdropToDetach.parentNode.removeChild(backdropToDetach); + } + } + // It is possible that a new portal has been attached to this overlay since we started + // removing the backdrop. If that is the case, only clear the backdrop reference if it + // is still the same instance that we started to remove. + if (this._backdropElement == backdropToDetach) { + this._backdropElement = null; + } + if (this._config.backdropClass) { + this._toggleClasses((/** @type {?} */ (backdropToDetach)), this._config.backdropClass, false); + } + clearTimeout(timeoutId); + }); + backdropToDetach.classList.remove('cdk-overlay-backdrop-showing'); + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + (/** @type {?} */ (backdropToDetach)).addEventListener('transitionend', finishDetach); + })); + // If the backdrop doesn't have a transition, the `transitionend` event won't fire. + // In this case we make it unclickable and we try to remove it after a delay. + backdropToDetach.style.pointerEvents = 'none'; + // Run this outside the Angular zone because there's nothing that Angular cares about. + // If it were to run inside the Angular zone, every test that used Overlay would have to be + // either async or fakeAsync. + timeoutId = this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => setTimeout(finishDetach, 500))); + } + /** + * Toggles a single CSS class or an array of classes on an element. + * @private + * @param {?} element + * @param {?} cssClasses + * @param {?} isAdd + * @return {?} + */ + _toggleClasses(element, cssClasses, isAdd) { + /** @type {?} */ + const classList = element.classList; + Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceArray"])(cssClasses).forEach((/** + * @param {?} cssClass + * @return {?} + */ + cssClass => { + // We can't do a spread here, because IE doesn't support setting multiple classes. + isAdd ? classList.add(cssClass) : classList.remove(cssClass); + })); + } + /** + * Detaches the overlay content next time the zone stabilizes. + * @private + * @return {?} + */ + _detachContentWhenStable() { + // Normally we wouldn't have to explicitly run this outside the `NgZone`, however + // if the consumer is using `zone-patch-rxjs`, the `Subscription.unsubscribe` call will + // be patched to run inside the zone, which will throw us into an infinite loop. + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + // We can't remove the host here immediately, because the overlay pane's content + // might still be animating. This stream helps us avoid interrupting the animation + // by waiting for the pane to become empty. + /** @type {?} */ + const subscription = this._ngZone.onStable + .asObservable() + .pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_5__["takeUntil"])(Object(rxjs__WEBPACK_IMPORTED_MODULE_4__["merge"])(this._attachments, this._detachments))) + .subscribe((/** + * @return {?} + */ + () => { + // Needs a couple of checks for the pane and host, because + // they may have been removed by the time the zone stabilizes. + if (!this._pane || !this._host || this._pane.children.length === 0) { + if (this._pane && this._config.panelClass) { + this._toggleClasses(this._pane, this._config.panelClass, false); + } + if (this._host && this._host.parentElement) { + this._previousHostParent = this._host.parentElement; + this._previousHostParent.removeChild(this._host); + } + subscription.unsubscribe(); + } + })); + })); + } + /** + * Disposes of a scroll strategy. + * @private + * @return {?} + */ + _disposeScrollStrategy() { + /** @type {?} */ + const scrollStrategy = this._scrollStrategy; + if (scrollStrategy) { + scrollStrategy.disable(); + if (scrollStrategy.detach) { + scrollStrategy.detach(); + } + } + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// TODO: refactor clipping detection into a separate thing (part of scrolling module) +// TODO: doesn't handle both flexible width and height when it has to scroll along both axis. +/** + * Class to be added to the overlay bounding box. + * @type {?} + */ +const boundingBoxClass = 'cdk-overlay-connected-position-bounding-box'; +/** + * A strategy for positioning overlays. Using this strategy, an overlay is given an + * implicit position relative some origin element. The relative position is defined in terms of + * a point on the origin element that is connected to a point on the overlay element. For example, + * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner + * of the overlay. + */ +class FlexibleConnectedPositionStrategy { + /** + * @param {?} connectedTo + * @param {?} _viewportRuler + * @param {?} _document + * @param {?} _platform + * @param {?} _overlayContainer + */ + constructor(connectedTo, _viewportRuler, _document, _platform, _overlayContainer) { + this._viewportRuler = _viewportRuler; + this._document = _document; + this._platform = _platform; + this._overlayContainer = _overlayContainer; + /** + * Last size used for the bounding box. Used to avoid resizing the overlay after open. + */ + this._lastBoundingBoxSize = { width: 0, height: 0 }; + /** + * Whether the overlay was pushed in a previous positioning. + */ + this._isPushed = false; + /** + * Whether the overlay can be pushed on-screen on the initial open. + */ + this._canPush = true; + /** + * Whether the overlay can grow via flexible width/height after the initial open. + */ + this._growAfterOpen = false; + /** + * Whether the overlay's width and height can be constrained to fit within the viewport. + */ + this._hasFlexibleDimensions = true; + /** + * Whether the overlay position is locked. + */ + this._positionLocked = false; + /** + * Amount of space that must be maintained between the overlay and the edge of the viewport. + */ + this._viewportMargin = 0; + /** + * The Scrollable containers used to check scrollable view properties on position change. + */ + this._scrollables = []; + /** + * Ordered list of preferred positions, from most to least desirable. + */ + this._preferredPositions = []; + /** + * Subject that emits whenever the position changes. + */ + this._positionChanges = new rxjs__WEBPACK_IMPORTED_MODULE_4__["Subject"](); + /** + * Subscription to viewport size changes. + */ + this._resizeSubscription = rxjs__WEBPACK_IMPORTED_MODULE_4__["Subscription"].EMPTY; + /** + * Default offset for the overlay along the x axis. + */ + this._offsetX = 0; + /** + * Default offset for the overlay along the y axis. + */ + this._offsetY = 0; + /** + * Keeps track of the CSS classes that the position strategy has applied on the overlay panel. + */ + this._appliedPanelClasses = []; + /** + * Observable sequence of position changes. + */ + this.positionChanges = this._positionChanges.asObservable(); + this.setOrigin(connectedTo); + } + /** + * Ordered list of preferred positions, from most to least desirable. + * @return {?} + */ + get positions() { + return this._preferredPositions; + } + /** + * Attaches this position strategy to an overlay. + * @param {?} overlayRef + * @return {?} + */ + attach(overlayRef) { + if (this._overlayRef && overlayRef !== this._overlayRef) { + throw Error('This position strategy is already attached to an overlay'); + } + this._validatePositions(); + overlayRef.hostElement.classList.add(boundingBoxClass); + this._overlayRef = overlayRef; + this._boundingBox = overlayRef.hostElement; + this._pane = overlayRef.overlayElement; + this._isDisposed = false; + this._isInitialRender = true; + this._lastPosition = null; + this._resizeSubscription.unsubscribe(); + this._resizeSubscription = this._viewportRuler.change().subscribe((/** + * @return {?} + */ + () => { + // When the window is resized, we want to trigger the next reposition as if it + // was an initial render, in order for the strategy to pick a new optimal position, + // otherwise position locking will cause it to stay at the old one. + this._isInitialRender = true; + this.apply(); + })); + } + /** + * Updates the position of the overlay element, using whichever preferred position relative + * to the origin best fits on-screen. + * + * The selection of a position goes as follows: + * - If any positions fit completely within the viewport as-is, + * choose the first position that does so. + * - If flexible dimensions are enabled and at least one satifies the given minimum width/height, + * choose the position with the greatest available size modified by the positions' weight. + * - If pushing is enabled, take the position that went off-screen the least and push it + * on-screen. + * - If none of the previous criteria were met, use the position that goes off-screen the least. + * \@docs-private + * @return {?} + */ + apply() { + // We shouldn't do anything if the strategy was disposed or we're on the server. + if (this._isDisposed || !this._platform.isBrowser) { + return; + } + // If the position has been applied already (e.g. when the overlay was opened) and the + // consumer opted into locking in the position, re-use the old position, in order to + // prevent the overlay from jumping around. + if (!this._isInitialRender && this._positionLocked && this._lastPosition) { + this.reapplyLastPosition(); + return; + } + this._clearPanelClasses(); + this._resetOverlayElementStyles(); + this._resetBoundingBoxStyles(); + // We need the bounding rects for the origin and the overlay to determine how to position + // the overlay relative to the origin. + // We use the viewport rect to determine whether a position would go off-screen. + this._viewportRect = this._getNarrowedViewportRect(); + this._originRect = this._getOriginRect(); + this._overlayRect = this._pane.getBoundingClientRect(); + /** @type {?} */ + const originRect = this._originRect; + /** @type {?} */ + const overlayRect = this._overlayRect; + /** @type {?} */ + const viewportRect = this._viewportRect; + // Positions where the overlay will fit with flexible dimensions. + /** @type {?} */ + const flexibleFits = []; + // Fallback if none of the preferred positions fit within the viewport. + /** @type {?} */ + let fallback; + // Go through each of the preferred positions looking for a good fit. + // If a good fit is found, it will be applied immediately. + for (let pos of this._preferredPositions) { + // Get the exact (x, y) coordinate for the point-of-origin on the origin element. + /** @type {?} */ + let originPoint = this._getOriginPoint(originRect, pos); + // From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the + // overlay in this position. We use the top-left corner for calculations and later translate + // this into an appropriate (top, left, bottom, right) style. + /** @type {?} */ + let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos); + // Calculate how well the overlay would fit into the viewport with this point. + /** @type {?} */ + let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos); + // If the overlay, without any further work, fits into the viewport, use this position. + if (overlayFit.isCompletelyWithinViewport) { + this._isPushed = false; + this._applyPosition(pos, originPoint); + return; + } + // If the overlay has flexible dimensions, we can use this position + // so long as there's enough space for the minimum dimensions. + if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) { + // Save positions where the overlay will fit with flexible dimensions. We will use these + // if none of the positions fit *without* flexible dimensions. + flexibleFits.push({ + position: pos, + origin: originPoint, + overlayRect, + boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos) + }); + continue; + } + // If the current preferred position does not fit on the screen, remember the position + // if it has more visible area on-screen than we've seen and move onto the next preferred + // position. + if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) { + fallback = { overlayFit, overlayPoint, originPoint, position: pos, overlayRect }; + } + } + // If there are any positions where the overlay would fit with flexible dimensions, choose the + // one that has the greatest area available modified by the position's weight + if (flexibleFits.length) { + /** @type {?} */ + let bestFit = null; + /** @type {?} */ + let bestScore = -1; + for (const fit of flexibleFits) { + /** @type {?} */ + const score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1); + if (score > bestScore) { + bestScore = score; + bestFit = fit; + } + } + this._isPushed = false; + this._applyPosition((/** @type {?} */ (bestFit)).position, (/** @type {?} */ (bestFit)).origin); + return; + } + // When none of the preferred positions fit within the viewport, take the position + // that went off-screen the least and attempt to push it on-screen. + if (this._canPush) { + // TODO(jelbourn): after pushing, the opening "direction" of the overlay might not make sense. + this._isPushed = true; + this._applyPosition((/** @type {?} */ (fallback)).position, (/** @type {?} */ (fallback)).originPoint); + return; + } + // All options for getting the overlay within the viewport have been exhausted, so go with the + // position that went off-screen the least. + this._applyPosition((/** @type {?} */ (fallback)).position, (/** @type {?} */ (fallback)).originPoint); + } + /** + * @return {?} + */ + detach() { + this._clearPanelClasses(); + this._lastPosition = null; + this._previousPushAmount = null; + this._resizeSubscription.unsubscribe(); + } + /** + * Cleanup after the element gets destroyed. + * @return {?} + */ + dispose() { + if (this._isDisposed) { + return; + } + // We can't use `_resetBoundingBoxStyles` here, because it resets + // some properties to zero, rather than removing them. + if (this._boundingBox) { + extendStyles(this._boundingBox.style, (/** @type {?} */ ({ + top: '', + left: '', + right: '', + bottom: '', + height: '', + width: '', + alignItems: '', + justifyContent: '', + }))); + } + if (this._pane) { + this._resetOverlayElementStyles(); + } + if (this._overlayRef) { + this._overlayRef.hostElement.classList.remove(boundingBoxClass); + } + this.detach(); + this._positionChanges.complete(); + this._overlayRef = this._boundingBox = (/** @type {?} */ (null)); + this._isDisposed = true; + } + /** + * This re-aligns the overlay element with the trigger in its last calculated position, + * even if a position higher in the "preferred positions" list would now fit. This + * allows one to re-align the panel without changing the orientation of the panel. + * @return {?} + */ + reapplyLastPosition() { + if (!this._isDisposed && (!this._platform || this._platform.isBrowser)) { + this._originRect = this._getOriginRect(); + this._overlayRect = this._pane.getBoundingClientRect(); + this._viewportRect = this._getNarrowedViewportRect(); + /** @type {?} */ + const lastPosition = this._lastPosition || this._preferredPositions[0]; + /** @type {?} */ + const originPoint = this._getOriginPoint(this._originRect, lastPosition); + this._applyPosition(lastPosition, originPoint); + } + } + /** + * Sets the list of Scrollable containers that host the origin element so that + * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every + * Scrollable must be an ancestor element of the strategy's origin element. + * @template THIS + * @this {THIS} + * @param {?} scrollables + * @return {THIS} + */ + withScrollableContainers(scrollables) { + (/** @type {?} */ (this))._scrollables = scrollables; + return (/** @type {?} */ (this)); + } + /** + * Adds new preferred positions. + * @template THIS + * @this {THIS} + * @param {?} positions List of positions options for this overlay. + * @return {THIS} + */ + withPositions(positions) { + (/** @type {?} */ (this))._preferredPositions = positions; + // If the last calculated position object isn't part of the positions anymore, clear + // it in order to avoid it being picked up if the consumer tries to re-apply. + if (positions.indexOf((/** @type {?} */ ((/** @type {?} */ (this))._lastPosition))) === -1) { + (/** @type {?} */ (this))._lastPosition = null; + } + (/** @type {?} */ (this))._validatePositions(); + return (/** @type {?} */ (this)); + } + /** + * Sets a minimum distance the overlay may be positioned to the edge of the viewport. + * @template THIS + * @this {THIS} + * @param {?} margin Required margin between the overlay and the viewport edge in pixels. + * @return {THIS} + */ + withViewportMargin(margin) { + (/** @type {?} */ (this))._viewportMargin = margin; + return (/** @type {?} */ (this)); + } + /** + * Sets whether the overlay's width and height can be constrained to fit within the viewport. + * @template THIS + * @this {THIS} + * @param {?=} flexibleDimensions + * @return {THIS} + */ + withFlexibleDimensions(flexibleDimensions = true) { + (/** @type {?} */ (this))._hasFlexibleDimensions = flexibleDimensions; + return (/** @type {?} */ (this)); + } + /** + * Sets whether the overlay can grow after the initial open via flexible width/height. + * @template THIS + * @this {THIS} + * @param {?=} growAfterOpen + * @return {THIS} + */ + withGrowAfterOpen(growAfterOpen = true) { + (/** @type {?} */ (this))._growAfterOpen = growAfterOpen; + return (/** @type {?} */ (this)); + } + /** + * Sets whether the overlay can be pushed on-screen if none of the provided positions fit. + * @template THIS + * @this {THIS} + * @param {?=} canPush + * @return {THIS} + */ + withPush(canPush = true) { + (/** @type {?} */ (this))._canPush = canPush; + return (/** @type {?} */ (this)); + } + /** + * Sets whether the overlay's position should be locked in after it is positioned + * initially. When an overlay is locked in, it won't attempt to reposition itself + * when the position is re-applied (e.g. when the user scrolls away). + * @template THIS + * @this {THIS} + * @param {?=} isLocked Whether the overlay should locked in. + * @return {THIS} + */ + withLockedPosition(isLocked = true) { + (/** @type {?} */ (this))._positionLocked = isLocked; + return (/** @type {?} */ (this)); + } + /** + * Sets the origin, relative to which to position the overlay. + * Using an element origin is useful for building components that need to be positioned + * relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be + * used for cases like contextual menus which open relative to the user's pointer. + * @template THIS + * @this {THIS} + * @param {?} origin Reference to the new origin. + * @return {THIS} + */ + setOrigin(origin) { + (/** @type {?} */ (this))._origin = origin; + return (/** @type {?} */ (this)); + } + /** + * Sets the default offset for the overlay's connection point on the x-axis. + * @template THIS + * @this {THIS} + * @param {?} offset New offset in the X axis. + * @return {THIS} + */ + withDefaultOffsetX(offset) { + (/** @type {?} */ (this))._offsetX = offset; + return (/** @type {?} */ (this)); + } + /** + * Sets the default offset for the overlay's connection point on the y-axis. + * @template THIS + * @this {THIS} + * @param {?} offset New offset in the Y axis. + * @return {THIS} + */ + withDefaultOffsetY(offset) { + (/** @type {?} */ (this))._offsetY = offset; + return (/** @type {?} */ (this)); + } + /** + * Configures that the position strategy should set a `transform-origin` on some elements + * inside the overlay, depending on the current position that is being applied. This is + * useful for the cases where the origin of an animation can change depending on the + * alignment of the overlay. + * @template THIS + * @this {THIS} + * @param {?} selector CSS selector that will be used to find the target + * elements onto which to set the transform origin. + * @return {THIS} + */ + withTransformOriginOn(selector) { + (/** @type {?} */ (this))._transformOriginSelector = selector; + return (/** @type {?} */ (this)); + } + /** + * Gets the (x, y) coordinate of a connection point on the origin based on a relative position. + * @private + * @param {?} originRect + * @param {?} pos + * @return {?} + */ + _getOriginPoint(originRect, pos) { + /** @type {?} */ + let x; + if (pos.originX == 'center') { + // Note: when centering we should always use the `left` + // offset, otherwise the position will be wrong in RTL. + x = originRect.left + (originRect.width / 2); + } + else { + /** @type {?} */ + const startX = this._isRtl() ? originRect.right : originRect.left; + /** @type {?} */ + const endX = this._isRtl() ? originRect.left : originRect.right; + x = pos.originX == 'start' ? startX : endX; + } + /** @type {?} */ + let y; + if (pos.originY == 'center') { + y = originRect.top + (originRect.height / 2); + } + else { + y = pos.originY == 'top' ? originRect.top : originRect.bottom; + } + return { x, y }; + } + /** + * Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and + * origin point to which the overlay should be connected. + * @private + * @param {?} originPoint + * @param {?} overlayRect + * @param {?} pos + * @return {?} + */ + _getOverlayPoint(originPoint, overlayRect, pos) { + // Calculate the (overlayStartX, overlayStartY), the start of the + // potential overlay position relative to the origin point. + /** @type {?} */ + let overlayStartX; + if (pos.overlayX == 'center') { + overlayStartX = -overlayRect.width / 2; + } + else if (pos.overlayX === 'start') { + overlayStartX = this._isRtl() ? -overlayRect.width : 0; + } + else { + overlayStartX = this._isRtl() ? 0 : -overlayRect.width; + } + /** @type {?} */ + let overlayStartY; + if (pos.overlayY == 'center') { + overlayStartY = -overlayRect.height / 2; + } + else { + overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height; + } + // The (x, y) coordinates of the overlay. + return { + x: originPoint.x + overlayStartX, + y: originPoint.y + overlayStartY, + }; + } + /** + * Gets how well an overlay at the given point will fit within the viewport. + * @private + * @param {?} point + * @param {?} overlay + * @param {?} viewport + * @param {?} position + * @return {?} + */ + _getOverlayFit(point, overlay, viewport, position) { + let { x, y } = point; + /** @type {?} */ + let offsetX = this._getOffset(position, 'x'); + /** @type {?} */ + let offsetY = this._getOffset(position, 'y'); + // Account for the offsets since they could push the overlay out of the viewport. + if (offsetX) { + x += offsetX; + } + if (offsetY) { + y += offsetY; + } + // How much the overlay would overflow at this position, on each side. + /** @type {?} */ + let leftOverflow = 0 - x; + /** @type {?} */ + let rightOverflow = (x + overlay.width) - viewport.width; + /** @type {?} */ + let topOverflow = 0 - y; + /** @type {?} */ + let bottomOverflow = (y + overlay.height) - viewport.height; + // Visible parts of the element on each axis. + /** @type {?} */ + let visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow); + /** @type {?} */ + let visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow); + /** @type {?} */ + let visibleArea = visibleWidth * visibleHeight; + return { + visibleArea, + isCompletelyWithinViewport: (overlay.width * overlay.height) === visibleArea, + fitsInViewportVertically: visibleHeight === overlay.height, + fitsInViewportHorizontally: visibleWidth == overlay.width, + }; + } + /** + * Whether the overlay can fit within the viewport when it may resize either its width or height. + * @private + * @param {?} fit How well the overlay fits in the viewport at some position. + * @param {?} point The (x, y) coordinates of the overlat at some position. + * @param {?} viewport The geometry of the viewport. + * @return {?} + */ + _canFitWithFlexibleDimensions(fit, point, viewport) { + if (this._hasFlexibleDimensions) { + /** @type {?} */ + const availableHeight = viewport.bottom - point.y; + /** @type {?} */ + const availableWidth = viewport.right - point.x; + /** @type {?} */ + const minHeight = this._overlayRef.getConfig().minHeight; + /** @type {?} */ + const minWidth = this._overlayRef.getConfig().minWidth; + /** @type {?} */ + const verticalFit = fit.fitsInViewportVertically || + (minHeight != null && minHeight <= availableHeight); + /** @type {?} */ + const horizontalFit = fit.fitsInViewportHorizontally || + (minWidth != null && minWidth <= availableWidth); + return verticalFit && horizontalFit; + } + } + /** + * Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than + * the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the + * right and bottom). + * + * @private + * @param {?} start Starting point from which the overlay is pushed. + * @param {?} overlay Dimensions of the overlay. + * @param {?} scrollPosition Current viewport scroll position. + * @return {?} The point at which to position the overlay after pushing. This is effectively a new + * originPoint. + */ + _pushOverlayOnScreen(start, overlay, scrollPosition) { + // If the position is locked and we've pushed the overlay already, reuse the previous push + // amount, rather than pushing it again. If we were to continue pushing, the element would + // remain in the viewport, which goes against the expectations when position locking is enabled. + if (this._previousPushAmount && this._positionLocked) { + return { + x: start.x + this._previousPushAmount.x, + y: start.y + this._previousPushAmount.y + }; + } + /** @type {?} */ + const viewport = this._viewportRect; + // Determine how much the overlay goes outside the viewport on each + // side, which we'll use to decide which direction to push it. + /** @type {?} */ + const overflowRight = Math.max(start.x + overlay.width - viewport.right, 0); + /** @type {?} */ + const overflowBottom = Math.max(start.y + overlay.height - viewport.bottom, 0); + /** @type {?} */ + const overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0); + /** @type {?} */ + const overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0); + // Amount by which to push the overlay in each axis such that it remains on-screen. + /** @type {?} */ + let pushX = 0; + /** @type {?} */ + let pushY = 0; + // If the overlay fits completely within the bounds of the viewport, push it from whichever + // direction is goes off-screen. Otherwise, push the top-left corner such that its in the + // viewport and allow for the trailing end of the overlay to go out of bounds. + if (overlay.width <= viewport.width) { + pushX = overflowLeft || -overflowRight; + } + else { + pushX = start.x < this._viewportMargin ? (viewport.left - scrollPosition.left) - start.x : 0; + } + if (overlay.height <= viewport.height) { + pushY = overflowTop || -overflowBottom; + } + else { + pushY = start.y < this._viewportMargin ? (viewport.top - scrollPosition.top) - start.y : 0; + } + this._previousPushAmount = { x: pushX, y: pushY }; + return { + x: start.x + pushX, + y: start.y + pushY, + }; + } + /** + * Applies a computed position to the overlay and emits a position change. + * @private + * @param {?} position The position preference + * @param {?} originPoint The point on the origin element where the overlay is connected. + * @return {?} + */ + _applyPosition(position, originPoint) { + this._setTransformOrigin(position); + this._setOverlayElementStyles(originPoint, position); + this._setBoundingBoxStyles(originPoint, position); + if (position.panelClass) { + this._addPanelClasses(position.panelClass); + } + // Save the last connected position in case the position needs to be re-calculated. + this._lastPosition = position; + // Notify that the position has been changed along with its change properties. + // We only emit if we've got any subscriptions, because the scroll visibility + // calculcations can be somewhat expensive. + if (this._positionChanges.observers.length) { + /** @type {?} */ + const scrollableViewProperties = this._getScrollVisibility(); + /** @type {?} */ + const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties); + this._positionChanges.next(changeEvent); + } + this._isInitialRender = false; + } + /** + * Sets the transform origin based on the configured selector and the passed-in position. + * @private + * @param {?} position + * @return {?} + */ + _setTransformOrigin(position) { + if (!this._transformOriginSelector) { + return; + } + /** @type {?} */ + const elements = (/** @type {?} */ (this._boundingBox)).querySelectorAll(this._transformOriginSelector); + /** @type {?} */ + let xOrigin; + /** @type {?} */ + let yOrigin = position.overlayY; + if (position.overlayX === 'center') { + xOrigin = 'center'; + } + else if (this._isRtl()) { + xOrigin = position.overlayX === 'start' ? 'right' : 'left'; + } + else { + xOrigin = position.overlayX === 'start' ? 'left' : 'right'; + } + for (let i = 0; i < elements.length; i++) { + elements[i].style.transformOrigin = `${xOrigin} ${yOrigin}`; + } + } + /** + * Gets the position and size of the overlay's sizing container. + * + * This method does no measuring and applies no styles so that we can cheaply compute the + * bounds for all positions and choose the best fit based on these results. + * @private + * @param {?} origin + * @param {?} position + * @return {?} + */ + _calculateBoundingBoxRect(origin, position) { + /** @type {?} */ + const viewport = this._viewportRect; + /** @type {?} */ + const isRtl = this._isRtl(); + /** @type {?} */ + let height; + /** @type {?} */ + let top; + /** @type {?} */ + let bottom; + if (position.overlayY === 'top') { + // Overlay is opening "downward" and thus is bound by the bottom viewport edge. + top = origin.y; + height = viewport.height - top + this._viewportMargin; + } + else if (position.overlayY === 'bottom') { + // Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add + // the viewport margin back in, because the viewport rect is narrowed down to remove the + // margin, whereas the `origin` position is calculated based on its `ClientRect`. + bottom = viewport.height - origin.y + this._viewportMargin * 2; + height = viewport.height - bottom + this._viewportMargin; + } + else { + // If neither top nor bottom, it means that the overlay is vertically centered on the + // origin point. Note that we want the position relative to the viewport, rather than + // the page, which is why we don't use something like `viewport.bottom - origin.y` and + // `origin.y - viewport.top`. + /** @type {?} */ + const smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y); + /** @type {?} */ + const previousHeight = this._lastBoundingBoxSize.height; + height = smallestDistanceToViewportEdge * 2; + top = origin.y - smallestDistanceToViewportEdge; + if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) { + top = origin.y - (previousHeight / 2); + } + } + // The overlay is opening 'right-ward' (the content flows to the right). + /** @type {?} */ + const isBoundedByRightViewportEdge = (position.overlayX === 'start' && !isRtl) || + (position.overlayX === 'end' && isRtl); + // The overlay is opening 'left-ward' (the content flows to the left). + /** @type {?} */ + const isBoundedByLeftViewportEdge = (position.overlayX === 'end' && !isRtl) || + (position.overlayX === 'start' && isRtl); + /** @type {?} */ + let width; + /** @type {?} */ + let left; + /** @type {?} */ + let right; + if (isBoundedByLeftViewportEdge) { + right = viewport.width - origin.x + this._viewportMargin; + width = origin.x - this._viewportMargin; + } + else if (isBoundedByRightViewportEdge) { + left = origin.x; + width = viewport.right - origin.x; + } + else { + // If neither start nor end, it means that the overlay is horizontally centered on the + // origin point. Note that we want the position relative to the viewport, rather than + // the page, which is why we don't use something like `viewport.right - origin.x` and + // `origin.x - viewport.left`. + /** @type {?} */ + const smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x); + /** @type {?} */ + const previousWidth = this._lastBoundingBoxSize.width; + width = smallestDistanceToViewportEdge * 2; + left = origin.x - smallestDistanceToViewportEdge; + if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) { + left = origin.x - (previousWidth / 2); + } + } + return { top: (/** @type {?} */ (top)), left: (/** @type {?} */ (left)), bottom: (/** @type {?} */ (bottom)), right: (/** @type {?} */ (right)), width, height }; + } + /** + * Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the + * origin's connection point and stetches to the bounds of the viewport. + * + * @private + * @param {?} origin The point on the origin element where the overlay is connected. + * @param {?} position The position preference + * @return {?} + */ + _setBoundingBoxStyles(origin, position) { + /** @type {?} */ + const boundingBoxRect = this._calculateBoundingBoxRect(origin, position); + // It's weird if the overlay *grows* while scrolling, so we take the last size into account + // when applying a new size. + if (!this._isInitialRender && !this._growAfterOpen) { + boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height); + boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width); + } + /** @type {?} */ + const styles = (/** @type {?} */ ({})); + if (this._hasExactPosition()) { + styles.top = styles.left = '0'; + styles.bottom = styles.right = ''; + styles.width = styles.height = '100%'; + } + else { + /** @type {?} */ + const maxHeight = this._overlayRef.getConfig().maxHeight; + /** @type {?} */ + const maxWidth = this._overlayRef.getConfig().maxWidth; + styles.height = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.height); + styles.top = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.top); + styles.bottom = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.bottom); + styles.width = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.width); + styles.left = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.left); + styles.right = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(boundingBoxRect.right); + // Push the pane content towards the proper direction. + if (position.overlayX === 'center') { + styles.alignItems = 'center'; + } + else { + styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start'; + } + if (position.overlayY === 'center') { + styles.justifyContent = 'center'; + } + else { + styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start'; + } + if (maxHeight) { + styles.maxHeight = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(maxHeight); + } + if (maxWidth) { + styles.maxWidth = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(maxWidth); + } + } + this._lastBoundingBoxSize = boundingBoxRect; + extendStyles((/** @type {?} */ (this._boundingBox)).style, styles); + } + /** + * Resets the styles for the bounding box so that a new positioning can be computed. + * @private + * @return {?} + */ + _resetBoundingBoxStyles() { + extendStyles((/** @type {?} */ (this._boundingBox)).style, (/** @type {?} */ ({ + top: '0', + left: '0', + right: '0', + bottom: '0', + height: '', + width: '', + alignItems: '', + justifyContent: '', + }))); + } + /** + * Resets the styles for the overlay pane so that a new positioning can be computed. + * @private + * @return {?} + */ + _resetOverlayElementStyles() { + extendStyles(this._pane.style, (/** @type {?} */ ({ + top: '', + left: '', + bottom: '', + right: '', + position: '', + transform: '', + }))); + } + /** + * Sets positioning styles to the overlay element. + * @private + * @param {?} originPoint + * @param {?} position + * @return {?} + */ + _setOverlayElementStyles(originPoint, position) { + /** @type {?} */ + const styles = (/** @type {?} */ ({})); + if (this._hasExactPosition()) { + /** @type {?} */ + const scrollPosition = this._viewportRuler.getViewportScrollPosition(); + extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition)); + extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition)); + } + else { + styles.position = 'static'; + } + // Use a transform to apply the offsets. We do this because the `center` positions rely on + // being in the normal flex flow and setting a `top` / `left` at all will completely throw + // off the position. We also can't use margins, because they won't have an effect in some + // cases where the element doesn't have anything to "push off of". Finally, this works + // better both with flexible and non-flexible positioning. + /** @type {?} */ + let transformString = ''; + /** @type {?} */ + let offsetX = this._getOffset(position, 'x'); + /** @type {?} */ + let offsetY = this._getOffset(position, 'y'); + if (offsetX) { + transformString += `translateX(${offsetX}px) `; + } + if (offsetY) { + transformString += `translateY(${offsetY}px)`; + } + styles.transform = transformString.trim(); + // If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because + // we need these values to both be set to "100%" for the automatic flexible sizing to work. + // The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint. + if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxHeight) { + styles.maxHeight = ''; + } + if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxWidth) { + styles.maxWidth = ''; + } + extendStyles(this._pane.style, styles); + } + /** + * Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. + * @private + * @param {?} position + * @param {?} originPoint + * @param {?} scrollPosition + * @return {?} + */ + _getExactOverlayY(position, originPoint, scrollPosition) { + // Reset any existing styles. This is necessary in case the + // preferred position has changed since the last `apply`. + /** @type {?} */ + let styles = (/** @type {?} */ ({ top: null, bottom: null })); + /** @type {?} */ + let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position); + if (this._isPushed) { + overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition); + } + /** @type {?} */ + let virtualKeyboardOffset = this._overlayContainer.getContainerElement().getBoundingClientRect().top; + // Normally this would be zero, however when the overlay is attached to an input (e.g. in an + // autocomplete), mobile browsers will shift everything in order to put the input in the middle + // of the screen and to make space for the virtual keyboard. We need to account for this offset, + // otherwise our positioning will be thrown off. + overlayPoint.y -= virtualKeyboardOffset; + // We want to set either `top` or `bottom` based on whether the overlay wants to appear + // above or below the origin and the direction in which the element will expand. + if (position.overlayY === 'bottom') { + // When using `bottom`, we adjust the y position such that it is the distance + // from the bottom of the viewport rather than the top. + /** @type {?} */ + const documentHeight = (/** @type {?} */ (this._document.documentElement)).clientHeight; + styles.bottom = `${documentHeight - (overlayPoint.y + this._overlayRect.height)}px`; + } + else { + styles.top = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(overlayPoint.y); + } + return styles; + } + /** + * Gets the exact left/right for the overlay when not using flexible sizing or when pushing. + * @private + * @param {?} position + * @param {?} originPoint + * @param {?} scrollPosition + * @return {?} + */ + _getExactOverlayX(position, originPoint, scrollPosition) { + // Reset any existing styles. This is necessary in case the preferred position has + // changed since the last `apply`. + /** @type {?} */ + let styles = (/** @type {?} */ ({ left: null, right: null })); + /** @type {?} */ + let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position); + if (this._isPushed) { + overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition); + } + // We want to set either `left` or `right` based on whether the overlay wants to appear "before" + // or "after" the origin, which determines the direction in which the element will expand. + // For the horizontal axis, the meaning of "before" and "after" change based on whether the + // page is in RTL or LTR. + /** @type {?} */ + let horizontalStyleProperty; + if (this._isRtl()) { + horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right'; + } + else { + horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left'; + } + // When we're setting `right`, we adjust the x position such that it is the distance + // from the right edge of the viewport rather than the left edge. + if (horizontalStyleProperty === 'right') { + /** @type {?} */ + const documentWidth = (/** @type {?} */ (this._document.documentElement)).clientWidth; + styles.right = `${documentWidth - (overlayPoint.x + this._overlayRect.width)}px`; + } + else { + styles.left = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceCssPixelValue"])(overlayPoint.x); + } + return styles; + } + /** + * Gets the view properties of the trigger and overlay, including whether they are clipped + * or completely outside the view of any of the strategy's scrollables. + * @private + * @return {?} + */ + _getScrollVisibility() { + // Note: needs fresh rects since the position could've changed. + /** @type {?} */ + const originBounds = this._getOriginRect(); + /** @type {?} */ + const overlayBounds = this._pane.getBoundingClientRect(); + // TODO(jelbourn): instead of needing all of the client rects for these scrolling containers + // every time, we should be able to use the scrollTop of the containers if the size of those + // containers hasn't changed. + /** @type {?} */ + const scrollContainerBounds = this._scrollables.map((/** + * @param {?} scrollable + * @return {?} + */ + scrollable => { + return scrollable.getElementRef().nativeElement.getBoundingClientRect(); + })); + return { + isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds), + isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds), + isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds), + isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds), + }; + } + /** + * Subtracts the amount that an element is overflowing on an axis from it's length. + * @private + * @param {?} length + * @param {...?} overflows + * @return {?} + */ + _subtractOverflows(length, ...overflows) { + return overflows.reduce((/** + * @param {?} currentValue + * @param {?} currentOverflow + * @return {?} + */ + (currentValue, currentOverflow) => { + return currentValue - Math.max(currentOverflow, 0); + }), length); + } + /** + * Narrows the given viewport rect by the current _viewportMargin. + * @private + * @return {?} + */ + _getNarrowedViewportRect() { + // We recalculate the viewport rect here ourselves, rather than using the ViewportRuler, + // because we want to use the `clientWidth` and `clientHeight` as the base. The difference + // being that the client properties don't include the scrollbar, as opposed to `innerWidth` + // and `innerHeight` that do. This is necessary, because the overlay container uses + // 100% `width` and `height` which don't include the scrollbar either. + /** @type {?} */ + const width = (/** @type {?} */ (this._document.documentElement)).clientWidth; + /** @type {?} */ + const height = (/** @type {?} */ (this._document.documentElement)).clientHeight; + /** @type {?} */ + const scrollPosition = this._viewportRuler.getViewportScrollPosition(); + return { + top: scrollPosition.top + this._viewportMargin, + left: scrollPosition.left + this._viewportMargin, + right: scrollPosition.left + width - this._viewportMargin, + bottom: scrollPosition.top + height - this._viewportMargin, + width: width - (2 * this._viewportMargin), + height: height - (2 * this._viewportMargin), + }; + } + /** + * Whether the we're dealing with an RTL context + * @private + * @return {?} + */ + _isRtl() { + return this._overlayRef.getDirection() === 'rtl'; + } + /** + * Determines whether the overlay uses exact or flexible positioning. + * @private + * @return {?} + */ + _hasExactPosition() { + return !this._hasFlexibleDimensions || this._isPushed; + } + /** + * Retrieves the offset of a position along the x or y axis. + * @private + * @param {?} position + * @param {?} axis + * @return {?} + */ + _getOffset(position, axis) { + if (axis === 'x') { + // We don't do something like `position['offset' + axis]` in + // order to avoid breking minifiers that rename properties. + return position.offsetX == null ? this._offsetX : position.offsetX; + } + return position.offsetY == null ? this._offsetY : position.offsetY; + } + /** + * Validates that the current position match the expected values. + * @private + * @return {?} + */ + _validatePositions() { + if (!this._preferredPositions.length) { + throw Error('FlexibleConnectedPositionStrategy: At least one position is required.'); + } + // TODO(crisbeto): remove these once Angular's template type + // checking is advanced enough to catch these cases. + this._preferredPositions.forEach((/** + * @param {?} pair + * @return {?} + */ + pair => { + validateHorizontalPosition('originX', pair.originX); + validateVerticalPosition('originY', pair.originY); + validateHorizontalPosition('overlayX', pair.overlayX); + validateVerticalPosition('overlayY', pair.overlayY); + })); + } + /** + * Adds a single CSS class or an array of classes on the overlay panel. + * @private + * @param {?} cssClasses + * @return {?} + */ + _addPanelClasses(cssClasses) { + if (this._pane) { + Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceArray"])(cssClasses).forEach((/** + * @param {?} cssClass + * @return {?} + */ + cssClass => { + if (cssClass !== '' && this._appliedPanelClasses.indexOf(cssClass) === -1) { + this._appliedPanelClasses.push(cssClass); + this._pane.classList.add(cssClass); + } + })); + } + } + /** + * Clears the classes that the position strategy has applied from the overlay panel. + * @private + * @return {?} + */ + _clearPanelClasses() { + if (this._pane) { + this._appliedPanelClasses.forEach((/** + * @param {?} cssClass + * @return {?} + */ + cssClass => { + this._pane.classList.remove(cssClass); + })); + this._appliedPanelClasses = []; + } + } + /** + * Returns the ClientRect of the current origin. + * @private + * @return {?} + */ + _getOriginRect() { + /** @type {?} */ + const origin = this._origin; + if (origin instanceof _angular_core__WEBPACK_IMPORTED_MODULE_3__["ElementRef"]) { + return origin.nativeElement.getBoundingClientRect(); + } + if (origin instanceof HTMLElement) { + return origin.getBoundingClientRect(); + } + // If the origin is a point, return a client rect as if it was a 0x0 element at the point. + return { + top: origin.y, + bottom: origin.y, + left: origin.x, + right: origin.x, + height: 0, + width: 0 + }; + } +} +/** + * Shallow-extends a stylesheet object with another stylesheet object. + * @param {?} dest + * @param {?} source + * @return {?} + */ +function extendStyles(dest, source) { + for (let key in source) { + if (source.hasOwnProperty(key)) { + dest[key] = source[key]; + } + } + return dest; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A strategy for positioning overlays. Using this strategy, an overlay is given an + * implicit position relative to some origin element. The relative position is defined in terms of + * a point on the origin element that is connected to a point on the overlay element. For example, + * a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner + * of the overlay. + * @deprecated Use `FlexibleConnectedPositionStrategy` instead. + * \@breaking-change 8.0.0 + */ +class ConnectedPositionStrategy { + /** + * @param {?} originPos + * @param {?} overlayPos + * @param {?} connectedTo + * @param {?} viewportRuler + * @param {?} document + * @param {?} platform + * @param {?} overlayContainer + */ + constructor(originPos, overlayPos, connectedTo, viewportRuler, document, platform, overlayContainer) { + /** + * Ordered list of preferred positions, from most to least desirable. + */ + this._preferredPositions = []; + // Since the `ConnectedPositionStrategy` is deprecated and we don't want to maintain + // the extra logic, we create an instance of the positioning strategy that has some + // defaults that make it behave as the old position strategy and to which we'll + // proxy all of the API calls. + this._positionStrategy = new FlexibleConnectedPositionStrategy(connectedTo, viewportRuler, document, platform, overlayContainer) + .withFlexibleDimensions(false) + .withPush(false) + .withViewportMargin(0); + this.withFallbackPosition(originPos, overlayPos); + } + /** + * Whether the we're dealing with an RTL context + * @return {?} + */ + get _isRtl() { + return this._overlayRef.getDirection() === 'rtl'; + } + /** + * Emits an event when the connection point changes. + * @return {?} + */ + get onPositionChange() { + return this._positionStrategy.positionChanges; + } + /** + * Ordered list of preferred positions, from most to least desirable. + * @return {?} + */ + get positions() { + return this._preferredPositions; + } + /** + * Attach this position strategy to an overlay. + * @param {?} overlayRef + * @return {?} + */ + attach(overlayRef) { + this._overlayRef = overlayRef; + this._positionStrategy.attach(overlayRef); + if (this._direction) { + overlayRef.setDirection(this._direction); + this._direction = null; + } + } + /** + * Disposes all resources used by the position strategy. + * @return {?} + */ + dispose() { + this._positionStrategy.dispose(); + } + /** + * \@docs-private + * @return {?} + */ + detach() { + this._positionStrategy.detach(); + } + /** + * Updates the position of the overlay element, using whichever preferred position relative + * to the origin fits on-screen. + * \@docs-private + * @return {?} + */ + apply() { + this._positionStrategy.apply(); + } + /** + * Re-positions the overlay element with the trigger in its last calculated position, + * even if a position higher in the "preferred positions" list would now fit. This + * allows one to re-align the panel without changing the orientation of the panel. + * @return {?} + */ + recalculateLastPosition() { + this._positionStrategy.reapplyLastPosition(); + } + /** + * Sets the list of Scrollable containers that host the origin element so that + * on reposition we can evaluate if it or the overlay has been clipped or outside view. Every + * Scrollable must be an ancestor element of the strategy's origin element. + * @param {?} scrollables + * @return {?} + */ + withScrollableContainers(scrollables) { + this._positionStrategy.withScrollableContainers(scrollables); + } + /** + * Adds a new preferred fallback position. + * @template THIS + * @this {THIS} + * @param {?} originPos + * @param {?} overlayPos + * @param {?=} offsetX + * @param {?=} offsetY + * @return {THIS} + */ + withFallbackPosition(originPos, overlayPos, offsetX, offsetY) { + /** @type {?} */ + const position = new ConnectionPositionPair(originPos, overlayPos, offsetX, offsetY); + (/** @type {?} */ (this))._preferredPositions.push(position); + (/** @type {?} */ (this))._positionStrategy.withPositions((/** @type {?} */ (this))._preferredPositions); + return (/** @type {?} */ (this)); + } + /** + * Sets the layout direction so the overlay's position can be adjusted to match. + * @template THIS + * @this {THIS} + * @param {?} dir New layout direction. + * @return {THIS} + */ + withDirection(dir) { + // Since the direction might be declared before the strategy is attached, + // we save the value in a temporary property and we'll transfer it to the + // overlay ref on attachment. + if ((/** @type {?} */ (this))._overlayRef) { + (/** @type {?} */ (this))._overlayRef.setDirection(dir); + } + else { + (/** @type {?} */ (this))._direction = dir; + } + return (/** @type {?} */ (this)); + } + /** + * Sets an offset for the overlay's connection point on the x-axis + * @template THIS + * @this {THIS} + * @param {?} offset New offset in the X axis. + * @return {THIS} + */ + withOffsetX(offset) { + (/** @type {?} */ (this))._positionStrategy.withDefaultOffsetX(offset); + return (/** @type {?} */ (this)); + } + /** + * Sets an offset for the overlay's connection point on the y-axis + * @template THIS + * @this {THIS} + * @param {?} offset New offset in the Y axis. + * @return {THIS} + */ + withOffsetY(offset) { + (/** @type {?} */ (this))._positionStrategy.withDefaultOffsetY(offset); + return (/** @type {?} */ (this)); + } + /** + * Sets whether the overlay's position should be locked in after it is positioned + * initially. When an overlay is locked in, it won't attempt to reposition itself + * when the position is re-applied (e.g. when the user scrolls away). + * @template THIS + * @this {THIS} + * @param {?} isLocked Whether the overlay should locked in. + * @return {THIS} + */ + withLockedPosition(isLocked) { + (/** @type {?} */ (this))._positionStrategy.withLockedPosition(isLocked); + return (/** @type {?} */ (this)); + } + /** + * Overwrites the current set of positions with an array of new ones. + * @template THIS + * @this {THIS} + * @param {?} positions Position pairs to be set on the strategy. + * @return {THIS} + */ + withPositions(positions) { + (/** @type {?} */ (this))._preferredPositions = positions.slice(); + (/** @type {?} */ (this))._positionStrategy.withPositions((/** @type {?} */ (this))._preferredPositions); + return (/** @type {?} */ (this)); + } + /** + * Sets the origin element, relative to which to position the overlay. + * @template THIS + * @this {THIS} + * @param {?} origin Reference to the new origin element. + * @return {THIS} + */ + setOrigin(origin) { + (/** @type {?} */ (this))._positionStrategy.setOrigin(origin); + return (/** @type {?} */ (this)); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Class to be added to the overlay pane wrapper. + * @type {?} + */ +const wrapperClass = 'cdk-global-overlay-wrapper'; +/** + * A strategy for positioning overlays. Using this strategy, an overlay is given an + * explicit position relative to the browser's viewport. We use flexbox, instead of + * transforms, in order to avoid issues with subpixel rendering which can cause the + * element to become blurry. + */ +class GlobalPositionStrategy { + constructor() { + this._cssPosition = 'static'; + this._topOffset = ''; + this._bottomOffset = ''; + this._leftOffset = ''; + this._rightOffset = ''; + this._alignItems = ''; + this._justifyContent = ''; + this._width = ''; + this._height = ''; + } + /** + * @param {?} overlayRef + * @return {?} + */ + attach(overlayRef) { + /** @type {?} */ + const config = overlayRef.getConfig(); + this._overlayRef = overlayRef; + if (this._width && !config.width) { + overlayRef.updateSize({ width: this._width }); + } + if (this._height && !config.height) { + overlayRef.updateSize({ height: this._height }); + } + overlayRef.hostElement.classList.add(wrapperClass); + this._isDisposed = false; + } + /** + * Sets the top position of the overlay. Clears any previously set vertical position. + * @template THIS + * @this {THIS} + * @param {?=} value New top offset. + * @return {THIS} + */ + top(value = '') { + (/** @type {?} */ (this))._bottomOffset = ''; + (/** @type {?} */ (this))._topOffset = value; + (/** @type {?} */ (this))._alignItems = 'flex-start'; + return (/** @type {?} */ (this)); + } + /** + * Sets the left position of the overlay. Clears any previously set horizontal position. + * @template THIS + * @this {THIS} + * @param {?=} value New left offset. + * @return {THIS} + */ + left(value = '') { + (/** @type {?} */ (this))._rightOffset = ''; + (/** @type {?} */ (this))._leftOffset = value; + (/** @type {?} */ (this))._justifyContent = 'flex-start'; + return (/** @type {?} */ (this)); + } + /** + * Sets the bottom position of the overlay. Clears any previously set vertical position. + * @template THIS + * @this {THIS} + * @param {?=} value New bottom offset. + * @return {THIS} + */ + bottom(value = '') { + (/** @type {?} */ (this))._topOffset = ''; + (/** @type {?} */ (this))._bottomOffset = value; + (/** @type {?} */ (this))._alignItems = 'flex-end'; + return (/** @type {?} */ (this)); + } + /** + * Sets the right position of the overlay. Clears any previously set horizontal position. + * @template THIS + * @this {THIS} + * @param {?=} value New right offset. + * @return {THIS} + */ + right(value = '') { + (/** @type {?} */ (this))._leftOffset = ''; + (/** @type {?} */ (this))._rightOffset = value; + (/** @type {?} */ (this))._justifyContent = 'flex-end'; + return (/** @type {?} */ (this)); + } + /** + * Sets the overlay width and clears any previously set width. + * @deprecated Pass the `width` through the `OverlayConfig`. + * \@breaking-change 8.0.0 + * @template THIS + * @this {THIS} + * @param {?=} value New width for the overlay + * @return {THIS} + */ + width(value = '') { + if ((/** @type {?} */ (this))._overlayRef) { + (/** @type {?} */ (this))._overlayRef.updateSize({ width: value }); + } + else { + (/** @type {?} */ (this))._width = value; + } + return (/** @type {?} */ (this)); + } + /** + * Sets the overlay height and clears any previously set height. + * @deprecated Pass the `height` through the `OverlayConfig`. + * \@breaking-change 8.0.0 + * @template THIS + * @this {THIS} + * @param {?=} value New height for the overlay + * @return {THIS} + */ + height(value = '') { + if ((/** @type {?} */ (this))._overlayRef) { + (/** @type {?} */ (this))._overlayRef.updateSize({ height: value }); + } + else { + (/** @type {?} */ (this))._height = value; + } + return (/** @type {?} */ (this)); + } + /** + * Centers the overlay horizontally with an optional offset. + * Clears any previously set horizontal position. + * + * @template THIS + * @this {THIS} + * @param {?=} offset Overlay offset from the horizontal center. + * @return {THIS} + */ + centerHorizontally(offset = '') { + (/** @type {?} */ (this)).left(offset); + (/** @type {?} */ (this))._justifyContent = 'center'; + return (/** @type {?} */ (this)); + } + /** + * Centers the overlay vertically with an optional offset. + * Clears any previously set vertical position. + * + * @template THIS + * @this {THIS} + * @param {?=} offset Overlay offset from the vertical center. + * @return {THIS} + */ + centerVertically(offset = '') { + (/** @type {?} */ (this)).top(offset); + (/** @type {?} */ (this))._alignItems = 'center'; + return (/** @type {?} */ (this)); + } + /** + * Apply the position to the element. + * \@docs-private + * @return {?} + */ + apply() { + // Since the overlay ref applies the strategy asynchronously, it could + // have been disposed before it ends up being applied. If that is the + // case, we shouldn't do anything. + if (!this._overlayRef || !this._overlayRef.hasAttached()) { + return; + } + /** @type {?} */ + const styles = this._overlayRef.overlayElement.style; + /** @type {?} */ + const parentStyles = this._overlayRef.hostElement.style; + /** @type {?} */ + const config = this._overlayRef.getConfig(); + styles.position = this._cssPosition; + styles.marginLeft = config.width === '100%' ? '0' : this._leftOffset; + styles.marginTop = config.height === '100%' ? '0' : this._topOffset; + styles.marginBottom = this._bottomOffset; + styles.marginRight = this._rightOffset; + if (config.width === '100%') { + parentStyles.justifyContent = 'flex-start'; + } + else if (this._justifyContent === 'center') { + parentStyles.justifyContent = 'center'; + } + else if (this._overlayRef.getConfig().direction === 'rtl') { + // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we + // don't want that because our positioning is explicitly `left` and `right`, hence + // why we do another inversion to ensure that the overlay stays in the same position. + // TODO: reconsider this if we add `start` and `end` methods. + if (this._justifyContent === 'flex-start') { + parentStyles.justifyContent = 'flex-end'; + } + else if (this._justifyContent === 'flex-end') { + parentStyles.justifyContent = 'flex-start'; + } + } + else { + parentStyles.justifyContent = this._justifyContent; + } + parentStyles.alignItems = config.height === '100%' ? 'flex-start' : this._alignItems; + } + /** + * Cleans up the DOM changes from the position strategy. + * \@docs-private + * @return {?} + */ + dispose() { + if (this._isDisposed || !this._overlayRef) { + return; + } + /** @type {?} */ + const styles = this._overlayRef.overlayElement.style; + /** @type {?} */ + const parent = this._overlayRef.hostElement; + /** @type {?} */ + const parentStyles = parent.style; + parent.classList.remove(wrapperClass); + parentStyles.justifyContent = parentStyles.alignItems = styles.marginTop = + styles.marginBottom = styles.marginLeft = styles.marginRight = styles.position = ''; + this._overlayRef = (/** @type {?} */ (null)); + this._isDisposed = true; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Builder for overlay position strategy. + */ +class OverlayPositionBuilder { + /** + * @param {?} _viewportRuler + * @param {?} _document + * @param {?} _platform + * @param {?} _overlayContainer + */ + constructor(_viewportRuler, _document, _platform, _overlayContainer) { + this._viewportRuler = _viewportRuler; + this._document = _document; + this._platform = _platform; + this._overlayContainer = _overlayContainer; + } + /** + * Creates a global position strategy. + * @return {?} + */ + global() { + return new GlobalPositionStrategy(); + } + /** + * Creates a relative position strategy. + * @deprecated Use `flexibleConnectedTo` instead. + * \@breaking-change 8.0.0 + * @param {?} elementRef + * @param {?} originPos + * @param {?} overlayPos + * @return {?} + */ + connectedTo(elementRef, originPos, overlayPos) { + return new ConnectedPositionStrategy(originPos, overlayPos, elementRef, this._viewportRuler, this._document, this._platform, this._overlayContainer); + } + /** + * Creates a flexible position strategy. + * @param {?} origin Origin relative to which to position the overlay. + * @return {?} + */ + flexibleConnectedTo(origin) { + return new FlexibleConnectedPositionStrategy(origin, this._viewportRuler, this._document, this._platform, this._overlayContainer); + } +} +OverlayPositionBuilder.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +OverlayPositionBuilder.ctorParameters = () => [ + { type: _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ViewportRuler"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] }, + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_6__["Platform"] }, + { type: OverlayContainer } +]; +/** @nocollapse */ OverlayPositionBuilder.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"])({ factory: function OverlayPositionBuilder_Factory() { return new OverlayPositionBuilder(Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ViewportRuler"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_6__["Platform"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(OverlayContainer)); }, token: OverlayPositionBuilder, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Next overlay unique ID. + * @type {?} + */ +let nextUniqueId = 0; +// Note that Overlay is *not* scoped to the app root because the ComponentFactoryResolver +// it needs is different based on where OverlayModule is imported. +/** + * Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be + * used as a low-level building block for other components. Dialogs, tooltips, menus, + * selects, etc. can all be built using overlays. The service should primarily be used by authors + * of re-usable components rather than developers building end-user applications. + * + * An overlay *is* a PortalOutlet, so any kind of Portal can be loaded into one. + */ +class Overlay { + /** + * @param {?} scrollStrategies + * @param {?} _overlayContainer + * @param {?} _componentFactoryResolver + * @param {?} _positionBuilder + * @param {?} _keyboardDispatcher + * @param {?} _injector + * @param {?} _ngZone + * @param {?} _document + * @param {?} _directionality + * @param {?=} _location + */ + constructor(scrollStrategies, _overlayContainer, _componentFactoryResolver, _positionBuilder, _keyboardDispatcher, _injector, _ngZone, _document, _directionality, _location) { + this.scrollStrategies = scrollStrategies; + this._overlayContainer = _overlayContainer; + this._componentFactoryResolver = _componentFactoryResolver; + this._positionBuilder = _positionBuilder; + this._keyboardDispatcher = _keyboardDispatcher; + this._injector = _injector; + this._ngZone = _ngZone; + this._document = _document; + this._directionality = _directionality; + this._location = _location; + } + /** + * Creates an overlay. + * @param {?=} config Configuration applied to the overlay. + * @return {?} Reference to the created overlay. + */ + create(config) { + /** @type {?} */ + const host = this._createHostElement(); + /** @type {?} */ + const pane = this._createPaneElement(host); + /** @type {?} */ + const portalOutlet = this._createPortalOutlet(pane); + /** @type {?} */ + const overlayConfig = new OverlayConfig(config); + overlayConfig.direction = overlayConfig.direction || this._directionality.value; + return new OverlayRef(portalOutlet, host, pane, overlayConfig, this._ngZone, this._keyboardDispatcher, this._document, this._location); + } + /** + * Gets a position builder that can be used, via fluent API, + * to construct and configure a position strategy. + * @return {?} An overlay position builder. + */ + position() { + return this._positionBuilder; + } + /** + * Creates the DOM element for an overlay and appends it to the overlay container. + * @private + * @param {?} host + * @return {?} Newly-created pane element + */ + _createPaneElement(host) { + /** @type {?} */ + const pane = this._document.createElement('div'); + pane.id = `cdk-overlay-${nextUniqueId++}`; + pane.classList.add('cdk-overlay-pane'); + host.appendChild(pane); + return pane; + } + /** + * Creates the host element that wraps around an overlay + * and can be used for advanced positioning. + * @private + * @return {?} Newly-create host element. + */ + _createHostElement() { + /** @type {?} */ + const host = this._document.createElement('div'); + this._overlayContainer.getContainerElement().appendChild(host); + return host; + } + /** + * Create a DomPortalOutlet into which the overlay content can be loaded. + * @private + * @param {?} pane The DOM element to turn into a portal outlet. + * @return {?} A portal outlet for the given DOM element. + */ + _createPortalOutlet(pane) { + // We have to resolve the ApplicationRef later in order to allow people + // to use overlay-based providers during app initialization. + if (!this._appRef) { + this._appRef = this._injector.get(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ApplicationRef"]); + } + return new _angular_cdk_portal__WEBPACK_IMPORTED_MODULE_8__["DomPortalOutlet"](pane, this._componentFactoryResolver, this._appRef, this._injector); + } +} +Overlay.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"] }, +]; +/** @nocollapse */ +Overlay.ctorParameters = () => [ + { type: ScrollStrategyOptions }, + { type: OverlayContainer }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ComponentFactoryResolver"] }, + { type: OverlayPositionBuilder }, + { type: OverlayKeyboardDispatcher }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injector"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["NgZone"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_7__["Directionality"] }, + { type: _angular_common__WEBPACK_IMPORTED_MODULE_2__["Location"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Default set of positions for the overlay. Follows the behavior of a dropdown. + * @type {?} + */ +const defaultPositionList = [ + { + originX: 'start', + originY: 'bottom', + overlayX: 'start', + overlayY: 'top' + }, + { + originX: 'start', + originY: 'top', + overlayX: 'start', + overlayY: 'bottom' + }, + { + originX: 'end', + originY: 'top', + overlayX: 'end', + overlayY: 'bottom' + }, + { + originX: 'end', + originY: 'bottom', + overlayX: 'end', + overlayY: 'top' + } +]; +/** + * Injection token that determines the scroll handling while the connected overlay is open. + * @type {?} + */ +const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["InjectionToken"]('cdk-connected-overlay-scroll-strategy'); +/** + * Directive applied to an element to make it usable as an origin for an Overlay using a + * ConnectedPositionStrategy. + */ +class CdkOverlayOrigin { + /** + * @param {?} elementRef + */ + constructor(elementRef) { + this.elementRef = elementRef; + } +} +CdkOverlayOrigin.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: '[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]', + exportAs: 'cdkOverlayOrigin', + },] }, +]; +/** @nocollapse */ +CdkOverlayOrigin.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ElementRef"] } +]; +/** + * Directive to facilitate declarative creation of an + * Overlay using a FlexibleConnectedPositionStrategy. + */ +class CdkConnectedOverlay { + // TODO(jelbourn): inputs for size, scroll behavior, animation, etc. + /** + * @param {?} _overlay + * @param {?} templateRef + * @param {?} viewContainerRef + * @param {?} scrollStrategyFactory + * @param {?} _dir + */ + constructor(_overlay, templateRef, viewContainerRef, scrollStrategyFactory, _dir) { + this._overlay = _overlay; + this._dir = _dir; + this._hasBackdrop = false; + this._lockPosition = false; + this._growAfterOpen = false; + this._flexibleDimensions = false; + this._push = false; + this._backdropSubscription = rxjs__WEBPACK_IMPORTED_MODULE_4__["Subscription"].EMPTY; + /** + * Margin between the overlay and the viewport edges. + */ + this.viewportMargin = 0; + /** + * Whether the overlay is open. + */ + this.open = false; + /** + * Event emitted when the backdrop is clicked. + */ + this.backdropClick = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"](); + /** + * Event emitted when the position has changed. + */ + this.positionChange = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"](); + /** + * Event emitted when the overlay has been attached. + */ + this.attach = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"](); + /** + * Event emitted when the overlay has been detached. + */ + this.detach = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"](); + /** + * Emits when there are keyboard events that are targeted at the overlay. + */ + this.overlayKeydown = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["EventEmitter"](); + this._templatePortal = new _angular_cdk_portal__WEBPACK_IMPORTED_MODULE_8__["TemplatePortal"](templateRef, viewContainerRef); + this._scrollStrategyFactory = scrollStrategyFactory; + this.scrollStrategy = this._scrollStrategyFactory(); + } + /** + * The offset in pixels for the overlay connection point on the x-axis + * @return {?} + */ + get offsetX() { return this._offsetX; } + /** + * @param {?} offsetX + * @return {?} + */ + set offsetX(offsetX) { + this._offsetX = offsetX; + if (this._position) { + this._updatePositionStrategy(this._position); + } + } + /** + * The offset in pixels for the overlay connection point on the y-axis + * @return {?} + */ + get offsetY() { return this._offsetY; } + /** + * @param {?} offsetY + * @return {?} + */ + set offsetY(offsetY) { + this._offsetY = offsetY; + if (this._position) { + this._updatePositionStrategy(this._position); + } + } + /** + * Whether or not the overlay should attach a backdrop. + * @return {?} + */ + get hasBackdrop() { return this._hasBackdrop; } + /** + * @param {?} value + * @return {?} + */ + set hasBackdrop(value) { this._hasBackdrop = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); } + /** + * Whether or not the overlay should be locked when scrolling. + * @return {?} + */ + get lockPosition() { return this._lockPosition; } + /** + * @param {?} value + * @return {?} + */ + set lockPosition(value) { this._lockPosition = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); } + /** + * Whether the overlay's width and height can be constrained to fit within the viewport. + * @return {?} + */ + get flexibleDimensions() { return this._flexibleDimensions; } + /** + * @param {?} value + * @return {?} + */ + set flexibleDimensions(value) { + this._flexibleDimensions = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); + } + /** + * Whether the overlay can grow after the initial open when flexible positioning is turned on. + * @return {?} + */ + get growAfterOpen() { return this._growAfterOpen; } + /** + * @param {?} value + * @return {?} + */ + set growAfterOpen(value) { this._growAfterOpen = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); } + /** + * Whether the overlay can be pushed on-screen if none of the provided positions fit. + * @return {?} + */ + get push() { return this._push; } + /** + * @param {?} value + * @return {?} + */ + set push(value) { this._push = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(value); } + /** + * The associated overlay reference. + * @return {?} + */ + get overlayRef() { + return this._overlayRef; + } + /** + * The element's layout direction. + * @return {?} + */ + get dir() { + return this._dir ? this._dir.value : 'ltr'; + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._overlayRef) { + this._overlayRef.dispose(); + } + this._backdropSubscription.unsubscribe(); + } + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + if (this._position) { + this._updatePositionStrategy(this._position); + this._overlayRef.updateSize({ + width: this.width, + minWidth: this.minWidth, + height: this.height, + minHeight: this.minHeight, + }); + if (changes['origin'] && this.open) { + this._position.apply(); + } + } + if (changes['open']) { + this.open ? this._attachOverlay() : this._detachOverlay(); + } + } + /** + * Creates an overlay + * @private + * @return {?} + */ + _createOverlay() { + if (!this.positions || !this.positions.length) { + this.positions = defaultPositionList; + } + this._overlayRef = this._overlay.create(this._buildConfig()); + this._overlayRef.keydownEvents().subscribe((/** + * @param {?} event + * @return {?} + */ + (event) => { + this.overlayKeydown.next(event); + if (event.keyCode === _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_9__["ESCAPE"] && !Object(_angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_9__["hasModifierKey"])(event)) { + event.preventDefault(); + this._detachOverlay(); + } + })); + } + /** + * Builds the overlay config based on the directive's inputs + * @private + * @return {?} + */ + _buildConfig() { + /** @type {?} */ + const positionStrategy = this._position = this._createPositionStrategy(); + /** @type {?} */ + const overlayConfig = new OverlayConfig({ + direction: this._dir, + positionStrategy, + scrollStrategy: this.scrollStrategy, + hasBackdrop: this.hasBackdrop + }); + if (this.width || this.width === 0) { + overlayConfig.width = this.width; + } + if (this.height || this.height === 0) { + overlayConfig.height = this.height; + } + if (this.minWidth || this.minWidth === 0) { + overlayConfig.minWidth = this.minWidth; + } + if (this.minHeight || this.minHeight === 0) { + overlayConfig.minHeight = this.minHeight; + } + if (this.backdropClass) { + overlayConfig.backdropClass = this.backdropClass; + } + if (this.panelClass) { + overlayConfig.panelClass = this.panelClass; + } + return overlayConfig; + } + /** + * Updates the state of a position strategy, based on the values of the directive inputs. + * @private + * @param {?} positionStrategy + * @return {?} + */ + _updatePositionStrategy(positionStrategy) { + /** @type {?} */ + const positions = this.positions.map((/** + * @param {?} currentPosition + * @return {?} + */ + currentPosition => ({ + originX: currentPosition.originX, + originY: currentPosition.originY, + overlayX: currentPosition.overlayX, + overlayY: currentPosition.overlayY, + offsetX: currentPosition.offsetX || this.offsetX, + offsetY: currentPosition.offsetY || this.offsetY, + panelClass: currentPosition.panelClass || undefined, + }))); + return positionStrategy + .setOrigin(this.origin.elementRef) + .withPositions(positions) + .withFlexibleDimensions(this.flexibleDimensions) + .withPush(this.push) + .withGrowAfterOpen(this.growAfterOpen) + .withViewportMargin(this.viewportMargin) + .withLockedPosition(this.lockPosition); + } + /** + * Returns the position strategy of the overlay to be set on the overlay config + * @private + * @return {?} + */ + _createPositionStrategy() { + /** @type {?} */ + const strategy = this._overlay.position().flexibleConnectedTo(this.origin.elementRef); + this._updatePositionStrategy(strategy); + strategy.positionChanges.subscribe((/** + * @param {?} p + * @return {?} + */ + p => this.positionChange.emit(p))); + return strategy; + } + /** + * Attaches the overlay and subscribes to backdrop clicks if backdrop exists + * @private + * @return {?} + */ + _attachOverlay() { + if (!this._overlayRef) { + this._createOverlay(); + } + else { + // Update the overlay size, in case the directive's inputs have changed + this._overlayRef.getConfig().hasBackdrop = this.hasBackdrop; + } + if (!this._overlayRef.hasAttached()) { + this._overlayRef.attach(this._templatePortal); + this.attach.emit(); + } + if (this.hasBackdrop) { + this._backdropSubscription = this._overlayRef.backdropClick().subscribe((/** + * @param {?} event + * @return {?} + */ + event => { + this.backdropClick.emit(event); + })); + } + else { + this._backdropSubscription.unsubscribe(); + } + } + /** + * Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists + * @private + * @return {?} + */ + _detachOverlay() { + if (this._overlayRef) { + this._overlayRef.detach(); + this.detach.emit(); + } + this._backdropSubscription.unsubscribe(); + } +} +CdkConnectedOverlay.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]', + exportAs: 'cdkConnectedOverlay' + },] }, +]; +/** @nocollapse */ +CdkConnectedOverlay.ctorParameters = () => [ + { type: Overlay }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ViewContainerRef"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY,] }] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_7__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"] }] } +]; +CdkConnectedOverlay.propDecorators = { + origin: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayOrigin',] }], + positions: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayPositions',] }], + offsetX: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayOffsetX',] }], + offsetY: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayOffsetY',] }], + width: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayWidth',] }], + height: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayHeight',] }], + minWidth: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayMinWidth',] }], + minHeight: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayMinHeight',] }], + backdropClass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayBackdropClass',] }], + panelClass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayPanelClass',] }], + viewportMargin: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayViewportMargin',] }], + scrollStrategy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayScrollStrategy',] }], + open: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayOpen',] }], + hasBackdrop: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayHasBackdrop',] }], + lockPosition: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayLockPosition',] }], + flexibleDimensions: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayFlexibleDimensions',] }], + growAfterOpen: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayGrowAfterOpen',] }], + push: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkConnectedOverlayPush',] }], + backdropClick: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Output"] }], + positionChange: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Output"] }], + attach: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Output"] }], + detach: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Output"] }], + overlayKeydown: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Output"] }] +}; +/** + * \@docs-private + * @param {?} overlay + * @return {?} + */ +function CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay) { + return (/** + * @return {?} + */ + () => overlay.scrollStrategies.reposition()); +} +/** + * \@docs-private + * @type {?} + */ +const CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER = { + provide: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY, + deps: [Overlay], + useFactory: CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER_FACTORY, +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class OverlayModule { +} +OverlayModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["NgModule"], args: [{ + imports: [_angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_7__["BidiModule"], _angular_cdk_portal__WEBPACK_IMPORTED_MODULE_8__["PortalModule"], _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ScrollingModule"]], + exports: [CdkConnectedOverlay, CdkOverlayOrigin, _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["ScrollingModule"]], + declarations: [CdkConnectedOverlay, CdkOverlayOrigin], + providers: [ + Overlay, + CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER, + ], + },] }, +]; +/** + * @deprecated Use `OverlayModule` instead. + * \@breaking-change 8.0.0 + * \@docs-private + * @type {?} + */ +const OVERLAY_PROVIDERS = [ + Overlay, + OverlayPositionBuilder, + OVERLAY_KEYBOARD_DISPATCHER_PROVIDER, + _angular_cdk_scrolling__WEBPACK_IMPORTED_MODULE_1__["VIEWPORT_RULER_PROVIDER"], + OVERLAY_CONTAINER_PROVIDER, + CDK_CONNECTED_OVERLAY_SCROLL_STRATEGY_PROVIDER, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Alternative to OverlayContainer that supports correct displaying of overlay elements in + * Fullscreen mode + * https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullScreen + * + * Should be provided in the root component. + */ +class FullscreenOverlayContainer extends OverlayContainer { + /** + * @param {?} _document + */ + constructor(_document) { + super(_document); + } + /** + * @return {?} + */ + ngOnDestroy() { + super.ngOnDestroy(); + if (this._fullScreenEventName && this._fullScreenListener) { + this._document.removeEventListener(this._fullScreenEventName, this._fullScreenListener); + } + } + /** + * @protected + * @return {?} + */ + _createContainer() { + super._createContainer(); + this._adjustParentForFullscreenChange(); + this._addFullscreenChangeListener((/** + * @return {?} + */ + () => this._adjustParentForFullscreenChange())); + } + /** + * @private + * @return {?} + */ + _adjustParentForFullscreenChange() { + if (!this._containerElement) { + return; + } + /** @type {?} */ + const fullscreenElement = this.getFullscreenElement(); + /** @type {?} */ + const parent = fullscreenElement || this._document.body; + parent.appendChild(this._containerElement); + } + /** + * @private + * @param {?} fn + * @return {?} + */ + _addFullscreenChangeListener(fn) { + /** @type {?} */ + const eventName = this._getEventName(); + if (eventName) { + if (this._fullScreenListener) { + this._document.removeEventListener(eventName, this._fullScreenListener); + } + this._document.addEventListener(eventName, fn); + this._fullScreenListener = fn; + } + } + /** + * @private + * @return {?} + */ + _getEventName() { + if (!this._fullScreenEventName) { + if (this._document.fullscreenEnabled) { + this._fullScreenEventName = 'fullscreenchange'; + } + else if (this._document.webkitFullscreenEnabled) { + this._fullScreenEventName = 'webkitfullscreenchange'; + } + else if (((/** @type {?} */ (this._document))).mozFullScreenEnabled) { + this._fullScreenEventName = 'mozfullscreenchange'; + } + else if (((/** @type {?} */ (this._document))).msFullscreenEnabled) { + this._fullScreenEventName = 'MSFullscreenChange'; + } + } + return this._fullScreenEventName; + } + /** + * When the page is put into fullscreen mode, a specific element is specified. + * Only that element and its children are visible when in fullscreen mode. + * @return {?} + */ + getFullscreenElement() { + return this._document.fullscreenElement || + this._document.webkitFullscreenElement || + ((/** @type {?} */ (this._document))).mozFullScreenElement || + ((/** @type {?} */ (this._document))).msFullscreenElement || + null; + } +} +FullscreenOverlayContainer.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +FullscreenOverlayContainer.ctorParameters = () => [ + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"],] }] } +]; +/** @nocollapse */ FullscreenOverlayContainer.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵdefineInjectable"])({ factory: function FullscreenOverlayContainer_Factory() { return new FullscreenOverlayContainer(Object(_angular_core__WEBPACK_IMPORTED_MODULE_3__["ɵɵinject"])(_angular_common__WEBPACK_IMPORTED_MODULE_2__["DOCUMENT"])); }, token: FullscreenOverlayContainer, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=overlay.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/platform.js": +/*!*******************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/platform.js ***! + \*******************************************************/ +/*! exports provided: Platform, PlatformModule, getSupportedInputTypes, supportsPassiveEventListeners, normalizePassiveListenerOptions, supportsScrollBehavior, getRtlScrollAxisType, RtlScrollAxisType */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Platform", function() { return Platform; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlatformModule", function() { return PlatformModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSupportedInputTypes", function() { return getSupportedInputTypes; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "supportsPassiveEventListeners", function() { return supportsPassiveEventListeners; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "normalizePassiveListenerOptions", function() { return normalizePassiveListenerOptions; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "supportsScrollBehavior", function() { return supportsScrollBehavior; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getRtlScrollAxisType", function() { return getRtlScrollAxisType; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RtlScrollAxisType", function() { return RtlScrollAxisType; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// Whether the current platform supports the V8 Break Iterator. The V8 check +// is necessary to detect all Blink based browsers. +/** @type {?} */ +let hasV8BreakIterator; +// We need a try/catch around the reference to `Intl`, because accessing it in some cases can +// cause IE to throw. These cases are tied to particular versions of Windows and can happen if +// the consumer is providing a polyfilled `Map`. See: +// https://github.com/Microsoft/ChakraCore/issues/3189 +// https://github.com/angular/components/issues/15687 +try { + hasV8BreakIterator = (typeof Intl !== 'undefined' && ((/** @type {?} */ (Intl))).v8BreakIterator); +} +catch (_a) { + hasV8BreakIterator = false; +} +/** + * Service to detect the current platform by comparing the userAgent strings and + * checking browser-specific global properties. + */ +class Platform { + /** + * \@breaking-change 8.0.0 remove optional decorator + * @param {?=} _platformId + */ + constructor(_platformId) { + this._platformId = _platformId; + /** + * Whether the Angular application is being rendered in the browser. + * We want to use the Angular platform check because if the Document is shimmed + * without the navigator, the following checks will fail. This is preferred because + * sometimes the Document may be shimmed without the user's knowledge or intention + */ + this.isBrowser = this._platformId ? + Object(_angular_common__WEBPACK_IMPORTED_MODULE_1__["isPlatformBrowser"])(this._platformId) : typeof document === 'object' && !!document; + /** + * Whether the current browser is Microsoft Edge. + */ + this.EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent); + /** + * Whether the current rendering engine is Microsoft Trident. + */ + this.TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent); + /** + * Whether the current rendering engine is Blink. + */ + // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check. + this.BLINK = this.isBrowser && (!!(((/** @type {?} */ (window))).chrome || hasV8BreakIterator) && + typeof CSS !== 'undefined' && !this.EDGE && !this.TRIDENT); + /** + * Whether the current rendering engine is WebKit. + */ + // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to + // ensure that Webkit runs standalone and is not used as another engine's base. + this.WEBKIT = this.isBrowser && + /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT; + /** + * Whether the current platform is Apple iOS. + */ + this.IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && + !('MSStream' in window); + /** + * Whether the current browser is Firefox. + */ + // It's difficult to detect the plain Gecko engine, because most of the browsers identify + // them self as Gecko-like browsers and modify the userAgent's according to that. + // Since we only cover one explicit Firefox case, we can simply check for Firefox + // instead of having an unstable check for Gecko. + this.FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent); + /** + * Whether the current platform is Android. + */ + // Trident on mobile adds the android platform to the userAgent to trick detections. + this.ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT; + /** + * Whether the current browser is Safari. + */ + // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake + // this and just place the Safari keyword in the userAgent. To be more safe about Safari every + // Safari browser should also use Webkit as its layout engine. + this.SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT; + } +} +Platform.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +Platform.ctorParameters = () => [ + { type: Object, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["PLATFORM_ID"],] }] } +]; +/** @nocollapse */ Platform.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: function Platform_Factory() { return new Platform(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["PLATFORM_ID"], 8)); }, token: Platform, providedIn: "root" }); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class PlatformModule { +} +PlatformModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{},] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Cached result Set of input types support by the current browser. + * @type {?} + */ +let supportedInputTypes; +/** + * Types of `` that *might* be supported. + * @type {?} + */ +const candidateInputTypes = [ + // `color` must come first. Chrome 56 shows a warning if we change the type to `color` after + // first changing it to something else: + // The specified value "" does not conform to the required format. + // The format is "#rrggbb" where rr, gg, bb are two-digit hexadecimal numbers. + 'color', + 'button', + 'checkbox', + 'date', + 'datetime-local', + 'email', + 'file', + 'hidden', + 'image', + 'month', + 'number', + 'password', + 'radio', + 'range', + 'reset', + 'search', + 'submit', + 'tel', + 'text', + 'time', + 'url', + 'week', +]; +/** + * @return {?} The input types supported by this browser. + */ +function getSupportedInputTypes() { + // Result is cached. + if (supportedInputTypes) { + return supportedInputTypes; + } + // We can't check if an input type is not supported until we're on the browser, so say that + // everything is supported when not on the browser. We don't use `Platform` here since it's + // just a helper function and can't inject it. + if (typeof document !== 'object' || !document) { + supportedInputTypes = new Set(candidateInputTypes); + return supportedInputTypes; + } + /** @type {?} */ + let featureTestInput = document.createElement('input'); + supportedInputTypes = new Set(candidateInputTypes.filter((/** + * @param {?} value + * @return {?} + */ + value => { + featureTestInput.setAttribute('type', value); + return featureTestInput.type === value; + }))); + return supportedInputTypes; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Cached result of whether the user's browser supports passive event listeners. + * @type {?} + */ +let supportsPassiveEvents; +/** + * Checks whether the user's browser supports passive event listeners. + * See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md + * @return {?} + */ +function supportsPassiveEventListeners() { + if (supportsPassiveEvents == null && typeof window !== 'undefined') { + try { + window.addEventListener('test', (/** @type {?} */ (null)), Object.defineProperty({}, 'passive', { + get: (/** + * @return {?} + */ + () => supportsPassiveEvents = true) + })); + } + finally { + supportsPassiveEvents = supportsPassiveEvents || false; + } + } + return supportsPassiveEvents; +} +/** + * Normalizes an `AddEventListener` object to something that can be passed + * to `addEventListener` on any browser, no matter whether it supports the + * `options` parameter. + * @param {?} options Object to be normalized. + * @return {?} + */ +function normalizePassiveListenerOptions(options) { + return supportsPassiveEventListeners() ? options : !!options.capture; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** @enum {number} */ +const RtlScrollAxisType = { + /** + * scrollLeft is 0 when scrolled all the way left and (scrollWidth - clientWidth) when scrolled + * all the way right. + */ + NORMAL: 0, + /** + * scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled + * all the way right. + */ + NEGATED: 1, + /** + * scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled + * all the way right. + */ + INVERTED: 2, +}; +RtlScrollAxisType[RtlScrollAxisType.NORMAL] = 'NORMAL'; +RtlScrollAxisType[RtlScrollAxisType.NEGATED] = 'NEGATED'; +RtlScrollAxisType[RtlScrollAxisType.INVERTED] = 'INVERTED'; +/** + * Cached result of the way the browser handles the horizontal scroll axis in RTL mode. + * @type {?} + */ +let rtlScrollAxisType; +/** + * Check whether the browser supports scroll behaviors. + * @return {?} + */ +function supportsScrollBehavior() { + return !!(typeof document == 'object' && 'scrollBehavior' in (/** @type {?} */ (document.documentElement)).style); +} +/** + * Checks the type of RTL scroll axis used by this browser. As of time of writing, Chrome is NORMAL, + * Firefox & Safari are NEGATED, and IE & Edge are INVERTED. + * @return {?} + */ +function getRtlScrollAxisType() { + // We can't check unless we're on the browser. Just assume 'normal' if we're not. + if (typeof document !== 'object' || !document) { + return RtlScrollAxisType.NORMAL; + } + if (!rtlScrollAxisType) { + // Create a 1px wide scrolling container and a 2px wide content element. + /** @type {?} */ + const scrollContainer = document.createElement('div'); + /** @type {?} */ + const containerStyle = scrollContainer.style; + scrollContainer.dir = 'rtl'; + containerStyle.height = '1px'; + containerStyle.width = '1px'; + containerStyle.overflow = 'auto'; + containerStyle.visibility = 'hidden'; + containerStyle.pointerEvents = 'none'; + containerStyle.position = 'absolute'; + /** @type {?} */ + const content = document.createElement('div'); + /** @type {?} */ + const contentStyle = content.style; + contentStyle.width = '2px'; + contentStyle.height = '1px'; + scrollContainer.appendChild(content); + document.body.appendChild(scrollContainer); + rtlScrollAxisType = RtlScrollAxisType.NORMAL; + // The viewport starts scrolled all the way to the right in RTL mode. If we are in a NORMAL + // browser this would mean that the scrollLeft should be 1. If it's zero instead we know we're + // dealing with one of the other two types of browsers. + if (scrollContainer.scrollLeft === 0) { + // In a NEGATED browser the scrollLeft is always somewhere in [-maxScrollAmount, 0]. For an + // INVERTED browser it is always somewhere in [0, maxScrollAmount]. We can determine which by + // setting to the scrollLeft to 1. This is past the max for a NEGATED browser, so it will + // return 0 when we read it again. + scrollContainer.scrollLeft = 1; + rtlScrollAxisType = + scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED; + } + (/** @type {?} */ (scrollContainer.parentNode)).removeChild(scrollContainer); + } + return rtlScrollAxisType; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=platform.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/portal.js": +/*!*****************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/portal.js ***! + \*****************************************************/ +/*! exports provided: DomPortalHost, PortalHostDirective, TemplatePortalDirective, BasePortalHost, Portal, ComponentPortal, TemplatePortal, BasePortalOutlet, DomPortalOutlet, CdkPortal, CdkPortalOutlet, PortalModule, PortalInjector */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DomPortalHost", function() { return DomPortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PortalHostDirective", function() { return CdkPortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplatePortalDirective", function() { return CdkPortal; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BasePortalHost", function() { return BasePortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Portal", function() { return Portal; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComponentPortal", function() { return ComponentPortal; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplatePortal", function() { return TemplatePortal; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BasePortalOutlet", function() { return BasePortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DomPortalOutlet", function() { return DomPortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkPortal", function() { return CdkPortal; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkPortalOutlet", function() { return CdkPortalOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PortalModule", function() { return PortalModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PortalInjector", function() { return PortalInjector; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Throws an exception when attempting to attach a null portal to a host. + * \@docs-private + * @return {?} + */ +function throwNullPortalError() { + throw Error('Must provide a portal to attach'); +} +/** + * Throws an exception when attempting to attach a portal to a host that is already attached. + * \@docs-private + * @return {?} + */ +function throwPortalAlreadyAttachedError() { + throw Error('Host already has a portal attached'); +} +/** + * Throws an exception when attempting to attach a portal to an already-disposed host. + * \@docs-private + * @return {?} + */ +function throwPortalOutletAlreadyDisposedError() { + throw Error('This PortalOutlet has already been disposed'); +} +/** + * Throws an exception when attempting to attach an unknown portal type. + * \@docs-private + * @return {?} + */ +function throwUnknownPortalTypeError() { + throw Error('Attempting to attach an unknown Portal type. BasePortalOutlet accepts either ' + + 'a ComponentPortal or a TemplatePortal.'); +} +/** + * Throws an exception when attempting to attach a portal to a null host. + * \@docs-private + * @return {?} + */ +function throwNullPortalOutletError() { + throw Error('Attempting to attach a portal to a null PortalOutlet'); +} +/** + * Throws an exception when attempting to detach a portal that is not attached. + * \@docs-private + * @return {?} + */ +function throwNoPortalAttachedError() { + throw Error('Attempting to detach a portal that is not attached to a host'); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A `Portal` is something that you want to render somewhere else. + * It can be attach to / detached from a `PortalOutlet`. + * @abstract + * @template T + */ +class Portal { + /** + * Attach this portal to a host. + * @param {?} host + * @return {?} + */ + attach(host) { + if (host == null) { + throwNullPortalOutletError(); + } + if (host.hasAttached()) { + throwPortalAlreadyAttachedError(); + } + this._attachedHost = host; + return (/** @type {?} */ (host.attach(this))); + } + /** + * Detach this portal from its host + * @return {?} + */ + detach() { + /** @type {?} */ + let host = this._attachedHost; + if (host == null) { + throwNoPortalAttachedError(); + } + else { + this._attachedHost = null; + host.detach(); + } + } + /** + * Whether this portal is attached to a host. + * @return {?} + */ + get isAttached() { + return this._attachedHost != null; + } + /** + * Sets the PortalOutlet reference without performing `attach()`. This is used directly by + * the PortalOutlet when it is performing an `attach()` or `detach()`. + * @param {?} host + * @return {?} + */ + setAttachedHost(host) { + this._attachedHost = host; + } +} +/** + * A `ComponentPortal` is a portal that instantiates some Component upon attachment. + * @template T + */ +class ComponentPortal extends Portal { + /** + * @param {?} component + * @param {?=} viewContainerRef + * @param {?=} injector + * @param {?=} componentFactoryResolver + */ + constructor(component, viewContainerRef, injector, componentFactoryResolver) { + super(); + this.component = component; + this.viewContainerRef = viewContainerRef; + this.injector = injector; + this.componentFactoryResolver = componentFactoryResolver; + } +} +/** + * A `TemplatePortal` is a portal that represents some embedded template (TemplateRef). + * @template C + */ +class TemplatePortal extends Portal { + /** + * @param {?} template + * @param {?} viewContainerRef + * @param {?=} context + */ + constructor(template, viewContainerRef, context) { + super(); + this.templateRef = template; + this.viewContainerRef = viewContainerRef; + this.context = context; + } + /** + * @return {?} + */ + get origin() { + return this.templateRef.elementRef; + } + /** + * Attach the portal to the provided `PortalOutlet`. + * When a context is provided it will override the `context` property of the `TemplatePortal` + * instance. + * @param {?} host + * @param {?=} context + * @return {?} + */ + attach(host, context = this.context) { + this.context = context; + return super.attach(host); + } + /** + * @return {?} + */ + detach() { + this.context = undefined; + return super.detach(); + } +} +/** + * Partial implementation of PortalOutlet that handles attaching + * ComponentPortal and TemplatePortal. + * @abstract + */ +class BasePortalOutlet { + constructor() { + /** + * Whether this host has already been permanently disposed. + */ + this._isDisposed = false; + } + /** + * Whether this host has an attached portal. + * @return {?} + */ + hasAttached() { + return !!this._attachedPortal; + } + /** + * Attaches a portal. + * @param {?} portal + * @return {?} + */ + attach(portal) { + if (!portal) { + throwNullPortalError(); + } + if (this.hasAttached()) { + throwPortalAlreadyAttachedError(); + } + if (this._isDisposed) { + throwPortalOutletAlreadyDisposedError(); + } + if (portal instanceof ComponentPortal) { + this._attachedPortal = portal; + return this.attachComponentPortal(portal); + } + else if (portal instanceof TemplatePortal) { + this._attachedPortal = portal; + return this.attachTemplatePortal(portal); + } + throwUnknownPortalTypeError(); + } + /** + * Detaches a previously attached portal. + * @return {?} + */ + detach() { + if (this._attachedPortal) { + this._attachedPortal.setAttachedHost(null); + this._attachedPortal = null; + } + this._invokeDisposeFn(); + } + /** + * Permanently dispose of this portal host. + * @return {?} + */ + dispose() { + if (this.hasAttached()) { + this.detach(); + } + this._invokeDisposeFn(); + this._isDisposed = true; + } + /** + * \@docs-private + * @param {?} fn + * @return {?} + */ + setDisposeFn(fn) { + this._disposeFn = fn; + } + /** + * @private + * @return {?} + */ + _invokeDisposeFn() { + if (this._disposeFn) { + this._disposeFn(); + this._disposeFn = null; + } + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A PortalOutlet for attaching portals to an arbitrary DOM element outside of the Angular + * application context. + */ +class DomPortalOutlet extends BasePortalOutlet { + /** + * @param {?} outletElement + * @param {?} _componentFactoryResolver + * @param {?} _appRef + * @param {?} _defaultInjector + */ + constructor(outletElement, _componentFactoryResolver, _appRef, _defaultInjector) { + super(); + this.outletElement = outletElement; + this._componentFactoryResolver = _componentFactoryResolver; + this._appRef = _appRef; + this._defaultInjector = _defaultInjector; + } + /** + * Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. + * @template T + * @param {?} portal Portal to be attached + * @return {?} Reference to the created component. + */ + attachComponentPortal(portal) { + /** @type {?} */ + const resolver = portal.componentFactoryResolver || this._componentFactoryResolver; + /** @type {?} */ + const componentFactory = resolver.resolveComponentFactory(portal.component); + /** @type {?} */ + let componentRef; + // If the portal specifies a ViewContainerRef, we will use that as the attachment point + // for the component (in terms of Angular's component tree, not rendering). + // When the ViewContainerRef is missing, we use the factory to create the component directly + // and then manually attach the view to the application. + if (portal.viewContainerRef) { + componentRef = portal.viewContainerRef.createComponent(componentFactory, portal.viewContainerRef.length, portal.injector || portal.viewContainerRef.injector); + this.setDisposeFn((/** + * @return {?} + */ + () => componentRef.destroy())); + } + else { + componentRef = componentFactory.create(portal.injector || this._defaultInjector); + this._appRef.attachView(componentRef.hostView); + this.setDisposeFn((/** + * @return {?} + */ + () => { + this._appRef.detachView(componentRef.hostView); + componentRef.destroy(); + })); + } + // At this point the component has been instantiated, so we move it to the location in the DOM + // where we want it to be rendered. + this.outletElement.appendChild(this._getComponentRootNode(componentRef)); + return componentRef; + } + /** + * Attaches a template portal to the DOM as an embedded view. + * @template C + * @param {?} portal Portal to be attached. + * @return {?} Reference to the created embedded view. + */ + attachTemplatePortal(portal) { + /** @type {?} */ + let viewContainer = portal.viewContainerRef; + /** @type {?} */ + let viewRef = viewContainer.createEmbeddedView(portal.templateRef, portal.context); + viewRef.detectChanges(); + // The method `createEmbeddedView` will add the view as a child of the viewContainer. + // But for the DomPortalOutlet the view can be added everywhere in the DOM + // (e.g Overlay Container) To move the view to the specified host element. We just + // re-append the existing root nodes. + viewRef.rootNodes.forEach((/** + * @param {?} rootNode + * @return {?} + */ + rootNode => this.outletElement.appendChild(rootNode))); + this.setDisposeFn(((/** + * @return {?} + */ + () => { + /** @type {?} */ + let index = viewContainer.indexOf(viewRef); + if (index !== -1) { + viewContainer.remove(index); + } + }))); + // TODO(jelbourn): Return locals from view. + return viewRef; + } + /** + * Clears out a portal from the DOM. + * @return {?} + */ + dispose() { + super.dispose(); + if (this.outletElement.parentNode != null) { + this.outletElement.parentNode.removeChild(this.outletElement); + } + } + /** + * Gets the root HTMLElement for an instantiated component. + * @private + * @param {?} componentRef + * @return {?} + */ + _getComponentRootNode(componentRef) { + return (/** @type {?} */ (((/** @type {?} */ (componentRef.hostView))).rootNodes[0])); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal, + * the directive instance itself can be attached to a host, enabling declarative use of portals. + */ +class CdkPortal extends TemplatePortal { + /** + * @param {?} templateRef + * @param {?} viewContainerRef + */ + constructor(templateRef, viewContainerRef) { + super(templateRef, viewContainerRef); + } +} +CdkPortal.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdk-portal], [cdkPortal], [portal]', + exportAs: 'cdkPortal', + },] }, +]; +/** @nocollapse */ +CdkPortal.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] } +]; +/** + * Directive version of a PortalOutlet. Because the directive *is* a PortalOutlet, portals can be + * directly attached to it, enabling declarative use. + * + * Usage: + * `` + */ +class CdkPortalOutlet extends BasePortalOutlet { + /** + * @param {?} _componentFactoryResolver + * @param {?} _viewContainerRef + */ + constructor(_componentFactoryResolver, _viewContainerRef) { + super(); + this._componentFactoryResolver = _componentFactoryResolver; + this._viewContainerRef = _viewContainerRef; + /** + * Whether the portal component is initialized. + */ + this._isInitialized = false; + /** + * Emits when a portal is attached to the outlet. + */ + this.attached = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["EventEmitter"](); + } + /** + * Portal associated with the Portal outlet. + * @return {?} + */ + get portal() { + return this._attachedPortal; + } + /** + * @param {?} portal + * @return {?} + */ + set portal(portal) { + // Ignore the cases where the `portal` is set to a falsy value before the lifecycle hooks have + // run. This handles the cases where the user might do something like `
` + // and attach a portal programmatically in the parent component. When Angular does the first CD + // round, it will fire the setter with empty string, causing the user's content to be cleared. + if (this.hasAttached() && !portal && !this._isInitialized) { + return; + } + if (this.hasAttached()) { + super.detach(); + } + if (portal) { + super.attach(portal); + } + this._attachedPortal = portal; + } + /** + * Component or view reference that is attached to the portal. + * @return {?} + */ + get attachedRef() { + return this._attachedRef; + } + /** + * @return {?} + */ + ngOnInit() { + this._isInitialized = true; + } + /** + * @return {?} + */ + ngOnDestroy() { + super.dispose(); + this._attachedPortal = null; + this._attachedRef = null; + } + /** + * Attach the given ComponentPortal to this PortalOutlet using the ComponentFactoryResolver. + * + * @template T + * @param {?} portal Portal to be attached to the portal outlet. + * @return {?} Reference to the created component. + */ + attachComponentPortal(portal) { + portal.setAttachedHost(this); + // If the portal specifies an origin, use that as the logical location of the component + // in the application tree. Otherwise use the location of this PortalOutlet. + /** @type {?} */ + const viewContainerRef = portal.viewContainerRef != null ? + portal.viewContainerRef : + this._viewContainerRef; + /** @type {?} */ + const resolver = portal.componentFactoryResolver || this._componentFactoryResolver; + /** @type {?} */ + const componentFactory = resolver.resolveComponentFactory(portal.component); + /** @type {?} */ + const ref = viewContainerRef.createComponent(componentFactory, viewContainerRef.length, portal.injector || viewContainerRef.injector); + super.setDisposeFn((/** + * @return {?} + */ + () => ref.destroy())); + this._attachedPortal = portal; + this._attachedRef = ref; + this.attached.emit(ref); + return ref; + } + /** + * Attach the given TemplatePortal to this PortlHost as an embedded View. + * @template C + * @param {?} portal Portal to be attached. + * @return {?} Reference to the created embedded view. + */ + attachTemplatePortal(portal) { + portal.setAttachedHost(this); + /** @type {?} */ + const viewRef = this._viewContainerRef.createEmbeddedView(portal.templateRef, portal.context); + super.setDisposeFn((/** + * @return {?} + */ + () => this._viewContainerRef.clear())); + this._attachedPortal = portal; + this._attachedRef = viewRef; + this.attached.emit(viewRef); + return viewRef; + } +} +CdkPortalOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdkPortalOutlet], [cdkPortalHost], [portalHost]', + exportAs: 'cdkPortalOutlet, cdkPortalHost', + inputs: ['portal: cdkPortalOutlet'] + },] }, +]; +/** @nocollapse */ +CdkPortalOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ComponentFactoryResolver"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] } +]; +CdkPortalOutlet.propDecorators = { + attached: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Output"] }] +}; +class PortalModule { +} +PortalModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + exports: [CdkPortal, CdkPortalOutlet], + declarations: [CdkPortal, CdkPortalOutlet], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Custom injector to be used when providing custom + * injection tokens to components inside a portal. + * \@docs-private + */ +class PortalInjector { + /** + * @param {?} _parentInjector + * @param {?} _customTokens + */ + constructor(_parentInjector, _customTokens) { + this._parentInjector = _parentInjector; + this._customTokens = _customTokens; + } + /** + * @param {?} token + * @param {?=} notFoundValue + * @return {?} + */ + get(token, notFoundValue) { + /** @type {?} */ + const value = this._customTokens.get(token); + if (typeof value !== 'undefined') { + return value; + } + return this._parentInjector.get(token, notFoundValue); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=portal.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/scrolling.js": +/*!********************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/scrolling.js ***! + \********************************************************/ +/*! exports provided: _fixedSizeVirtualScrollStrategyFactory, FixedSizeVirtualScrollStrategy, CdkFixedSizeVirtualScroll, SCROLL_DISPATCHER_PROVIDER_FACTORY, DEFAULT_SCROLL_TIME, ScrollDispatcher, SCROLL_DISPATCHER_PROVIDER, CdkScrollable, ScrollingModule, ScrollDispatchModule, VIEWPORT_RULER_PROVIDER_FACTORY, DEFAULT_RESIZE_TIME, ViewportRuler, VIEWPORT_RULER_PROVIDER, CdkVirtualForOf, VIRTUAL_SCROLL_STRATEGY, CdkVirtualScrollViewport */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_fixedSizeVirtualScrollStrategyFactory", function() { return _fixedSizeVirtualScrollStrategyFactory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FixedSizeVirtualScrollStrategy", function() { return FixedSizeVirtualScrollStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkFixedSizeVirtualScroll", function() { return CdkFixedSizeVirtualScroll; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SCROLL_DISPATCHER_PROVIDER_FACTORY", function() { return SCROLL_DISPATCHER_PROVIDER_FACTORY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_SCROLL_TIME", function() { return DEFAULT_SCROLL_TIME; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollDispatcher", function() { return ScrollDispatcher; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SCROLL_DISPATCHER_PROVIDER", function() { return SCROLL_DISPATCHER_PROVIDER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkScrollable", function() { return CdkScrollable; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollingModule", function() { return ScrollingModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollDispatchModule", function() { return ScrollDispatchModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VIEWPORT_RULER_PROVIDER_FACTORY", function() { return VIEWPORT_RULER_PROVIDER_FACTORY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_RESIZE_TIME", function() { return DEFAULT_RESIZE_TIME; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewportRuler", function() { return ViewportRuler; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VIEWPORT_RULER_PROVIDER", function() { return VIEWPORT_RULER_PROVIDER; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkVirtualForOf", function() { return CdkVirtualForOf; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VIRTUAL_SCROLL_STRATEGY", function() { return VIRTUAL_SCROLL_STRATEGY; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkVirtualScrollViewport", function() { return CdkVirtualScrollViewport; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/* harmony import */ var _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/cdk/platform */ "./node_modules/@angular/cdk/esm2015/platform.js"); +/* harmony import */ var _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/cdk/bidi */ "./node_modules/@angular/cdk/esm2015/bidi.js"); +/* harmony import */ var _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/cdk/collections */ "./node_modules/@angular/cdk/esm2015/collections.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * The injection token used to specify the virtual scrolling strategy. + * @type {?} + */ +const VIRTUAL_SCROLL_STRATEGY = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('VIRTUAL_SCROLL_STRATEGY'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Virtual scrolling strategy for lists with items of known fixed size. + */ +class FixedSizeVirtualScrollStrategy { + /** + * @param {?} itemSize The size of the items in the virtually scrolling list. + * @param {?} minBufferPx The minimum amount of buffer (in pixels) before needing to render more + * @param {?} maxBufferPx The amount of buffer (in pixels) to render when rendering more. + */ + constructor(itemSize, minBufferPx, maxBufferPx) { + this._scrolledIndexChange = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * \@docs-private Implemented as part of VirtualScrollStrategy. + */ + this.scrolledIndexChange = this._scrolledIndexChange.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["distinctUntilChanged"])()); + /** + * The attached viewport. + */ + this._viewport = null; + this._itemSize = itemSize; + this._minBufferPx = minBufferPx; + this._maxBufferPx = maxBufferPx; + } + /** + * Attaches this scroll strategy to a viewport. + * @param {?} viewport The viewport to attach this strategy to. + * @return {?} + */ + attach(viewport) { + this._viewport = viewport; + this._updateTotalContentSize(); + this._updateRenderedRange(); + } + /** + * Detaches this scroll strategy from the currently attached viewport. + * @return {?} + */ + detach() { + this._scrolledIndexChange.complete(); + this._viewport = null; + } + /** + * Update the item size and buffer size. + * @param {?} itemSize The size of the items in the virtually scrolling list. + * @param {?} minBufferPx The minimum amount of buffer (in pixels) before needing to render more + * @param {?} maxBufferPx The amount of buffer (in pixels) to render when rendering more. + * @return {?} + */ + updateItemAndBufferSize(itemSize, minBufferPx, maxBufferPx) { + if (maxBufferPx < minBufferPx) { + throw Error('CDK virtual scroll: maxBufferPx must be greater than or equal to minBufferPx'); + } + this._itemSize = itemSize; + this._minBufferPx = minBufferPx; + this._maxBufferPx = maxBufferPx; + this._updateTotalContentSize(); + this._updateRenderedRange(); + } + /** + * \@docs-private Implemented as part of VirtualScrollStrategy. + * @return {?} + */ + onContentScrolled() { + this._updateRenderedRange(); + } + /** + * \@docs-private Implemented as part of VirtualScrollStrategy. + * @return {?} + */ + onDataLengthChanged() { + this._updateTotalContentSize(); + this._updateRenderedRange(); + } + /** + * \@docs-private Implemented as part of VirtualScrollStrategy. + * @return {?} + */ + onContentRendered() { } + /** + * \@docs-private Implemented as part of VirtualScrollStrategy. + * @return {?} + */ + onRenderedOffsetChanged() { } + /** + * Scroll to the offset for the given index. + * @param {?} index The index of the element to scroll to. + * @param {?} behavior The ScrollBehavior to use when scrolling. + * @return {?} + */ + scrollToIndex(index, behavior) { + if (this._viewport) { + this._viewport.scrollToOffset(index * this._itemSize, behavior); + } + } + /** + * Update the viewport's total content size. + * @private + * @return {?} + */ + _updateTotalContentSize() { + if (!this._viewport) { + return; + } + this._viewport.setTotalContentSize(this._viewport.getDataLength() * this._itemSize); + } + /** + * Update the viewport's rendered range. + * @private + * @return {?} + */ + _updateRenderedRange() { + if (!this._viewport) { + return; + } + /** @type {?} */ + const scrollOffset = this._viewport.measureScrollOffset(); + /** @type {?} */ + const firstVisibleIndex = scrollOffset / this._itemSize; + /** @type {?} */ + const renderedRange = this._viewport.getRenderedRange(); + /** @type {?} */ + const newRange = { start: renderedRange.start, end: renderedRange.end }; + /** @type {?} */ + const viewportSize = this._viewport.getViewportSize(); + /** @type {?} */ + const dataLength = this._viewport.getDataLength(); + /** @type {?} */ + const startBuffer = scrollOffset - newRange.start * this._itemSize; + if (startBuffer < this._minBufferPx && newRange.start != 0) { + /** @type {?} */ + const expandStart = Math.ceil((this._maxBufferPx - startBuffer) / this._itemSize); + newRange.start = Math.max(0, newRange.start - expandStart); + newRange.end = Math.min(dataLength, Math.ceil(firstVisibleIndex + (viewportSize + this._minBufferPx) / this._itemSize)); + } + else { + /** @type {?} */ + const endBuffer = newRange.end * this._itemSize - (scrollOffset + viewportSize); + if (endBuffer < this._minBufferPx && newRange.end != dataLength) { + /** @type {?} */ + const expandEnd = Math.ceil((this._maxBufferPx - endBuffer) / this._itemSize); + if (expandEnd > 0) { + newRange.end = Math.min(dataLength, newRange.end + expandEnd); + newRange.start = Math.max(0, Math.floor(firstVisibleIndex - this._minBufferPx / this._itemSize)); + } + } + } + this._viewport.setRenderedRange(newRange); + this._viewport.setRenderedContentOffset(this._itemSize * newRange.start); + this._scrolledIndexChange.next(Math.floor(firstVisibleIndex)); + } +} +/** + * Provider factory for `FixedSizeVirtualScrollStrategy` that simply extracts the already created + * `FixedSizeVirtualScrollStrategy` from the given directive. + * @param {?} fixedSizeDir The instance of `CdkFixedSizeVirtualScroll` to extract the + * `FixedSizeVirtualScrollStrategy` from. + * @return {?} + */ +function _fixedSizeVirtualScrollStrategyFactory(fixedSizeDir) { + return fixedSizeDir._scrollStrategy; +} +/** + * A virtual scroll strategy that supports fixed-size items. + */ +class CdkFixedSizeVirtualScroll { + constructor() { + this._itemSize = 20; + this._minBufferPx = 100; + this._maxBufferPx = 200; + /** + * The scroll strategy used by this directive. + */ + this._scrollStrategy = new FixedSizeVirtualScrollStrategy(this.itemSize, this.minBufferPx, this.maxBufferPx); + } + /** + * The size of the items in the list (in pixels). + * @return {?} + */ + get itemSize() { return this._itemSize; } + /** + * @param {?} value + * @return {?} + */ + set itemSize(value) { this._itemSize = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_1__["coerceNumberProperty"])(value); } + /** + * The minimum amount of buffer rendered beyond the viewport (in pixels). + * If the amount of buffer dips below this number, more items will be rendered. Defaults to 100px. + * @return {?} + */ + get minBufferPx() { return this._minBufferPx; } + /** + * @param {?} value + * @return {?} + */ + set minBufferPx(value) { this._minBufferPx = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_1__["coerceNumberProperty"])(value); } + /** + * The number of pixels worth of buffer to render for when rendering new items. Defaults to 200px. + * @return {?} + */ + get maxBufferPx() { return this._maxBufferPx; } + /** + * @param {?} value + * @return {?} + */ + set maxBufferPx(value) { this._maxBufferPx = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_1__["coerceNumberProperty"])(value); } + /** + * @return {?} + */ + ngOnChanges() { + this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.minBufferPx, this.maxBufferPx); + } +} +CdkFixedSizeVirtualScroll.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: 'cdk-virtual-scroll-viewport[itemSize]', + providers: [{ + provide: VIRTUAL_SCROLL_STRATEGY, + useFactory: _fixedSizeVirtualScrollStrategyFactory, + deps: [Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["forwardRef"])((/** + * @return {?} + */ + () => CdkFixedSizeVirtualScroll))], + }], + },] }, +]; +CdkFixedSizeVirtualScroll.propDecorators = { + itemSize: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + minBufferPx: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + maxBufferPx: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Time in ms to throttle the scrolling events by default. + * @type {?} + */ +const DEFAULT_SCROLL_TIME = 20; +/** + * Service contained all registered Scrollable references and emits an event when any one of the + * Scrollable references emit a scrolled event. + */ +class ScrollDispatcher { + /** + * @param {?} _ngZone + * @param {?} _platform + */ + constructor(_ngZone, _platform) { + this._ngZone = _ngZone; + this._platform = _platform; + /** + * Subject for notifying that a registered scrollable reference element has been scrolled. + */ + this._scrolled = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * Keeps track of the global `scroll` and `resize` subscriptions. + */ + this._globalSubscription = null; + /** + * Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. + */ + this._scrolledCount = 0; + /** + * Map of all the scrollable references that are registered with the service and their + * scroll event subscriptions. + */ + this.scrollContainers = new Map(); + } + /** + * Registers a scrollable instance with the service and listens for its scrolled events. When the + * scrollable is scrolled, the service emits the event to its scrolled observable. + * @param {?} scrollable Scrollable instance to be registered. + * @return {?} + */ + register(scrollable) { + if (!this.scrollContainers.has(scrollable)) { + this.scrollContainers.set(scrollable, scrollable.elementScrolled() + .subscribe((/** + * @return {?} + */ + () => this._scrolled.next(scrollable)))); + } + } + /** + * Deregisters a Scrollable reference and unsubscribes from its scroll event observable. + * @param {?} scrollable Scrollable instance to be deregistered. + * @return {?} + */ + deregister(scrollable) { + /** @type {?} */ + const scrollableReference = this.scrollContainers.get(scrollable); + if (scrollableReference) { + scrollableReference.unsubscribe(); + this.scrollContainers.delete(scrollable); + } + } + /** + * Returns an observable that emits an event whenever any of the registered Scrollable + * references (or window, document, or body) fire a scrolled event. Can provide a time in ms + * to override the default "throttle" time. + * + * **Note:** in order to avoid hitting change detection for every scroll event, + * all of the events emitted from this stream will be run outside the Angular zone. + * If you need to update any data bindings as a result of a scroll event, you have + * to run the callback using `NgZone.run`. + * @param {?=} auditTimeInMs + * @return {?} + */ + scrolled(auditTimeInMs = DEFAULT_SCROLL_TIME) { + if (!this._platform.isBrowser) { + return Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["of"])(); + } + return new rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => { + if (!this._globalSubscription) { + this._addGlobalListener(); + } + // In the case of a 0ms delay, use an observable without auditTime + // since it does add a perceptible delay in processing overhead. + /** @type {?} */ + const subscription = auditTimeInMs > 0 ? + this._scrolled.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["auditTime"])(auditTimeInMs)).subscribe(observer) : + this._scrolled.subscribe(observer); + this._scrolledCount++; + return (/** + * @return {?} + */ + () => { + subscription.unsubscribe(); + this._scrolledCount--; + if (!this._scrolledCount) { + this._removeGlobalListener(); + } + }); + })); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._removeGlobalListener(); + this.scrollContainers.forEach((/** + * @param {?} _ + * @param {?} container + * @return {?} + */ + (_, container) => this.deregister(container))); + this._scrolled.complete(); + } + /** + * Returns an observable that emits whenever any of the + * scrollable ancestors of an element are scrolled. + * @param {?} elementRef Element whose ancestors to listen for. + * @param {?=} auditTimeInMs Time to throttle the scroll events. + * @return {?} + */ + ancestorScrolled(elementRef, auditTimeInMs) { + /** @type {?} */ + const ancestors = this.getAncestorScrollContainers(elementRef); + return this.scrolled(auditTimeInMs).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["filter"])((/** + * @param {?} target + * @return {?} + */ + target => { + return !target || ancestors.indexOf(target) > -1; + }))); + } + /** + * Returns all registered Scrollables that contain the provided element. + * @param {?} elementRef + * @return {?} + */ + getAncestorScrollContainers(elementRef) { + /** @type {?} */ + const scrollingContainers = []; + this.scrollContainers.forEach((/** + * @param {?} _subscription + * @param {?} scrollable + * @return {?} + */ + (_subscription, scrollable) => { + if (this._scrollableContainsElement(scrollable, elementRef)) { + scrollingContainers.push(scrollable); + } + })); + return scrollingContainers; + } + /** + * Returns true if the element is contained within the provided Scrollable. + * @private + * @param {?} scrollable + * @param {?} elementRef + * @return {?} + */ + _scrollableContainsElement(scrollable, elementRef) { + /** @type {?} */ + let element = elementRef.nativeElement; + /** @type {?} */ + let scrollableElement = scrollable.getElementRef().nativeElement; + // Traverse through the element parents until we reach null, checking if any of the elements + // are the scrollable's element. + do { + if (element == scrollableElement) { + return true; + } + } while (element = (/** @type {?} */ (element)).parentElement); + return false; + } + /** + * Sets up the global scroll listeners. + * @private + * @return {?} + */ + _addGlobalListener() { + this._globalSubscription = this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + return Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["fromEvent"])(window.document, 'scroll').subscribe((/** + * @return {?} + */ + () => this._scrolled.next())); + })); + } + /** + * Cleans up the global scroll listener. + * @private + * @return {?} + */ + _removeGlobalListener() { + if (this._globalSubscription) { + this._globalSubscription.unsubscribe(); + this._globalSubscription = null; + } + } +} +ScrollDispatcher.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +ScrollDispatcher.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] }, + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"] } +]; +/** @nocollapse */ ScrollDispatcher.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: function ScrollDispatcher_Factory() { return new ScrollDispatcher(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"])); }, token: ScrollDispatcher, providedIn: "root" }); +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} parentDispatcher + * @param {?} ngZone + * @param {?} platform + * @return {?} + */ +function SCROLL_DISPATCHER_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) { + return parentDispatcher || new ScrollDispatcher(ngZone, platform); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const SCROLL_DISPATCHER_PROVIDER = { + // If there is already a ScrollDispatcher available, use that. Otherwise, provide a new one. + provide: ScrollDispatcher, + deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_0__["SkipSelf"](), ScrollDispatcher], _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"], _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"]], + useFactory: SCROLL_DISPATCHER_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Sends an event when the directive's element is scrolled. Registers itself with the + * ScrollDispatcher service to include itself as part of its collection of scrolling events that it + * can be listened to through the service. + */ +class CdkScrollable { + /** + * @param {?} elementRef + * @param {?} scrollDispatcher + * @param {?} ngZone + * @param {?=} dir + */ + constructor(elementRef, scrollDispatcher, ngZone, dir) { + this.elementRef = elementRef; + this.scrollDispatcher = scrollDispatcher; + this.ngZone = ngZone; + this.dir = dir; + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + this._elementScrolled = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => this.ngZone.runOutsideAngular((/** + * @return {?} + */ + () => Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["fromEvent"])(this.elementRef.nativeElement, 'scroll').pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["takeUntil"])(this._destroyed)) + .subscribe(observer))))); + } + /** + * @return {?} + */ + ngOnInit() { + this.scrollDispatcher.register(this); + } + /** + * @return {?} + */ + ngOnDestroy() { + this.scrollDispatcher.deregister(this); + this._destroyed.next(); + this._destroyed.complete(); + } + /** + * Returns observable that emits when a scroll event is fired on the host element. + * @return {?} + */ + elementScrolled() { + return this._elementScrolled; + } + /** + * Gets the ElementRef for the viewport. + * @return {?} + */ + getElementRef() { + return this.elementRef; + } + /** + * Scrolls to the specified offsets. This is a normalized version of the browser's native scrollTo + * method, since browsers are not consistent about what scrollLeft means in RTL. For this method + * left and right always refer to the left and right side of the scrolling container irrespective + * of the layout direction. start and end refer to left and right in an LTR context and vice-versa + * in an RTL context. + * @param {?} options specified the offsets to scroll to. + * @return {?} + */ + scrollTo(options) { + /** @type {?} */ + const el = this.elementRef.nativeElement; + /** @type {?} */ + const isRtl = this.dir && this.dir.value == 'rtl'; + // Rewrite start & end offsets as right or left offsets. + options.left = options.left == null ? (isRtl ? options.end : options.start) : options.left; + options.right = options.right == null ? (isRtl ? options.start : options.end) : options.right; + // Rewrite the bottom offset as a top offset. + if (options.bottom != null) { + ((/** @type {?} */ (options))).top = + el.scrollHeight - el.clientHeight - options.bottom; + } + // Rewrite the right offset as a left offset. + if (isRtl && Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["getRtlScrollAxisType"])() != _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["RtlScrollAxisType"].NORMAL) { + if (options.left != null) { + ((/** @type {?} */ (options))).right = + el.scrollWidth - el.clientWidth - options.left; + } + if (Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["getRtlScrollAxisType"])() == _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["RtlScrollAxisType"].INVERTED) { + options.left = options.right; + } + else if (Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["getRtlScrollAxisType"])() == _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["RtlScrollAxisType"].NEGATED) { + options.left = options.right ? -options.right : options.right; + } + } + else { + if (options.right != null) { + ((/** @type {?} */ (options))).left = + el.scrollWidth - el.clientWidth - options.right; + } + } + this._applyScrollToOptions(options); + } + /** + * @private + * @param {?} options + * @return {?} + */ + _applyScrollToOptions(options) { + /** @type {?} */ + const el = this.elementRef.nativeElement; + if (Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["supportsScrollBehavior"])()) { + el.scrollTo(options); + } + else { + if (options.top != null) { + el.scrollTop = options.top; + } + if (options.left != null) { + el.scrollLeft = options.left; + } + } + } + /** + * Measures the scroll offset relative to the specified edge of the viewport. This method can be + * used instead of directly checking scrollLeft or scrollTop, since browsers are not consistent + * about what scrollLeft means in RTL. The values returned by this method are normalized such that + * left and right always refer to the left and right side of the scrolling container irrespective + * of the layout direction. start and end refer to left and right in an LTR context and vice-versa + * in an RTL context. + * @param {?} from The edge to measure from. + * @return {?} + */ + measureScrollOffset(from) { + /** @type {?} */ + const LEFT = 'left'; + /** @type {?} */ + const RIGHT = 'right'; + /** @type {?} */ + const el = this.elementRef.nativeElement; + if (from == 'top') { + return el.scrollTop; + } + if (from == 'bottom') { + return el.scrollHeight - el.clientHeight - el.scrollTop; + } + // Rewrite start & end as left or right offsets. + /** @type {?} */ + const isRtl = this.dir && this.dir.value == 'rtl'; + if (from == 'start') { + from = isRtl ? RIGHT : LEFT; + } + else if (from == 'end') { + from = isRtl ? LEFT : RIGHT; + } + if (isRtl && Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["getRtlScrollAxisType"])() == _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["RtlScrollAxisType"].INVERTED) { + // For INVERTED, scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and + // 0 when scrolled all the way right. + if (from == LEFT) { + return el.scrollWidth - el.clientWidth - el.scrollLeft; + } + else { + return el.scrollLeft; + } + } + else if (isRtl && Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["getRtlScrollAxisType"])() == _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["RtlScrollAxisType"].NEGATED) { + // For NEGATED, scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and + // 0 when scrolled all the way right. + if (from == LEFT) { + return el.scrollLeft + el.scrollWidth - el.clientWidth; + } + else { + return -el.scrollLeft; + } + } + else { + // For NORMAL, as well as non-RTL contexts, scrollLeft is 0 when scrolled all the way left and + // (scrollWidth - clientWidth) when scrolled all the way right. + if (from == LEFT) { + return el.scrollLeft; + } + else { + return el.scrollWidth - el.clientWidth - el.scrollLeft; + } + } + } +} +CdkScrollable.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdk-scrollable], [cdkScrollable]' + },] }, +]; +/** @nocollapse */ +CdkScrollable.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, + { type: ScrollDispatcher }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_5__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Checks if the given ranges are equal. + * @param {?} r1 + * @param {?} r2 + * @return {?} + */ +function rangesEqual(r1, r2) { + return r1.start == r2.start && r1.end == r2.end; +} +/** + * Scheduler to be used for scroll events. Needs to fall back to + * something that doesn't rely on requestAnimationFrame on environments + * that don't support it (e.g. server-side rendering). + * @type {?} + */ +const SCROLL_SCHEDULER = typeof requestAnimationFrame !== 'undefined' ? rxjs__WEBPACK_IMPORTED_MODULE_2__["animationFrameScheduler"] : rxjs__WEBPACK_IMPORTED_MODULE_2__["asapScheduler"]; +/** + * A viewport that virtualizes it's scrolling with the help of `CdkVirtualForOf`. + */ +class CdkVirtualScrollViewport extends CdkScrollable { + /** + * @param {?} elementRef + * @param {?} _changeDetectorRef + * @param {?} ngZone + * @param {?} _scrollStrategy + * @param {?} dir + * @param {?} scrollDispatcher + */ + constructor(elementRef, _changeDetectorRef, ngZone, _scrollStrategy, dir, scrollDispatcher) { + super(elementRef, scrollDispatcher, ngZone, dir); + this.elementRef = elementRef; + this._changeDetectorRef = _changeDetectorRef; + this._scrollStrategy = _scrollStrategy; + /** + * Emits when the viewport is detached from a CdkVirtualForOf. + */ + this._detachedSubject = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * Emits when the rendered range changes. + */ + this._renderedRangeSubject = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * The direction the viewport scrolls. + */ + this.orientation = 'vertical'; + // Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll + // strategy lazily (i.e. only if the user is actually listening to the events). We do this because + // depending on how the strategy calculates the scrolled index, it may come at a cost to + // performance. + /** + * Emits when the index of the first element visible in the viewport changes. + */ + this.scrolledIndexChange = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => this._scrollStrategy.scrolledIndexChange.subscribe((/** + * @param {?} index + * @return {?} + */ + index => Promise.resolve().then((/** + * @return {?} + */ + () => this.ngZone.run((/** + * @return {?} + */ + () => observer.next(index))))))))); + /** + * A stream that emits whenever the rendered range changes. + */ + this.renderedRangeStream = this._renderedRangeSubject.asObservable(); + /** + * The transform used to scale the spacer to the same size as all content, including content that + * is not currently rendered. + */ + this._totalContentSizeTransform = ''; + /** + * The total size of all content (in pixels), including content that is not currently rendered. + */ + this._totalContentSize = 0; + /** + * The currently rendered range of indices. + */ + this._renderedRange = { start: 0, end: 0 }; + /** + * The length of the data bound to this viewport (in number of items). + */ + this._dataLength = 0; + /** + * The size of the viewport (in pixels). + */ + this._viewportSize = 0; + /** + * The last rendered content offset that was set. + */ + this._renderedContentOffset = 0; + /** + * Whether the last rendered content offset was to the end of the content (and therefore needs to + * be rewritten as an offset to the start of the content). + */ + this._renderedContentOffsetNeedsRewrite = false; + /** + * Whether there is a pending change detection cycle. + */ + this._isChangeDetectionPending = false; + /** + * A list of functions to run after the next change detection cycle. + */ + this._runAfterChangeDetection = []; + if (!_scrollStrategy) { + throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.'); + } + } + /** + * @return {?} + */ + ngOnInit() { + super.ngOnInit(); + // It's still too early to measure the viewport at this point. Deferring with a promise allows + // the Viewport to be rendered with the correct size before we measure. We run this outside the + // zone to avoid causing more change detection cycles. We handle the change detection loop + // ourselves instead. + this.ngZone.runOutsideAngular((/** + * @return {?} + */ + () => Promise.resolve().then((/** + * @return {?} + */ + () => { + this._measureViewportSize(); + this._scrollStrategy.attach(this); + this.elementScrolled() + .pipe( + // Start off with a fake scroll event so we properly detect our initial position. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["startWith"])((/** @type {?} */ (null))), + // Collect multiple events into one until the next animation frame. This way if + // there are multiple scroll events in the same frame we only need to recheck + // our layout once. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["auditTime"])(0, SCROLL_SCHEDULER)) + .subscribe((/** + * @return {?} + */ + () => this._scrollStrategy.onContentScrolled())); + this._markChangeDetectionNeeded(); + })))); + } + /** + * @return {?} + */ + ngOnDestroy() { + this.detach(); + this._scrollStrategy.detach(); + // Complete all subjects + this._renderedRangeSubject.complete(); + this._detachedSubject.complete(); + super.ngOnDestroy(); + } + /** + * Attaches a `CdkVirtualForOf` to this viewport. + * @param {?} forOf + * @return {?} + */ + attach(forOf) { + if (this._forOf) { + throw Error('CdkVirtualScrollViewport is already attached.'); + } + // Subscribe to the data stream of the CdkVirtualForOf to keep track of when the data length + // changes. Run outside the zone to avoid triggering change detection, since we're managing the + // change detection loop ourselves. + this.ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + this._forOf = forOf; + this._forOf.dataStream.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["takeUntil"])(this._detachedSubject)).subscribe((/** + * @param {?} data + * @return {?} + */ + data => { + /** @type {?} */ + const newLength = data.length; + if (newLength !== this._dataLength) { + this._dataLength = newLength; + this._scrollStrategy.onDataLengthChanged(); + } + this._doChangeDetection(); + })); + })); + } + /** + * Detaches the current `CdkVirtualForOf`. + * @return {?} + */ + detach() { + this._forOf = null; + this._detachedSubject.next(); + } + /** + * Gets the length of the data bound to this viewport (in number of items). + * @return {?} + */ + getDataLength() { + return this._dataLength; + } + /** + * Gets the size of the viewport (in pixels). + * @return {?} + */ + getViewportSize() { + return this._viewportSize; + } + // TODO(mmalerba): This is technically out of sync with what's really rendered until a render + // cycle happens. I'm being careful to only call it after the render cycle is complete and before + // setting it to something else, but its error prone and should probably be split into + // `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM. + /** + * Get the current rendered range of items. + * @return {?} + */ + getRenderedRange() { + return this._renderedRange; + } + /** + * Sets the total size of all content (in pixels), including content that is not currently + * rendered. + * @param {?} size + * @return {?} + */ + setTotalContentSize(size) { + if (this._totalContentSize !== size) { + this._totalContentSize = size; + /** @type {?} */ + const axis = this.orientation == 'horizontal' ? 'X' : 'Y'; + this._totalContentSizeTransform = `scale${axis}(${this._totalContentSize})`; + this._markChangeDetectionNeeded(); + } + } + /** + * Sets the currently rendered range of indices. + * @param {?} range + * @return {?} + */ + setRenderedRange(range) { + if (!rangesEqual(this._renderedRange, range)) { + this._renderedRangeSubject.next(this._renderedRange = range); + this._markChangeDetectionNeeded((/** + * @return {?} + */ + () => this._scrollStrategy.onContentRendered())); + } + } + /** + * Gets the offset from the start of the viewport to the start of the rendered data (in pixels). + * @return {?} + */ + getOffsetToRenderedContentStart() { + return this._renderedContentOffsetNeedsRewrite ? null : this._renderedContentOffset; + } + /** + * Sets the offset from the start of the viewport to either the start or end of the rendered data + * (in pixels). + * @param {?} offset + * @param {?=} to + * @return {?} + */ + setRenderedContentOffset(offset, to = 'to-start') { + // For a horizontal viewport in a right-to-left language we need to translate along the x-axis + // in the negative direction. + /** @type {?} */ + const isRtl = this.dir && this.dir.value == 'rtl'; + /** @type {?} */ + const isHorizontal = this.orientation == 'horizontal'; + /** @type {?} */ + const axis = isHorizontal ? 'X' : 'Y'; + /** @type {?} */ + const axisDirection = isHorizontal && isRtl ? -1 : 1; + /** @type {?} */ + let transform = `translate${axis}(${Number(axisDirection * offset)}px)`; + this._renderedContentOffset = offset; + if (to === 'to-end') { + transform += ` translate${axis}(-100%)`; + // The viewport should rewrite this as a `to-start` offset on the next render cycle. Otherwise + // elements will appear to expand in the wrong direction (e.g. `mat-expansion-panel` would + // expand upward). + this._renderedContentOffsetNeedsRewrite = true; + } + if (this._renderedContentTransform != transform) { + // We know this value is safe because we parse `offset` with `Number()` before passing it + // into the string. + this._renderedContentTransform = transform; + this._markChangeDetectionNeeded((/** + * @return {?} + */ + () => { + if (this._renderedContentOffsetNeedsRewrite) { + this._renderedContentOffset -= this.measureRenderedContentSize(); + this._renderedContentOffsetNeedsRewrite = false; + this.setRenderedContentOffset(this._renderedContentOffset); + } + else { + this._scrollStrategy.onRenderedOffsetChanged(); + } + })); + } + } + /** + * Scrolls to the given offset from the start of the viewport. Please note that this is not always + * the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left + * direction, this would be the equivalent of setting a fictional `scrollRight` property. + * @param {?} offset The offset to scroll to. + * @param {?=} behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`. + * @return {?} + */ + scrollToOffset(offset, behavior = 'auto') { + /** @type {?} */ + const options = { behavior }; + if (this.orientation === 'horizontal') { + options.start = offset; + } + else { + options.top = offset; + } + this.scrollTo(options); + } + /** + * Scrolls to the offset for the given index. + * @param {?} index The index of the element to scroll to. + * @param {?=} behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`. + * @return {?} + */ + scrollToIndex(index, behavior = 'auto') { + this._scrollStrategy.scrollToIndex(index, behavior); + } + /** + * Gets the current scroll offset from the start of the viewport (in pixels). + * @param {?=} from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start' + * in horizontal mode. + * @return {?} + */ + measureScrollOffset(from) { + return super.measureScrollOffset(from ? from : this.orientation === 'horizontal' ? 'start' : 'top'); + } + /** + * Measure the combined size of all of the rendered items. + * @return {?} + */ + measureRenderedContentSize() { + /** @type {?} */ + const contentEl = this._contentWrapper.nativeElement; + return this.orientation === 'horizontal' ? contentEl.offsetWidth : contentEl.offsetHeight; + } + /** + * Measure the total combined size of the given range. Throws if the range includes items that are + * not rendered. + * @param {?} range + * @return {?} + */ + measureRangeSize(range) { + if (!this._forOf) { + return 0; + } + return this._forOf.measureRangeSize(range, this.orientation); + } + /** + * Update the viewport dimensions and re-render. + * @return {?} + */ + checkViewportSize() { + // TODO: Cleanup later when add logic for handling content resize + this._measureViewportSize(); + this._scrollStrategy.onDataLengthChanged(); + } + /** + * Measure the viewport size. + * @private + * @return {?} + */ + _measureViewportSize() { + /** @type {?} */ + const viewportEl = this.elementRef.nativeElement; + this._viewportSize = this.orientation === 'horizontal' ? + viewportEl.clientWidth : viewportEl.clientHeight; + } + /** + * Queue up change detection to run. + * @private + * @param {?=} runAfter + * @return {?} + */ + _markChangeDetectionNeeded(runAfter) { + if (runAfter) { + this._runAfterChangeDetection.push(runAfter); + } + // Use a Promise to batch together calls to `_doChangeDetection`. This way if we set a bunch of + // properties sequentially we only have to run `_doChangeDetection` once at the end. + if (!this._isChangeDetectionPending) { + this._isChangeDetectionPending = true; + this.ngZone.runOutsideAngular((/** + * @return {?} + */ + () => Promise.resolve().then((/** + * @return {?} + */ + () => { + this._doChangeDetection(); + })))); + } + } + /** + * Run change detection. + * @private + * @return {?} + */ + _doChangeDetection() { + this._isChangeDetectionPending = false; + // Apply changes to Angular bindings. Note: We must call `markForCheck` to run change detection + // from the root, since the repeated items are content projected in. Calling `detectChanges` + // instead does not properly check the projected content. + this.ngZone.run((/** + * @return {?} + */ + () => this._changeDetectorRef.markForCheck())); + // Apply the content transform. The transform can't be set via an Angular binding because + // bypassSecurityTrustStyle is banned in Google. However the value is safe, it's composed of + // string literals, a variable that can only be 'X' or 'Y', and user input that is run through + // the `Number` function first to coerce it to a numeric value. + this._contentWrapper.nativeElement.style.transform = this._renderedContentTransform; + /** @type {?} */ + const runAfterChangeDetection = this._runAfterChangeDetection; + this._runAfterChangeDetection = []; + for (const fn of runAfterChangeDetection) { + fn(); + } + } +} +CdkVirtualScrollViewport.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Component"], args: [{selector: 'cdk-virtual-scroll-viewport', + template: "
", + 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:0}.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:0}.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}"], + host: { + 'class': 'cdk-virtual-scroll-viewport', + '[class.cdk-virtual-scroll-orientation-horizontal]': 'orientation === "horizontal"', + '[class.cdk-virtual-scroll-orientation-vertical]': 'orientation !== "horizontal"', + }, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewEncapsulation"].None, + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectionStrategy"].OnPush, + providers: [{ + provide: CdkScrollable, + useExisting: CdkVirtualScrollViewport, + }] + },] }, +]; +/** @nocollapse */ +CdkVirtualScrollViewport.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [VIRTUAL_SCROLL_STRATEGY,] }] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_5__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }] }, + { type: ScrollDispatcher } +]; +CdkVirtualScrollViewport.propDecorators = { + orientation: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + scrolledIndexChange: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Output"] }], + _contentWrapper: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"], args: ['contentWrapper', { static: true },] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Helper to extract size from a DOM Node. + * @param {?} orientation + * @param {?} node + * @return {?} + */ +function getSize(orientation, node) { + /** @type {?} */ + const el = (/** @type {?} */ (node)); + if (!el.getBoundingClientRect) { + return 0; + } + /** @type {?} */ + const rect = el.getBoundingClientRect(); + return orientation == 'horizontal' ? rect.width : rect.height; +} +/** + * A directive similar to `ngForOf` to be used for rendering data inside a virtual scrolling + * container. + * @template T + */ +class CdkVirtualForOf { + /** + * @param {?} _viewContainerRef + * @param {?} _template + * @param {?} _differs + * @param {?} _viewport + * @param {?} ngZone + */ + constructor(_viewContainerRef, _template, _differs, _viewport, ngZone) { + this._viewContainerRef = _viewContainerRef; + this._template = _template; + this._differs = _differs; + this._viewport = _viewport; + /** + * Emits when the rendered view of the data changes. + */ + this.viewChange = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * Subject that emits when a new DataSource instance is given. + */ + this._dataSourceChanges = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + /** + * The size of the cache used to store templates that are not being used for re-use later. + * Setting the cache size to `0` will disable caching. Defaults to 20 templates. + */ + this.cdkVirtualForTemplateCacheSize = 20; + /** + * Emits whenever the data in the current DataSource changes. + */ + this.dataStream = this._dataSourceChanges + .pipe( + // Start off with null `DataSource`. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["startWith"])((/** @type {?} */ (null))), + // Bundle up the previous and current data sources so we can work with both. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["pairwise"])(), + // Use `_changeDataSource` to disconnect from the previous data source and connect to the + // new one, passing back a stream of data changes which we run through `switchMap` to give + // us a data stream that emits the latest data from whatever the current `DataSource` is. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["switchMap"])((/** + * @param {?} __0 + * @return {?} + */ + ([prev, cur]) => this._changeDataSource(prev, cur))), + // Replay the last emitted data when someone subscribes. + Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["shareReplay"])(1)); + /** + * The differ used to calculate changes to the data. + */ + this._differ = null; + /** + * The template cache used to hold on ot template instancess that have been stamped out, but don't + * currently need to be rendered. These instances will be reused in the future rather than + * stamping out brand new ones. + */ + this._templateCache = []; + /** + * Whether the rendered data should be updated during the next ngDoCheck cycle. + */ + this._needsUpdate = false; + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_2__["Subject"](); + this.dataStream.subscribe((/** + * @param {?} data + * @return {?} + */ + data => { + this._data = data; + this._onRenderedDataChange(); + })); + this._viewport.renderedRangeStream.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["takeUntil"])(this._destroyed)).subscribe((/** + * @param {?} range + * @return {?} + */ + range => { + this._renderedRange = range; + ngZone.run((/** + * @return {?} + */ + () => this.viewChange.next(this._renderedRange))); + this._onRenderedDataChange(); + })); + this._viewport.attach(this); + } + /** + * The DataSource to display. + * @return {?} + */ + get cdkVirtualForOf() { + return this._cdkVirtualForOf; + } + /** + * @param {?} value + * @return {?} + */ + set cdkVirtualForOf(value) { + this._cdkVirtualForOf = value; + /** @type {?} */ + const ds = Object(_angular_cdk_collections__WEBPACK_IMPORTED_MODULE_6__["isDataSource"])(value) ? value : + // Slice the value if its an NgIterable to ensure we're working with an array. + new _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_6__["ArrayDataSource"](value instanceof rxjs__WEBPACK_IMPORTED_MODULE_2__["Observable"] ? value : Array.prototype.slice.call(value || [])); + this._dataSourceChanges.next(ds); + } + /** + * The `TrackByFunction` to use for tracking changes. The `TrackByFunction` takes the index and + * the item and produces a value to be used as the item's identity when tracking changes. + * @return {?} + */ + get cdkVirtualForTrackBy() { + return this._cdkVirtualForTrackBy; + } + /** + * @param {?} fn + * @return {?} + */ + set cdkVirtualForTrackBy(fn) { + this._needsUpdate = true; + this._cdkVirtualForTrackBy = fn ? + (/** + * @param {?} index + * @param {?} item + * @return {?} + */ + (index, item) => fn(index + (this._renderedRange ? this._renderedRange.start : 0), item)) : + undefined; + } + /** + * The template used to stamp out new elements. + * @param {?} value + * @return {?} + */ + set cdkVirtualForTemplate(value) { + if (value) { + this._needsUpdate = true; + this._template = value; + } + } + /** + * Measures the combined size (width for horizontal orientation, height for vertical) of all items + * in the specified range. Throws an error if the range includes items that are not currently + * rendered. + * @param {?} range + * @param {?} orientation + * @return {?} + */ + measureRangeSize(range, orientation) { + if (range.start >= range.end) { + return 0; + } + if (range.start < this._renderedRange.start || range.end > this._renderedRange.end) { + throw Error(`Error: attempted to measure an item that isn't rendered.`); + } + // The index into the list of rendered views for the first item in the range. + /** @type {?} */ + const renderedStartIndex = range.start - this._renderedRange.start; + // The length of the range we're measuring. + /** @type {?} */ + const rangeLen = range.end - range.start; + // Loop over all root nodes for all items in the range and sum up their size. + /** @type {?} */ + let totalSize = 0; + /** @type {?} */ + let i = rangeLen; + while (i--) { + /** @type {?} */ + const view = (/** @type {?} */ (this._viewContainerRef.get(i + renderedStartIndex))); + /** @type {?} */ + let j = view ? view.rootNodes.length : 0; + while (j--) { + totalSize += getSize(orientation, (/** @type {?} */ (view)).rootNodes[j]); + } + } + return totalSize; + } + /** + * @return {?} + */ + ngDoCheck() { + if (this._differ && this._needsUpdate) { + // TODO(mmalerba): We should differentiate needs update due to scrolling and a new portion of + // this list being rendered (can use simpler algorithm) vs needs update due to data actually + // changing (need to do this diff). + /** @type {?} */ + const changes = this._differ.diff(this._renderedItems); + if (!changes) { + this._updateContext(); + } + else { + this._applyChanges(changes); + } + this._needsUpdate = false; + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._viewport.detach(); + this._dataSourceChanges.next(); + this._dataSourceChanges.complete(); + this.viewChange.complete(); + this._destroyed.next(); + this._destroyed.complete(); + for (let view of this._templateCache) { + view.destroy(); + } + } + /** + * React to scroll state changes in the viewport. + * @private + * @return {?} + */ + _onRenderedDataChange() { + if (!this._renderedRange) { + return; + } + this._renderedItems = this._data.slice(this._renderedRange.start, this._renderedRange.end); + if (!this._differ) { + this._differ = this._differs.find(this._renderedItems).create(this.cdkVirtualForTrackBy); + } + this._needsUpdate = true; + } + /** + * Swap out one `DataSource` for another. + * @private + * @param {?} oldDs + * @param {?} newDs + * @return {?} + */ + _changeDataSource(oldDs, newDs) { + if (oldDs) { + oldDs.disconnect(this); + } + this._needsUpdate = true; + return newDs ? newDs.connect(this) : Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["of"])(); + } + /** + * Update the `CdkVirtualForOfContext` for all views. + * @private + * @return {?} + */ + _updateContext() { + /** @type {?} */ + const count = this._data.length; + /** @type {?} */ + let i = this._viewContainerRef.length; + while (i--) { + /** @type {?} */ + let view = (/** @type {?} */ (this._viewContainerRef.get(i))); + view.context.index = this._renderedRange.start + i; + view.context.count = count; + this._updateComputedContextProperties(view.context); + view.detectChanges(); + } + } + /** + * Apply changes to the DOM. + * @private + * @param {?} changes + * @return {?} + */ + _applyChanges(changes) { + // Rearrange the views to put them in the right location. + changes.forEachOperation((/** + * @param {?} record + * @param {?} adjustedPreviousIndex + * @param {?} currentIndex + * @return {?} + */ + (record, adjustedPreviousIndex, currentIndex) => { + if (record.previousIndex == null) { // Item added. + // Item added. + /** @type {?} */ + const view = this._insertViewForNewItem((/** @type {?} */ (currentIndex))); + view.context.$implicit = record.item; + } + else if (currentIndex == null) { // Item removed. + this._cacheView(this._detachView((/** @type {?} */ (adjustedPreviousIndex)))); + } + else { // Item moved. + // Item moved. + /** @type {?} */ + const view = (/** @type {?} */ (this._viewContainerRef.get((/** @type {?} */ (adjustedPreviousIndex))))); + this._viewContainerRef.move(view, currentIndex); + view.context.$implicit = record.item; + } + })); + // Update $implicit for any items that had an identity change. + changes.forEachIdentityChange((/** + * @param {?} record + * @return {?} + */ + (record) => { + /** @type {?} */ + const view = (/** @type {?} */ (this._viewContainerRef.get((/** @type {?} */ (record.currentIndex))))); + view.context.$implicit = record.item; + })); + // Update the context variables on all items. + /** @type {?} */ + const count = this._data.length; + /** @type {?} */ + let i = this._viewContainerRef.length; + while (i--) { + /** @type {?} */ + const view = (/** @type {?} */ (this._viewContainerRef.get(i))); + view.context.index = this._renderedRange.start + i; + view.context.count = count; + this._updateComputedContextProperties(view.context); + } + } + /** + * Cache the given detached view. + * @private + * @param {?} view + * @return {?} + */ + _cacheView(view) { + if (this._templateCache.length < this.cdkVirtualForTemplateCacheSize) { + this._templateCache.push(view); + } + else { + /** @type {?} */ + const index = this._viewContainerRef.indexOf(view); + // It's very unlikely that the index will ever be -1, but just in case, + // destroy the view on its own, otherwise destroy it through the + // container to ensure that all the references are removed. + if (index === -1) { + view.destroy(); + } + else { + this._viewContainerRef.remove(index); + } + } + } + /** + * Inserts a view for a new item, either from the cache or by creating a new one. + * @private + * @param {?} index + * @return {?} + */ + _insertViewForNewItem(index) { + return this._insertViewFromCache(index) || this._createEmbeddedViewAt(index); + } + /** + * Update the computed properties on the `CdkVirtualForOfContext`. + * @private + * @param {?} context + * @return {?} + */ + _updateComputedContextProperties(context) { + context.first = context.index === 0; + context.last = context.index === context.count - 1; + context.even = context.index % 2 === 0; + context.odd = !context.even; + } + /** + * Creates a new embedded view and moves it to the given index + * @private + * @param {?} index + * @return {?} + */ + _createEmbeddedViewAt(index) { + // Note that it's important that we insert the item directly at the proper index, + // rather than inserting it and the moving it in place, because if there's a directive + // on the same node that injects the `ViewContainerRef`, Angular will insert another + // comment node which can throw off the move when it's being repeated for all items. + return this._viewContainerRef.createEmbeddedView(this._template, { + $implicit: (/** @type {?} */ (null)), + cdkVirtualForOf: this._cdkVirtualForOf, + index: -1, + count: -1, + first: false, + last: false, + odd: false, + even: false + }, index); + } + /** + * Inserts a recycled view from the cache at the given index. + * @private + * @param {?} index + * @return {?} + */ + _insertViewFromCache(index) { + /** @type {?} */ + const cachedView = this._templateCache.pop(); + if (cachedView) { + this._viewContainerRef.insert(cachedView, index); + } + return cachedView || null; + } + /** + * Detaches the embedded view at the given index. + * @private + * @param {?} index + * @return {?} + */ + _detachView(index) { + return (/** @type {?} */ (this._viewContainerRef.detach(index))); + } +} +CdkVirtualForOf.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdkVirtualFor][cdkVirtualForOf]', + },] }, +]; +/** @nocollapse */ +CdkVirtualForOf.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }, + { type: CdkVirtualScrollViewport, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["SkipSelf"] }] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] } +]; +CdkVirtualForOf.propDecorators = { + cdkVirtualForOf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + cdkVirtualForTrackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + cdkVirtualForTemplate: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + cdkVirtualForTemplateCacheSize: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class ScrollingModule { +} +ScrollingModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + imports: [_angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_5__["BidiModule"], _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["PlatformModule"]], + exports: [ + _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_5__["BidiModule"], + CdkFixedSizeVirtualScroll, + CdkScrollable, + CdkVirtualForOf, + CdkVirtualScrollViewport, + ], + declarations: [ + CdkFixedSizeVirtualScroll, + CdkScrollable, + CdkVirtualForOf, + CdkVirtualScrollViewport, + ], + },] }, +]; +/** + * @deprecated ScrollDispatchModule has been renamed to ScrollingModule. + * \@breaking-change 8.0.0 delete this alias + */ +class ScrollDispatchModule { +} +ScrollDispatchModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + imports: [ScrollingModule], + exports: [ScrollingModule], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Time in ms to throttle the resize events by default. + * @type {?} + */ +const DEFAULT_RESIZE_TIME = 20; +/** + * Simple utility for getting the bounds of the browser viewport. + * \@docs-private + */ +class ViewportRuler { + /** + * @param {?} _platform + * @param {?} ngZone + */ + constructor(_platform, ngZone) { + this._platform = _platform; + ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + this._change = _platform.isBrowser ? + Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["merge"])(Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["fromEvent"])(window, 'resize'), Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["fromEvent"])(window, 'orientationchange')) : + Object(rxjs__WEBPACK_IMPORTED_MODULE_2__["of"])(); + // Note that we need to do the subscription inside `runOutsideAngular` + // since subscribing is what causes the event listener to be added. + this._invalidateCache = this.change().subscribe((/** + * @return {?} + */ + () => this._updateViewportSize())); + })); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._invalidateCache.unsubscribe(); + } + /** + * Returns the viewport's width and height. + * @return {?} + */ + getViewportSize() { + if (!this._viewportSize) { + this._updateViewportSize(); + } + /** @type {?} */ + const output = { width: this._viewportSize.width, height: this._viewportSize.height }; + // If we're not on a browser, don't cache the size since it'll be mocked out anyway. + if (!this._platform.isBrowser) { + this._viewportSize = (/** @type {?} */ (null)); + } + return output; + } + /** + * Gets a ClientRect for the viewport's bounds. + * @return {?} + */ + getViewportRect() { + // Use the document element's bounding rect rather than the window scroll properties + // (e.g. pageYOffset, scrollY) due to in issue in Chrome and IE where window scroll + // properties and client coordinates (boundingClientRect, clientX/Y, etc.) are in different + // conceptual viewports. Under most circumstances these viewports are equivalent, but they + // can disagree when the page is pinch-zoomed (on devices that support touch). + // See https://bugs.chromium.org/p/chromium/issues/detail?id=489206#c4 + // We use the documentElement instead of the body because, by default (without a css reset) + // browsers typically give the document body an 8px margin, which is not included in + // getBoundingClientRect(). + /** @type {?} */ + const scrollPosition = this.getViewportScrollPosition(); + const { width, height } = this.getViewportSize(); + return { + top: scrollPosition.top, + left: scrollPosition.left, + bottom: scrollPosition.top + height, + right: scrollPosition.left + width, + height, + width, + }; + } + /** + * Gets the (top, left) scroll position of the viewport. + * @return {?} + */ + getViewportScrollPosition() { + // While we can get a reference to the fake document + // during SSR, it doesn't have getBoundingClientRect. + if (!this._platform.isBrowser) { + return { top: 0, left: 0 }; + } + // The top-left-corner of the viewport is determined by the scroll position of the document + // body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about + // whether `document.body` or `document.documentElement` is the scrolled element, so reading + // `scrollTop` and `scrollLeft` is inconsistent. However, using the bounding rect of + // `document.documentElement` works consistently, where the `top` and `left` values will + // equal negative the scroll position. + /** @type {?} */ + const documentElement = (/** @type {?} */ (document.documentElement)); + /** @type {?} */ + const documentRect = documentElement.getBoundingClientRect(); + /** @type {?} */ + const top = -documentRect.top || document.body.scrollTop || window.scrollY || + documentElement.scrollTop || 0; + /** @type {?} */ + const left = -documentRect.left || document.body.scrollLeft || window.scrollX || + documentElement.scrollLeft || 0; + return { top, left }; + } + /** + * Returns a stream that emits whenever the size of the viewport changes. + * @param {?=} throttleTime Time in milliseconds to throttle the stream. + * @return {?} + */ + change(throttleTime = DEFAULT_RESIZE_TIME) { + return throttleTime > 0 ? this._change.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_3__["auditTime"])(throttleTime)) : this._change; + } + /** + * Updates the cached viewport size. + * @private + * @return {?} + */ + _updateViewportSize() { + this._viewportSize = this._platform.isBrowser ? + { width: window.innerWidth, height: window.innerHeight } : + { width: 0, height: 0 }; + } +} +ViewportRuler.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +ViewportRuler.ctorParameters = () => [ + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"] } +]; +/** @nocollapse */ ViewportRuler.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: function ViewportRuler_Factory() { return new ViewportRuler(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"])); }, token: ViewportRuler, providedIn: "root" }); +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @param {?} parentRuler + * @param {?} platform + * @param {?} ngZone + * @return {?} + */ +function VIEWPORT_RULER_PROVIDER_FACTORY(parentRuler, platform, ngZone) { + return parentRuler || new ViewportRuler(platform, ngZone); +} +/** + * \@docs-private \@deprecated \@breaking-change 8.0.0 + * @type {?} + */ +const VIEWPORT_RULER_PROVIDER = { + // If there is already a ViewportRuler available, use that. Otherwise, provide a new one. + provide: ViewportRuler, + deps: [[new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"](), new _angular_core__WEBPACK_IMPORTED_MODULE_0__["SkipSelf"](), ViewportRuler], _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"], _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgZone"]], + useFactory: VIEWPORT_RULER_PROVIDER_FACTORY +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=scrolling.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/stepper.js": +/*!******************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/stepper.js ***! + \******************************************************/ +/*! exports provided: StepperSelectionEvent, STEP_STATE, STEPPER_GLOBAL_OPTIONS, MAT_STEPPER_GLOBAL_OPTIONS, CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious, CdkStepperModule, CdkStepHeader */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StepperSelectionEvent", function() { return StepperSelectionEvent; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "STEP_STATE", function() { return STEP_STATE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "STEPPER_GLOBAL_OPTIONS", function() { return STEPPER_GLOBAL_OPTIONS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MAT_STEPPER_GLOBAL_OPTIONS", function() { return MAT_STEPPER_GLOBAL_OPTIONS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStep", function() { return CdkStep; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepper", function() { return CdkStepper; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepLabel", function() { return CdkStepLabel; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepperNext", function() { return CdkStepperNext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepperPrevious", function() { return CdkStepperPrevious; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepperModule", function() { return CdkStepperModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkStepHeader", function() { return CdkStepHeader; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_a11y__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/cdk/a11y */ "./node_modules/@angular/cdk/esm2015/a11y.js"); +/* harmony import */ var _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/cdk/bidi */ "./node_modules/@angular/cdk/esm2015/bidi.js"); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/cdk/keycodes */ "./node_modules/@angular/cdk/esm2015/keycodes.js"); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class CdkStepLabel { + /** + * @param {?} template + */ + constructor(/** @docs-private */ template) { + this.template = template; + } +} +CdkStepLabel.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdkStepLabel]', + },] }, +]; +/** @nocollapse */ +CdkStepLabel.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class CdkStepHeader { + /** + * @param {?} _elementRef + */ + constructor(_elementRef) { + this._elementRef = _elementRef; + } + /** + * Focuses the step header. + * @return {?} + */ + focus() { + this._elementRef.nativeElement.focus(); + } +} +CdkStepHeader.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdkStepHeader]', + host: { + 'role': 'tab', + }, + },] }, +]; +/** @nocollapse */ +CdkStepHeader.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Used to generate unique ID for each stepper component. + * @type {?} + */ +let nextId = 0; +/** + * Change event emitted on selection changes. + */ +class StepperSelectionEvent { +} +/** + * Enum to represent the different states of the steps. + * @type {?} + */ +const STEP_STATE = { + NUMBER: 'number', + EDIT: 'edit', + DONE: 'done', + ERROR: 'error' +}; +/** + * InjectionToken that can be used to specify the global stepper options. + * @type {?} + */ +const STEPPER_GLOBAL_OPTIONS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('STEPPER_GLOBAL_OPTIONS'); +/** + * InjectionToken that can be used to specify the global stepper options. + * @deprecated Use `STEPPER_GLOBAL_OPTIONS` instead. + * \@breaking-change 8.0.0. + * @type {?} + */ +const MAT_STEPPER_GLOBAL_OPTIONS = STEPPER_GLOBAL_OPTIONS; +class CdkStep { + /** + * \@breaking-change 8.0.0 remove the `?` after `stepperOptions` + * @param {?} _stepper + * @param {?=} stepperOptions + */ + constructor(_stepper, stepperOptions) { + this._stepper = _stepper; + /** + * Whether user has seen the expanded step content or not. + */ + this.interacted = false; + this._editable = true; + this._optional = false; + this._customCompleted = null; + this._customError = null; + this._stepperOptions = stepperOptions ? stepperOptions : {}; + this._displayDefaultIndicatorType = this._stepperOptions.displayDefaultIndicatorType !== false; + this._showError = !!this._stepperOptions.showError; + } + /** + * Whether the user can return to this step once it has been marked as completed. + * @return {?} + */ + get editable() { return this._editable; } + /** + * @param {?} value + * @return {?} + */ + set editable(value) { + this._editable = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceBooleanProperty"])(value); + } + /** + * Whether the completion of step is optional. + * @return {?} + */ + get optional() { return this._optional; } + /** + * @param {?} value + * @return {?} + */ + set optional(value) { + this._optional = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceBooleanProperty"])(value); + } + /** + * Whether step is marked as completed. + * @return {?} + */ + get completed() { + return this._customCompleted == null ? this._getDefaultCompleted() : this._customCompleted; + } + /** + * @param {?} value + * @return {?} + */ + set completed(value) { + this._customCompleted = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceBooleanProperty"])(value); + } + /** + * @private + * @return {?} + */ + _getDefaultCompleted() { + return this.stepControl ? this.stepControl.valid && this.interacted : this.interacted; + } + /** + * Whether step has an error. + * @return {?} + */ + get hasError() { + return this._customError == null ? this._getDefaultError() : this._customError; + } + /** + * @param {?} value + * @return {?} + */ + set hasError(value) { + this._customError = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceBooleanProperty"])(value); + } + /** + * @private + * @return {?} + */ + _getDefaultError() { + return this.stepControl && this.stepControl.invalid && this.interacted; + } + /** + * Selects this step component. + * @return {?} + */ + select() { + this._stepper.selected = this; + } + /** + * Resets the step to its initial state. Note that this includes resetting form data. + * @return {?} + */ + reset() { + this.interacted = false; + if (this._customCompleted != null) { + this._customCompleted = false; + } + if (this._customError != null) { + this._customError = false; + } + if (this.stepControl) { + this.stepControl.reset(); + } + } + /** + * @return {?} + */ + ngOnChanges() { + // Since basically all inputs of the MatStep get proxied through the view down to the + // underlying MatStepHeader, we have to make sure that change detection runs correctly. + this._stepper._stateChanged(); + } +} +CdkStep.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Component"], args: [{selector: 'cdk-step', + exportAs: 'cdkStep', + template: '', + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewEncapsulation"].None, + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectionStrategy"].OnPush, + },] }, +]; +/** @nocollapse */ +CdkStep.ctorParameters = () => [ + { type: CdkStepper, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["forwardRef"])((/** + * @return {?} + */ + () => CdkStepper)),] }] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [STEPPER_GLOBAL_OPTIONS,] }] } +]; +CdkStep.propDecorators = { + stepLabel: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ContentChild"], args: [CdkStepLabel, { static: false },] }], + content: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewChild"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"], { static: true },] }], + stepControl: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + label: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + errorMessage: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ariaLabel: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['aria-label',] }], + ariaLabelledby: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['aria-labelledby',] }], + state: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + editable: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + optional: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + completed: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + hasError: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +class CdkStepper { + /** + * @param {?} _dir + * @param {?} _changeDetectorRef + * @param {?=} _elementRef + * @param {?=} _document + */ + constructor(_dir, _changeDetectorRef, _elementRef, _document) { + this._dir = _dir; + this._changeDetectorRef = _changeDetectorRef; + this._elementRef = _elementRef; + /** + * Emits when the component is destroyed. + */ + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_6__["Subject"](); + this._linear = false; + this._selectedIndex = 0; + /** + * Event emitted when the selected step has changed. + */ + this.selectionChange = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["EventEmitter"](); + this._orientation = 'horizontal'; + this._groupId = nextId++; + this._document = _document; + } + /** + * The list of step components that the stepper is holding. + * @return {?} + */ + get steps() { + return this._steps; + } + /** + * Whether the validity of previous steps should be checked or not. + * @return {?} + */ + get linear() { return this._linear; } + /** + * @param {?} value + * @return {?} + */ + set linear(value) { this._linear = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceBooleanProperty"])(value); } + /** + * The index of the selected step. + * @return {?} + */ + get selectedIndex() { return this._selectedIndex; } + /** + * @param {?} index + * @return {?} + */ + set selectedIndex(index) { + /** @type {?} */ + const newIndex = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_3__["coerceNumberProperty"])(index); + if (this.steps) { + // Ensure that the index can't be out of bounds. + if (newIndex < 0 || newIndex > this.steps.length - 1) { + throw Error('cdkStepper: Cannot assign out-of-bounds value to `selectedIndex`.'); + } + if (this._selectedIndex != newIndex && + !this._anyControlsInvalidOrPending(newIndex) && + (newIndex >= this._selectedIndex || this.steps.toArray()[newIndex].editable)) { + this._updateSelectedItemIndex(index); + } + } + else { + this._selectedIndex = newIndex; + } + } + /** + * The step that is selected. + * @return {?} + */ + get selected() { + // @breaking-change 8.0.0 Change return type to `CdkStep | undefined`. + return this.steps ? this.steps.toArray()[this.selectedIndex] : (/** @type {?} */ (undefined)); + } + /** + * @param {?} step + * @return {?} + */ + set selected(step) { + this.selectedIndex = this.steps ? this.steps.toArray().indexOf(step) : -1; + } + /** + * @return {?} + */ + ngAfterViewInit() { + // Note that while the step headers are content children by default, any components that + // extend this one might have them as view chidren. We initialize the keyboard handling in + // AfterViewInit so we're guaranteed for both view and content children to be defined. + this._keyManager = new _angular_cdk_a11y__WEBPACK_IMPORTED_MODULE_1__["FocusKeyManager"](this._stepHeader) + .withWrap() + .withVerticalOrientation(this._orientation === 'vertical'); + (this._dir ? (/** @type {?} */ (this._dir.change)) : Object(rxjs__WEBPACK_IMPORTED_MODULE_6__["of"])()) + .pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_7__["startWith"])(this._layoutDirection()), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_7__["takeUntil"])(this._destroyed)) + .subscribe((/** + * @param {?} direction + * @return {?} + */ + direction => this._keyManager.withHorizontalOrientation(direction))); + this._keyManager.updateActiveItemIndex(this._selectedIndex); + this.steps.changes.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_7__["takeUntil"])(this._destroyed)).subscribe((/** + * @return {?} + */ + () => { + if (!this.selected) { + this._selectedIndex = Math.max(this._selectedIndex - 1, 0); + } + })); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._destroyed.next(); + this._destroyed.complete(); + } + /** + * Selects and focuses the next step in list. + * @return {?} + */ + next() { + this.selectedIndex = Math.min(this._selectedIndex + 1, this.steps.length - 1); + } + /** + * Selects and focuses the previous step in list. + * @return {?} + */ + previous() { + this.selectedIndex = Math.max(this._selectedIndex - 1, 0); + } + /** + * Resets the stepper to its initial state. Note that this includes clearing form data. + * @return {?} + */ + reset() { + this._updateSelectedItemIndex(0); + this.steps.forEach((/** + * @param {?} step + * @return {?} + */ + step => step.reset())); + this._stateChanged(); + } + /** + * Returns a unique id for each step label element. + * @param {?} i + * @return {?} + */ + _getStepLabelId(i) { + return `cdk-step-label-${this._groupId}-${i}`; + } + /** + * Returns unique id for each step content element. + * @param {?} i + * @return {?} + */ + _getStepContentId(i) { + return `cdk-step-content-${this._groupId}-${i}`; + } + /** + * Marks the component to be change detected. + * @return {?} + */ + _stateChanged() { + this._changeDetectorRef.markForCheck(); + } + /** + * Returns position state of the step with the given index. + * @param {?} index + * @return {?} + */ + _getAnimationDirection(index) { + /** @type {?} */ + const position = index - this._selectedIndex; + if (position < 0) { + return this._layoutDirection() === 'rtl' ? 'next' : 'previous'; + } + else if (position > 0) { + return this._layoutDirection() === 'rtl' ? 'previous' : 'next'; + } + return 'current'; + } + /** + * Returns the type of icon to be displayed. + * @param {?} index + * @param {?=} state + * @return {?} + */ + _getIndicatorType(index, state = STEP_STATE.NUMBER) { + /** @type {?} */ + const step = this.steps.toArray()[index]; + /** @type {?} */ + const isCurrentStep = this._isCurrentStep(index); + return step._displayDefaultIndicatorType + ? this._getDefaultIndicatorLogic(step, isCurrentStep) + : this._getGuidelineLogic(step, isCurrentStep, state); + } + /** + * @private + * @param {?} step + * @param {?} isCurrentStep + * @return {?} + */ + _getDefaultIndicatorLogic(step, isCurrentStep) { + if (step._showError && step.hasError && !isCurrentStep) { + return STEP_STATE.ERROR; + } + else if (!step.completed || isCurrentStep) { + return STEP_STATE.NUMBER; + } + else { + return step.editable ? STEP_STATE.EDIT : STEP_STATE.DONE; + } + } + /** + * @private + * @param {?} step + * @param {?} isCurrentStep + * @param {?=} state + * @return {?} + */ + _getGuidelineLogic(step, isCurrentStep, state = STEP_STATE.NUMBER) { + if (step._showError && step.hasError && !isCurrentStep) { + return STEP_STATE.ERROR; + } + else if (step.completed && !isCurrentStep) { + return STEP_STATE.DONE; + } + else if (step.completed && isCurrentStep) { + return state; + } + else if (step.editable && isCurrentStep) { + return STEP_STATE.EDIT; + } + else { + return state; + } + } + /** + * @private + * @param {?} index + * @return {?} + */ + _isCurrentStep(index) { + return this._selectedIndex === index; + } + /** + * Returns the index of the currently-focused step header. + * @return {?} + */ + _getFocusIndex() { + return this._keyManager ? this._keyManager.activeItemIndex : this._selectedIndex; + } + /** + * @private + * @param {?} newIndex + * @return {?} + */ + _updateSelectedItemIndex(newIndex) { + /** @type {?} */ + const stepsArray = this.steps.toArray(); + this.selectionChange.emit({ + selectedIndex: newIndex, + previouslySelectedIndex: this._selectedIndex, + selectedStep: stepsArray[newIndex], + previouslySelectedStep: stepsArray[this._selectedIndex], + }); + // If focus is inside the stepper, move it to the next header, otherwise it may become + // lost when the active step content is hidden. We can't be more granular with the check + // (e.g. checking whether focus is inside the active step), because we don't have a + // reference to the elements that are rendering out the content. + this._containsFocus() ? this._keyManager.setActiveItem(newIndex) : + this._keyManager.updateActiveItemIndex(newIndex); + this._selectedIndex = newIndex; + this._stateChanged(); + } + /** + * @param {?} event + * @return {?} + */ + _onKeydown(event) { + /** @type {?} */ + const hasModifier = Object(_angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__["hasModifierKey"])(event); + /** @type {?} */ + const keyCode = event.keyCode; + /** @type {?} */ + const manager = this._keyManager; + if (manager.activeItemIndex != null && !hasModifier && + (keyCode === _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__["SPACE"] || keyCode === _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__["ENTER"])) { + this.selectedIndex = manager.activeItemIndex; + event.preventDefault(); + } + else if (keyCode === _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__["HOME"]) { + manager.setFirstItemActive(); + event.preventDefault(); + } + else if (keyCode === _angular_cdk_keycodes__WEBPACK_IMPORTED_MODULE_4__["END"]) { + manager.setLastItemActive(); + event.preventDefault(); + } + else { + manager.onKeydown(event); + } + } + /** + * @private + * @param {?} index + * @return {?} + */ + _anyControlsInvalidOrPending(index) { + /** @type {?} */ + const steps = this.steps.toArray(); + steps[this._selectedIndex].interacted = true; + if (this._linear && index >= 0) { + return steps.slice(0, index).some((/** + * @param {?} step + * @return {?} + */ + step => { + /** @type {?} */ + const control = step.stepControl; + /** @type {?} */ + const isIncomplete = control ? + (control.invalid || control.pending || !step.interacted) : + !step.completed; + return isIncomplete && !step.optional; + })); + } + return false; + } + /** + * @private + * @return {?} + */ + _layoutDirection() { + return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr'; + } + /** + * Checks whether the stepper contains the focused element. + * @private + * @return {?} + */ + _containsFocus() { + if (!this._document || !this._elementRef) { + return false; + } + /** @type {?} */ + const stepperElement = this._elementRef.nativeElement; + /** @type {?} */ + const focusedElement = this._document.activeElement; + return stepperElement === focusedElement || stepperElement.contains(focusedElement); + } +} +CdkStepper.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: '[cdkStepper]', + exportAs: 'cdkStepper', + },] }, +]; +/** @nocollapse */ +CdkStepper.ctorParameters = () => [ + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_2__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_5__["DOCUMENT"],] }] } +]; +CdkStepper.propDecorators = { + _steps: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ContentChildren"], args: [CdkStep,] }], + _stepHeader: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ContentChildren"], args: [CdkStepHeader,] }], + linear: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + selectedIndex: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + selected: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + selectionChange: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Output"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Button that moves to the next step in a stepper workflow. + */ +class CdkStepperNext { + /** + * @param {?} _stepper + */ + constructor(_stepper) { + this._stepper = _stepper; + /** + * Type of the next button. Defaults to "submit" if not specified. + */ + this.type = 'submit'; + } + // We have to use a `HostListener` here in order to support both Ivy and ViewEngine. + // In Ivy the `host` bindings will be merged when this class is extended, whereas in + // ViewEngine they're overwritte. + // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default. + // tslint:disable-next-line:no-host-decorator-in-concrete + /** + * @return {?} + */ + _handleClick() { + this._stepper.next(); + } +} +CdkStepperNext.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: 'button[cdkStepperNext]', + host: { + '[type]': 'type', + } + },] }, +]; +/** @nocollapse */ +CdkStepperNext.ctorParameters = () => [ + { type: CdkStepper } +]; +CdkStepperNext.propDecorators = { + type: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + _handleClick: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["HostListener"], args: ['click',] }] +}; +/** + * Button that moves to the previous step in a stepper workflow. + */ +class CdkStepperPrevious { + /** + * @param {?} _stepper + */ + constructor(_stepper) { + this._stepper = _stepper; + /** + * Type of the previous button. Defaults to "button" if not specified. + */ + this.type = 'button'; + } + // We have to use a `HostListener` here in order to support both Ivy and ViewEngine. + // In Ivy the `host` bindings will be merged when this class is extended, whereas in + // ViewEngine they're overwritte. + // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default. + // tslint:disable-next-line:no-host-decorator-in-concrete + /** + * @return {?} + */ + _handleClick() { + this._stepper.previous(); + } +} +CdkStepperPrevious.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ + selector: 'button[cdkStepperPrevious]', + host: { + '[type]': 'type', + } + },] }, +]; +/** @nocollapse */ +CdkStepperPrevious.ctorParameters = () => [ + { type: CdkStepper } +]; +CdkStepperPrevious.propDecorators = { + type: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + _handleClick: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["HostListener"], args: ['click',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class CdkStepperModule { +} +CdkStepperModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + imports: [_angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_2__["BidiModule"], _angular_common__WEBPACK_IMPORTED_MODULE_5__["CommonModule"]], + exports: [ + CdkStep, + CdkStepper, + CdkStepHeader, + CdkStepLabel, + CdkStepperNext, + CdkStepperPrevious, + ], + declarations: [ + CdkStep, + CdkStepper, + CdkStepHeader, + CdkStepLabel, + CdkStepperNext, + CdkStepperPrevious, + ] + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=stepper.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/table.js": +/*!****************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/table.js ***! + \****************************************************/ +/*! exports provided: DataSource, DataRowOutlet, HeaderRowOutlet, FooterRowOutlet, CDK_TABLE_TEMPLATE, CdkTable, CdkCellDef, CdkHeaderCellDef, CdkFooterCellDef, CdkColumnDef, BaseCdkCell, CdkHeaderCell, CdkFooterCell, CdkCell, CDK_ROW_TEMPLATE, BaseRowDef, CdkHeaderRowDef, CdkFooterRowDef, CdkRowDef, CdkCellOutlet, CdkHeaderRow, CdkFooterRow, CdkRow, CdkTableModule, STICKY_DIRECTIONS, StickyStyler, mixinHasStickyInput, TEXT_COLUMN_OPTIONS, CdkTextColumn */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DataRowOutlet", function() { return DataRowOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HeaderRowOutlet", function() { return HeaderRowOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FooterRowOutlet", function() { return FooterRowOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CDK_TABLE_TEMPLATE", function() { return CDK_TABLE_TEMPLATE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTable", function() { return CdkTable; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkCellDef", function() { return CdkCellDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkHeaderCellDef", function() { return CdkHeaderCellDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkFooterCellDef", function() { return CdkFooterCellDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkColumnDef", function() { return CdkColumnDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseCdkCell", function() { return BaseCdkCell; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkHeaderCell", function() { return CdkHeaderCell; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkFooterCell", function() { return CdkFooterCell; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkCell", function() { return CdkCell; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CDK_ROW_TEMPLATE", function() { return CDK_ROW_TEMPLATE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseRowDef", function() { return BaseRowDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkHeaderRowDef", function() { return CdkHeaderRowDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkFooterRowDef", function() { return CdkFooterRowDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkRowDef", function() { return CdkRowDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkCellOutlet", function() { return CdkCellOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkHeaderRow", function() { return CdkHeaderRow; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkFooterRow", function() { return CdkFooterRow; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkRow", function() { return CdkRow; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTableModule", function() { return CdkTableModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "STICKY_DIRECTIONS", function() { return STICKY_DIRECTIONS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StickyStyler", function() { return StickyStyler; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mixinHasStickyInput", function() { return mixinHasStickyInput; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TEXT_COLUMN_OPTIONS", function() { return TEXT_COLUMN_OPTIONS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTextColumn", function() { return CdkTextColumn; }); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/cdk/bidi */ "./node_modules/@angular/cdk/esm2015/bidi.js"); +/* harmony import */ var _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/cdk/collections */ "./node_modules/@angular/cdk/esm2015/collections.js"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "DataSource", function() { return _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__["DataSource"]; }); + +/* harmony import */ var _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/cdk/platform */ "./node_modules/@angular/cdk/esm2015/platform.js"); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Mixin to provide a directive with a function that checks if the sticky input has been + * changed since the last time the function was called. Essentially adds a dirty-check to the + * sticky value. + * \@docs-private + * @template T + * @param {?} base + * @return {?} + */ +function mixinHasStickyInput(base) { + return class extends base { + /** + * @param {...?} args + */ + constructor(...args) { + super(...args); + this._sticky = false; + /** + * Whether the sticky input has changed since it was last checked. + */ + this._hasStickyChanged = false; + } + /** + * Whether sticky positioning should be applied. + * @return {?} + */ + get sticky() { return this._sticky; } + /** + * @param {?} v + * @return {?} + */ + set sticky(v) { + /** @type {?} */ + const prevValue = this._sticky; + this._sticky = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(v); + this._hasStickyChanged = prevValue !== this._sticky; + } + /** + * Whether the sticky value has changed since this was last called. + * @return {?} + */ + hasStickyChanged() { + /** @type {?} */ + const hasStickyChanged = this._hasStickyChanged; + this._hasStickyChanged = false; + return hasStickyChanged; + } + /** + * Resets the dirty check for cases where the sticky state has been used without checking. + * @return {?} + */ + resetStickyChanged() { + this._hasStickyChanged = false; + } + }; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Cell definition for a CDK table. + * Captures the template of a column's data row cell as well as cell-specific properties. + */ +class CdkCellDef { + /** + * @param {?} template + */ + constructor(/** @docs-private */ template) { + this.template = template; + } +} +CdkCellDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[cdkCellDef]' },] }, +]; +/** @nocollapse */ +CdkCellDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] } +]; +/** + * Header cell definition for a CDK table. + * Captures the template of a column's header cell and as well as cell-specific properties. + */ +class CdkHeaderCellDef { + /** + * @param {?} template + */ + constructor(/** @docs-private */ template) { + this.template = template; + } +} +CdkHeaderCellDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[cdkHeaderCellDef]' },] }, +]; +/** @nocollapse */ +CdkHeaderCellDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] } +]; +/** + * Footer cell definition for a CDK table. + * Captures the template of a column's footer cell and as well as cell-specific properties. + */ +class CdkFooterCellDef { + /** + * @param {?} template + */ + constructor(/** @docs-private */ template) { + this.template = template; + } +} +CdkFooterCellDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[cdkFooterCellDef]' },] }, +]; +/** @nocollapse */ +CdkFooterCellDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] } +]; +// Boilerplate for applying mixins to CdkColumnDef. +/** + * \@docs-private + */ +class CdkColumnDefBase { +} +/** @type {?} */ +const _CdkColumnDefBase = mixinHasStickyInput(CdkColumnDefBase); +/** + * Column definition for the CDK table. + * Defines a set of cells available for a table column. + */ +class CdkColumnDef extends _CdkColumnDefBase { + constructor() { + super(...arguments); + this._stickyEnd = false; + } + /** + * Unique name for this column. + * @return {?} + */ + get name() { + return this._name; + } + /** + * @param {?} name + * @return {?} + */ + set name(name) { + // If the directive is set without a name (updated programatically), then this setter will + // trigger with an empty string and should not overwrite the programatically set value. + if (!name) { + return; + } + this._name = name; + this.cssClassFriendlyName = name.replace(/[^a-z0-9_-]/ig, '-'); + } + /** + * Whether this column should be sticky positioned on the end of the row. Should make sure + * that it mimics the `CanStick` mixin such that `_hasStickyChanged` is set to true if the value + * has been changed. + * @return {?} + */ + get stickyEnd() { + return this._stickyEnd; + } + /** + * @param {?} v + * @return {?} + */ + set stickyEnd(v) { + /** @type {?} */ + const prevValue = this._stickyEnd; + this._stickyEnd = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(v); + this._hasStickyChanged = prevValue !== this._stickyEnd; + } +} +CdkColumnDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkColumnDef]', + inputs: ['sticky'], + providers: [{ provide: 'MAT_SORT_HEADER_COLUMN_DEF', useExisting: CdkColumnDef }], + },] }, +]; +CdkColumnDef.propDecorators = { + name: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkColumnDef',] }], + stickyEnd: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['stickyEnd',] }], + cell: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChild"], args: [CdkCellDef, { static: false },] }], + headerCell: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChild"], args: [CdkHeaderCellDef, { static: false },] }], + footerCell: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChild"], args: [CdkFooterCellDef, { static: false },] }] +}; +/** + * Base class for the cells. Adds a CSS classname that identifies the column it renders in. + */ +class BaseCdkCell { + /** + * @param {?} columnDef + * @param {?} elementRef + */ + constructor(columnDef, elementRef) { + /** @type {?} */ + const columnClassName = `cdk-column-${columnDef.cssClassFriendlyName}`; + elementRef.nativeElement.classList.add(columnClassName); + } +} +/** + * Header cell template container that adds the right classes and role. + */ +class CdkHeaderCell extends BaseCdkCell { + /** + * @param {?} columnDef + * @param {?} elementRef + */ + constructor(columnDef, elementRef) { + super(columnDef, elementRef); + } +} +CdkHeaderCell.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'cdk-header-cell, th[cdk-header-cell]', + host: { + 'class': 'cdk-header-cell', + 'role': 'columnheader', + }, + },] }, +]; +/** @nocollapse */ +CdkHeaderCell.ctorParameters = () => [ + { type: CdkColumnDef }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; +/** + * Footer cell template container that adds the right classes and role. + */ +class CdkFooterCell extends BaseCdkCell { + /** + * @param {?} columnDef + * @param {?} elementRef + */ + constructor(columnDef, elementRef) { + super(columnDef, elementRef); + } +} +CdkFooterCell.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'cdk-footer-cell, td[cdk-footer-cell]', + host: { + 'class': 'cdk-footer-cell', + 'role': 'gridcell', + }, + },] }, +]; +/** @nocollapse */ +CdkFooterCell.ctorParameters = () => [ + { type: CdkColumnDef }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; +/** + * Cell template container that adds the right classes and role. + */ +class CdkCell extends BaseCdkCell { + /** + * @param {?} columnDef + * @param {?} elementRef + */ + constructor(columnDef, elementRef) { + super(columnDef, elementRef); + } +} +CdkCell.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'cdk-cell, td[cdk-cell]', + host: { + 'class': 'cdk-cell', + 'role': 'gridcell', + }, + },] }, +]; +/** @nocollapse */ +CdkCell.ctorParameters = () => [ + { type: CdkColumnDef }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * The row template that can be used by the mat-table. Should not be used outside of the + * material library. + * @type {?} + */ +const CDK_ROW_TEMPLATE = ``; +/** + * Base class for the CdkHeaderRowDef and CdkRowDef that handles checking their columns inputs + * for changes and notifying the table. + * @abstract + */ +class BaseRowDef { + /** + * @param {?} template + * @param {?} _differs + */ + constructor(template, _differs) { + this.template = template; + this._differs = _differs; + } + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + // Create a new columns differ if one does not yet exist. Initialize it based on initial value + // of the columns property or an empty array if none is provided. + if (!this._columnsDiffer) { + /** @type {?} */ + const columns = (changes['columns'] && changes['columns'].currentValue) || []; + this._columnsDiffer = this._differs.find(columns).create(); + this._columnsDiffer.diff(columns); + } + } + /** + * Returns the difference between the current columns and the columns from the last diff, or null + * if there is no difference. + * @return {?} + */ + getColumnsDiff() { + return this._columnsDiffer.diff(this.columns); + } + /** + * Gets this row def's relevant cell template from the provided column def. + * @param {?} column + * @return {?} + */ + extractCellTemplate(column) { + if (this instanceof CdkHeaderRowDef) { + return column.headerCell.template; + } + if (this instanceof CdkFooterRowDef) { + return column.footerCell.template; + } + else { + return column.cell.template; + } + } +} +// Boilerplate for applying mixins to CdkHeaderRowDef. +/** + * \@docs-private + */ +class CdkHeaderRowDefBase extends BaseRowDef { +} +/** @type {?} */ +const _CdkHeaderRowDefBase = mixinHasStickyInput(CdkHeaderRowDefBase); +/** + * Header row definition for the CDK table. + * Captures the header row's template and other header properties such as the columns to display. + */ +class CdkHeaderRowDef extends _CdkHeaderRowDefBase { + /** + * @param {?} template + * @param {?} _differs + */ + constructor(template, _differs) { + super(template, _differs); + } + // Prerender fails to recognize that ngOnChanges in a part of this class through inheritance. + // Explicitly define it so that the method is called as part of the Angular lifecycle. + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + super.ngOnChanges(changes); + } +} +CdkHeaderRowDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkHeaderRowDef]', + inputs: ['columns: cdkHeaderRowDef', 'sticky: cdkHeaderRowDefSticky'], + },] }, +]; +/** @nocollapse */ +CdkHeaderRowDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["IterableDiffers"] } +]; +// Boilerplate for applying mixins to CdkFooterRowDef. +/** + * \@docs-private + */ +class CdkFooterRowDefBase extends BaseRowDef { +} +/** @type {?} */ +const _CdkFooterRowDefBase = mixinHasStickyInput(CdkFooterRowDefBase); +/** + * Footer row definition for the CDK table. + * Captures the footer row's template and other footer properties such as the columns to display. + */ +class CdkFooterRowDef extends _CdkFooterRowDefBase { + /** + * @param {?} template + * @param {?} _differs + */ + constructor(template, _differs) { + super(template, _differs); + } + // Prerender fails to recognize that ngOnChanges in a part of this class through inheritance. + // Explicitly define it so that the method is called as part of the Angular lifecycle. + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + super.ngOnChanges(changes); + } +} +CdkFooterRowDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkFooterRowDef]', + inputs: ['columns: cdkFooterRowDef', 'sticky: cdkFooterRowDefSticky'], + },] }, +]; +/** @nocollapse */ +CdkFooterRowDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["IterableDiffers"] } +]; +/** + * Data row definition for the CDK table. + * Captures the header row's template and other row properties such as the columns to display and + * a when predicate that describes when this row should be used. + * @template T + */ +class CdkRowDef extends BaseRowDef { + // TODO(andrewseguin): Add an input for providing a switch function to determine + // if this template should be used. + /** + * @param {?} template + * @param {?} _differs + */ + constructor(template, _differs) { + super(template, _differs); + } +} +CdkRowDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkRowDef]', + inputs: ['columns: cdkRowDefColumns', 'when: cdkRowDefWhen'], + },] }, +]; +/** @nocollapse */ +CdkRowDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["IterableDiffers"] } +]; +/** + * Outlet for rendering cells inside of a row or header row. + * \@docs-private + */ +class CdkCellOutlet { + /** + * @param {?} _viewContainer + */ + constructor(_viewContainer) { + this._viewContainer = _viewContainer; + CdkCellOutlet.mostRecentCellOutlet = this; + } + /** + * @return {?} + */ + ngOnDestroy() { + // If this was the last outlet being rendered in the view, remove the reference + // from the static property after it has been destroyed to avoid leaking memory. + if (CdkCellOutlet.mostRecentCellOutlet === this) { + CdkCellOutlet.mostRecentCellOutlet = null; + } + } +} +/** + * Static property containing the latest constructed instance of this class. + * Used by the CDK table when each CdkHeaderRow and CdkRow component is created using + * createEmbeddedView. After one of these components are created, this property will provide + * a handle to provide that component's cells and context. After init, the CdkCellOutlet will + * construct the cells with the provided context. + */ +CdkCellOutlet.mostRecentCellOutlet = null; +CdkCellOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[cdkCellOutlet]' },] }, +]; +/** @nocollapse */ +CdkCellOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewContainerRef"] } +]; +/** + * Header template container that contains the cell outlet. Adds the right class and role. + */ +class CdkHeaderRow { +} +CdkHeaderRow.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Component"], args: [{selector: 'cdk-header-row, tr[cdk-header-row]', + template: CDK_ROW_TEMPLATE, + host: { + 'class': 'cdk-header-row', + 'role': 'row', + }, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectionStrategy"].Default, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewEncapsulation"].None, + },] }, +]; +/** + * Footer template container that contains the cell outlet. Adds the right class and role. + */ +class CdkFooterRow { +} +CdkFooterRow.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Component"], args: [{selector: 'cdk-footer-row, tr[cdk-footer-row]', + template: CDK_ROW_TEMPLATE, + host: { + 'class': 'cdk-footer-row', + 'role': 'row', + }, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectionStrategy"].Default, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewEncapsulation"].None, + },] }, +]; +/** + * Data row template container that contains the cell outlet. Adds the right class and role. + */ +class CdkRow { +} +CdkRow.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Component"], args: [{selector: 'cdk-row, tr[cdk-row]', + template: CDK_ROW_TEMPLATE, + host: { + 'class': 'cdk-row', + 'role': 'row', + }, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectionStrategy"].Default, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewEncapsulation"].None, + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * List of all possible directions that can be used for sticky positioning. + * \@docs-private + * @type {?} + */ +const STICKY_DIRECTIONS = ['top', 'bottom', 'left', 'right']; +/** + * Applies and removes sticky positioning styles to the `CdkTable` rows and columns cells. + * \@docs-private + */ +class StickyStyler { + /** + * @param {?} _isNativeHtmlTable Whether the sticky logic should be based on a table + * that uses the native `` element. + * @param {?} _stickCellCss The CSS class that will be applied to every row/cell that has + * sticky positioning applied. + * @param {?} direction The directionality context of the table (ltr/rtl); affects column positioning + * by reversing left/right positions. + * @param {?=} _isBrowser Whether the table is currently being rendered on the server or the client. + */ + constructor(_isNativeHtmlTable, _stickCellCss, direction, _isBrowser = true) { + this._isNativeHtmlTable = _isNativeHtmlTable; + this._stickCellCss = _stickCellCss; + this.direction = direction; + this._isBrowser = _isBrowser; + } + /** + * Clears the sticky positioning styles from the row and its cells by resetting the `position` + * style, setting the zIndex to 0, and unsetting each provided sticky direction. + * @param {?} rows The list of rows that should be cleared from sticking in the provided directions + * @param {?} stickyDirections The directions that should no longer be set as sticky on the rows. + * @return {?} + */ + clearStickyPositioning(rows, stickyDirections) { + for (const row of rows) { + // If the row isn't an element (e.g. if it's an `ng-container`), + // it won't have inline styles or `children` so we skip it. + if (row.nodeType !== row.ELEMENT_NODE) { + continue; + } + this._removeStickyStyle(row, stickyDirections); + for (let i = 0; i < row.children.length; i++) { + /** @type {?} */ + const cell = (/** @type {?} */ (row.children[i])); + this._removeStickyStyle(cell, stickyDirections); + } + } + } + /** + * Applies sticky left and right positions to the cells of each row according to the sticky + * states of the rendered column definitions. + * @param {?} rows The rows that should have its set of cells stuck according to the sticky states. + * @param {?} stickyStartStates A list of boolean states where each state represents whether the cell + * in this index position should be stuck to the start of the row. + * @param {?} stickyEndStates A list of boolean states where each state represents whether the cell + * in this index position should be stuck to the end of the row. + * @return {?} + */ + updateStickyColumns(rows, stickyStartStates, stickyEndStates) { + /** @type {?} */ + const hasStickyColumns = stickyStartStates.some((/** + * @param {?} state + * @return {?} + */ + state => state)) || stickyEndStates.some((/** + * @param {?} state + * @return {?} + */ + state => state)); + if (!rows.length || !hasStickyColumns || !this._isBrowser) { + return; + } + /** @type {?} */ + const firstRow = rows[0]; + /** @type {?} */ + const numCells = firstRow.children.length; + /** @type {?} */ + const cellWidths = this._getCellWidths(firstRow); + /** @type {?} */ + const startPositions = this._getStickyStartColumnPositions(cellWidths, stickyStartStates); + /** @type {?} */ + const endPositions = this._getStickyEndColumnPositions(cellWidths, stickyEndStates); + /** @type {?} */ + const isRtl = this.direction === 'rtl'; + for (const row of rows) { + for (let i = 0; i < numCells; i++) { + /** @type {?} */ + const cell = (/** @type {?} */ (row.children[i])); + if (stickyStartStates[i]) { + this._addStickyStyle(cell, isRtl ? 'right' : 'left', startPositions[i]); + } + if (stickyEndStates[i]) { + this._addStickyStyle(cell, isRtl ? 'left' : 'right', endPositions[i]); + } + } + } + } + /** + * Applies sticky positioning to the row's cells if using the native table layout, and to the + * row itself otherwise. + * @param {?} rowsToStick The list of rows that should be stuck according to their corresponding + * sticky state and to the provided top or bottom position. + * @param {?} stickyStates A list of boolean states where each state represents whether the row + * should be stuck in the particular top or bottom position. + * @param {?} position The position direction in which the row should be stuck if that row should be + * sticky. + * + * @return {?} + */ + stickRows(rowsToStick, stickyStates, position) { + // Since we can't measure the rows on the server, we can't stick the rows properly. + if (!this._isBrowser) { + return; + } + // If positioning the rows to the bottom, reverse their order when evaluating the sticky + // position such that the last row stuck will be "bottom: 0px" and so on. + /** @type {?} */ + const rows = position === 'bottom' ? rowsToStick.reverse() : rowsToStick; + /** @type {?} */ + let stickyHeight = 0; + for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) { + if (!stickyStates[rowIndex]) { + continue; + } + /** @type {?} */ + const row = rows[rowIndex]; + if (this._isNativeHtmlTable) { + for (let j = 0; j < row.children.length; j++) { + /** @type {?} */ + const cell = (/** @type {?} */ (row.children[j])); + this._addStickyStyle(cell, position, stickyHeight); + } + } + else { + // Flex does not respect the stick positioning on the cells, needs to be applied to the row. + // If this is applied on a native table, Safari causes the header to fly in wrong direction. + this._addStickyStyle(row, position, stickyHeight); + } + if (rowIndex === rows.length - 1) { + // prevent unnecessary reflow from getBoundingClientRect() + return; + } + stickyHeight += row.getBoundingClientRect().height; + } + } + /** + * When using the native table in Safari, sticky footer cells do not stick. The only way to stick + * footer rows is to apply sticky styling to the tfoot container. This should only be done if + * all footer rows are sticky. If not all footer rows are sticky, remove sticky positioning from + * the tfoot element. + * @param {?} tableElement + * @param {?} stickyStates + * @return {?} + */ + updateStickyFooterContainer(tableElement, stickyStates) { + if (!this._isNativeHtmlTable) { + return; + } + /** @type {?} */ + const tfoot = (/** @type {?} */ (tableElement.querySelector('tfoot'))); + if (stickyStates.some((/** + * @param {?} state + * @return {?} + */ + state => !state))) { + this._removeStickyStyle(tfoot, ['bottom']); + } + else { + this._addStickyStyle(tfoot, 'bottom', 0); + } + } + /** + * Removes the sticky style on the element by removing the sticky cell CSS class, re-evaluating + * the zIndex, removing each of the provided sticky directions, and removing the + * sticky position if there are no more directions. + * @param {?} element + * @param {?} stickyDirections + * @return {?} + */ + _removeStickyStyle(element, stickyDirections) { + for (const dir of stickyDirections) { + element.style[dir] = ''; + } + element.style.zIndex = this._getCalculatedZIndex(element); + // If the element no longer has any more sticky directions, remove sticky positioning and + // the sticky CSS class. + /** @type {?} */ + const hasDirection = STICKY_DIRECTIONS.some((/** + * @param {?} dir + * @return {?} + */ + dir => !!element.style[dir])); + if (!hasDirection) { + element.style.position = ''; + element.classList.remove(this._stickCellCss); + } + } + /** + * Adds the sticky styling to the element by adding the sticky style class, changing position + * to be sticky (and -webkit-sticky), setting the appropriate zIndex, and adding a sticky + * direction and value. + * @param {?} element + * @param {?} dir + * @param {?} dirValue + * @return {?} + */ + _addStickyStyle(element, dir, dirValue) { + element.classList.add(this._stickCellCss); + element.style[dir] = `${dirValue}px`; + element.style.cssText += 'position: -webkit-sticky; position: sticky; '; + element.style.zIndex = this._getCalculatedZIndex(element); + } + /** + * Calculate what the z-index should be for the element, depending on what directions (top, + * bottom, left, right) have been set. It should be true that elements with a top direction + * should have the highest index since these are elements like a table header. If any of those + * elements are also sticky in another direction, then they should appear above other elements + * that are only sticky top (e.g. a sticky column on a sticky header). Bottom-sticky elements + * (e.g. footer rows) should then be next in the ordering such that they are below the header + * but above any non-sticky elements. Finally, left/right sticky elements (e.g. sticky columns) + * should minimally increment so that they are above non-sticky elements but below top and bottom + * elements. + * @param {?} element + * @return {?} + */ + _getCalculatedZIndex(element) { + /** @type {?} */ + const zIndexIncrements = { + top: 100, + bottom: 10, + left: 1, + right: 1, + }; + /** @type {?} */ + let zIndex = 0; + for (const dir of STICKY_DIRECTIONS) { + if (element.style[dir]) { + zIndex += zIndexIncrements[dir]; + } + } + return zIndex ? `${zIndex}` : ''; + } + /** + * Gets the widths for each cell in the provided row. + * @param {?} row + * @return {?} + */ + _getCellWidths(row) { + /** @type {?} */ + const cellWidths = []; + /** @type {?} */ + const firstRowCells = row.children; + for (let i = 0; i < firstRowCells.length; i++) { + /** @type {?} */ + let cell = (/** @type {?} */ (firstRowCells[i])); + cellWidths.push(cell.getBoundingClientRect().width); + } + return cellWidths; + } + /** + * Determines the left and right positions of each sticky column cell, which will be the + * accumulation of all sticky column cell widths to the left and right, respectively. + * Non-sticky cells do not need to have a value set since their positions will not be applied. + * @param {?} widths + * @param {?} stickyStates + * @return {?} + */ + _getStickyStartColumnPositions(widths, stickyStates) { + /** @type {?} */ + const positions = []; + /** @type {?} */ + let nextPosition = 0; + for (let i = 0; i < widths.length; i++) { + if (stickyStates[i]) { + positions[i] = nextPosition; + nextPosition += widths[i]; + } + } + return positions; + } + /** + * Determines the left and right positions of each sticky column cell, which will be the + * accumulation of all sticky column cell widths to the left and right, respectively. + * Non-sticky cells do not need to have a value set since their positions will not be applied. + * @param {?} widths + * @param {?} stickyStates + * @return {?} + */ + _getStickyEndColumnPositions(widths, stickyStates) { + /** @type {?} */ + const positions = []; + /** @type {?} */ + let nextPosition = 0; + for (let i = widths.length; i > 0; i--) { + if (stickyStates[i]) { + positions[i] = nextPosition; + nextPosition += widths[i]; + } + } + return positions; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Returns an error to be thrown when attempting to find an unexisting column. + * \@docs-private + * @param {?} id Id whose lookup failed. + * @return {?} + */ +function getTableUnknownColumnError(id) { + return Error(`Could not find column with id "${id}".`); +} +/** + * Returns an error to be thrown when two column definitions have the same name. + * \@docs-private + * @param {?} name + * @return {?} + */ +function getTableDuplicateColumnNameError(name) { + return Error(`Duplicate column definition name provided: "${name}".`); +} +/** + * Returns an error to be thrown when there are multiple rows that are missing a when function. + * \@docs-private + * @return {?} + */ +function getTableMultipleDefaultRowDefsError() { + return Error(`There can only be one default row without a when predicate function.`); +} +/** + * Returns an error to be thrown when there are no matching row defs for a particular set of data. + * \@docs-private + * @param {?} data + * @return {?} + */ +function getTableMissingMatchingRowDefError(data) { + return Error(`Could not find a matching row definition for the` + + `provided row data: ${JSON.stringify(data)}`); +} +/** + * Returns an error to be thrown when there is no row definitions present in the content. + * \@docs-private + * @return {?} + */ +function getTableMissingRowDefsError() { + return Error('Missing definitions for header, footer, and row; ' + + 'cannot determine which columns should be rendered.'); +} +/** + * Returns an error to be thrown when the data source does not match the compatible types. + * \@docs-private + * @return {?} + */ +function getTableUnknownDataSourceError() { + return Error(`Provided data source did not match an array, Observable, or DataSource`); +} +/** + * Returns an error to be thrown when the text column cannot find a parent table to inject. + * \@docs-private + * @return {?} + */ +function getTableTextColumnMissingParentTableError() { + return Error(`Text column could not find a parent table for registration.`); +} +/** + * Returns an error to be thrown when a table text column doesn't have a name. + * \@docs-private + * @return {?} + */ +function getTableTextColumnMissingNameError() { + return Error(`Table text column must have a name.`); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Provides a handle for the table to grab the view container's ng-container to insert data rows. + * \@docs-private + */ +class DataRowOutlet { + /** + * @param {?} viewContainer + * @param {?} elementRef + */ + constructor(viewContainer, elementRef) { + this.viewContainer = viewContainer; + this.elementRef = elementRef; + } +} +DataRowOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[rowOutlet]' },] }, +]; +/** @nocollapse */ +DataRowOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; +/** + * Provides a handle for the table to grab the view container's ng-container to insert the header. + * \@docs-private + */ +class HeaderRowOutlet { + /** + * @param {?} viewContainer + * @param {?} elementRef + */ + constructor(viewContainer, elementRef) { + this.viewContainer = viewContainer; + this.elementRef = elementRef; + } +} +HeaderRowOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[headerRowOutlet]' },] }, +]; +/** @nocollapse */ +HeaderRowOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; +/** + * Provides a handle for the table to grab the view container's ng-container to insert the footer. + * \@docs-private + */ +class FooterRowOutlet { + /** + * @param {?} viewContainer + * @param {?} elementRef + */ + constructor(viewContainer, elementRef) { + this.viewContainer = viewContainer; + this.elementRef = elementRef; + } +} +FooterRowOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ selector: '[footerRowOutlet]' },] }, +]; +/** @nocollapse */ +FooterRowOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] } +]; +/** + * The table template that can be used by the mat-table. Should not be used outside of the + * material library. + * \@docs-private + * @type {?} + */ +const CDK_TABLE_TEMPLATE = +// Note that according to MDN, the `caption` element has to be projected as the **first** +// element in the table. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption +` + + + + +`; +/** + * A data table that can render a header row, data rows, and a footer row. + * Uses the dataSource input to determine the data to be rendered. The data can be provided either + * as a data array, an Observable stream that emits the data array to render, or a DataSource with a + * connect function that will return an Observable stream that emits the data array to render. + * @template T + */ +class CdkTable { + /** + * @param {?} _differs + * @param {?} _changeDetectorRef + * @param {?} _elementRef + * @param {?} role + * @param {?} _dir + * @param {?} _document + * @param {?} _platform + */ + constructor(_differs, _changeDetectorRef, _elementRef, role, _dir, _document, _platform) { + this._differs = _differs; + this._changeDetectorRef = _changeDetectorRef; + this._elementRef = _elementRef; + this._dir = _dir; + this._platform = _platform; + /** + * Subject that emits when the component has been destroyed. + */ + this._onDestroy = new rxjs__WEBPACK_IMPORTED_MODULE_6__["Subject"](); + /** + * Map of all the user's defined columns (header, data, and footer cell template) identified by + * name. Collection populated by the column definitions gathered by `ContentChildren` as well as + * any custom column definitions added to `_customColumnDefs`. + */ + this._columnDefsByName = new Map(); + /** + * Column definitions that were defined outside of the direct content children of the table. + * These will be defined when, e.g., creating a wrapper around the cdkTable that has + * column definitions as *it's* content child. + */ + this._customColumnDefs = new Set(); + /** + * Data row definitions that were defined outside of the direct content children of the table. + * These will be defined when, e.g., creating a wrapper around the cdkTable that has + * built-in data rows as *it's* content child. + */ + this._customRowDefs = new Set(); + /** + * Header row definitions that were defined outside of the direct content children of the table. + * These will be defined when, e.g., creating a wrapper around the cdkTable that has + * built-in header rows as *it's* content child. + */ + this._customHeaderRowDefs = new Set(); + /** + * Footer row definitions that were defined outside of the direct content children of the table. + * These will be defined when, e.g., creating a wrapper around the cdkTable that has a + * built-in footer row as *it's* content child. + */ + this._customFooterRowDefs = new Set(); + /** + * Whether the header row definition has been changed. Triggers an update to the header row after + * content is checked. Initialized as true so that the table renders the initial set of rows. + */ + this._headerRowDefChanged = true; + /** + * Whether the footer row definition has been changed. Triggers an update to the footer row after + * content is checked. Initialized as true so that the table renders the initial set of rows. + */ + this._footerRowDefChanged = true; + /** + * Cache of the latest rendered `RenderRow` objects as a map for easy retrieval when constructing + * a new list of `RenderRow` objects for rendering rows. Since the new list is constructed with + * the cached `RenderRow` objects when possible, the row identity is preserved when the data + * and row template matches, which allows the `IterableDiffer` to check rows by reference + * and understand which rows are added/moved/removed. + * + * Implemented as a map of maps where the first key is the `data: T` object and the second is the + * `CdkRowDef` object. With the two keys, the cache points to a `RenderRow` object that + * contains an array of created pairs. The array is necessary to handle cases where the data + * array contains multiple duplicate data objects and each instantiated `RenderRow` must be + * stored. + */ + this._cachedRenderRowsMap = new Map(); + /** + * CSS class added to any row or cell that has sticky positioning applied. May be overriden by + * table subclasses. + */ + this.stickyCssClass = 'cdk-table-sticky'; + this._multiTemplateDataRows = false; + // TODO(andrewseguin): Remove max value as the end index + // and instead calculate the view on init and scroll. + /** + * Stream containing the latest information on what rows are being displayed on screen. + * Can be used by the data source to as a heuristic of what data should be provided. + * + * \@docs-private + */ + this.viewChange = new rxjs__WEBPACK_IMPORTED_MODULE_6__["BehaviorSubject"]({ start: 0, end: Number.MAX_VALUE }); + if (!role) { + this._elementRef.nativeElement.setAttribute('role', 'grid'); + } + this._document = _document; + this._isNativeHtmlTable = this._elementRef.nativeElement.nodeName === 'TABLE'; + } + /** + * Tracking function that will be used to check the differences in data changes. Used similarly + * to `ngFor` `trackBy` function. Optimize row operations by identifying a row based on its data + * relative to the function to know if a row should be added/removed/moved. + * Accepts a function that takes two parameters, `index` and `item`. + * @return {?} + */ + get trackBy() { + return this._trackByFn; + } + /** + * @param {?} fn + * @return {?} + */ + set trackBy(fn) { + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["isDevMode"])() && fn != null && typeof fn !== 'function' && (/** @type {?} */ (console)) && + (/** @type {?} */ (console.warn))) { + console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`); + } + this._trackByFn = fn; + } + /** + * The table's source of data, which can be provided in three ways (in order of complexity): + * - Simple data array (each object represents one table row) + * - Stream that emits a data array each time the array changes + * - `DataSource` object that implements the connect/disconnect interface. + * + * If a data array is provided, the table must be notified when the array's objects are + * added, removed, or moved. This can be done by calling the `renderRows()` function which will + * render the diff since the last table render. If the data array reference is changed, the table + * will automatically trigger an update to the rows. + * + * When providing an Observable stream, the table will trigger an update automatically when the + * stream emits a new array of data. + * + * Finally, when providing a `DataSource` object, the table will use the Observable stream + * provided by the connect function and trigger updates when that stream emits new data array + * values. During the table's ngOnDestroy or when the data source is removed from the table, the + * table will call the DataSource's `disconnect` function (may be useful for cleaning up any + * subscriptions registered during the connect process). + * @return {?} + */ + get dataSource() { + return this._dataSource; + } + /** + * @param {?} dataSource + * @return {?} + */ + set dataSource(dataSource) { + if (this._dataSource !== dataSource) { + this._switchDataSource(dataSource); + } + } + /** + * Whether to allow multiple rows per data object by evaluating which rows evaluate their 'when' + * predicate to true. If `multiTemplateDataRows` is false, which is the default value, then each + * dataobject will render the first row that evaluates its when predicate to true, in the order + * defined in the table, or otherwise the default row which does not have a when predicate. + * @return {?} + */ + get multiTemplateDataRows() { + return this._multiTemplateDataRows; + } + /** + * @param {?} v + * @return {?} + */ + set multiTemplateDataRows(v) { + this._multiTemplateDataRows = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_0__["coerceBooleanProperty"])(v); + // In Ivy if this value is set via a static attribute (e.g.
), + // this setter will be invoked before the row outlet has been defined hence the null check. + if (this._rowOutlet && this._rowOutlet.viewContainer.length) { + this._forceRenderDataRows(); + } + } + /** + * @return {?} + */ + ngOnInit() { + this._setupStickyStyler(); + if (this._isNativeHtmlTable) { + this._applyNativeTableSections(); + } + // Set up the trackBy function so that it uses the `RenderRow` as its identity by default. If + // the user has provided a custom trackBy, return the result of that function as evaluated + // with the values of the `RenderRow`'s data and index. + this._dataDiffer = this._differs.find([]).create((/** + * @param {?} _i + * @param {?} dataRow + * @return {?} + */ + (_i, dataRow) => { + return this.trackBy ? this.trackBy(dataRow.dataIndex, dataRow.data) : dataRow; + })); + } + /** + * @return {?} + */ + ngAfterContentChecked() { + // Cache the row and column definitions gathered by ContentChildren and programmatic injection. + this._cacheRowDefs(); + this._cacheColumnDefs(); + // Make sure that the user has at least added header, footer, or data row def. + if (!this._headerRowDefs.length && !this._footerRowDefs.length && !this._rowDefs.length) { + throw getTableMissingRowDefsError(); + } + // Render updates if the list of columns have been changed for the header, row, or footer defs. + this._renderUpdatedColumns(); + // If the header row definition has been changed, trigger a render to the header row. + if (this._headerRowDefChanged) { + this._forceRenderHeaderRows(); + this._headerRowDefChanged = false; + } + // If the footer row definition has been changed, trigger a render to the footer row. + if (this._footerRowDefChanged) { + this._forceRenderFooterRows(); + this._footerRowDefChanged = false; + } + // If there is a data source and row definitions, connect to the data source unless a + // connection has already been made. + if (this.dataSource && this._rowDefs.length > 0 && !this._renderChangeSubscription) { + this._observeRenderChanges(); + } + this._checkStickyStates(); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._rowOutlet.viewContainer.clear(); + this._headerRowOutlet.viewContainer.clear(); + this._footerRowOutlet.viewContainer.clear(); + this._cachedRenderRowsMap.clear(); + this._onDestroy.next(); + this._onDestroy.complete(); + if (Object(_angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__["isDataSource"])(this.dataSource)) { + this.dataSource.disconnect(this); + } + } + /** + * Renders rows based on the table's latest set of data, which was either provided directly as an + * input or retrieved through an Observable stream (directly or from a DataSource). + * Checks for differences in the data since the last diff to perform only the necessary + * changes (add/remove/move rows). + * + * If the table's data source is a DataSource or Observable, this will be invoked automatically + * each time the provided Observable stream emits a new data array. Otherwise if your data is + * an array, this function will need to be called to render any changes. + * @return {?} + */ + renderRows() { + this._renderRows = this._getAllRenderRows(); + /** @type {?} */ + const changes = this._dataDiffer.diff(this._renderRows); + if (!changes) { + return; + } + /** @type {?} */ + const viewContainer = this._rowOutlet.viewContainer; + changes.forEachOperation((/** + * @param {?} record + * @param {?} prevIndex + * @param {?} currentIndex + * @return {?} + */ + (record, prevIndex, currentIndex) => { + if (record.previousIndex == null) { + this._insertRow(record.item, (/** @type {?} */ (currentIndex))); + } + else if (currentIndex == null) { + viewContainer.remove((/** @type {?} */ (prevIndex))); + } + else { + /** @type {?} */ + const view = (/** @type {?} */ (viewContainer.get((/** @type {?} */ (prevIndex))))); + viewContainer.move((/** @type {?} */ (view)), currentIndex); + } + })); + // Update the meta context of a row's context data (index, count, first, last, ...) + this._updateRowIndexContext(); + // Update rows that did not get added/removed/moved but may have had their identity changed, + // e.g. if trackBy matched data on some property but the actual data reference changed. + changes.forEachIdentityChange((/** + * @param {?} record + * @return {?} + */ + (record) => { + /** @type {?} */ + const rowView = (/** @type {?} */ (viewContainer.get((/** @type {?} */ (record.currentIndex))))); + rowView.context.$implicit = record.item.data; + })); + this.updateStickyColumnStyles(); + } + /** + * Sets the header row definition to be used. Overrides the header row definition gathered by + * using `ContentChild`, if one exists. Sets a flag that will re-render the header row after the + * table's content is checked. + * \@docs-private + * @deprecated Use `addHeaderRowDef` and `removeHeaderRowDef` instead + * \@breaking-change 8.0.0 + * @param {?} headerRowDef + * @return {?} + */ + setHeaderRowDef(headerRowDef) { + this._customHeaderRowDefs = new Set([headerRowDef]); + this._headerRowDefChanged = true; + } + /** + * Sets the footer row definition to be used. Overrides the footer row definition gathered by + * using `ContentChild`, if one exists. Sets a flag that will re-render the footer row after the + * table's content is checked. + * \@docs-private + * @deprecated Use `addFooterRowDef` and `removeFooterRowDef` instead + * \@breaking-change 8.0.0 + * @param {?} footerRowDef + * @return {?} + */ + setFooterRowDef(footerRowDef) { + this._customFooterRowDefs = new Set([footerRowDef]); + this._footerRowDefChanged = true; + } + /** + * Adds a column definition that was not included as part of the content children. + * @param {?} columnDef + * @return {?} + */ + addColumnDef(columnDef) { + this._customColumnDefs.add(columnDef); + } + /** + * Removes a column definition that was not included as part of the content children. + * @param {?} columnDef + * @return {?} + */ + removeColumnDef(columnDef) { + this._customColumnDefs.delete(columnDef); + } + /** + * Adds a row definition that was not included as part of the content children. + * @param {?} rowDef + * @return {?} + */ + addRowDef(rowDef) { + this._customRowDefs.add(rowDef); + } + /** + * Removes a row definition that was not included as part of the content children. + * @param {?} rowDef + * @return {?} + */ + removeRowDef(rowDef) { + this._customRowDefs.delete(rowDef); + } + /** + * Adds a header row definition that was not included as part of the content children. + * @param {?} headerRowDef + * @return {?} + */ + addHeaderRowDef(headerRowDef) { + this._customHeaderRowDefs.add(headerRowDef); + this._headerRowDefChanged = true; + } + /** + * Removes a header row definition that was not included as part of the content children. + * @param {?} headerRowDef + * @return {?} + */ + removeHeaderRowDef(headerRowDef) { + this._customHeaderRowDefs.delete(headerRowDef); + this._headerRowDefChanged = true; + } + /** + * Adds a footer row definition that was not included as part of the content children. + * @param {?} footerRowDef + * @return {?} + */ + addFooterRowDef(footerRowDef) { + this._customFooterRowDefs.add(footerRowDef); + this._footerRowDefChanged = true; + } + /** + * Removes a footer row definition that was not included as part of the content children. + * @param {?} footerRowDef + * @return {?} + */ + removeFooterRowDef(footerRowDef) { + this._customFooterRowDefs.delete(footerRowDef); + this._footerRowDefChanged = true; + } + /** + * Updates the header sticky styles. First resets all applied styles with respect to the cells + * sticking to the top. Then, evaluating which cells need to be stuck to the top. This is + * automatically called when the header row changes its displayed set of columns, or if its + * sticky input changes. May be called manually for cases where the cell content changes outside + * of these events. + * @return {?} + */ + updateStickyHeaderRowStyles() { + /** @type {?} */ + const headerRows = this._getRenderedRows(this._headerRowOutlet); + /** @type {?} */ + const tableElement = (/** @type {?} */ (this._elementRef.nativeElement)); + // Hide the thead element if there are no header rows. This is necessary to satisfy + // overzealous a11y checkers that fail because the `rowgroup` element does not contain + // required child `row`. + /** @type {?} */ + const thead = tableElement.querySelector('thead'); + if (thead) { + thead.style.display = headerRows.length ? '' : 'none'; + } + /** @type {?} */ + const stickyStates = this._headerRowDefs.map((/** + * @param {?} def + * @return {?} + */ + def => def.sticky)); + this._stickyStyler.clearStickyPositioning(headerRows, ['top']); + this._stickyStyler.stickRows(headerRows, stickyStates, 'top'); + // Reset the dirty state of the sticky input change since it has been used. + this._headerRowDefs.forEach((/** + * @param {?} def + * @return {?} + */ + def => def.resetStickyChanged())); + } + /** + * Updates the footer sticky styles. First resets all applied styles with respect to the cells + * sticking to the bottom. Then, evaluating which cells need to be stuck to the bottom. This is + * automatically called when the footer row changes its displayed set of columns, or if its + * sticky input changes. May be called manually for cases where the cell content changes outside + * of these events. + * @return {?} + */ + updateStickyFooterRowStyles() { + /** @type {?} */ + const footerRows = this._getRenderedRows(this._footerRowOutlet); + /** @type {?} */ + const tableElement = (/** @type {?} */ (this._elementRef.nativeElement)); + // Hide the tfoot element if there are no footer rows. This is necessary to satisfy + // overzealous a11y checkers that fail because the `rowgroup` element does not contain + // required child `row`. + /** @type {?} */ + const tfoot = tableElement.querySelector('tfoot'); + if (tfoot) { + tfoot.style.display = footerRows.length ? '' : 'none'; + } + /** @type {?} */ + const stickyStates = this._footerRowDefs.map((/** + * @param {?} def + * @return {?} + */ + def => def.sticky)); + this._stickyStyler.clearStickyPositioning(footerRows, ['bottom']); + this._stickyStyler.stickRows(footerRows, stickyStates, 'bottom'); + this._stickyStyler.updateStickyFooterContainer(this._elementRef.nativeElement, stickyStates); + // Reset the dirty state of the sticky input change since it has been used. + this._footerRowDefs.forEach((/** + * @param {?} def + * @return {?} + */ + def => def.resetStickyChanged())); + } + /** + * Updates the column sticky styles. First resets all applied styles with respect to the cells + * sticking to the left and right. Then sticky styles are added for the left and right according + * to the column definitions for each cell in each row. This is automatically called when + * the data source provides a new set of data or when a column definition changes its sticky + * input. May be called manually for cases where the cell content changes outside of these events. + * @return {?} + */ + updateStickyColumnStyles() { + /** @type {?} */ + const headerRows = this._getRenderedRows(this._headerRowOutlet); + /** @type {?} */ + const dataRows = this._getRenderedRows(this._rowOutlet); + /** @type {?} */ + const footerRows = this._getRenderedRows(this._footerRowOutlet); + // Clear the left and right positioning from all columns in the table across all rows since + // sticky columns span across all table sections (header, data, footer) + this._stickyStyler.clearStickyPositioning([...headerRows, ...dataRows, ...footerRows], ['left', 'right']); + // Update the sticky styles for each header row depending on the def's sticky state + headerRows.forEach((/** + * @param {?} headerRow + * @param {?} i + * @return {?} + */ + (headerRow, i) => { + this._addStickyColumnStyles([headerRow], this._headerRowDefs[i]); + })); + // Update the sticky styles for each data row depending on its def's sticky state + this._rowDefs.forEach((/** + * @param {?} rowDef + * @return {?} + */ + rowDef => { + // Collect all the rows rendered with this row definition. + /** @type {?} */ + const rows = []; + for (let i = 0; i < dataRows.length; i++) { + if (this._renderRows[i].rowDef === rowDef) { + rows.push(dataRows[i]); + } + } + this._addStickyColumnStyles(rows, rowDef); + })); + // Update the sticky styles for each footer row depending on the def's sticky state + footerRows.forEach((/** + * @param {?} footerRow + * @param {?} i + * @return {?} + */ + (footerRow, i) => { + this._addStickyColumnStyles([footerRow], this._footerRowDefs[i]); + })); + // Reset the dirty state of the sticky input change since it has been used. + Array.from(this._columnDefsByName.values()).forEach((/** + * @param {?} def + * @return {?} + */ + def => def.resetStickyChanged())); + } + /** + * Get the list of RenderRow objects to render according to the current list of data and defined + * row definitions. If the previous list already contained a particular pair, it should be reused + * so that the differ equates their references. + * @private + * @return {?} + */ + _getAllRenderRows() { + /** @type {?} */ + const renderRows = []; + // Store the cache and create a new one. Any re-used RenderRow objects will be moved into the + // new cache while unused ones can be picked up by garbage collection. + /** @type {?} */ + const prevCachedRenderRows = this._cachedRenderRowsMap; + this._cachedRenderRowsMap = new Map(); + // For each data object, get the list of rows that should be rendered, represented by the + // respective `RenderRow` object which is the pair of `data` and `CdkRowDef`. + for (let i = 0; i < this._data.length; i++) { + /** @type {?} */ + let data = this._data[i]; + /** @type {?} */ + const renderRowsForData = this._getRenderRowsForData(data, i, prevCachedRenderRows.get(data)); + if (!this._cachedRenderRowsMap.has(data)) { + this._cachedRenderRowsMap.set(data, new WeakMap()); + } + for (let j = 0; j < renderRowsForData.length; j++) { + /** @type {?} */ + let renderRow = renderRowsForData[j]; + /** @type {?} */ + const cache = (/** @type {?} */ (this._cachedRenderRowsMap.get(renderRow.data))); + if (cache.has(renderRow.rowDef)) { + (/** @type {?} */ (cache.get(renderRow.rowDef))).push(renderRow); + } + else { + cache.set(renderRow.rowDef, [renderRow]); + } + renderRows.push(renderRow); + } + } + return renderRows; + } + /** + * Gets a list of `RenderRow` for the provided data object and any `CdkRowDef` objects that + * should be rendered for this data. Reuses the cached RenderRow objects if they match the same + * `(T, CdkRowDef)` pair. + * @private + * @param {?} data + * @param {?} dataIndex + * @param {?=} cache + * @return {?} + */ + _getRenderRowsForData(data, dataIndex, cache) { + /** @type {?} */ + const rowDefs = this._getRowDefs(data, dataIndex); + return rowDefs.map((/** + * @param {?} rowDef + * @return {?} + */ + rowDef => { + /** @type {?} */ + const cachedRenderRows = (cache && cache.has(rowDef)) ? (/** @type {?} */ (cache.get(rowDef))) : []; + if (cachedRenderRows.length) { + /** @type {?} */ + const dataRow = (/** @type {?} */ (cachedRenderRows.shift())); + dataRow.dataIndex = dataIndex; + return dataRow; + } + else { + return { data, rowDef, dataIndex }; + } + })); + } + /** + * Update the map containing the content's column definitions. + * @private + * @return {?} + */ + _cacheColumnDefs() { + this._columnDefsByName.clear(); + /** @type {?} */ + const columnDefs = mergeQueryListAndSet(this._contentColumnDefs, this._customColumnDefs); + columnDefs.forEach((/** + * @param {?} columnDef + * @return {?} + */ + columnDef => { + if (this._columnDefsByName.has(columnDef.name)) { + throw getTableDuplicateColumnNameError(columnDef.name); + } + this._columnDefsByName.set(columnDef.name, columnDef); + })); + } + /** + * Update the list of all available row definitions that can be used. + * @private + * @return {?} + */ + _cacheRowDefs() { + this._headerRowDefs = + mergeQueryListAndSet(this._contentHeaderRowDefs, this._customHeaderRowDefs); + this._footerRowDefs = + mergeQueryListAndSet(this._contentFooterRowDefs, this._customFooterRowDefs); + this._rowDefs = mergeQueryListAndSet(this._contentRowDefs, this._customRowDefs); + // After all row definitions are determined, find the row definition to be considered default. + /** @type {?} */ + const defaultRowDefs = this._rowDefs.filter((/** + * @param {?} def + * @return {?} + */ + def => !def.when)); + if (!this.multiTemplateDataRows && defaultRowDefs.length > 1) { + throw getTableMultipleDefaultRowDefsError(); + } + this._defaultRowDef = defaultRowDefs[0]; + } + /** + * Check if the header, data, or footer rows have changed what columns they want to display or + * whether the sticky states have changed for the header or footer. If there is a diff, then + * re-render that section. + * @private + * @return {?} + */ + _renderUpdatedColumns() { + /** @type {?} */ + const columnsDiffReducer = (/** + * @param {?} acc + * @param {?} def + * @return {?} + */ + (acc, def) => acc || !!def.getColumnsDiff()); + // Force re-render data rows if the list of column definitions have changed. + if (this._rowDefs.reduce(columnsDiffReducer, false)) { + this._forceRenderDataRows(); + } + // Force re-render header/footer rows if the list of column definitions have changed.. + if (this._headerRowDefs.reduce(columnsDiffReducer, false)) { + this._forceRenderHeaderRows(); + } + if (this._footerRowDefs.reduce(columnsDiffReducer, false)) { + this._forceRenderFooterRows(); + } + } + /** + * Switch to the provided data source by resetting the data and unsubscribing from the current + * render change subscription if one exists. If the data source is null, interpret this by + * clearing the row outlet. Otherwise start listening for new data. + * @private + * @param {?} dataSource + * @return {?} + */ + _switchDataSource(dataSource) { + this._data = []; + if (Object(_angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__["isDataSource"])(this.dataSource)) { + this.dataSource.disconnect(this); + } + // Stop listening for data from the previous data source. + if (this._renderChangeSubscription) { + this._renderChangeSubscription.unsubscribe(); + this._renderChangeSubscription = null; + } + if (!dataSource) { + if (this._dataDiffer) { + this._dataDiffer.diff([]); + } + this._rowOutlet.viewContainer.clear(); + } + this._dataSource = dataSource; + } + /** + * Set up a subscription for the data provided by the data source. + * @private + * @return {?} + */ + _observeRenderChanges() { + // If no data source has been set, there is nothing to observe for changes. + if (!this.dataSource) { + return; + } + /** @type {?} */ + let dataStream; + if (Object(_angular_cdk_collections__WEBPACK_IMPORTED_MODULE_3__["isDataSource"])(this.dataSource)) { + dataStream = this.dataSource.connect(this); + } + else if (this.dataSource instanceof rxjs__WEBPACK_IMPORTED_MODULE_6__["Observable"]) { + dataStream = this.dataSource; + } + else if (Array.isArray(this.dataSource)) { + dataStream = Object(rxjs__WEBPACK_IMPORTED_MODULE_6__["of"])(this.dataSource); + } + if (dataStream === undefined) { + throw getTableUnknownDataSourceError(); + } + this._renderChangeSubscription = dataStream.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_7__["takeUntil"])(this._onDestroy)).subscribe((/** + * @param {?} data + * @return {?} + */ + data => { + this._data = data || []; + this.renderRows(); + })); + } + /** + * Clears any existing content in the header row outlet and creates a new embedded view + * in the outlet using the header row definition. + * @private + * @return {?} + */ + _forceRenderHeaderRows() { + // Clear the header row outlet if any content exists. + if (this._headerRowOutlet.viewContainer.length > 0) { + this._headerRowOutlet.viewContainer.clear(); + } + this._headerRowDefs.forEach((/** + * @param {?} def + * @param {?} i + * @return {?} + */ + (def, i) => this._renderRow(this._headerRowOutlet, def, i))); + this.updateStickyHeaderRowStyles(); + this.updateStickyColumnStyles(); + } + /** + * Clears any existing content in the footer row outlet and creates a new embedded view + * in the outlet using the footer row definition. + * @private + * @return {?} + */ + _forceRenderFooterRows() { + // Clear the footer row outlet if any content exists. + if (this._footerRowOutlet.viewContainer.length > 0) { + this._footerRowOutlet.viewContainer.clear(); + } + this._footerRowDefs.forEach((/** + * @param {?} def + * @param {?} i + * @return {?} + */ + (def, i) => this._renderRow(this._footerRowOutlet, def, i))); + this.updateStickyFooterRowStyles(); + this.updateStickyColumnStyles(); + } + /** + * Adds the sticky column styles for the rows according to the columns' stick states. + * @private + * @param {?} rows + * @param {?} rowDef + * @return {?} + */ + _addStickyColumnStyles(rows, rowDef) { + /** @type {?} */ + const columnDefs = Array.from(rowDef.columns || []).map((/** + * @param {?} columnName + * @return {?} + */ + columnName => { + /** @type {?} */ + const columnDef = this._columnDefsByName.get(columnName); + if (!columnDef) { + throw getTableUnknownColumnError(columnName); + } + return (/** @type {?} */ (columnDef)); + })); + /** @type {?} */ + const stickyStartStates = columnDefs.map((/** + * @param {?} columnDef + * @return {?} + */ + columnDef => columnDef.sticky)); + /** @type {?} */ + const stickyEndStates = columnDefs.map((/** + * @param {?} columnDef + * @return {?} + */ + columnDef => columnDef.stickyEnd)); + this._stickyStyler.updateStickyColumns(rows, stickyStartStates, stickyEndStates); + } + /** + * Gets the list of rows that have been rendered in the row outlet. + * @param {?} rowOutlet + * @return {?} + */ + _getRenderedRows(rowOutlet) { + /** @type {?} */ + const renderedRows = []; + for (let i = 0; i < rowOutlet.viewContainer.length; i++) { + /** @type {?} */ + const viewRef = ((/** @type {?} */ ((/** @type {?} */ (rowOutlet.viewContainer.get(i)))))); + renderedRows.push(viewRef.rootNodes[0]); + } + return renderedRows; + } + /** + * Get the matching row definitions that should be used for this row data. If there is only + * one row definition, it is returned. Otherwise, find the row definitions that has a when + * predicate that returns true with the data. If none return true, return the default row + * definition. + * @param {?} data + * @param {?} dataIndex + * @return {?} + */ + _getRowDefs(data, dataIndex) { + if (this._rowDefs.length == 1) { + return [this._rowDefs[0]]; + } + /** @type {?} */ + let rowDefs = []; + if (this.multiTemplateDataRows) { + rowDefs = this._rowDefs.filter((/** + * @param {?} def + * @return {?} + */ + def => !def.when || def.when(dataIndex, data))); + } + else { + /** @type {?} */ + let rowDef = this._rowDefs.find((/** + * @param {?} def + * @return {?} + */ + def => def.when && def.when(dataIndex, data))) || this._defaultRowDef; + if (rowDef) { + rowDefs.push(rowDef); + } + } + if (!rowDefs.length) { + throw getTableMissingMatchingRowDefError(data); + } + return rowDefs; + } + /** + * Create the embedded view for the data row template and place it in the correct index location + * within the data row view container. + * @private + * @param {?} renderRow + * @param {?} renderIndex + * @return {?} + */ + _insertRow(renderRow, renderIndex) { + /** @type {?} */ + const rowDef = renderRow.rowDef; + /** @type {?} */ + const context = { $implicit: renderRow.data }; + this._renderRow(this._rowOutlet, rowDef, renderIndex, context); + } + /** + * Creates a new row template in the outlet and fills it with the set of cell templates. + * Optionally takes a context to provide to the row and cells, as well as an optional index + * of where to place the new row template in the outlet. + * @private + * @param {?} outlet + * @param {?} rowDef + * @param {?} index + * @param {?=} context + * @return {?} + */ + _renderRow(outlet, rowDef, index, context = {}) { + // TODO(andrewseguin): enforce that one outlet was instantiated from createEmbeddedView + outlet.viewContainer.createEmbeddedView(rowDef.template, context, index); + for (let cellTemplate of this._getCellTemplates(rowDef)) { + if (CdkCellOutlet.mostRecentCellOutlet) { + CdkCellOutlet.mostRecentCellOutlet._viewContainer.createEmbeddedView(cellTemplate, context); + } + } + this._changeDetectorRef.markForCheck(); + } + /** + * Updates the index-related context for each row to reflect any changes in the index of the rows, + * e.g. first/last/even/odd. + * @private + * @return {?} + */ + _updateRowIndexContext() { + /** @type {?} */ + const viewContainer = this._rowOutlet.viewContainer; + for (let renderIndex = 0, count = viewContainer.length; renderIndex < count; renderIndex++) { + /** @type {?} */ + const viewRef = (/** @type {?} */ (viewContainer.get(renderIndex))); + /** @type {?} */ + const context = (/** @type {?} */ (viewRef.context)); + context.count = count; + context.first = renderIndex === 0; + context.last = renderIndex === count - 1; + context.even = renderIndex % 2 === 0; + context.odd = !context.even; + if (this.multiTemplateDataRows) { + context.dataIndex = this._renderRows[renderIndex].dataIndex; + context.renderIndex = renderIndex; + } + else { + context.index = this._renderRows[renderIndex].dataIndex; + } + } + } + /** + * Gets the column definitions for the provided row def. + * @private + * @param {?} rowDef + * @return {?} + */ + _getCellTemplates(rowDef) { + if (!rowDef || !rowDef.columns) { + return []; + } + return Array.from(rowDef.columns, (/** + * @param {?} columnId + * @return {?} + */ + columnId => { + /** @type {?} */ + const column = this._columnDefsByName.get(columnId); + if (!column) { + throw getTableUnknownColumnError(columnId); + } + return rowDef.extractCellTemplate(column); + })); + } + /** + * Adds native table sections (e.g. tbody) and moves the row outlets into them. + * @private + * @return {?} + */ + _applyNativeTableSections() { + /** @type {?} */ + const documentFragment = this._document.createDocumentFragment(); + /** @type {?} */ + const sections = [ + { tag: 'thead', outlet: this._headerRowOutlet }, + { tag: 'tbody', outlet: this._rowOutlet }, + { tag: 'tfoot', outlet: this._footerRowOutlet }, + ]; + for (const section of sections) { + /** @type {?} */ + const element = this._document.createElement(section.tag); + element.setAttribute('role', 'rowgroup'); + element.appendChild(section.outlet.elementRef.nativeElement); + documentFragment.appendChild(element); + } + // Use a DocumentFragment so we don't hit the DOM on each iteration. + this._elementRef.nativeElement.appendChild(documentFragment); + } + /** + * Forces a re-render of the data rows. Should be called in cases where there has been an input + * change that affects the evaluation of which rows should be rendered, e.g. toggling + * `multiTemplateDataRows` or adding/removing row definitions. + * @private + * @return {?} + */ + _forceRenderDataRows() { + this._dataDiffer.diff([]); + this._rowOutlet.viewContainer.clear(); + this.renderRows(); + this.updateStickyColumnStyles(); + } + /** + * Checks if there has been a change in sticky states since last check and applies the correct + * sticky styles. Since checking resets the "dirty" state, this should only be performed once + * during a change detection and after the inputs are settled (after content check). + * @private + * @return {?} + */ + _checkStickyStates() { + /** @type {?} */ + const stickyCheckReducer = (/** + * @param {?} acc + * @param {?} d + * @return {?} + */ + (acc, d) => { + return acc || d.hasStickyChanged(); + }); + // Note that the check needs to occur for every definition since it notifies the definition + // that it can reset its dirty state. Using another operator like `some` may short-circuit + // remaining definitions and leave them in an unchecked state. + if (this._headerRowDefs.reduce(stickyCheckReducer, false)) { + this.updateStickyHeaderRowStyles(); + } + if (this._footerRowDefs.reduce(stickyCheckReducer, false)) { + this.updateStickyFooterRowStyles(); + } + if (Array.from(this._columnDefsByName.values()).reduce(stickyCheckReducer, false)) { + this.updateStickyColumnStyles(); + } + } + /** + * Creates the sticky styler that will be used for sticky rows and columns. Listens + * for directionality changes and provides the latest direction to the styler. Re-applies column + * stickiness when directionality changes. + * @private + * @return {?} + */ + _setupStickyStyler() { + /** @type {?} */ + const direction = this._dir ? this._dir.value : 'ltr'; + this._stickyStyler = new StickyStyler(this._isNativeHtmlTable, this.stickyCssClass, direction, this._platform.isBrowser); + (this._dir ? this._dir.change : Object(rxjs__WEBPACK_IMPORTED_MODULE_6__["of"])()) + .pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_7__["takeUntil"])(this._onDestroy)) + .subscribe((/** + * @param {?} value + * @return {?} + */ + value => { + this._stickyStyler.direction = value; + this.updateStickyColumnStyles(); + })); + } +} +CdkTable.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Component"], args: [{selector: 'cdk-table, table[cdk-table]', + exportAs: 'cdkTable', + template: CDK_TABLE_TEMPLATE, + host: { + 'class': 'cdk-table', + }, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewEncapsulation"].None, + // The "OnPush" status for the `MatTable` component is effectively a noop, so we are removing it. + // The view for `MatTable` consists entirely of templates declared in other views. As they are + // declared elsewhere, they are checked when their declaration points are checked. + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectionStrategy"].Default, + },] }, +]; +/** @nocollapse */ +CdkTable.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["IterableDiffers"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectorRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Attribute"], args: ['role',] }] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_2__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [_angular_common__WEBPACK_IMPORTED_MODULE_5__["DOCUMENT"],] }] }, + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_4__["Platform"] } +]; +CdkTable.propDecorators = { + trackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + dataSource: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + multiTemplateDataRows: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + _rowOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [DataRowOutlet, { static: true },] }], + _headerRowOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [HeaderRowOutlet, { static: true },] }], + _footerRowOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [FooterRowOutlet, { static: true },] }], + _contentColumnDefs: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChildren"], args: [CdkColumnDef,] }], + _contentRowDefs: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChildren"], args: [CdkRowDef,] }], + _contentHeaderRowDefs: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChildren"], args: [CdkHeaderRowDef,] }], + _contentFooterRowDefs: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ContentChildren"], args: [CdkFooterRowDef,] }] +}; +/** + * Utility function that gets a merged list of the entries in a QueryList and values of a Set. + * @template T + * @param {?} queryList + * @param {?} set + * @return {?} + */ +function mergeQueryListAndSet(queryList, set) { + return queryList.toArray().concat(Array.from(set)); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Injection token that can be used to specify the text column options. + * @type {?} + */ +const TEXT_COLUMN_OPTIONS = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["InjectionToken"]('text-column-options'); +/** + * Column that simply shows text content for the header and row cells. Assumes that the table + * is using the native table implementation (`
`). + * + * By default, the name of this column will be the header text and data property accessor. + * The header text can be overridden with the `headerText` input. Cell values can be overridden with + * the `dataAccessor` input. Change the text justification to the start or end using the `justify` + * input. + * @template T + */ +class CdkTextColumn { + /** + * @param {?} _table + * @param {?} _options + */ + constructor(_table, _options) { + this._table = _table; + this._options = _options; + /** + * Alignment of the cell values. + */ + this.justify = 'start'; + this._options = _options || {}; + } + /** + * Column name that should be used to reference this column. + * @return {?} + */ + get name() { + return this._name; + } + /** + * @param {?} name + * @return {?} + */ + set name(name) { + this._name = name; + // With Ivy, inputs can be initialized before static query results are + // available. In that case, we defer the synchronization until "ngOnInit" fires. + this._syncColumnDefName(); + } + /** + * @return {?} + */ + ngOnInit() { + this._syncColumnDefName(); + if (this.headerText === undefined) { + this.headerText = this._createDefaultHeaderText(); + } + if (!this.dataAccessor) { + this.dataAccessor = + this._options.defaultDataAccessor || ((/** + * @param {?} data + * @param {?} name + * @return {?} + */ + (data, name) => ((/** @type {?} */ (data)))[name])); + } + if (this._table) { + // Provide the cell and headerCell directly to the table with the static `ViewChild` query, + // since the columnDef will not pick up its content by the time the table finishes checking + // its content and initializing the rows. + this.columnDef.cell = this.cell; + this.columnDef.headerCell = this.headerCell; + this._table.addColumnDef(this.columnDef); + } + else { + throw getTableTextColumnMissingParentTableError(); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._table) { + this._table.removeColumnDef(this.columnDef); + } + } + /** + * Creates a default header text. Use the options' header text transformation function if one + * has been provided. Otherwise simply capitalize the column name. + * @return {?} + */ + _createDefaultHeaderText() { + /** @type {?} */ + const name = this.name; + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["isDevMode"])() && !name) { + throw getTableTextColumnMissingNameError(); + } + if (this._options && this._options.defaultHeaderTextTransform) { + return this._options.defaultHeaderTextTransform(name); + } + return name[0].toUpperCase() + name.slice(1); + } + /** + * Synchronizes the column definition name with the text column name. + * @private + * @return {?} + */ + _syncColumnDefName() { + if (this.columnDef) { + this.columnDef.name = this.name; + } + } +} +CdkTextColumn.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Component"], args: [{selector: 'cdk-text-column', + template: ` + + + + + `, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewEncapsulation"].None, + // Change detection is intentionally not set to OnPush. This component's template will be provided + // to the table to be inserted into its view. This is problematic when change detection runs since + // the bindings in this template will be evaluated _after_ the table's view is evaluated, which + // mean's the template in the table's view will not have the updated value (and in fact will cause + // an ExpressionChangedAfterItHasBeenCheckedError). + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ChangeDetectionStrategy"].Default, + },] }, +]; +/** @nocollapse */ +CdkTextColumn.ctorParameters = () => [ + { type: CdkTable, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Inject"], args: [TEXT_COLUMN_OPTIONS,] }] } +]; +CdkTextColumn.propDecorators = { + name: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + headerText: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + dataAccessor: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + justify: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"] }], + columnDef: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [CdkColumnDef, { static: true },] }], + cell: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [CdkCellDef, { static: true },] }], + headerCell: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ViewChild"], args: [CdkHeaderCellDef, { static: true },] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const EXPORTED_DECLARATIONS = [ + CdkTable, + CdkRowDef, + CdkCellDef, + CdkCellOutlet, + CdkHeaderCellDef, + CdkFooterCellDef, + CdkColumnDef, + CdkCell, + CdkRow, + CdkHeaderCell, + CdkFooterCell, + CdkHeaderRow, + CdkHeaderRowDef, + CdkFooterRow, + CdkFooterRowDef, + DataRowOutlet, + HeaderRowOutlet, + FooterRowOutlet, + CdkTextColumn, +]; +class CdkTableModule { +} +CdkTableModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + imports: [_angular_common__WEBPACK_IMPORTED_MODULE_5__["CommonModule"]], + exports: EXPORTED_DECLARATIONS, + declarations: EXPORTED_DECLARATIONS + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=table.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/text-field.js": +/*!*********************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/text-field.js ***! + \*********************************************************/ +/*! exports provided: AutofillMonitor, CdkAutofill, CdkTextareaAutosize, TextFieldModule */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AutofillMonitor", function() { return AutofillMonitor; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkAutofill", function() { return CdkAutofill; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTextareaAutosize", function() { return CdkTextareaAutosize; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextFieldModule", function() { return TextFieldModule; }); +/* harmony import */ var _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/platform */ "./node_modules/@angular/cdk/esm2015/platform.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Options to pass to the animationstart listener. + * @type {?} + */ +const listenerOptions = Object(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__["normalizePassiveListenerOptions"])({ passive: true }); +/** + * An injectable service that can be used to monitor the autofill state of an input. + * Based on the following blog post: + * https://medium.com/\@brunn/detecting-autofilled-fields-in-javascript-aed598d25da7 + */ +class AutofillMonitor { + /** + * @param {?} _platform + * @param {?} _ngZone + */ + constructor(_platform, _ngZone) { + this._platform = _platform; + this._ngZone = _ngZone; + this._monitoredElements = new Map(); + } + /** + * @param {?} elementOrRef + * @return {?} + */ + monitor(elementOrRef) { + if (!this._platform.isBrowser) { + return rxjs__WEBPACK_IMPORTED_MODULE_3__["EMPTY"]; + } + /** @type {?} */ + const element = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_2__["coerceElement"])(elementOrRef); + /** @type {?} */ + const info = this._monitoredElements.get(element); + if (info) { + return info.subject.asObservable(); + } + /** @type {?} */ + const result = new rxjs__WEBPACK_IMPORTED_MODULE_3__["Subject"](); + /** @type {?} */ + const cssClass = 'cdk-text-field-autofilled'; + /** @type {?} */ + const listener = (/** @type {?} */ (((/** + * @param {?} event + * @return {?} + */ + (event) => { + // Animation events fire on initial element render, we check for the presence of the autofill + // CSS class to make sure this is a real change in state, not just the initial render before + // we fire off events. + if (event.animationName === 'cdk-text-field-autofill-start' && + !element.classList.contains(cssClass)) { + element.classList.add(cssClass); + this._ngZone.run((/** + * @return {?} + */ + () => result.next({ target: (/** @type {?} */ (event.target)), isAutofilled: true }))); + } + else if (event.animationName === 'cdk-text-field-autofill-end' && + element.classList.contains(cssClass)) { + element.classList.remove(cssClass); + this._ngZone.run((/** + * @return {?} + */ + () => result.next({ target: (/** @type {?} */ (event.target)), isAutofilled: false }))); + } + })))); + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + element.addEventListener('animationstart', listener, listenerOptions); + element.classList.add('cdk-text-field-autofill-monitored'); + })); + this._monitoredElements.set(element, { + subject: result, + unlisten: (/** + * @return {?} + */ + () => { + element.removeEventListener('animationstart', listener, listenerOptions); + }) + }); + return result.asObservable(); + } + /** + * @param {?} elementOrRef + * @return {?} + */ + stopMonitoring(elementOrRef) { + /** @type {?} */ + const element = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_2__["coerceElement"])(elementOrRef); + /** @type {?} */ + const info = this._monitoredElements.get(element); + if (info) { + info.unlisten(); + info.subject.complete(); + element.classList.remove('cdk-text-field-autofill-monitored'); + element.classList.remove('cdk-text-field-autofilled'); + this._monitoredElements.delete(element); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._monitoredElements.forEach((/** + * @param {?} _info + * @param {?} element + * @return {?} + */ + (_info, element) => this.stopMonitoring(element))); + } +} +AutofillMonitor.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Injectable"], args: [{ providedIn: 'root' },] }, +]; +/** @nocollapse */ +AutofillMonitor.ctorParameters = () => [ + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__["Platform"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] } +]; +/** @nocollapse */ AutofillMonitor.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵdefineInjectable"])({ factory: function AutofillMonitor_Factory() { return new AutofillMonitor(Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__["Platform"]), Object(_angular_core__WEBPACK_IMPORTED_MODULE_1__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"])); }, token: AutofillMonitor, providedIn: "root" }); +/** + * A directive that can be used to monitor the autofill state of an input. + */ +class CdkAutofill { + /** + * @param {?} _elementRef + * @param {?} _autofillMonitor + */ + constructor(_elementRef, _autofillMonitor) { + this._elementRef = _elementRef; + this._autofillMonitor = _autofillMonitor; + /** + * Emits when the autofill state of the element changes. + */ + this.cdkAutofill = new _angular_core__WEBPACK_IMPORTED_MODULE_1__["EventEmitter"](); + } + /** + * @return {?} + */ + ngOnInit() { + this._autofillMonitor + .monitor(this._elementRef) + .subscribe((/** + * @param {?} event + * @return {?} + */ + event => this.cdkAutofill.emit(event))); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._autofillMonitor.stopMonitoring(this._elementRef); + } +} +CdkAutofill.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: '[cdkAutofill]', + },] }, +]; +/** @nocollapse */ +CdkAutofill.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: AutofillMonitor } +]; +CdkAutofill.propDecorators = { + cdkAutofill: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Output"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Directive to automatically resize a textarea to fit its content. + */ +class CdkTextareaAutosize { + /** + * @param {?} _elementRef + * @param {?} _platform + * @param {?} _ngZone + */ + constructor(_elementRef, _platform, _ngZone) { + this._elementRef = _elementRef; + this._platform = _platform; + this._ngZone = _ngZone; + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_3__["Subject"](); + this._enabled = true; + /** + * Value of minRows as of last resize. If the minRows has decreased, the + * height of the textarea needs to be recomputed to reflect the new minimum. The maxHeight + * does not have the same problem because it does not affect the textarea's scrollHeight. + */ + this._previousMinRows = -1; + this._textareaElement = (/** @type {?} */ (this._elementRef.nativeElement)); + } + /** + * Minimum amount of rows in the textarea. + * @return {?} + */ + get minRows() { return this._minRows; } + /** + * @param {?} value + * @return {?} + */ + set minRows(value) { + this._minRows = value; + this._setMinHeight(); + } + /** + * Maximum amount of rows in the textarea. + * @return {?} + */ + get maxRows() { return this._maxRows; } + /** + * @param {?} value + * @return {?} + */ + set maxRows(value) { + this._maxRows = value; + this._setMaxHeight(); + } + /** + * Whether autosizing is enabled or not + * @return {?} + */ + get enabled() { return this._enabled; } + /** + * @param {?} value + * @return {?} + */ + set enabled(value) { + value = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_2__["coerceBooleanProperty"])(value); + // Only act if the actual value changed. This specifically helps to not run + // resizeToFitContent too early (i.e. before ngAfterViewInit) + if (this._enabled !== value) { + (this._enabled = value) ? this.resizeToFitContent(true) : this.reset(); + } + } + /** + * Sets the minimum height of the textarea as determined by minRows. + * @return {?} + */ + _setMinHeight() { + /** @type {?} */ + const minHeight = this.minRows && this._cachedLineHeight ? + `${this.minRows * this._cachedLineHeight}px` : null; + if (minHeight) { + this._textareaElement.style.minHeight = minHeight; + } + } + /** + * Sets the maximum height of the textarea as determined by maxRows. + * @return {?} + */ + _setMaxHeight() { + /** @type {?} */ + const maxHeight = this.maxRows && this._cachedLineHeight ? + `${this.maxRows * this._cachedLineHeight}px` : null; + if (maxHeight) { + this._textareaElement.style.maxHeight = maxHeight; + } + } + /** + * @return {?} + */ + ngAfterViewInit() { + if (this._platform.isBrowser) { + // Remember the height which we started with in case autosizing is disabled + this._initialHeight = this._textareaElement.style.height; + this.resizeToFitContent(); + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + Object(rxjs__WEBPACK_IMPORTED_MODULE_3__["fromEvent"])(window, 'resize') + .pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_4__["auditTime"])(16), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_4__["takeUntil"])(this._destroyed)) + .subscribe((/** + * @return {?} + */ + () => this.resizeToFitContent(true))); + })); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._destroyed.next(); + this._destroyed.complete(); + } + /** + * Cache the height of a single-row textarea if it has not already been cached. + * + * We need to know how large a single "row" of a textarea is in order to apply minRows and + * maxRows. For the initial version, we will assume that the height of a single line in the + * textarea does not ever change. + * @private + * @return {?} + */ + _cacheTextareaLineHeight() { + if (this._cachedLineHeight) { + return; + } + // Use a clone element because we have to override some styles. + /** @type {?} */ + let textareaClone = (/** @type {?} */ (this._textareaElement.cloneNode(false))); + textareaClone.rows = 1; + // Use `position: absolute` so that this doesn't cause a browser layout and use + // `visibility: hidden` so that nothing is rendered. Clear any other styles that + // would affect the height. + textareaClone.style.position = 'absolute'; + textareaClone.style.visibility = 'hidden'; + textareaClone.style.border = 'none'; + textareaClone.style.padding = '0'; + textareaClone.style.height = ''; + textareaClone.style.minHeight = ''; + textareaClone.style.maxHeight = ''; + // In Firefox it happens that textarea elements are always bigger than the specified amount + // of rows. This is because Firefox tries to add extra space for the horizontal scrollbar. + // As a workaround that removes the extra space for the scrollbar, we can just set overflow + // to hidden. This ensures that there is no invalid calculation of the line height. + // See Firefox bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=33654 + textareaClone.style.overflow = 'hidden'; + (/** @type {?} */ (this._textareaElement.parentNode)).appendChild(textareaClone); + this._cachedLineHeight = textareaClone.clientHeight; + (/** @type {?} */ (this._textareaElement.parentNode)).removeChild(textareaClone); + // Min and max heights have to be re-calculated if the cached line height changes + this._setMinHeight(); + this._setMaxHeight(); + } + /** + * @return {?} + */ + ngDoCheck() { + if (this._platform.isBrowser) { + this.resizeToFitContent(); + } + } + /** + * Resize the textarea to fit its content. + * @param {?=} force Whether to force a height recalculation. By default the height will be + * recalculated only if the value changed since the last call. + * @return {?} + */ + resizeToFitContent(force = false) { + // If autosizing is disabled, just skip everything else + if (!this._enabled) { + return; + } + this._cacheTextareaLineHeight(); + // If we haven't determined the line-height yet, we know we're still hidden and there's no point + // in checking the height of the textarea. + if (!this._cachedLineHeight) { + return; + } + /** @type {?} */ + const textarea = (/** @type {?} */ (this._elementRef.nativeElement)); + /** @type {?} */ + const value = textarea.value; + // Only resize if the value or minRows have changed since these calculations can be expensive. + if (!force && this._minRows === this._previousMinRows && value === this._previousValue) { + return; + } + /** @type {?} */ + const placeholderText = textarea.placeholder; + // Reset the textarea height to auto in order to shrink back to its default size. + // Also temporarily force overflow:hidden, so scroll bars do not interfere with calculations. + // Long placeholders that are wider than the textarea width may lead to a bigger scrollHeight + // value. To ensure that the scrollHeight is not bigger than the content, the placeholders + // need to be removed temporarily. + textarea.classList.add('cdk-textarea-autosize-measuring'); + textarea.placeholder = ''; + // The cdk-textarea-autosize-measuring class includes a 2px padding to workaround an issue with + // Chrome, so we account for that extra space here by subtracting 4 (2px top + 2px bottom). + /** @type {?} */ + const height = textarea.scrollHeight - 4; + // Use the scrollHeight to know how large the textarea *would* be if fit its entire value. + textarea.style.height = `${height}px`; + textarea.classList.remove('cdk-textarea-autosize-measuring'); + textarea.placeholder = placeholderText; + this._ngZone.runOutsideAngular((/** + * @return {?} + */ + () => { + if (typeof requestAnimationFrame !== 'undefined') { + requestAnimationFrame((/** + * @return {?} + */ + () => this._scrollToCaretPosition(textarea))); + } + else { + setTimeout((/** + * @return {?} + */ + () => this._scrollToCaretPosition(textarea))); + } + })); + this._previousValue = value; + this._previousMinRows = this._minRows; + } + /** + * Resets the textarea to it's original size + * @return {?} + */ + reset() { + // Do not try to change the textarea, if the initialHeight has not been determined yet + // This might potentially remove styles when reset() is called before ngAfterViewInit + if (this._initialHeight === undefined) { + return; + } + this._textareaElement.style.height = this._initialHeight; + } + /** + * @return {?} + */ + _noopInputHandler() { + // no-op handler that ensures we're running change detection on input events. + } + /** + * Scrolls a textarea to the caret position. On Firefox resizing the textarea will + * prevent it from scrolling to the caret position. We need to re-set the selection + * in order for it to scroll to the proper position. + * @private + * @param {?} textarea + * @return {?} + */ + _scrollToCaretPosition(textarea) { + const { selectionStart, selectionEnd } = textarea; + // IE will throw an "Unspecified error" if we try to set the selection range after the + // element has been removed from the DOM. Assert that the directive hasn't been destroyed + // between the time we requested the animation frame and when it was executed. + // Also note that we have to assert that the textarea is focused before we set the + // selection range. Setting the selection range on a non-focused textarea will cause + // it to receive focus on IE and Edge. + if (!this._destroyed.isStopped && document.activeElement === textarea) { + textarea.setSelectionRange(selectionStart, selectionEnd); + } + } +} +CdkTextareaAutosize.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Directive"], args: [{ + selector: 'textarea[cdkTextareaAutosize]', + exportAs: 'cdkTextareaAutosize', + host: { + 'class': 'cdk-textarea-autosize', + // Textarea elements that have the directive applied should have a single row by default. + // Browsers normally show two rows by default and therefore this limits the minRows binding. + 'rows': '1', + '(input)': '_noopInputHandler()', + }, + },] }, +]; +/** @nocollapse */ +CdkTextareaAutosize.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["ElementRef"] }, + { type: _angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__["Platform"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgZone"] } +]; +CdkTextareaAutosize.propDecorators = { + minRows: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkAutosizeMinRows',] }], + maxRows: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkAutosizeMaxRows',] }], + enabled: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["Input"], args: ['cdkTextareaAutosize',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class TextFieldModule { +} +TextFieldModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_1__["NgModule"], args: [{ + declarations: [CdkAutofill, CdkTextareaAutosize], + imports: [_angular_cdk_platform__WEBPACK_IMPORTED_MODULE_0__["PlatformModule"]], + exports: [CdkAutofill, CdkTextareaAutosize], + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=text-field.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/cdk/esm2015/tree.js": +/*!***************************************************!*\ + !*** ./node_modules/@angular/cdk/esm2015/tree.js ***! + \***************************************************/ +/*! exports provided: BaseTreeControl, FlatTreeControl, NestedTreeControl, CdkNestedTreeNode, CdkTreeNodeOutletContext, CdkTreeNodeDef, CdkTreeNodePadding, CDK_TREE_NODE_OUTLET_NODE, CdkTreeNodeOutlet, CdkTree, CdkTreeNode, getTreeNoValidDataSourceError, getTreeMultipleDefaultNodeDefsError, getTreeMissingMatchingNodeDefError, getTreeControlMissingError, getTreeControlFunctionsMissingError, CdkTreeModule, CdkTreeNodeToggle */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseTreeControl", function() { return BaseTreeControl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FlatTreeControl", function() { return FlatTreeControl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NestedTreeControl", function() { return NestedTreeControl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkNestedTreeNode", function() { return CdkNestedTreeNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNodeOutletContext", function() { return CdkTreeNodeOutletContext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNodeDef", function() { return CdkTreeNodeDef; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNodePadding", function() { return CdkTreeNodePadding; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CDK_TREE_NODE_OUTLET_NODE", function() { return CDK_TREE_NODE_OUTLET_NODE; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNodeOutlet", function() { return CdkTreeNodeOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTree", function() { return CdkTree; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNode", function() { return CdkTreeNode; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTreeNoValidDataSourceError", function() { return getTreeNoValidDataSourceError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTreeMultipleDefaultNodeDefsError", function() { return getTreeMultipleDefaultNodeDefsError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTreeMissingMatchingNodeDefError", function() { return getTreeMissingMatchingNodeDefError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTreeControlMissingError", function() { return getTreeControlMissingError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTreeControlFunctionsMissingError", function() { return getTreeControlFunctionsMissingError; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeModule", function() { return CdkTreeModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CdkTreeNodeToggle", function() { return CdkTreeNodeToggle; }); +/* harmony import */ var _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/cdk/collections */ "./node_modules/@angular/cdk/esm2015/collections.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/cdk/bidi */ "./node_modules/@angular/cdk/esm2015/bidi.js"); +/* harmony import */ var _angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/cdk/coercion */ "./node_modules/@angular/cdk/esm2015/coercion.js"); +/* harmony import */ var _angular_cdk_a11y__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/cdk/a11y */ "./node_modules/@angular/cdk/esm2015/a11y.js"); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Base tree control. It has basic toggle/expand/collapse operations on a single data node. + * @abstract + * @template T + */ +class BaseTreeControl { + constructor() { + /** + * A selection model with multi-selection to track expansion status. + */ + this.expansionModel = new _angular_cdk_collections__WEBPACK_IMPORTED_MODULE_0__["SelectionModel"](true); + } + /** + * Toggles one single data node's expanded/collapsed state. + * @param {?} dataNode + * @return {?} + */ + toggle(dataNode) { + this.expansionModel.toggle(dataNode); + } + /** + * Expands one single data node. + * @param {?} dataNode + * @return {?} + */ + expand(dataNode) { + this.expansionModel.select(dataNode); + } + /** + * Collapses one single data node. + * @param {?} dataNode + * @return {?} + */ + collapse(dataNode) { + this.expansionModel.deselect(dataNode); + } + /** + * Whether a given data node is expanded or not. Returns true if the data node is expanded. + * @param {?} dataNode + * @return {?} + */ + isExpanded(dataNode) { + return this.expansionModel.isSelected(dataNode); + } + /** + * Toggles a subtree rooted at `node` recursively. + * @param {?} dataNode + * @return {?} + */ + toggleDescendants(dataNode) { + this.expansionModel.isSelected(dataNode) + ? this.collapseDescendants(dataNode) + : this.expandDescendants(dataNode); + } + /** + * Collapse all dataNodes in the tree. + * @return {?} + */ + collapseAll() { + this.expansionModel.clear(); + } + /** + * Expands a subtree rooted at given data node recursively. + * @param {?} dataNode + * @return {?} + */ + expandDescendants(dataNode) { + /** @type {?} */ + let toBeProcessed = [dataNode]; + toBeProcessed.push(...this.getDescendants(dataNode)); + this.expansionModel.select(...toBeProcessed); + } + /** + * Collapses a subtree rooted at given data node recursively. + * @param {?} dataNode + * @return {?} + */ + collapseDescendants(dataNode) { + /** @type {?} */ + let toBeProcessed = [dataNode]; + toBeProcessed.push(...this.getDescendants(dataNode)); + this.expansionModel.deselect(...toBeProcessed); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Flat tree control. Able to expand/collapse a subtree recursively for flattened tree. + * @template T + */ +class FlatTreeControl extends BaseTreeControl { + /** + * Construct with flat tree data node functions getLevel and isExpandable. + * @param {?} getLevel + * @param {?} isExpandable + */ + constructor(getLevel, isExpandable) { + super(); + this.getLevel = getLevel; + this.isExpandable = isExpandable; + } + /** + * Gets a list of the data node's subtree of descendent data nodes. + * + * To make this working, the `dataNodes` of the TreeControl must be flattened tree nodes + * with correct levels. + * @param {?} dataNode + * @return {?} + */ + getDescendants(dataNode) { + /** @type {?} */ + const startIndex = this.dataNodes.indexOf(dataNode); + /** @type {?} */ + const results = []; + // Goes through flattened tree nodes in the `dataNodes` array, and get all descendants. + // The level of descendants of a tree node must be greater than the level of the given + // tree node. + // If we reach a node whose level is equal to the level of the tree node, we hit a sibling. + // If we reach a node whose level is greater than the level of the tree node, we hit a + // sibling of an ancestor. + for (let i = startIndex + 1; i < this.dataNodes.length && this.getLevel(dataNode) < this.getLevel(this.dataNodes[i]); i++) { + results.push(this.dataNodes[i]); + } + return results; + } + /** + * Expands all data nodes in the tree. + * + * To make this working, the `dataNodes` variable of the TreeControl must be set to all flattened + * data nodes of the tree. + * @return {?} + */ + expandAll() { + this.expansionModel.select(...this.dataNodes); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Nested tree control. Able to expand/collapse a subtree recursively for NestedNode type. + * @template T + */ +class NestedTreeControl extends BaseTreeControl { + /** + * Construct with nested tree function getChildren. + * @param {?} getChildren + */ + constructor(getChildren) { + super(); + this.getChildren = getChildren; + } + /** + * Expands all dataNodes in the tree. + * + * To make this working, the `dataNodes` variable of the TreeControl must be set to all root level + * data nodes of the tree. + * @return {?} + */ + expandAll() { + this.expansionModel.clear(); + /** @type {?} */ + const allNodes = this.dataNodes.reduce((/** + * @param {?} accumulator + * @param {?} dataNode + * @return {?} + */ + (accumulator, dataNode) => [...accumulator, ...this.getDescendants(dataNode), dataNode]), []); + this.expansionModel.select(...allNodes); + } + /** + * Gets a list of descendant dataNodes of a subtree rooted at given data node recursively. + * @param {?} dataNode + * @return {?} + */ + getDescendants(dataNode) { + /** @type {?} */ + const descendants = []; + this._getDescendants(descendants, dataNode); + // Remove the node itself + return descendants.splice(1); + } + /** + * A helper function to get descendants recursively. + * @protected + * @param {?} descendants + * @param {?} dataNode + * @return {?} + */ + _getDescendants(descendants, dataNode) { + descendants.push(dataNode); + /** @type {?} */ + const childrenNodes = this.getChildren(dataNode); + if (Array.isArray(childrenNodes)) { + childrenNodes.forEach((/** + * @param {?} child + * @return {?} + */ + (child) => this._getDescendants(descendants, child))); + } + else if (childrenNodes instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__["Observable"]) { + // TypeScript as of version 3.5 doesn't seem to treat `Boolean` like a function that + // returns a `boolean` specifically in the context of `filter`, so we manually clarify that. + childrenNodes.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["take"])(1), Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["filter"])((/** @type {?} */ (Boolean)))) + .subscribe((/** + * @param {?} children + * @return {?} + */ + children => { + for (const child of children) { + this._getDescendants(descendants, child); + } + })); + } + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Injection token used to provide a `CdkTreeNode` to its outlet. + * Used primarily to avoid circular imports. + * \@docs-private + * @type {?} + */ +const CDK_TREE_NODE_OUTLET_NODE = new _angular_core__WEBPACK_IMPORTED_MODULE_3__["InjectionToken"]('CDK_TREE_NODE_OUTLET_NODE'); +/** + * Outlet for nested CdkNode. Put `[cdkTreeNodeOutlet]` on a tag to place children dataNodes + * inside the outlet. + */ +class CdkTreeNodeOutlet { + /** + * @param {?} viewContainer + * @param {?=} _node + */ + constructor(viewContainer, _node) { + this.viewContainer = viewContainer; + this._node = _node; + } +} +CdkTreeNodeOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: '[cdkTreeNodeOutlet]' + },] }, +]; +/** @nocollapse */ +CdkTreeNodeOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ViewContainerRef"] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Inject"], args: [CDK_TREE_NODE_OUTLET_NODE,] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Context provided to the tree node component. + * @template T + */ +class CdkTreeNodeOutletContext { + /** + * @param {?} data + */ + constructor(data) { + this.$implicit = data; + } +} +/** + * Data node definition for the CdkTree. + * Captures the node's template and a when predicate that describes when this node should be used. + * @template T + */ +class CdkTreeNodeDef { + /** + * \@docs-private + * @param {?} template + */ + constructor(template) { + this.template = template; + } +} +CdkTreeNodeDef.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: '[cdkTreeNodeDef]', + inputs: [ + 'when: cdkTreeNodeDefWhen' + ], + },] }, +]; +/** @nocollapse */ +CdkTreeNodeDef.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["TemplateRef"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Returns an error to be thrown when there is no usable data. + * \@docs-private + * @return {?} + */ +function getTreeNoValidDataSourceError() { + return Error(`A valid data source must be provided.`); +} +/** + * Returns an error to be thrown when there are multiple nodes that are missing a when function. + * \@docs-private + * @return {?} + */ +function getTreeMultipleDefaultNodeDefsError() { + return Error(`There can only be one default row without a when predicate function.`); +} +/** + * Returns an error to be thrown when there are no matching node defs for a particular set of data. + * \@docs-private + * @return {?} + */ +function getTreeMissingMatchingNodeDefError() { + return Error(`Could not find a matching node definition for the provided node data.`); +} +/** + * Returns an error to be thrown when there are tree control. + * \@docs-private + * @return {?} + */ +function getTreeControlMissingError() { + return Error(`Could not find a tree control for the tree.`); +} +/** + * Returns an error to be thrown when tree control did not implement functions for flat/nested node. + * \@docs-private + * @return {?} + */ +function getTreeControlFunctionsMissingError() { + return Error(`Could not find functions for nested/flat tree in tree control.`); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * CDK tree component that connects with a data source to retrieve data of type `T` and renders + * dataNodes with hierarchy. Updates the dataNodes when new data is provided by the data source. + * @template T + */ +class CdkTree { + /** + * @param {?} _differs + * @param {?} _changeDetectorRef + */ + constructor(_differs, _changeDetectorRef) { + this._differs = _differs; + this._changeDetectorRef = _changeDetectorRef; + /** + * Subject that emits when the component has been destroyed. + */ + this._onDestroy = new rxjs__WEBPACK_IMPORTED_MODULE_1__["Subject"](); + /** + * Level of nodes + */ + this._levels = new Map(); + // TODO(tinayuangao): Setup a listener for scrolling, emit the calculated view to viewChange. + // Remove the MAX_VALUE in viewChange + /** + * Stream containing the latest information on what rows are being displayed on screen. + * Can be used by the data source to as a heuristic of what data should be provided. + */ + this.viewChange = new rxjs__WEBPACK_IMPORTED_MODULE_1__["BehaviorSubject"]({ start: 0, end: Number.MAX_VALUE }); + } + /** + * Provides a stream containing the latest data array to render. Influenced by the tree's + * stream of view window (what dataNodes are currently on screen). + * Data source can be an observable of data array, or a data array to render. + * @return {?} + */ + get dataSource() { return this._dataSource; } + /** + * @param {?} dataSource + * @return {?} + */ + set dataSource(dataSource) { + if (this._dataSource !== dataSource) { + this._switchDataSource(dataSource); + } + } + /** + * @return {?} + */ + ngOnInit() { + this._dataDiffer = this._differs.find([]).create(this.trackBy); + if (!this.treeControl) { + throw getTreeControlMissingError(); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + this._nodeOutlet.viewContainer.clear(); + this._onDestroy.next(); + this._onDestroy.complete(); + if (this._dataSource && typeof ((/** @type {?} */ (this._dataSource))).disconnect === 'function') { + ((/** @type {?} */ (this.dataSource))).disconnect(this); + } + if (this._dataSubscription) { + this._dataSubscription.unsubscribe(); + this._dataSubscription = null; + } + } + /** + * @return {?} + */ + ngAfterContentChecked() { + /** @type {?} */ + const defaultNodeDefs = this._nodeDefs.filter((/** + * @param {?} def + * @return {?} + */ + def => !def.when)); + if (defaultNodeDefs.length > 1) { + throw getTreeMultipleDefaultNodeDefsError(); + } + this._defaultNodeDef = defaultNodeDefs[0]; + if (this.dataSource && this._nodeDefs && !this._dataSubscription) { + this._observeRenderChanges(); + } + } + // TODO(tinayuangao): Work on keyboard traversal and actions, make sure it's working for RTL + // and nested trees. + /** + * Switch to the provided data source by resetting the data and unsubscribing from the current + * render change subscription if one exists. If the data source is null, interpret this by + * clearing the node outlet. Otherwise start listening for new data. + * @private + * @param {?} dataSource + * @return {?} + */ + _switchDataSource(dataSource) { + if (this._dataSource && typeof ((/** @type {?} */ (this._dataSource))).disconnect === 'function') { + ((/** @type {?} */ (this.dataSource))).disconnect(this); + } + if (this._dataSubscription) { + this._dataSubscription.unsubscribe(); + this._dataSubscription = null; + } + // Remove the all dataNodes if there is now no data source + if (!dataSource) { + this._nodeOutlet.viewContainer.clear(); + } + this._dataSource = dataSource; + if (this._nodeDefs) { + this._observeRenderChanges(); + } + } + /** + * Set up a subscription for the data provided by the data source. + * @private + * @return {?} + */ + _observeRenderChanges() { + /** @type {?} */ + let dataStream; + if (Object(_angular_cdk_collections__WEBPACK_IMPORTED_MODULE_0__["isDataSource"])(this._dataSource)) { + dataStream = this._dataSource.connect(this); + } + else if (this._dataSource instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__["Observable"]) { + dataStream = this._dataSource; + } + else if (Array.isArray(this._dataSource)) { + dataStream = Object(rxjs__WEBPACK_IMPORTED_MODULE_1__["of"])(this._dataSource); + } + if (dataStream) { + this._dataSubscription = dataStream.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["takeUntil"])(this._onDestroy)) + .subscribe((/** + * @param {?} data + * @return {?} + */ + data => this.renderNodeChanges(data))); + } + else { + throw getTreeNoValidDataSourceError(); + } + } + /** + * Check for changes made in the data and render each change (node added/removed/moved). + * @param {?} data + * @param {?=} dataDiffer + * @param {?=} viewContainer + * @param {?=} parentData + * @return {?} + */ + renderNodeChanges(data, dataDiffer = this._dataDiffer, viewContainer = this._nodeOutlet.viewContainer, parentData) { + /** @type {?} */ + const changes = dataDiffer.diff(data); + if (!changes) { + return; + } + changes.forEachOperation((/** + * @param {?} item + * @param {?} adjustedPreviousIndex + * @param {?} currentIndex + * @return {?} + */ + (item, adjustedPreviousIndex, currentIndex) => { + if (item.previousIndex == null) { + this.insertNode(data[(/** @type {?} */ (currentIndex))], (/** @type {?} */ (currentIndex)), viewContainer, parentData); + } + else if (currentIndex == null) { + viewContainer.remove((/** @type {?} */ (adjustedPreviousIndex))); + this._levels.delete(item.item); + } + else { + /** @type {?} */ + const view = viewContainer.get((/** @type {?} */ (adjustedPreviousIndex))); + viewContainer.move((/** @type {?} */ (view)), currentIndex); + } + })); + this._changeDetectorRef.detectChanges(); + } + /** + * Finds the matching node definition that should be used for this node data. If there is only + * one node definition, it is returned. Otherwise, find the node definition that has a when + * predicate that returns true with the data. If none return true, return the default node + * definition. + * @param {?} data + * @param {?} i + * @return {?} + */ + _getNodeDef(data, i) { + if (this._nodeDefs.length === 1) { + return this._nodeDefs.first; + } + /** @type {?} */ + const nodeDef = this._nodeDefs.find((/** + * @param {?} def + * @return {?} + */ + def => def.when && def.when(i, data))) || this._defaultNodeDef; + if (!nodeDef) { + throw getTreeMissingMatchingNodeDefError(); + } + return nodeDef; + } + /** + * Create the embedded view for the data node template and place it in the correct index location + * within the data node view container. + * @param {?} nodeData + * @param {?} index + * @param {?=} viewContainer + * @param {?=} parentData + * @return {?} + */ + insertNode(nodeData, index, viewContainer, parentData) { + /** @type {?} */ + const node = this._getNodeDef(nodeData, index); + // Node context that will be provided to created embedded view + /** @type {?} */ + const context = new CdkTreeNodeOutletContext(nodeData); + // If the tree is flat tree, then use the `getLevel` function in flat tree control + // Otherwise, use the level of parent node. + if (this.treeControl.getLevel) { + context.level = this.treeControl.getLevel(nodeData); + } + else if (typeof parentData !== 'undefined' && this._levels.has(parentData)) { + context.level = (/** @type {?} */ (this._levels.get(parentData))) + 1; + } + else { + context.level = 0; + } + this._levels.set(nodeData, context.level); + // Use default tree nodeOutlet, or nested node's nodeOutlet + /** @type {?} */ + const container = viewContainer ? viewContainer : this._nodeOutlet.viewContainer; + container.createEmbeddedView(node.template, context, index); + // Set the data to just created `CdkTreeNode`. + // The `CdkTreeNode` created from `createEmbeddedView` will be saved in static variable + // `mostRecentTreeNode`. We get it from static variable and pass the node data to it. + if (CdkTreeNode.mostRecentTreeNode) { + CdkTreeNode.mostRecentTreeNode.data = nodeData; + } + } +} +CdkTree.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Component"], args: [{selector: 'cdk-tree', + exportAs: 'cdkTree', + template: ``, + host: { + 'class': 'cdk-tree', + 'role': 'tree', + }, + encapsulation: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ViewEncapsulation"].None, + // The "OnPush" status for the `CdkTree` component is effectively a noop, so we are removing it. + // The view for `CdkTree` consists entirely of templates declared in other views. As they are + // declared elsewhere, they are checked when their declaration points are checked. + // tslint:disable-next-line:validate-decorators + changeDetection: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ChangeDetectionStrategy"].Default + },] }, +]; +/** @nocollapse */ +CdkTree.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["IterableDiffers"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ChangeDetectorRef"] } +]; +CdkTree.propDecorators = { + dataSource: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"] }], + treeControl: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"] }], + trackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"] }], + _nodeOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ViewChild"], args: [CdkTreeNodeOutlet, { static: true },] }], + _nodeDefs: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ContentChildren"], args: [CdkTreeNodeDef,] }] +}; +/** + * Tree node for CdkTree. It contains the data in the tree node. + * @template T + */ +class CdkTreeNode { + /** + * @param {?} _elementRef + * @param {?} _tree + */ + constructor(_elementRef, _tree) { + this._elementRef = _elementRef; + this._tree = _tree; + /** + * Subject that emits when the component has been destroyed. + */ + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_1__["Subject"](); + /** + * Emits when the node's data has changed. + */ + this._dataChanges = new rxjs__WEBPACK_IMPORTED_MODULE_1__["Subject"](); + /** + * The role of the node should be 'group' if it's an internal node, + * and 'treeitem' if it's a leaf node. + */ + this.role = 'treeitem'; + CdkTreeNode.mostRecentTreeNode = (/** @type {?} */ (this)); + } + /** + * The tree node's data. + * @return {?} + */ + get data() { return this._data; } + /** + * @param {?} value + * @return {?} + */ + set data(value) { + if (value !== this._data) { + this._data = value; + this._setRoleFromData(); + this._dataChanges.next(); + } + } + /** + * @return {?} + */ + get isExpanded() { + return this._tree.treeControl.isExpanded(this._data); + } + /** + * @return {?} + */ + get level() { + return this._tree.treeControl.getLevel ? this._tree.treeControl.getLevel(this._data) : 0; + } + /** + * @return {?} + */ + ngOnDestroy() { + // If this is the last tree node being destroyed, + // clear out the reference to avoid leaking memory. + if (CdkTreeNode.mostRecentTreeNode === this) { + CdkTreeNode.mostRecentTreeNode = null; + } + this._dataChanges.complete(); + this._destroyed.next(); + this._destroyed.complete(); + } + /** + * Focuses the menu item. Implements for FocusableOption. + * @return {?} + */ + focus() { + this._elementRef.nativeElement.focus(); + } + /** + * @protected + * @return {?} + */ + _setRoleFromData() { + if (this._tree.treeControl.isExpandable) { + this.role = this._tree.treeControl.isExpandable(this._data) ? 'group' : 'treeitem'; + } + else { + if (!this._tree.treeControl.getChildren) { + throw getTreeControlFunctionsMissingError(); + } + /** @type {?} */ + const childrenNodes = this._tree.treeControl.getChildren(this._data); + if (Array.isArray(childrenNodes)) { + this._setRoleFromChildren((/** @type {?} */ (childrenNodes))); + } + else if (childrenNodes instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__["Observable"]) { + childrenNodes.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["takeUntil"])(this._destroyed)) + .subscribe((/** + * @param {?} children + * @return {?} + */ + children => this._setRoleFromChildren(children))); + } + } + } + /** + * @protected + * @param {?} children + * @return {?} + */ + _setRoleFromChildren(children) { + this.role = children && children.length ? 'group' : 'treeitem'; + } +} +/** + * The most recently created `CdkTreeNode`. We save it in static variable so we can retrieve it + * in `CdkTree` and set the data to it. + */ +CdkTreeNode.mostRecentTreeNode = null; +CdkTreeNode.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: 'cdk-tree-node', + exportAs: 'cdkTreeNode', + host: { + '[attr.aria-expanded]': 'isExpanded', + '[attr.aria-level]': 'role === "treeitem" ? level : null', + '[attr.role]': 'role', + 'class': 'cdk-tree-node', + }, + },] }, +]; +/** @nocollapse */ +CdkTreeNode.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ElementRef"] }, + { type: CdkTree } +]; +CdkTreeNode.propDecorators = { + role: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Nested node is a child of ``. It works with nested tree. + * By using `cdk-nested-tree-node` component in tree node template, children of the parent node will + * be added in the `cdkTreeNodeOutlet` in tree node template. + * For example: + * ```html + * + * {{node.name}} + * + * + * ``` + * The children of node will be automatically added to `cdkTreeNodeOutlet`, the result dom will be + * like this: + * ```html + * + * {{node.name}} + * {{child1.name}} + * {{child2.name}} + * + * ``` + * @template T + */ +class CdkNestedTreeNode extends CdkTreeNode { + /** + * @param {?} _elementRef + * @param {?} _tree + * @param {?} _differs + */ + constructor(_elementRef, _tree, _differs) { + super(_elementRef, _tree); + this._elementRef = _elementRef; + this._tree = _tree; + this._differs = _differs; + } + /** + * @return {?} + */ + ngAfterContentInit() { + this._dataDiffer = this._differs.find([]).create(this._tree.trackBy); + if (!this._tree.treeControl.getChildren) { + throw getTreeControlFunctionsMissingError(); + } + /** @type {?} */ + const childrenNodes = this._tree.treeControl.getChildren(this.data); + if (Array.isArray(childrenNodes)) { + this.updateChildrenNodes((/** @type {?} */ (childrenNodes))); + } + else if (childrenNodes instanceof rxjs__WEBPACK_IMPORTED_MODULE_1__["Observable"]) { + childrenNodes.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["takeUntil"])(this._destroyed)) + .subscribe((/** + * @param {?} result + * @return {?} + */ + result => this.updateChildrenNodes(result))); + } + this.nodeOutlet.changes.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["takeUntil"])(this._destroyed)) + .subscribe((/** + * @return {?} + */ + () => this.updateChildrenNodes())); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._clear(); + super.ngOnDestroy(); + } + /** + * Add children dataNodes to the NodeOutlet + * @protected + * @param {?=} children + * @return {?} + */ + updateChildrenNodes(children) { + /** @type {?} */ + const outlet = this._getNodeOutlet(); + if (children) { + this._children = children; + } + if (outlet && this._children) { + /** @type {?} */ + const viewContainer = outlet.viewContainer; + this._tree.renderNodeChanges(this._children, this._dataDiffer, viewContainer, this._data); + } + else { + // Reset the data differ if there's no children nodes displayed + this._dataDiffer.diff([]); + } + } + /** + * Clear the children dataNodes. + * @protected + * @return {?} + */ + _clear() { + /** @type {?} */ + const outlet = this._getNodeOutlet(); + if (outlet) { + outlet.viewContainer.clear(); + this._dataDiffer.diff([]); + } + } + /** + * Gets the outlet for the current node. + * @private + * @return {?} + */ + _getNodeOutlet() { + /** @type {?} */ + const outlets = this.nodeOutlet; + if (outlets) { + // Note that since we use `descendants: true` on the query, we have to ensure + // that we don't pick up the outlet of a child node by accident. + return outlets.find((/** + * @param {?} outlet + * @return {?} + */ + outlet => !outlet._node || outlet._node === this)); + } + } +} +CdkNestedTreeNode.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: 'cdk-nested-tree-node', + exportAs: 'cdkNestedTreeNode', + host: { + '[attr.aria-expanded]': 'isExpanded', + '[attr.role]': 'role', + 'class': 'cdk-tree-node cdk-nested-tree-node', + }, + providers: [ + { provide: CdkTreeNode, useExisting: CdkNestedTreeNode }, + { provide: CDK_TREE_NODE_OUTLET_NODE, useExisting: CdkNestedTreeNode } + ] + },] }, +]; +/** @nocollapse */ +CdkNestedTreeNode.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ElementRef"] }, + { type: CdkTree }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["IterableDiffers"] } +]; +CdkNestedTreeNode.propDecorators = { + nodeOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ContentChildren"], args: [CdkTreeNodeOutlet, { + // We need to use `descendants: true`, because Ivy will no longer match + // indirect descendants if it's left as false. + descendants: true + },] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Regex used to split a string on its CSS units. + * @type {?} + */ +const cssUnitPattern = /([A-Za-z%]+)$/; +/** + * Indent for the children tree dataNodes. + * This directive will add left-padding to the node to show hierarchy. + * @template T + */ +class CdkTreeNodePadding { + /** + * @param {?} _treeNode + * @param {?} _tree + * @param {?} _renderer + * @param {?} _element + * @param {?} _dir + */ + constructor(_treeNode, _tree, _renderer, _element, _dir) { + this._treeNode = _treeNode; + this._tree = _tree; + this._renderer = _renderer; + this._element = _element; + this._dir = _dir; + /** + * Subject that emits when the component has been destroyed. + */ + this._destroyed = new rxjs__WEBPACK_IMPORTED_MODULE_1__["Subject"](); + /** + * CSS units used for the indentation value. + */ + this.indentUnits = 'px'; + this._indent = 40; + this._setPadding(); + if (_dir) { + _dir.change.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["takeUntil"])(this._destroyed)).subscribe((/** + * @return {?} + */ + () => this._setPadding(true))); + } + // In Ivy the indentation binding might be set before the tree node's data has been added, + // which means that we'll miss the first render. We have to subscribe to changes in the + // data to ensure that everything is up to date. + _treeNode._dataChanges.subscribe((/** + * @return {?} + */ + () => this._setPadding())); + } + /** + * The level of depth of the tree node. The padding will be `level * indent` pixels. + * @return {?} + */ + get level() { return this._level; } + /** + * @param {?} value + * @return {?} + */ + set level(value) { + this._level = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_5__["coerceNumberProperty"])(value); + this._setPadding(); + } + /** + * The indent for each level. Can be a number or a CSS string. + * Default number 40px from material design menu sub-menu spec. + * @return {?} + */ + get indent() { return this._indent; } + /** + * @param {?} indent + * @return {?} + */ + set indent(indent) { + /** @type {?} */ + let value = indent; + /** @type {?} */ + let units = 'px'; + if (typeof indent === 'string') { + /** @type {?} */ + const parts = indent.split(cssUnitPattern); + value = parts[0]; + units = parts[1] || units; + } + this.indentUnits = units; + this._indent = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_5__["coerceNumberProperty"])(value); + this._setPadding(); + } + /** + * @return {?} + */ + ngOnDestroy() { + this._destroyed.next(); + this._destroyed.complete(); + } + /** + * The padding indent value for the tree node. Returns a string with px numbers if not null. + * @return {?} + */ + _paddingIndent() { + /** @type {?} */ + const nodeLevel = (this._treeNode.data && this._tree.treeControl.getLevel) + ? this._tree.treeControl.getLevel(this._treeNode.data) + : null; + /** @type {?} */ + const level = this._level || nodeLevel; + return level ? `${level * this._indent}${this.indentUnits}` : null; + } + /** + * @param {?=} forceChange + * @return {?} + */ + _setPadding(forceChange = false) { + /** @type {?} */ + const padding = this._paddingIndent(); + if (padding !== this._currentPadding || forceChange) { + /** @type {?} */ + const element = this._element.nativeElement; + /** @type {?} */ + const paddingProp = this._dir && this._dir.value === 'rtl' ? 'paddingRight' : 'paddingLeft'; + /** @type {?} */ + const resetProp = paddingProp === 'paddingLeft' ? 'paddingRight' : 'paddingLeft'; + this._renderer.setStyle(element, paddingProp, padding); + this._renderer.setStyle(element, resetProp, null); + this._currentPadding = padding; + } + } +} +CdkTreeNodePadding.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ + selector: '[cdkTreeNodePadding]', + },] }, +]; +/** @nocollapse */ +CdkTreeNodePadding.ctorParameters = () => [ + { type: CdkTreeNode }, + { type: CdkTree }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Renderer2"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["ElementRef"] }, + { type: _angular_cdk_bidi__WEBPACK_IMPORTED_MODULE_4__["Directionality"], decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Optional"] }] } +]; +CdkTreeNodePadding.propDecorators = { + level: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkTreeNodePadding',] }], + indent: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkTreeNodePaddingIndent',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Node toggle to expand/collapse the node. + * @template T + */ +class CdkTreeNodeToggle { + /** + * @param {?} _tree + * @param {?} _treeNode + */ + constructor(_tree, _treeNode) { + this._tree = _tree; + this._treeNode = _treeNode; + this._recursive = false; + } + /** + * Whether expand/collapse the node recursively. + * @return {?} + */ + get recursive() { return this._recursive; } + /** + * @param {?} value + * @return {?} + */ + set recursive(value) { this._recursive = Object(_angular_cdk_coercion__WEBPACK_IMPORTED_MODULE_5__["coerceBooleanProperty"])(value); } + // We have to use a `HostListener` here in order to support both Ivy and ViewEngine. + // In Ivy the `host` bindings will be merged when this class is extended, whereas in + // ViewEngine they're overwritten. + // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default. + // tslint:disable-next-line:no-host-decorator-in-concrete + /** + * @param {?} event + * @return {?} + */ + _toggle(event) { + this.recursive + ? this._tree.treeControl.toggleDescendants(this._treeNode.data) + : this._tree.treeControl.toggle(this._treeNode.data); + event.stopPropagation(); + } +} +CdkTreeNodeToggle.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Directive"], args: [{ selector: '[cdkTreeNodeToggle]' },] }, +]; +/** @nocollapse */ +CdkTreeNodeToggle.ctorParameters = () => [ + { type: CdkTree }, + { type: CdkTreeNode } +]; +CdkTreeNodeToggle.propDecorators = { + recursive: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["Input"], args: ['cdkTreeNodeToggleRecursive',] }], + _toggle: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["HostListener"], args: ['click', ['$event'],] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const EXPORTED_DECLARATIONS = [ + CdkNestedTreeNode, + CdkTreeNodeDef, + CdkTreeNodePadding, + CdkTreeNodeToggle, + CdkTree, + CdkTreeNode, + CdkTreeNodeOutlet, +]; +class CdkTreeModule { +} +CdkTreeModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_3__["NgModule"], args: [{ + imports: [_angular_common__WEBPACK_IMPORTED_MODULE_7__["CommonModule"]], + exports: EXPORTED_DECLARATIONS, + declarations: EXPORTED_DECLARATIONS, + providers: [_angular_cdk_a11y__WEBPACK_IMPORTED_MODULE_6__["FocusMonitor"], CdkTreeNodeDef] + },] }, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + + +//# sourceMappingURL=tree.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/common/fesm2015/common.js": +/*!*********************************************************!*\ + !*** ./node_modules/@angular/common/fesm2015/common.js ***! + \*********************************************************/ +/*! exports provided: ɵangular_packages_common_common_c, ɵangular_packages_common_common_h, ɵangular_packages_common_common_g, ɵangular_packages_common_common_f, ɵangular_packages_common_common_k, ɵangular_packages_common_common_j, ɵangular_packages_common_common_i, ɵangular_packages_common_common_a, ɵangular_packages_common_common_b, ɵangular_packages_common_common_e, ɵangular_packages_common_common_d, ɵregisterLocaleData, registerLocaleData, formatDate, formatCurrency, formatNumber, formatPercent, NgLocaleLocalization, NgLocalization, Plural, NumberFormatStyle, FormStyle, TranslationWidth, FormatWidth, NumberSymbol, WeekDay, getNumberOfCurrencyDigits, getCurrencySymbol, getLocaleDayPeriods, getLocaleDayNames, getLocaleMonthNames, getLocaleId, getLocaleEraNames, getLocaleWeekEndRange, getLocaleFirstDayOfWeek, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocalePluralCase, getLocaleTimeFormat, getLocaleNumberSymbol, getLocaleNumberFormat, getLocaleCurrencyName, getLocaleCurrencySymbol, ɵparseCookieValue, CommonModule, DeprecatedI18NPipesModule, NgClass, NgClassBase, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgStyleBase, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe, KeyValuePipe, DeprecatedDatePipe, DeprecatedCurrencyPipe, DeprecatedDecimalPipe, DeprecatedPercentPipe, ɵPLATFORM_BROWSER_ID, ɵPLATFORM_SERVER_ID, ɵPLATFORM_WORKER_APP_ID, ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi, VERSION, ViewportScroller, ɵNullViewportScroller, ɵNgClassImplProvider__POST_R3__, ɵNgClassR2Impl, ɵNgClassImpl, ɵNgStyleImplProvider__POST_R3__, ɵNgStyleR2Impl, ɵNgStyleImpl, ɵngStyleDirectiveDef__POST_R3__, ɵngClassDirectiveDef__POST_R3__, PlatformLocation, LOCATION_INITIALIZED, LocationStrategy, APP_BASE_HREF, HashLocationStrategy, PathLocationStrategy, Location */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_c", function() { return COMMON_DIRECTIVES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_h", function() { return NgClassImplProvider; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_g", function() { return NgClassImplProvider__PRE_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_f", function() { return NgClassR3Impl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_k", function() { return NgStyleImplProvider; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_j", function() { return NgStyleImplProvider__PRE_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_i", function() { return NgStyleR3Impl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_a", function() { return DEPRECATED_PLURAL_FN; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_b", function() { return getPluralCase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_e", function() { return COMMON_DEPRECATED_I18N_PIPES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_d", function() { return COMMON_PIPES; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵregisterLocaleData", function() { return registerLocaleData; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "registerLocaleData", function() { return registerLocaleData; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatDate", function() { return formatDate; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatCurrency", function() { return formatCurrency; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatNumber", function() { return formatNumber; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatPercent", function() { return formatPercent; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocaleLocalization", function() { return NgLocaleLocalization; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocalization", function() { return NgLocalization; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Plural", function() { return Plural; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberFormatStyle", function() { return NumberFormatStyle; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormStyle", function() { return FormStyle; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TranslationWidth", function() { return TranslationWidth; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormatWidth", function() { return FormatWidth; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberSymbol", function() { return NumberSymbol; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WeekDay", function() { return WeekDay; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNumberOfCurrencyDigits", function() { return getNumberOfCurrencyDigits; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getCurrencySymbol", function() { return getCurrencySymbol; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayPeriods", function() { return getLocaleDayPeriods; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayNames", function() { return getLocaleDayNames; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleMonthNames", function() { return getLocaleMonthNames; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleId", function() { return getLocaleId; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleEraNames", function() { return getLocaleEraNames; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleWeekEndRange", function() { return getLocaleWeekEndRange; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleFirstDayOfWeek", function() { return getLocaleFirstDayOfWeek; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateFormat", function() { return getLocaleDateFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateTimeFormat", function() { return getLocaleDateTimeFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriodRules", function() { return getLocaleExtraDayPeriodRules; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriods", function() { return getLocaleExtraDayPeriods; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocalePluralCase", function() { return getLocalePluralCase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleTimeFormat", function() { return getLocaleTimeFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberSymbol", function() { return getLocaleNumberSymbol; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberFormat", function() { return getLocaleNumberFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencyName", function() { return getLocaleCurrencyName; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencySymbol", function() { return getLocaleCurrencySymbol; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵparseCookieValue", function() { return parseCookieValue; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommonModule", function() { return CommonModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedI18NPipesModule", function() { return DeprecatedI18NPipesModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgClass", function() { return NgClass; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgClassBase", function() { return NgClassBase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOf", function() { return NgForOf; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOfContext", function() { return NgForOfContext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIf", function() { return NgIf; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIfContext", function() { return NgIfContext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPlural", function() { return NgPlural; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPluralCase", function() { return NgPluralCase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgStyle", function() { return NgStyle; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgStyleBase", function() { return NgStyleBase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitch", function() { return NgSwitch; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchCase", function() { return NgSwitchCase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchDefault", function() { return NgSwitchDefault; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgTemplateOutlet", function() { return NgTemplateOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgComponentOutlet", function() { return NgComponentOutlet; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DOCUMENT", function() { return DOCUMENT; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncPipe", function() { return AsyncPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DatePipe", function() { return DatePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nPluralPipe", function() { return I18nPluralPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nSelectPipe", function() { return I18nSelectPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JsonPipe", function() { return JsonPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LowerCasePipe", function() { return LowerCasePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CurrencyPipe", function() { return CurrencyPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DecimalPipe", function() { return DecimalPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PercentPipe", function() { return PercentPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SlicePipe", function() { return SlicePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UpperCasePipe", function() { return UpperCasePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TitleCasePipe", function() { return TitleCasePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyValuePipe", function() { return KeyValuePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedDatePipe", function() { return DeprecatedDatePipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedCurrencyPipe", function() { return DeprecatedCurrencyPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedDecimalPipe", function() { return DeprecatedDecimalPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeprecatedPercentPipe", function() { return DeprecatedPercentPipe; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_BROWSER_ID", function() { return PLATFORM_BROWSER_ID; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_SERVER_ID", function() { return PLATFORM_SERVER_ID; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_APP_ID", function() { return PLATFORM_WORKER_APP_ID; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_UI_ID", function() { return PLATFORM_WORKER_UI_ID; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformBrowser", function() { return isPlatformBrowser; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformServer", function() { return isPlatformServer; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerApp", function() { return isPlatformWorkerApp; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerUi", function() { return isPlatformWorkerUi; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewportScroller", function() { return ViewportScroller; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNullViewportScroller", function() { return NullViewportScroller; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassImplProvider__POST_R3__", function() { return NgClassImplProvider__POST_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassR2Impl", function() { return NgClassR2Impl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgClassImpl", function() { return NgClassImpl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleImplProvider__POST_R3__", function() { return NgStyleImplProvider__POST_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleR2Impl", function() { return NgStyleR2Impl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNgStyleImpl", function() { return NgStyleImpl; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵngStyleDirectiveDef__POST_R3__", function() { return ngStyleDirectiveDef__POST_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵngClassDirectiveDef__POST_R3__", function() { return ngClassDirectiveDef__POST_R3__; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlatformLocation", function() { return PlatformLocation; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LOCATION_INITIALIZED", function() { return LOCATION_INITIALIZED; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LocationStrategy", function() { return LocationStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "APP_BASE_HREF", function() { return APP_BASE_HREF; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HashLocationStrategy", function() { return HashLocationStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PathLocationStrategy", function() { return PathLocationStrategy; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Location", function() { return Location; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/** + * @license Angular v8.1.2 + * (c) 2010-2019 Google LLC. https://angular.io/ + * License: MIT + */ + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * This class should not be used directly by an application developer. Instead, use + * {\@link Location}. + * + * `PlatformLocation` encapsulates all calls to DOM apis, which allows the Router to be platform + * agnostic. + * This means that we can have different implementation of `PlatformLocation` for the different + * platforms that angular supports. For example, `\@angular/platform-browser` provides an + * implementation specific to the browser environment, while `\@angular/platform-webworker` provides + * one suitable for use with web workers. + * + * The `PlatformLocation` class is used directly by all implementations of {\@link LocationStrategy} + * when they need to interact with the DOM apis like pushState, popState, etc... + * + * {\@link LocationStrategy} in turn is used by the {\@link Location} service which is used directly + * by the {\@link Router} in order to navigate between routes. Since all interactions between {\@link + * Router} / + * {\@link Location} / {\@link LocationStrategy} and DOM apis flow through the `PlatformLocation` + * class they are all platform independent. + * + * \@publicApi + * @abstract + */ +class PlatformLocation { +} +/** + * \@description + * Indicates when a location is initialized. + * + * \@publicApi + * @type {?} + */ +const LOCATION_INITIALIZED = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('Location Initialized'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Enables the `Location` service to read route state from the browser's URL. + * Angular provides two strategies: + * `HashLocationStrategy` and `PathLocationStrategy`. + * + * Applications should use the `Router` or `Location` services to + * interact with application route state. + * + * For instance, `HashLocationStrategy` produces URLs like + * http://example.com#/foo, + * and `PathLocationStrategy` produces + * http://example.com/foo as an equivalent URL. + * + * See these two classes for more. + * + * \@publicApi + * @abstract + */ +class LocationStrategy { +} +/** + * A predefined [DI token](guide/glossary#di-token) for the base href + * to be used with the `PathLocationStrategy`. + * The base href is the URL prefix that should be preserved when generating + * and recognizing URLs. + * + * \@usageNotes + * + * The following example shows how to use this token to configure the root app injector + * with a base href value, so that the DI framework can supply the dependency anywhere in the app. + * + * ```typescript + * import {Component, NgModule} from '\@angular/core'; + * import {APP_BASE_HREF} from '\@angular/common'; + * + * \@NgModule({ + * providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}] + * }) + * class AppModule {} + * ``` + * + * \@publicApi + * @type {?} + */ +const APP_BASE_HREF = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('appBaseHref'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@description + * + * A service that applications can use to interact with a browser's URL. + * + * Depending on the `LocationStrategy` used, `Location` will either persist + * to the URL's path or the URL's hash segment. + * + * \@usageNotes + * + * It's better to use the {\@link Router#navigate} service to trigger route changes. Use + * `Location` only if you need to interact with or create normalized URLs outside of + * routing. + * + * `Location` is responsible for normalizing the URL against the application's base href. + * A normalized URL is absolute from the URL host, includes the application's base href, and has no + * trailing slash: + * - `/my/app/user/123` is normalized + * - `my/app/user/123` **is not** normalized + * - `/my/app/user/123/` **is not** normalized + * + * ### Example + * + * + * + * \@publicApi + */ +class Location { + /** + * @param {?} platformStrategy + * @param {?} platformLocation + */ + constructor(platformStrategy, platformLocation) { + /** + * \@internal + */ + this._subject = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["EventEmitter"](); + /** + * \@internal + */ + this._urlChangeListeners = []; + this._platformStrategy = platformStrategy; + /** @type {?} */ + const browserBaseHref = this._platformStrategy.getBaseHref(); + this._platformLocation = platformLocation; + this._baseHref = Location.stripTrailingSlash(_stripIndexHtml(browserBaseHref)); + this._platformStrategy.onPopState((/** + * @param {?} ev + * @return {?} + */ + (ev) => { + this._subject.emit({ + 'url': this.path(true), + 'pop': true, + 'state': ev.state, + 'type': ev.type, + }); + })); + } + /** + * Returns the normalized URL path. + * + * @param {?=} includeHash Whether path has an anchor fragment. + * + * @return {?} The normalized URL path. + */ + // TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is + // removed. + path(includeHash = false) { + return this.normalize(this._platformStrategy.path(includeHash)); + } + /** + * Returns the current value of the history.state object. + * @return {?} + */ + getState() { return this._platformLocation.getState(); } + /** + * Normalizes the given path and compares to the current normalized path. + * + * @param {?} path The given URL path + * @param {?=} query Query parameters + * + * @return {?} `true` if the given URL path is equal to the current normalized path, `false` + * otherwise. + */ + isCurrentPathEqualTo(path, query = '') { + return this.path() == this.normalize(path + Location.normalizeQueryParams(query)); + } + /** + * Given a string representing a URL, returns the URL path after stripping the + * trailing slashes. + * + * @param {?} url String representing a URL. + * + * @return {?} Normalized URL string. + */ + normalize(url) { + return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url))); + } + /** + * Given a string representing a URL, returns the platform-specific external URL path. + * If the given URL doesn't begin with a leading slash (`'/'`), this method adds one + * before normalizing. This method also adds a hash if `HashLocationStrategy` is + * used, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use. + * + * + * @param {?} url String representing a URL. + * + * @return {?} A normalized platform-specific URL. + */ + prepareExternalUrl(url) { + if (url && url[0] !== '/') { + url = '/' + url; + } + return this._platformStrategy.prepareExternalUrl(url); + } + // TODO: rename this method to pushState + /** + * Changes the browsers URL to a normalized version of the given URL, and pushes a + * new item onto the platform's history. + * + * @param {?} path URL path to normalizze + * @param {?=} query Query parameters + * @param {?=} state Location history state + * + * @return {?} + */ + go(path, query = '', state = null) { + this._platformStrategy.pushState(state, '', path, query); + this._notifyUrlChangeListeners(this.prepareExternalUrl(path + Location.normalizeQueryParams(query)), state); + } + /** + * Changes the browser's URL to a normalized version of the given URL, and replaces + * the top item on the platform's history stack. + * + * @param {?} path URL path to normalizze + * @param {?=} query Query parameters + * @param {?=} state Location history state + * @return {?} + */ + replaceState(path, query = '', state = null) { + this._platformStrategy.replaceState(state, '', path, query); + this._notifyUrlChangeListeners(this.prepareExternalUrl(path + Location.normalizeQueryParams(query)), state); + } + /** + * Navigates forward in the platform's history. + * @return {?} + */ + forward() { this._platformStrategy.forward(); } + /** + * Navigates back in the platform's history. + * @return {?} + */ + back() { this._platformStrategy.back(); } + /** + * Register URL change listeners. This API can be used to catch updates performed by the Angular + * framework. These are not detectible through "popstate" or "hashchange" events. + * @param {?} fn + * @return {?} + */ + onUrlChange(fn) { + this._urlChangeListeners.push(fn); + this.subscribe((/** + * @param {?} v + * @return {?} + */ + v => { this._notifyUrlChangeListeners(v.url, v.state); })); + } + /** + * \@internal + * @param {?=} url + * @param {?=} state + * @return {?} + */ + _notifyUrlChangeListeners(url = '', state) { + this._urlChangeListeners.forEach((/** + * @param {?} fn + * @return {?} + */ + fn => fn(url, state))); + } + /** + * Subscribe to the platform's `popState` events. + * + * @param {?} onNext + * @param {?=} onThrow + * @param {?=} onReturn + * @return {?} Subscribed events. + */ + subscribe(onNext, onThrow, onReturn) { + return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn }); + } + /** + * Given a string of url parameters, prepend with `?` if needed, otherwise return the + * parameters as is. + * + * @param {?} params String of URL parameters + * + * @return {?} URL parameters prepended with `?` or the parameters as is. + */ + static normalizeQueryParams(params) { + return params && params[0] !== '?' ? '?' + params : params; + } + /** + * Given 2 parts of a URL, join them with a slash if needed. + * + * @param {?} start URL string + * @param {?} end URL string + * + * + * @return {?} Given URL strings joined with a slash, if needed. + */ + static joinWithSlash(start, end) { + if (start.length == 0) { + return end; + } + if (end.length == 0) { + return start; + } + /** @type {?} */ + let slashes = 0; + if (start.endsWith('/')) { + slashes++; + } + if (end.startsWith('/')) { + slashes++; + } + if (slashes == 2) { + return start + end.substring(1); + } + if (slashes == 1) { + return start + end; + } + return start + '/' + end; + } + /** + * If URL has a trailing slash, remove it, otherwise return the URL as is. The + * method looks for the first occurrence of either `#`, `?`, or the end of the + * line as `/` characters and removes the trailing slash if one exists. + * + * @param {?} url URL string + * + * @return {?} Returns a URL string after removing the trailing slash if one exists, otherwise + * returns the string as is. + */ + static stripTrailingSlash(url) { + /** @type {?} */ + const match = url.match(/#|\?|$/); + /** @type {?} */ + const pathEndIdx = match && match.index || url.length; + /** @type {?} */ + const droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0); + return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx); + } +} +Location.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +Location.ctorParameters = () => [ + { type: LocationStrategy }, + { type: PlatformLocation } +]; +/** + * @param {?} baseHref + * @param {?} url + * @return {?} + */ +function _stripBaseHref(baseHref, url) { + return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url; +} +/** + * @param {?} url + * @return {?} + */ +function _stripIndexHtml(url) { + return url.replace(/\/index.html$/, ''); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@description + * A {\@link LocationStrategy} used to configure the {\@link Location} service to + * represent its state in the + * [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) + * of the browser's URL. + * + * For instance, if you call `location.go('/foo')`, the browser's URL will become + * `example.com#/foo`. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/location/ts/hash_location_component.ts region='LocationComponent'} + * + * \@publicApi + */ +class HashLocationStrategy extends LocationStrategy { + /** + * @param {?} _platformLocation + * @param {?=} _baseHref + */ + constructor(_platformLocation, _baseHref) { + super(); + this._platformLocation = _platformLocation; + this._baseHref = ''; + if (_baseHref != null) { + this._baseHref = _baseHref; + } + } + /** + * @param {?} fn + * @return {?} + */ + onPopState(fn) { + this._platformLocation.onPopState(fn); + this._platformLocation.onHashChange(fn); + } + /** + * @return {?} + */ + getBaseHref() { return this._baseHref; } + /** + * @param {?=} includeHash + * @return {?} + */ + path(includeHash = false) { + // the hash value is always prefixed with a `#` + // and if it is empty then it will stay empty + /** @type {?} */ + let path = this._platformLocation.hash; + if (path == null) + path = '#'; + return path.length > 0 ? path.substring(1) : path; + } + /** + * @param {?} internal + * @return {?} + */ + prepareExternalUrl(internal) { + /** @type {?} */ + const url = Location.joinWithSlash(this._baseHref, internal); + return url.length > 0 ? ('#' + url) : url; + } + /** + * @param {?} state + * @param {?} title + * @param {?} path + * @param {?} queryParams + * @return {?} + */ + pushState(state, title, path, queryParams) { + /** @type {?} */ + let url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams)); + if (url.length == 0) { + url = this._platformLocation.pathname; + } + this._platformLocation.pushState(state, title, url); + } + /** + * @param {?} state + * @param {?} title + * @param {?} path + * @param {?} queryParams + * @return {?} + */ + replaceState(state, title, path, queryParams) { + /** @type {?} */ + let url = this.prepareExternalUrl(path + Location.normalizeQueryParams(queryParams)); + if (url.length == 0) { + url = this._platformLocation.pathname; + } + this._platformLocation.replaceState(state, title, url); + } + /** + * @return {?} + */ + forward() { this._platformLocation.forward(); } + /** + * @return {?} + */ + back() { this._platformLocation.back(); } +} +HashLocationStrategy.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +HashLocationStrategy.ctorParameters = () => [ + { type: PlatformLocation }, + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@description + * A {\@link LocationStrategy} used to configure the {\@link Location} service to + * represent its state in the + * [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the + * browser's URL. + * + * If you're using `PathLocationStrategy`, you must provide a {\@link APP_BASE_HREF} + * or add a base element to the document. This URL prefix that will be preserved + * when generating and recognizing URLs. + * + * For instance, if you provide an `APP_BASE_HREF` of `'/my/app'` and call + * `location.go('/foo')`, the browser's URL will become + * `example.com/my/app/foo`. + * + * Similarly, if you add `` to the document and call + * `location.go('/foo')`, the browser's URL will become + * `example.com/my/app/foo`. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/location/ts/path_location_component.ts region='LocationComponent'} + * + * \@publicApi + */ +class PathLocationStrategy extends LocationStrategy { + /** + * @param {?} _platformLocation + * @param {?=} href + */ + constructor(_platformLocation, href) { + super(); + this._platformLocation = _platformLocation; + if (href == null) { + href = this._platformLocation.getBaseHrefFromDOM(); + } + if (href == null) { + throw new Error(`No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.`); + } + this._baseHref = href; + } + /** + * @param {?} fn + * @return {?} + */ + onPopState(fn) { + this._platformLocation.onPopState(fn); + this._platformLocation.onHashChange(fn); + } + /** + * @return {?} + */ + getBaseHref() { return this._baseHref; } + /** + * @param {?} internal + * @return {?} + */ + prepareExternalUrl(internal) { + return Location.joinWithSlash(this._baseHref, internal); + } + /** + * @param {?=} includeHash + * @return {?} + */ + path(includeHash = false) { + /** @type {?} */ + const pathname = this._platformLocation.pathname + + Location.normalizeQueryParams(this._platformLocation.search); + /** @type {?} */ + const hash = this._platformLocation.hash; + return hash && includeHash ? `${pathname}${hash}` : pathname; + } + /** + * @param {?} state + * @param {?} title + * @param {?} url + * @param {?} queryParams + * @return {?} + */ + pushState(state, title, url, queryParams) { + /** @type {?} */ + const externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams)); + this._platformLocation.pushState(state, title, externalUrl); + } + /** + * @param {?} state + * @param {?} title + * @param {?} url + * @param {?} queryParams + * @return {?} + */ + replaceState(state, title, url, queryParams) { + /** @type {?} */ + const externalUrl = this.prepareExternalUrl(url + Location.normalizeQueryParams(queryParams)); + this._platformLocation.replaceState(state, title, externalUrl); + } + /** + * @return {?} + */ + forward() { this._platformLocation.forward(); } + /** + * @return {?} + */ + back() { this._platformLocation.back(); } +} +PathLocationStrategy.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +PathLocationStrategy.ctorParameters = () => [ + { type: PlatformLocation }, + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +// THIS CODE IS GENERATED - DO NOT MODIFY +// See angular/tools/gulp-tasks/cldr/extract.js +/** + * \@internal + * @type {?} + */ +const CURRENCIES_EN = { + 'ADP': [undefined, undefined, 0], + 'AFN': [undefined, undefined, 0], + 'ALL': [undefined, undefined, 0], + 'AMD': [undefined, undefined, 0], + 'AOA': [undefined, 'Kz'], + 'ARS': [undefined, '$'], + 'AUD': ['A$', '$'], + 'BAM': [undefined, 'KM'], + 'BBD': [undefined, '$'], + 'BDT': [undefined, '৳'], + 'BHD': [undefined, undefined, 3], + 'BIF': [undefined, undefined, 0], + 'BMD': [undefined, '$'], + 'BND': [undefined, '$'], + 'BOB': [undefined, 'Bs'], + 'BRL': ['R$'], + 'BSD': [undefined, '$'], + 'BWP': [undefined, 'P'], + 'BYN': [undefined, 'р.', 2], + 'BYR': [undefined, undefined, 0], + 'BZD': [undefined, '$'], + 'CAD': ['CA$', '$', 2], + 'CHF': [undefined, undefined, 2], + 'CLF': [undefined, undefined, 4], + 'CLP': [undefined, '$', 0], + 'CNY': ['CN¥', '¥'], + 'COP': [undefined, '$', 0], + 'CRC': [undefined, '₡', 2], + 'CUC': [undefined, '$'], + 'CUP': [undefined, '$'], + 'CZK': [undefined, 'Kč', 2], + 'DJF': [undefined, undefined, 0], + 'DKK': [undefined, 'kr', 2], + 'DOP': [undefined, '$'], + 'EGP': [undefined, 'E£'], + 'ESP': [undefined, '₧', 0], + 'EUR': ['€'], + 'FJD': [undefined, '$'], + 'FKP': [undefined, '£'], + 'GBP': ['£'], + 'GEL': [undefined, '₾'], + 'GIP': [undefined, '£'], + 'GNF': [undefined, 'FG', 0], + 'GTQ': [undefined, 'Q'], + 'GYD': [undefined, '$', 0], + 'HKD': ['HK$', '$'], + 'HNL': [undefined, 'L'], + 'HRK': [undefined, 'kn'], + 'HUF': [undefined, 'Ft', 2], + 'IDR': [undefined, 'Rp', 0], + 'ILS': ['₪'], + 'INR': ['₹'], + 'IQD': [undefined, undefined, 0], + 'IRR': [undefined, undefined, 0], + 'ISK': [undefined, 'kr', 0], + 'ITL': [undefined, undefined, 0], + 'JMD': [undefined, '$'], + 'JOD': [undefined, undefined, 3], + 'JPY': ['¥', undefined, 0], + 'KHR': [undefined, '៛'], + 'KMF': [undefined, 'CF', 0], + 'KPW': [undefined, '₩', 0], + 'KRW': ['₩', undefined, 0], + 'KWD': [undefined, undefined, 3], + 'KYD': [undefined, '$'], + 'KZT': [undefined, '₸'], + 'LAK': [undefined, '₭', 0], + 'LBP': [undefined, 'L£', 0], + 'LKR': [undefined, 'Rs'], + 'LRD': [undefined, '$'], + 'LTL': [undefined, 'Lt'], + 'LUF': [undefined, undefined, 0], + 'LVL': [undefined, 'Ls'], + 'LYD': [undefined, undefined, 3], + 'MGA': [undefined, 'Ar', 0], + 'MGF': [undefined, undefined, 0], + 'MMK': [undefined, 'K', 0], + 'MNT': [undefined, '₮', 0], + 'MRO': [undefined, undefined, 0], + 'MUR': [undefined, 'Rs', 0], + 'MXN': ['MX$', '$'], + 'MYR': [undefined, 'RM'], + 'NAD': [undefined, '$'], + 'NGN': [undefined, '₦'], + 'NIO': [undefined, 'C$'], + 'NOK': [undefined, 'kr', 2], + 'NPR': [undefined, 'Rs'], + 'NZD': ['NZ$', '$'], + 'OMR': [undefined, undefined, 3], + 'PHP': [undefined, '₱'], + 'PKR': [undefined, 'Rs', 0], + 'PLN': [undefined, 'zł'], + 'PYG': [undefined, '₲', 0], + 'RON': [undefined, 'lei'], + 'RSD': [undefined, undefined, 0], + 'RUB': [undefined, '₽'], + 'RUR': [undefined, 'р.'], + 'RWF': [undefined, 'RF', 0], + 'SBD': [undefined, '$'], + 'SEK': [undefined, 'kr', 2], + 'SGD': [undefined, '$'], + 'SHP': [undefined, '£'], + 'SLL': [undefined, undefined, 0], + 'SOS': [undefined, undefined, 0], + 'SRD': [undefined, '$'], + 'SSP': [undefined, '£'], + 'STD': [undefined, undefined, 0], + 'STN': [undefined, 'Db'], + 'SYP': [undefined, '£', 0], + 'THB': [undefined, '฿'], + 'TMM': [undefined, undefined, 0], + 'TND': [undefined, undefined, 3], + 'TOP': [undefined, 'T$'], + 'TRL': [undefined, undefined, 0], + 'TRY': [undefined, '₺'], + 'TTD': [undefined, '$'], + 'TWD': ['NT$', '$', 2], + 'TZS': [undefined, undefined, 0], + 'UAH': [undefined, '₴'], + 'UGX': [undefined, undefined, 0], + 'USD': ['$'], + 'UYI': [undefined, undefined, 0], + 'UYU': [undefined, '$'], + 'UZS': [undefined, undefined, 0], + 'VEF': [undefined, 'Bs'], + 'VND': ['₫', undefined, 0], + 'VUV': [undefined, undefined, 0], + 'XAF': ['FCFA', undefined, 0], + 'XCD': ['EC$', '$'], + 'XOF': ['CFA', undefined, 0], + 'XPF': ['CFPF', undefined, 0], + 'YER': [undefined, undefined, 0], + 'ZAR': [undefined, 'R'], + 'ZMK': [undefined, undefined, 0], + 'ZMW': [undefined, 'ZK'], + 'ZWD': [undefined, undefined, 0] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @enum {number} */ +const NumberFormatStyle = { + Decimal: 0, + Percent: 1, + Currency: 2, + Scientific: 3, +}; +NumberFormatStyle[NumberFormatStyle.Decimal] = 'Decimal'; +NumberFormatStyle[NumberFormatStyle.Percent] = 'Percent'; +NumberFormatStyle[NumberFormatStyle.Currency] = 'Currency'; +NumberFormatStyle[NumberFormatStyle.Scientific] = 'Scientific'; +/** @enum {number} */ +const Plural = { + Zero: 0, + One: 1, + Two: 2, + Few: 3, + Many: 4, + Other: 5, +}; +Plural[Plural.Zero] = 'Zero'; +Plural[Plural.One] = 'One'; +Plural[Plural.Two] = 'Two'; +Plural[Plural.Few] = 'Few'; +Plural[Plural.Many] = 'Many'; +Plural[Plural.Other] = 'Other'; +/** @enum {number} */ +const FormStyle = { + Format: 0, + Standalone: 1, +}; +FormStyle[FormStyle.Format] = 'Format'; +FormStyle[FormStyle.Standalone] = 'Standalone'; +/** @enum {number} */ +const TranslationWidth = { + /** 1 character for `en-US`. For example: 'S' */ + Narrow: 0, + /** 3 characters for `en-US`. For example: 'Sun' */ + Abbreviated: 1, + /** Full length for `en-US`. For example: "Sunday" */ + Wide: 2, + /** 2 characters for `en-US`, For example: "Su" */ + Short: 3, +}; +TranslationWidth[TranslationWidth.Narrow] = 'Narrow'; +TranslationWidth[TranslationWidth.Abbreviated] = 'Abbreviated'; +TranslationWidth[TranslationWidth.Wide] = 'Wide'; +TranslationWidth[TranslationWidth.Short] = 'Short'; +/** @enum {number} */ +const FormatWidth = { + /** + * For `en-US`, 'M/d/yy, h:mm a'` + * (Example: `6/15/15, 9:03 AM`) + */ + Short: 0, + /** + * For `en-US`, `'MMM d, y, h:mm:ss a'` + * (Example: `Jun 15, 2015, 9:03:01 AM`) + */ + Medium: 1, + /** + * For `en-US`, `'MMMM d, y, h:mm:ss a z'` + * (Example: `June 15, 2015 at 9:03:01 AM GMT+1`) + */ + Long: 2, + /** + * For `en-US`, `'EEEE, MMMM d, y, h:mm:ss a zzzz'` + * (Example: `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00`) + */ + Full: 3, +}; +FormatWidth[FormatWidth.Short] = 'Short'; +FormatWidth[FormatWidth.Medium] = 'Medium'; +FormatWidth[FormatWidth.Long] = 'Long'; +FormatWidth[FormatWidth.Full] = 'Full'; +/** @enum {number} */ +const NumberSymbol = { + /** + * Decimal separator. + * For `en-US`, the dot character. + * Example : 2,345`.`67 + */ + Decimal: 0, + /** + * Grouping separator, typically for thousands. + * For `en-US`, the comma character. + * Example: 2`,`345.67 + */ + Group: 1, + /** + * List-item separator. + * Example: "one, two, and three" + */ + List: 2, + /** + * Sign for percentage (out of 100). + * Example: 23.4% + */ + PercentSign: 3, + /** + * Sign for positive numbers. + * Example: +23 + */ + PlusSign: 4, + /** + * Sign for negative numbers. + * Example: -23 + */ + MinusSign: 5, + /** + * Computer notation for exponential value (n times a power of 10). + * Example: 1.2E3 + */ + Exponential: 6, + /** + * Human-readable format of exponential. + * Example: 1.2x103 + */ + SuperscriptingExponent: 7, + /** + * Sign for permille (out of 1000). + * Example: 23.4‰ + */ + PerMille: 8, + /** + * Infinity, can be used with plus and minus. + * Example: ∞, +∞, -∞ + */ + Infinity: 9, + /** + * Not a number. + * Example: NaN + */ + NaN: 10, + /** + * Symbol used between time units. + * Example: 10:52 + */ + TimeSeparator: 11, + /** + * Decimal separator for currency values (fallback to `Decimal`). + * Example: $2,345.67 + */ + CurrencyDecimal: 12, + /** + * Group separator for currency values (fallback to `Group`). + * Example: $2,345.67 + */ + CurrencyGroup: 13, +}; +NumberSymbol[NumberSymbol.Decimal] = 'Decimal'; +NumberSymbol[NumberSymbol.Group] = 'Group'; +NumberSymbol[NumberSymbol.List] = 'List'; +NumberSymbol[NumberSymbol.PercentSign] = 'PercentSign'; +NumberSymbol[NumberSymbol.PlusSign] = 'PlusSign'; +NumberSymbol[NumberSymbol.MinusSign] = 'MinusSign'; +NumberSymbol[NumberSymbol.Exponential] = 'Exponential'; +NumberSymbol[NumberSymbol.SuperscriptingExponent] = 'SuperscriptingExponent'; +NumberSymbol[NumberSymbol.PerMille] = 'PerMille'; +NumberSymbol[NumberSymbol.Infinity] = 'Infinity'; +NumberSymbol[NumberSymbol.NaN] = 'NaN'; +NumberSymbol[NumberSymbol.TimeSeparator] = 'TimeSeparator'; +NumberSymbol[NumberSymbol.CurrencyDecimal] = 'CurrencyDecimal'; +NumberSymbol[NumberSymbol.CurrencyGroup] = 'CurrencyGroup'; +/** @enum {number} */ +const WeekDay = { + Sunday: 0, + Monday: 1, + Tuesday: 2, + Wednesday: 3, + Thursday: 4, + Friday: 5, + Saturday: 6, +}; +WeekDay[WeekDay.Sunday] = 'Sunday'; +WeekDay[WeekDay.Monday] = 'Monday'; +WeekDay[WeekDay.Tuesday] = 'Tuesday'; +WeekDay[WeekDay.Wednesday] = 'Wednesday'; +WeekDay[WeekDay.Thursday] = 'Thursday'; +WeekDay[WeekDay.Friday] = 'Friday'; +WeekDay[WeekDay.Saturday] = 'Saturday'; +/** + * Retrieves the locale ID from the currently loaded locale. + * The loaded locale could be, for example, a global one rather than a regional one. + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code, such as `fr-FR`. + * @return {?} The locale code. For example, `fr`. + */ +function getLocaleId(locale) { + return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale)[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]; +} +/** + * Retrieves day period strings for the given locale. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} formStyle The required grammatical form. + * @param {?} width The required character width. + * @return {?} An array of localized period strings. For example, `[AM, PM]` for `en-US`. + */ +function getLocaleDayPeriods(locale, formStyle, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const amPmData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsStandalone]])); + /** @type {?} */ + const amPm = getLastDefinedValue(amPmData, formStyle); + return getLastDefinedValue(amPm, width); +} +/** + * Retrieves days of the week for the given locale, using the Gregorian calendar. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} formStyle The required grammatical form. + * @param {?} width The required character width. + * @return {?} An array of localized name strings. + * For example,`[Sunday, Monday, ... Saturday]` for `en-US`. + */ +function getLocaleDayNames(locale, formStyle, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const daysData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysStandalone]])); + /** @type {?} */ + const days = getLastDefinedValue(daysData, formStyle); + return getLastDefinedValue(days, width); +} +/** + * Retrieves months of the year for the given locale, using the Gregorian calendar. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} formStyle The required grammatical form. + * @param {?} width The required character width. + * @return {?} An array of localized name strings. + * For example, `[January, February, ...]` for `en-US`. + */ +function getLocaleMonthNames(locale, formStyle, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const monthsData = (/** @type {?} */ ([data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsStandalone]])); + /** @type {?} */ + const months = getLastDefinedValue(monthsData, formStyle); + return getLastDefinedValue(months, width); +} +/** + * Retrieves Gregorian-calendar eras for the given locale. + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} width The required character width. + * @return {?} An array of localized era strings. + * For example, `[AD, BC]` for `en-US`. + */ +function getLocaleEraNames(locale, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const erasData = (/** @type {?} */ (data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Eras])); + return getLastDefinedValue(erasData, width); +} +/** + * Retrieves the first day of the week for the given locale. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} A day index number, using the 0-based week-day index for `en-US` + * (Sunday = 0, Monday = 1, ...). + * For example, for `fr-FR`, returns 1 to indicate that the first day is Monday. + */ +function getLocaleFirstDayOfWeek(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].FirstDayOfWeek]; +} +/** + * Range of week days that are considered the week-end for the given locale. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} The range of day values, `[startDay, endDay]`. + */ +function getLocaleWeekEndRange(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].WeekendRange]; +} +/** + * Retrieves a localized date-value formating string. + * + * @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} width The format type. + * @return {?} The localized formating string. + */ +function getLocaleDateFormat(locale, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateFormat], width); +} +/** + * Retrieves a localized time-value formatting string. + * + * @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} width The format type. + * @return {?} The localized formatting string. + */ +function getLocaleTimeFormat(locale, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].TimeFormat], width); +} +/** + * Retrieves a localized date-time formatting string. + * + * @see `FormatWidth` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} width The format type. + * @return {?} The localized formatting string. + */ +function getLocaleDateTimeFormat(locale, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const dateTimeFormatData = (/** @type {?} */ (data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateTimeFormat])); + return getLastDefinedValue(dateTimeFormatData, width); +} +/** + * Retrieves a localized number symbol that can be used to replace placeholders in number formats. + * @see `NumberSymbol` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale The locale code. + * @param {?} symbol The symbol to localize. + * @return {?} The character for the localized symbol. + */ +function getLocaleNumberSymbol(locale, symbol) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + /** @type {?} */ + const res = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][symbol]; + if (typeof res === 'undefined') { + if (symbol === NumberSymbol.CurrencyDecimal) { + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Decimal]; + } + else if (symbol === NumberSymbol.CurrencyGroup) { + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Group]; + } + } + return res; +} +/** + * Retrieves a number format for a given locale. + * + * Numbers are formatted using patterns, like `#,###.00`. For example, the pattern `#,###.00` + * when used to format the number 12345.678 could result in "12'345,678". That would happen if the + * grouping separator for your language is an apostrophe, and the decimal separator is a comma. + * + * Important: The characters `.` `,` `0` `#` (and others below) are special placeholders + * that stand for the decimal separator, and so on, and are NOT real characters. + * You must NOT "translate" the placeholders. For example, don't change `.` to `,` even though in + * your language the decimal point is written with a comma. The symbols should be replaced by the + * local equivalents, using the appropriate `NumberSymbol` for your language. + * + * Here are the special characters used in number patterns: + * + * | Symbol | Meaning | + * |--------|---------| + * | . | Replaced automatically by the character used for the decimal point. | + * | , | Replaced by the "grouping" (thousands) separator. | + * | 0 | Replaced by a digit (or zero if there aren't enough digits). | + * | # | Replaced by a digit (or nothing if there aren't enough). | + * | ¤ | Replaced by a currency symbol, such as $ or USD. | + * | % | Marks a percent format. The % symbol may change position, but must be retained. | + * | E | Marks a scientific format. The E symbol may change position, but must be retained. | + * | ' | Special characters used as literal characters are quoted with ASCII single quotes. | + * + * @see `NumberFormatStyle` / [CLDR website](http://cldr.unicode.org/translation/number-patterns) / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} type The type of numeric value to be formatted (such as `Decimal` or `Currency`.) + * @return {?} The localized format string. + */ +function getLocaleNumberFormat(locale, type) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberFormats][type]; +} +/** + * Retrieves the symbol used to represent the currency for the main country + * corresponding to a given locale. For example, '$' for `en-US`. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} The localized symbol character, + * or `null` if the main country cannot be determined. + */ +function getLocaleCurrencySymbol(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencySymbol] || null; +} +/** + * Retrieves the name of the currency for the main country corresponding + * to a given locale. For example, 'US Dollar' for `en-US`. + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} The currency name, + * or `null` if the main country cannot be determined. + */ +function getLocaleCurrencyName(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencyName] || null; +} +/** + * Retrieves the currency values for a given locale. + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} The currency values. + */ +function getLocaleCurrencies(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Currencies]; +} +/** + * \@alias core/ɵgetLocalePluralCase + * \@publicApi + * @type {?} + */ +const getLocalePluralCase = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocalePluralCase"]; +/** + * @param {?} data + * @return {?} + */ +function checkFullData(data) { + if (!data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData]) { + throw new Error(`Missing extra locale data for the locale "${data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`); + } +} +/** + * Retrieves locale-specific rules used to determine which day period to use + * when more than one period is defined for a locale. + * + * There is a rule for each defined day period. The + * first rule is applied to the first day period and so on. + * Fall back to AM/PM when no rules are available. + * + * A rule can specify a period as time range, or as a single time value. + * + * This functionality is only available when you have loaded the full locale data. + * See the ["I18n guide"](guide/i18n#i18n-pipes). + * + * @see `getLocaleExtraDayPeriods()` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @return {?} The rules for the locale, a single time value or array of *from-time, to-time*, + * or null if no periods are available. + * + */ +function getLocaleExtraDayPeriodRules(locale) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + checkFullData(data); + /** @type {?} */ + const rules = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][2 /* ExtraDayPeriodsRules */] || []; + return rules.map((/** + * @param {?} rule + * @return {?} + */ + (rule) => { + if (typeof rule === 'string') { + return extractTime(rule); + } + return [extractTime(rule[0]), extractTime(rule[1])]; + })); +} +/** + * Retrieves locale-specific day periods, which indicate roughly how a day is broken up + * in different languages. + * For example, for `en-US`, periods are morning, noon, afternoon, evening, and midnight. + * + * This functionality is only available when you have loaded the full locale data. + * See the ["I18n guide"](guide/i18n#i18n-pipes). + * + * @see `getLocaleExtraDayPeriodRules()` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} formStyle The required grammatical form. + * @param {?} width The required character width. + * @return {?} The translated day-period strings. + */ +function getLocaleExtraDayPeriods(locale, formStyle, width) { + /** @type {?} */ + const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale); + checkFullData(data); + /** @type {?} */ + const dayPeriodsData = (/** @type {?} */ ([ + data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][0 /* ExtraDayPeriodFormats */], + data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][1 /* ExtraDayPeriodStandalone */] + ])); + /** @type {?} */ + const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || []; + return getLastDefinedValue(dayPeriods, width) || []; +} +/** + * Retrieves the first value that is defined in an array, going backwards from an index position. + * + * To avoid repeating the same data (as when the "format" and "standalone" forms are the same) + * add the first value to the locale data arrays, and add other values only if they are different. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @template T + * @param {?} data The data array to retrieve from. + * @param {?} index A 0-based index into the array to start from. + * @return {?} The value immediately before the given index position. + */ +function getLastDefinedValue(data, index) { + for (let i = index; i > -1; i--) { + if (typeof data[i] !== 'undefined') { + return data[i]; + } + } + throw new Error('Locale data API: locale data undefined'); +} +/** + * Extracts the hours and minutes from a string like "15:45" + * @param {?} time + * @return {?} + */ +function extractTime(time) { + const [h, m] = time.split(':'); + return { hours: +h, minutes: +m }; +} +/** + * Retrieves the currency symbol for a given currency code. + * + * For example, for the default `en-US` locale, the code `USD` can + * be represented by the narrow symbol `$` or the wide symbol `US$`. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} code The currency code. + * @param {?} format The format, `wide` or `narrow`. + * @param {?=} locale A locale code for the locale format rules to use. + * + * @return {?} The symbol, or the currency code if no symbol is available.0 + */ +function getCurrencySymbol(code, format, locale = 'en') { + /** @type {?} */ + const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || []; + /** @type {?} */ + const symbolNarrow = currency[1 /* SymbolNarrow */]; + if (format === 'narrow' && typeof symbolNarrow === 'string') { + return symbolNarrow; + } + return currency[0 /* Symbol */] || code; +} +// Most currencies have cents, that's why the default is 2 +/** @type {?} */ +const DEFAULT_NB_OF_CURRENCY_DIGITS = 2; +/** + * Reports the number of decimal digits for a given currency. + * The value depends upon the presence of cents in that particular currency. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} code The currency code. + * @return {?} The number of decimal digits, typically 0 or 2. + */ +function getNumberOfCurrencyDigits(code) { + /** @type {?} */ + let digits; + /** @type {?} */ + const currency = CURRENCIES_EN[code]; + if (currency) { + digits = currency[2 /* NbOfDigits */]; + } + return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; +// 1 2 3 4 5 6 7 8 9 10 11 +/** @type {?} */ +const NAMED_FORMATS = {}; +/** @type {?} */ +const DATE_FORMATS_SPLIT = /((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/; +/** @enum {number} */ +const ZoneWidth = { + Short: 0, + ShortGMT: 1, + Long: 2, + Extended: 3, +}; +ZoneWidth[ZoneWidth.Short] = 'Short'; +ZoneWidth[ZoneWidth.ShortGMT] = 'ShortGMT'; +ZoneWidth[ZoneWidth.Long] = 'Long'; +ZoneWidth[ZoneWidth.Extended] = 'Extended'; +/** @enum {number} */ +const DateType = { + FullYear: 0, + Month: 1, + Date: 2, + Hours: 3, + Minutes: 4, + Seconds: 5, + FractionalSeconds: 6, + Day: 7, +}; +DateType[DateType.FullYear] = 'FullYear'; +DateType[DateType.Month] = 'Month'; +DateType[DateType.Date] = 'Date'; +DateType[DateType.Hours] = 'Hours'; +DateType[DateType.Minutes] = 'Minutes'; +DateType[DateType.Seconds] = 'Seconds'; +DateType[DateType.FractionalSeconds] = 'FractionalSeconds'; +DateType[DateType.Day] = 'Day'; +/** @enum {number} */ +const TranslationType = { + DayPeriods: 0, + Days: 1, + Months: 2, + Eras: 3, +}; +TranslationType[TranslationType.DayPeriods] = 'DayPeriods'; +TranslationType[TranslationType.Days] = 'Days'; +TranslationType[TranslationType.Months] = 'Months'; +TranslationType[TranslationType.Eras] = 'Eras'; +/** + * \@ngModule CommonModule + * \@description + * + * Formats a date according to locale rules. + * + * @see `DatePipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} value The date to format, as a Date, or a number (milliseconds since UTC epoch) + * or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime). + * @param {?} format The date-time components to include. See `DatePipe` for details. + * @param {?} locale A locale code for the locale format rules to use. + * @param {?=} timezone The time zone. A time zone offset from GMT (such as `'+0430'`), + * or a standard UTC/GMT or continental US time zone abbreviation. + * If not specified, uses host system settings. + * + * @return {?} The formatted date string. + * + */ +function formatDate(value, format, locale, timezone) { + /** @type {?} */ + let date = toDate(value); + /** @type {?} */ + const namedFormat = getNamedFormat(locale, format); + format = namedFormat || format; + /** @type {?} */ + let parts = []; + /** @type {?} */ + let match; + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = parts.concat(match.slice(1)); + /** @type {?} */ + const part = parts.pop(); + if (!part) { + break; + } + format = part; + } + else { + parts.push(format); + break; + } + } + /** @type {?} */ + let dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + date = convertTimezoneToLocal(date, timezone, true); + } + /** @type {?} */ + let text = ''; + parts.forEach((/** + * @param {?} value + * @return {?} + */ + value => { + /** @type {?} */ + const dateFormatter = getDateFormatter(value); + text += dateFormatter ? + dateFormatter(date, locale, dateTimezoneOffset) : + value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\''); + })); + return text; +} +/** + * @param {?} locale + * @param {?} format + * @return {?} + */ +function getNamedFormat(locale, format) { + /** @type {?} */ + const localeId = getLocaleId(locale); + NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {}; + if (NAMED_FORMATS[localeId][format]) { + return NAMED_FORMATS[localeId][format]; + } + /** @type {?} */ + let formatValue = ''; + switch (format) { + case 'shortDate': + formatValue = getLocaleDateFormat(locale, FormatWidth.Short); + break; + case 'mediumDate': + formatValue = getLocaleDateFormat(locale, FormatWidth.Medium); + break; + case 'longDate': + formatValue = getLocaleDateFormat(locale, FormatWidth.Long); + break; + case 'fullDate': + formatValue = getLocaleDateFormat(locale, FormatWidth.Full); + break; + case 'shortTime': + formatValue = getLocaleTimeFormat(locale, FormatWidth.Short); + break; + case 'mediumTime': + formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium); + break; + case 'longTime': + formatValue = getLocaleTimeFormat(locale, FormatWidth.Long); + break; + case 'fullTime': + formatValue = getLocaleTimeFormat(locale, FormatWidth.Full); + break; + case 'short': + /** @type {?} */ + const shortTime = getNamedFormat(locale, 'shortTime'); + /** @type {?} */ + const shortDate = getNamedFormat(locale, 'shortDate'); + formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]); + break; + case 'medium': + /** @type {?} */ + const mediumTime = getNamedFormat(locale, 'mediumTime'); + /** @type {?} */ + const mediumDate = getNamedFormat(locale, 'mediumDate'); + formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]); + break; + case 'long': + /** @type {?} */ + const longTime = getNamedFormat(locale, 'longTime'); + /** @type {?} */ + const longDate = getNamedFormat(locale, 'longDate'); + formatValue = + formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]); + break; + case 'full': + /** @type {?} */ + const fullTime = getNamedFormat(locale, 'fullTime'); + /** @type {?} */ + const fullDate = getNamedFormat(locale, 'fullDate'); + formatValue = + formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]); + break; + } + if (formatValue) { + NAMED_FORMATS[localeId][format] = formatValue; + } + return formatValue; +} +/** + * @param {?} str + * @param {?} opt_values + * @return {?} + */ +function formatDateTime(str, opt_values) { + if (opt_values) { + str = str.replace(/\{([^}]+)}/g, (/** + * @param {?} match + * @param {?} key + * @return {?} + */ + function (match, key) { + return (opt_values != null && key in opt_values) ? opt_values[key] : match; + })); + } + return str; +} +/** + * @param {?} num + * @param {?} digits + * @param {?=} minusSign + * @param {?=} trim + * @param {?=} negWrap + * @return {?} + */ +function padNumber(num, digits, minusSign = '-', trim, negWrap) { + /** @type {?} */ + let neg = ''; + if (num < 0 || (negWrap && num <= 0)) { + if (negWrap) { + num = -num + 1; + } + else { + num = -num; + neg = minusSign; + } + } + /** @type {?} */ + let strNum = String(num); + while (strNum.length < digits) { + strNum = '0' + strNum; + } + if (trim) { + strNum = strNum.substr(strNum.length - digits); + } + return neg + strNum; +} +/** + * @param {?} milliseconds + * @param {?} digits + * @return {?} + */ +function formatFractionalSeconds(milliseconds, digits) { + /** @type {?} */ + const strMs = padNumber(milliseconds, 3); + return strMs.substr(0, digits); +} +/** + * Returns a date formatter that transforms a date into its locale digit representation + * @param {?} name + * @param {?} size + * @param {?=} offset + * @param {?=} trim + * @param {?=} negWrap + * @return {?} + */ +function dateGetter(name, size, offset = 0, trim = false, negWrap = false) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { + /** @type {?} */ + let part = getDatePart(name, date); + if (offset > 0 || part > -offset) { + part += offset; + } + if (name === DateType.Hours) { + if (part === 0 && offset === -12) { + part = 12; + } + } + else if (name === DateType.FractionalSeconds) { + return formatFractionalSeconds(part, size); + } + /** @type {?} */ + const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign); + return padNumber(part, size, localeMinus, trim, negWrap); + }); +} +/** + * @param {?} part + * @param {?} date + * @return {?} + */ +function getDatePart(part, date) { + switch (part) { + case DateType.FullYear: + return date.getFullYear(); + case DateType.Month: + return date.getMonth(); + case DateType.Date: + return date.getDate(); + case DateType.Hours: + return date.getHours(); + case DateType.Minutes: + return date.getMinutes(); + case DateType.Seconds: + return date.getSeconds(); + case DateType.FractionalSeconds: + return date.getMilliseconds(); + case DateType.Day: + return date.getDay(); + default: + throw new Error(`Unknown DateType value "${part}".`); + } +} +/** + * Returns a date formatter that transforms a date into its locale string representation + * @param {?} name + * @param {?} width + * @param {?=} form + * @param {?=} extended + * @return {?} + */ +function dateStrGetter(name, width, form = FormStyle.Format, extended = false) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { + return getDateTranslation(date, locale, name, width, form, extended); + }); +} +/** + * Returns the locale translation of a date for a given form, type and width + * @param {?} date + * @param {?} locale + * @param {?} name + * @param {?} width + * @param {?} form + * @param {?} extended + * @return {?} + */ +function getDateTranslation(date, locale, name, width, form, extended) { + switch (name) { + case TranslationType.Months: + return getLocaleMonthNames(locale, form, width)[date.getMonth()]; + case TranslationType.Days: + return getLocaleDayNames(locale, form, width)[date.getDay()]; + case TranslationType.DayPeriods: + /** @type {?} */ + const currentHours = date.getHours(); + /** @type {?} */ + const currentMinutes = date.getMinutes(); + if (extended) { + /** @type {?} */ + const rules = getLocaleExtraDayPeriodRules(locale); + /** @type {?} */ + const dayPeriods = getLocaleExtraDayPeriods(locale, form, width); + /** @type {?} */ + let result; + rules.forEach((/** + * @param {?} rule + * @param {?} index + * @return {?} + */ + (rule, index) => { + if (Array.isArray(rule)) { + // morning, afternoon, evening, night + const { hours: hoursFrom, minutes: minutesFrom } = rule[0]; + const { hours: hoursTo, minutes: minutesTo } = rule[1]; + if (currentHours >= hoursFrom && currentMinutes >= minutesFrom && + (currentHours < hoursTo || + (currentHours === hoursTo && currentMinutes < minutesTo))) { + result = dayPeriods[index]; + } + } + else { // noon or midnight + // noon or midnight + const { hours, minutes } = rule; + if (hours === currentHours && minutes === currentMinutes) { + result = dayPeriods[index]; + } + } + })); + if (result) { + return result; + } + } + // if no rules for the day periods, we use am/pm by default + return getLocaleDayPeriods(locale, form, (/** @type {?} */ (width)))[currentHours < 12 ? 0 : 1]; + case TranslationType.Eras: + return getLocaleEraNames(locale, (/** @type {?} */ (width)))[date.getFullYear() <= 0 ? 0 : 1]; + default: + // This default case is not needed by TypeScript compiler, as the switch is exhaustive. + // However Closure Compiler does not understand that and reports an error in typed mode. + // The `throw new Error` below works around the problem, and the unexpected: never variable + // makes sure tsc still checks this code is unreachable. + /** @type {?} */ + const unexpected = name; + throw new Error(`unexpected translation type ${unexpected}`); + } +} +/** + * Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or + * GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30, + * extended = +04:30) + * @param {?} width + * @return {?} + */ +function timeZoneGetter(width) { + return (/** + * @param {?} date + * @param {?} locale + * @param {?} offset + * @return {?} + */ + function (date, locale, offset) { + /** @type {?} */ + const zone = -1 * offset; + /** @type {?} */ + const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign); + /** @type {?} */ + const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60); + switch (width) { + case ZoneWidth.Short: + return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + + padNumber(Math.abs(zone % 60), 2, minusSign); + case ZoneWidth.ShortGMT: + return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 1, minusSign); + case ZoneWidth.Long: + return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' + + padNumber(Math.abs(zone % 60), 2, minusSign); + case ZoneWidth.Extended: + if (offset === 0) { + return 'Z'; + } + else { + return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' + + padNumber(Math.abs(zone % 60), 2, minusSign); + } + default: + throw new Error(`Unknown zone width "${width}"`); + } + }); +} +/** @type {?} */ +const JANUARY = 0; +/** @type {?} */ +const THURSDAY = 4; +/** + * @param {?} year + * @return {?} + */ +function getFirstThursdayOfYear(year) { + /** @type {?} */ + const firstDayOfYear = (new Date(year, JANUARY, 1)).getDay(); + return new Date(year, 0, 1 + ((firstDayOfYear <= THURSDAY) ? THURSDAY : THURSDAY + 7) - firstDayOfYear); +} +/** + * @param {?} datetime + * @return {?} + */ +function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (THURSDAY - datetime.getDay())); +} +/** + * @param {?} size + * @param {?=} monthBased + * @return {?} + */ +function weekGetter(size, monthBased = false) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { + /** @type {?} */ + let result; + if (monthBased) { + /** @type {?} */ + const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1; + /** @type {?} */ + const today = date.getDate(); + result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7); + } + else { + /** @type {?} */ + const firstThurs = getFirstThursdayOfYear(date.getFullYear()); + /** @type {?} */ + const thisThurs = getThursdayThisWeek(date); + /** @type {?} */ + const diff = thisThurs.getTime() - firstThurs.getTime(); + result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week + } + return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); + }); +} +/** @type {?} */ +const DATE_FORMATS = {}; +// Based on CLDR formats: +// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table +// See also explanations: http://cldr.unicode.org/translation/date-time +// TODO(ocombe): support all missing cldr formats: Y, U, Q, D, F, e, c, j, J, C, A, v, V, X, x +/** + * @param {?} format + * @return {?} + */ +function getDateFormatter(format) { + if (DATE_FORMATS[format]) { + return DATE_FORMATS[format]; + } + /** @type {?} */ + let formatter; + switch (format) { + // Era name (AD/BC) + case 'G': + case 'GG': + case 'GGG': + formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated); + break; + case 'GGGG': + formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide); + break; + case 'GGGGG': + formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow); + break; + // 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199) + case 'y': + formatter = dateGetter(DateType.FullYear, 1, 0, false, true); + break; + // 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + case 'yy': + formatter = dateGetter(DateType.FullYear, 2, 0, true, true); + break; + // 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10) + case 'yyy': + formatter = dateGetter(DateType.FullYear, 3, 0, false, true); + break; + // 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010) + case 'yyyy': + formatter = dateGetter(DateType.FullYear, 4, 0, false, true); + break; + // Month of the year (1-12), numeric + case 'M': + case 'L': + formatter = dateGetter(DateType.Month, 1, 1); + break; + case 'MM': + case 'LL': + formatter = dateGetter(DateType.Month, 2, 1); + break; + // Month of the year (January, ...), string, format + case 'MMM': + formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated); + break; + case 'MMMM': + formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide); + break; + case 'MMMMM': + formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow); + break; + // Month of the year (January, ...), string, standalone + case 'LLL': + formatter = + dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone); + break; + case 'LLLL': + formatter = + dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone); + break; + case 'LLLLL': + formatter = + dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone); + break; + // Week of the year (1, ... 52) + case 'w': + formatter = weekGetter(1); + break; + case 'ww': + formatter = weekGetter(2); + break; + // Week of the month (1, ...) + case 'W': + formatter = weekGetter(1, true); + break; + // Day of the month (1-31) + case 'd': + formatter = dateGetter(DateType.Date, 1); + break; + case 'dd': + formatter = dateGetter(DateType.Date, 2); + break; + // Day of the Week + case 'E': + case 'EE': + case 'EEE': + formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated); + break; + case 'EEEE': + formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide); + break; + case 'EEEEE': + formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow); + break; + case 'EEEEEE': + formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short); + break; + // Generic period of the day (am-pm) + case 'a': + case 'aa': + case 'aaa': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated); + break; + case 'aaaa': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide); + break; + case 'aaaaa': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow); + break; + // Extended period of the day (midnight, at night, ...), standalone + case 'b': + case 'bb': + case 'bbb': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true); + break; + case 'bbbb': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true); + break; + case 'bbbbb': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true); + break; + // Extended period of the day (midnight, night, ...), standalone + case 'B': + case 'BB': + case 'BBB': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true); + break; + case 'BBBB': + formatter = + dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true); + break; + case 'BBBBB': + formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true); + break; + // Hour in AM/PM, (1-12) + case 'h': + formatter = dateGetter(DateType.Hours, 1, -12); + break; + case 'hh': + formatter = dateGetter(DateType.Hours, 2, -12); + break; + // Hour of the day (0-23) + case 'H': + formatter = dateGetter(DateType.Hours, 1); + break; + // Hour in day, padded (00-23) + case 'HH': + formatter = dateGetter(DateType.Hours, 2); + break; + // Minute of the hour (0-59) + case 'm': + formatter = dateGetter(DateType.Minutes, 1); + break; + case 'mm': + formatter = dateGetter(DateType.Minutes, 2); + break; + // Second of the minute (0-59) + case 's': + formatter = dateGetter(DateType.Seconds, 1); + break; + case 'ss': + formatter = dateGetter(DateType.Seconds, 2); + break; + // Fractional second + case 'S': + formatter = dateGetter(DateType.FractionalSeconds, 1); + break; + case 'SS': + formatter = dateGetter(DateType.FractionalSeconds, 2); + break; + case 'SSS': + formatter = dateGetter(DateType.FractionalSeconds, 3); + break; + // Timezone ISO8601 short format (-0430) + case 'Z': + case 'ZZ': + case 'ZZZ': + formatter = timeZoneGetter(ZoneWidth.Short); + break; + // Timezone ISO8601 extended format (-04:30) + case 'ZZZZZ': + formatter = timeZoneGetter(ZoneWidth.Extended); + break; + // Timezone GMT short format (GMT+4) + case 'O': + case 'OO': + case 'OOO': + // Should be location, but fallback to format O instead because we don't have the data yet + case 'z': + case 'zz': + case 'zzz': + formatter = timeZoneGetter(ZoneWidth.ShortGMT); + break; + // Timezone GMT long format (GMT+0430) + case 'OOOO': + case 'ZZZZ': + // Should be location, but fallback to format O instead because we don't have the data yet + case 'zzzz': + formatter = timeZoneGetter(ZoneWidth.Long); + break; + default: + return null; + } + DATE_FORMATS[format] = formatter; + return formatter; +} +/** + * @param {?} timezone + * @param {?} fallback + * @return {?} + */ +function timezoneToOffset(timezone, fallback) { + // Support: IE 9-11 only, Edge 13-15+ + // IE/Edge do not "understand" colon (`:`) in timezone + timezone = timezone.replace(/:/g, ''); + /** @type {?} */ + const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} +/** + * @param {?} date + * @param {?} minutes + * @return {?} + */ +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} +/** + * @param {?} date + * @param {?} timezone + * @param {?} reverse + * @return {?} + */ +function convertTimezoneToLocal(date, timezone, reverse) { + /** @type {?} */ + const reverseValue = reverse ? -1 : 1; + /** @type {?} */ + const dateTimezoneOffset = date.getTimezoneOffset(); + /** @type {?} */ + const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); + return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset)); +} +/** + * Converts a value to date. + * + * Supported input formats: + * - `Date` + * - number: timestamp + * - string: numeric (e.g. "1234"), ISO and date strings in a format supported by + * [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse). + * Note: ISO strings without time return a date without timeoffset. + * + * Throws if unable to convert to a date. + * @param {?} value + * @return {?} + */ +function toDate(value) { + if (isDate(value)) { + return value; + } + if (typeof value === 'number' && !isNaN(value)) { + return new Date(value); + } + if (typeof value === 'string') { + value = value.trim(); + /** @type {?} */ + const parsedNb = parseFloat(value); + // any string that only contains numbers, like "1234" but not like "1234hello" + if (!isNaN((/** @type {?} */ (value)) - parsedNb)) { + return new Date(parsedNb); + } + if (/^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) { + /* For ISO Strings without time the day, month and year must be extracted from the ISO String + before Date creation to avoid time offset and errors in the new Date. + If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new + date, some browsers (e.g. IE 9) will throw an invalid Date error. + If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset + is applied. + Note: ISO months are 0 for January, 1 for February, ... */ + const [y, m, d] = value.split('-').map((/** + * @param {?} val + * @return {?} + */ + (val) => +val)); + return new Date(y, m - 1, d); + } + /** @type {?} */ + let match; + if (match = value.match(ISO8601_DATE_REGEX)) { + return isoStringToDate(match); + } + } + /** @type {?} */ + const date = new Date((/** @type {?} */ (value))); + if (!isDate(date)) { + throw new Error(`Unable to convert "${value}" into a date`); + } + return date; +} +/** + * Converts a date in ISO8601 to a Date. + * Used instead of `Date.parse` because of browser discrepancies. + * @param {?} match + * @return {?} + */ +function isoStringToDate(match) { + /** @type {?} */ + const date = new Date(0); + /** @type {?} */ + let tzHour = 0; + /** @type {?} */ + let tzMin = 0; + // match[8] means that the string contains "Z" (UTC) or a timezone like "+01:00" or "+0100" + /** @type {?} */ + const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear; + /** @type {?} */ + const timeSetter = match[8] ? date.setUTCHours : date.setHours; + // if there is a timezone defined like "+01:00" or "+0100" + if (match[9]) { + tzHour = Number(match[9] + match[10]); + tzMin = Number(match[9] + match[11]); + } + dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3])); + /** @type {?} */ + const h = Number(match[4] || 0) - tzHour; + /** @type {?} */ + const m = Number(match[5] || 0) - tzMin; + /** @type {?} */ + const s = Number(match[6] || 0); + /** @type {?} */ + const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; +} +/** + * @param {?} value + * @return {?} + */ +function isDate(value) { + return value instanceof Date && !isNaN(value.valueOf()); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/; +/** @type {?} */ +const MAX_DIGITS = 22; +/** @type {?} */ +const DECIMAL_SEP = '.'; +/** @type {?} */ +const ZERO_CHAR = '0'; +/** @type {?} */ +const PATTERN_SEP = ';'; +/** @type {?} */ +const GROUP_SEP = ','; +/** @type {?} */ +const DIGIT_CHAR = '#'; +/** @type {?} */ +const CURRENCY_CHAR = '¤'; +/** @type {?} */ +const PERCENT_CHAR = '%'; +/** + * Transforms a number to a locale string based on a style and a format. + * @param {?} value + * @param {?} pattern + * @param {?} locale + * @param {?} groupSymbol + * @param {?} decimalSymbol + * @param {?=} digitsInfo + * @param {?=} isPercent + * @return {?} + */ +function formatNumberToLocaleString(value, pattern, locale, groupSymbol, decimalSymbol, digitsInfo, isPercent = false) { + /** @type {?} */ + let formattedText = ''; + /** @type {?} */ + let isZero = false; + if (!isFinite(value)) { + formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity); + } + else { + /** @type {?} */ + let parsedNumber = parseNumber(value); + if (isPercent) { + parsedNumber = toPercent(parsedNumber); + } + /** @type {?} */ + let minInt = pattern.minInt; + /** @type {?} */ + let minFraction = pattern.minFrac; + /** @type {?} */ + let maxFraction = pattern.maxFrac; + if (digitsInfo) { + /** @type {?} */ + const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP); + if (parts === null) { + throw new Error(`${digitsInfo} is not a valid digit info`); + } + /** @type {?} */ + const minIntPart = parts[1]; + /** @type {?} */ + const minFractionPart = parts[3]; + /** @type {?} */ + const maxFractionPart = parts[5]; + if (minIntPart != null) { + minInt = parseIntAutoRadix(minIntPart); + } + if (minFractionPart != null) { + minFraction = parseIntAutoRadix(minFractionPart); + } + if (maxFractionPart != null) { + maxFraction = parseIntAutoRadix(maxFractionPart); + } + else if (minFractionPart != null && minFraction > maxFraction) { + maxFraction = minFraction; + } + } + roundNumber(parsedNumber, minFraction, maxFraction); + /** @type {?} */ + let digits = parsedNumber.digits; + /** @type {?} */ + let integerLen = parsedNumber.integerLen; + /** @type {?} */ + const exponent = parsedNumber.exponent; + /** @type {?} */ + let decimals = []; + isZero = digits.every((/** + * @param {?} d + * @return {?} + */ + d => !d)); + // pad zeros for small numbers + for (; integerLen < minInt; integerLen++) { + digits.unshift(0); + } + // pad zeros for small numbers + for (; integerLen < 0; integerLen++) { + digits.unshift(0); + } + // extract decimals digits + if (integerLen > 0) { + decimals = digits.splice(integerLen, digits.length); + } + else { + decimals = digits; + digits = [0]; + } + // format the integer digits with grouping separators + /** @type {?} */ + const groups = []; + if (digits.length >= pattern.lgSize) { + groups.unshift(digits.splice(-pattern.lgSize, digits.length).join('')); + } + while (digits.length > pattern.gSize) { + groups.unshift(digits.splice(-pattern.gSize, digits.length).join('')); + } + if (digits.length) { + groups.unshift(digits.join('')); + } + formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol)); + // append the decimal digits + if (decimals.length) { + formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join(''); + } + if (exponent) { + formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + '+' + exponent; + } + } + if (value < 0 && !isZero) { + formattedText = pattern.negPre + formattedText + pattern.negSuf; + } + else { + formattedText = pattern.posPre + formattedText + pattern.posSuf; + } + return formattedText; +} +/** + * \@ngModule CommonModule + * \@description + * + * Formats a number as currency using locale rules. + * + * @see `formatNumber()` / `DecimalPipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} value The number to format. + * @param {?} locale A locale code for the locale format rules to use. + * @param {?} currency A string containing the currency symbol or its name, + * such as "$" or "Canadian Dollar". Used in output string, but does not affect the operation + * of the function. + * @param {?=} currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) + * currency code to use in the result string, such as `USD` for the US dollar and `EUR` for the euro. + * @param {?=} digitsInfo + * @return {?} The formatted currency value. + * + */ +function formatCurrency(value, locale, currency, currencyCode, digitsInfo) { + /** @type {?} */ + const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency); + /** @type {?} */ + const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); + pattern.minFrac = getNumberOfCurrencyDigits((/** @type {?} */ (currencyCode))); + pattern.maxFrac = pattern.minFrac; + /** @type {?} */ + const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo); + return res + .replace(CURRENCY_CHAR, currency) + // if we have 2 time the currency character, the second one is ignored + .replace(CURRENCY_CHAR, ''); +} +/** + * \@ngModule CommonModule + * \@description + * + * Formats a number as a percentage according to locale rules. + * + * @see `formatNumber()` / `DecimalPipe` / [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * \@publicApi + * + * @param {?} value The number to format. + * @param {?} locale A locale code for the locale format rules to use. + * @param {?=} digitsInfo + * @return {?} The formatted percentage value. + * + */ +function formatPercent(value, locale, digitsInfo) { + /** @type {?} */ + const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent); + /** @type {?} */ + const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); + /** @type {?} */ + const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true); + return res.replace(new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign)); +} +/** + * \@ngModule CommonModule + * \@description + * + * Formats a number as text, with group sizing, separator, and other + * parameters based on the locale. + * + * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n) + * + * \@publicApi + * @param {?} value The number to format. + * @param {?} locale A locale code for the locale format rules to use. + * @param {?=} digitsInfo + * @return {?} The formatted text string. + */ +function formatNumber(value, locale, digitsInfo) { + /** @type {?} */ + const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal); + /** @type {?} */ + const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign)); + return formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo); +} +/** + * @param {?} format + * @param {?=} minusSign + * @return {?} + */ +function parseNumberFormat(format, minusSign = '-') { + /** @type {?} */ + const p = { + minInt: 1, + minFrac: 0, + maxFrac: 0, + posPre: '', + posSuf: '', + negPre: '', + negSuf: '', + gSize: 0, + lgSize: 0 + }; + /** @type {?} */ + const patternParts = format.split(PATTERN_SEP); + /** @type {?} */ + const positive = patternParts[0]; + /** @type {?} */ + const negative = patternParts[1]; + /** @type {?} */ + const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ? + positive.split(DECIMAL_SEP) : + [ + positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1), + positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1) + ]; + /** @type {?} */ + const integer = positiveParts[0]; + /** @type {?} */ + const fraction = positiveParts[1] || ''; + p.posPre = integer.substr(0, integer.indexOf(DIGIT_CHAR)); + for (let i = 0; i < fraction.length; i++) { + /** @type {?} */ + const ch = fraction.charAt(i); + if (ch === ZERO_CHAR) { + p.minFrac = p.maxFrac = i + 1; + } + else if (ch === DIGIT_CHAR) { + p.maxFrac = i + 1; + } + else { + p.posSuf += ch; + } + } + /** @type {?} */ + const groups = integer.split(GROUP_SEP); + p.gSize = groups[1] ? groups[1].length : 0; + p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0; + if (negative) { + /** @type {?} */ + const trunkLen = positive.length - p.posPre.length - p.posSuf.length; + /** @type {?} */ + const pos = negative.indexOf(DIGIT_CHAR); + p.negPre = negative.substr(0, pos).replace(/'/g, ''); + p.negSuf = negative.substr(pos + trunkLen).replace(/'/g, ''); + } + else { + p.negPre = minusSign + p.posPre; + p.negSuf = p.posSuf; + } + return p; +} +// Transforms a parsed number into a percentage by multiplying it by 100 +/** + * @param {?} parsedNumber + * @return {?} + */ +function toPercent(parsedNumber) { + // if the number is 0, don't do anything + if (parsedNumber.digits[0] === 0) { + return parsedNumber; + } + // Getting the current number of decimals + /** @type {?} */ + const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen; + if (parsedNumber.exponent) { + parsedNumber.exponent += 2; + } + else { + if (fractionLen === 0) { + parsedNumber.digits.push(0, 0); + } + else if (fractionLen === 1) { + parsedNumber.digits.push(0); + } + parsedNumber.integerLen += 2; + } + return parsedNumber; +} +/** + * Parses a number. + * Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/ + * @param {?} num + * @return {?} + */ +function parseNumber(num) { + /** @type {?} */ + let numStr = Math.abs(num) + ''; + /** @type {?} */ + let exponent = 0; + /** @type {?} */ + let digits; + /** @type {?} */ + let integerLen; + /** @type {?} */ + let i; + /** @type {?} */ + let j; + /** @type {?} */ + let zeros; + // Decimal point? + if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) { + numStr = numStr.replace(DECIMAL_SEP, ''); + } + // Exponential form? + if ((i = numStr.search(/e/i)) > 0) { + // Work out the exponent. + if (integerLen < 0) + integerLen = i; + integerLen += +numStr.slice(i + 1); + numStr = numStr.substring(0, i); + } + else if (integerLen < 0) { + // There was no decimal point or exponent so it is an integer. + integerLen = numStr.length; + } + // Count the number of leading zeros. + for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */ + } + if (i === (zeros = numStr.length)) { + // The digits are all zero. + digits = [0]; + integerLen = 1; + } + else { + // Count the number of trailing zeros + zeros--; + while (numStr.charAt(zeros) === ZERO_CHAR) + zeros--; + // Trailing zeros are insignificant so ignore them + integerLen -= i; + digits = []; + // Convert string to array of digits without leading/trailing zeros. + for (j = 0; i <= zeros; i++, j++) { + digits[j] = Number(numStr.charAt(i)); + } + } + // If the number overflows the maximum allowed digits then use an exponent. + if (integerLen > MAX_DIGITS) { + digits = digits.splice(0, MAX_DIGITS - 1); + exponent = integerLen - 1; + integerLen = 1; + } + return { digits, exponent, integerLen }; +} +/** + * Round the parsed number to the specified number of decimal places + * This function changes the parsedNumber in-place + * @param {?} parsedNumber + * @param {?} minFrac + * @param {?} maxFrac + * @return {?} + */ +function roundNumber(parsedNumber, minFrac, maxFrac) { + if (minFrac > maxFrac) { + throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`); + } + /** @type {?} */ + let digits = parsedNumber.digits; + /** @type {?} */ + let fractionLen = digits.length - parsedNumber.integerLen; + /** @type {?} */ + const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac); + // The index of the digit to where rounding is to occur + /** @type {?} */ + let roundAt = fractionSize + parsedNumber.integerLen; + /** @type {?} */ + let digit = digits[roundAt]; + if (roundAt > 0) { + // Drop fractional digits beyond `roundAt` + digits.splice(Math.max(parsedNumber.integerLen, roundAt)); + // Set non-fractional digits beyond `roundAt` to 0 + for (let j = roundAt; j < digits.length; j++) { + digits[j] = 0; + } + } + else { + // We rounded to zero so reset the parsedNumber + fractionLen = Math.max(0, fractionLen); + parsedNumber.integerLen = 1; + digits.length = Math.max(1, roundAt = fractionSize + 1); + digits[0] = 0; + for (let i = 1; i < roundAt; i++) + digits[i] = 0; + } + if (digit >= 5) { + if (roundAt - 1 < 0) { + for (let k = 0; k > roundAt; k--) { + digits.unshift(0); + parsedNumber.integerLen++; + } + digits.unshift(1); + parsedNumber.integerLen++; + } + else { + digits[roundAt - 1]++; + } + } + // Pad out with zeros to get the required fraction length + for (; fractionLen < Math.max(0, fractionSize); fractionLen++) + digits.push(0); + /** @type {?} */ + let dropTrailingZeros = fractionSize !== 0; + // Minimal length = nb of decimals required + current nb of integers + // Any number besides that is optional and can be removed if it's a trailing 0 + /** @type {?} */ + const minLen = minFrac + parsedNumber.integerLen; + // Do any carrying, e.g. a digit was rounded up to 10 + /** @type {?} */ + const carry = digits.reduceRight((/** + * @param {?} carry + * @param {?} d + * @param {?} i + * @param {?} digits + * @return {?} + */ + function (carry, d, i, digits) { + d = d + carry; + digits[i] = d < 10 ? d : d - 10; // d % 10 + if (dropTrailingZeros) { + // Do not keep meaningless fractional trailing zeros (e.g. 15.52000 --> 15.52) + if (digits[i] === 0 && i >= minLen) { + digits.pop(); + } + else { + dropTrailingZeros = false; + } + } + return d >= 10 ? 1 : 0; // Math.floor(d / 10); + }), 0); + if (carry) { + digits.unshift(carry); + parsedNumber.integerLen++; + } +} +/** + * @param {?} text + * @return {?} + */ +function parseIntAutoRadix(text) { + /** @type {?} */ + const result = parseInt(text); + if (isNaN(result)) { + throw new Error('Invalid integer literal when parsing ' + text); + } + return result; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @deprecated from v5 + * @type {?} + */ +const DEPRECATED_PLURAL_FN = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('UseV4Plurals'); +/** + * \@publicApi + * @abstract + */ +class NgLocalization { +} +/** + * Returns the plural category for a given value. + * - "=value" when the case exists, + * - the plural category otherwise + * @param {?} value + * @param {?} cases + * @param {?} ngLocalization + * @param {?=} locale + * @return {?} + */ +function getPluralCategory(value, cases, ngLocalization, locale) { + /** @type {?} */ + let key = `=${value}`; + if (cases.indexOf(key) > -1) { + return key; + } + key = ngLocalization.getPluralCategory(value, locale); + if (cases.indexOf(key) > -1) { + return key; + } + if (cases.indexOf('other') > -1) { + return 'other'; + } + throw new Error(`No plural message found for value "${value}"`); +} +/** + * Returns the plural case based on the locale + * + * \@publicApi + */ +class NgLocaleLocalization extends NgLocalization { + /** + * @param {?} locale + * @param {?=} deprecatedPluralFn + */ + constructor(locale, deprecatedPluralFn) { + super(); + this.locale = locale; + this.deprecatedPluralFn = deprecatedPluralFn; + } + /** + * @param {?} value + * @param {?=} locale + * @return {?} + */ + getPluralCategory(value, locale) { + /** @type {?} */ + const plural = this.deprecatedPluralFn ? this.deprecatedPluralFn(locale || this.locale, value) : + getLocalePluralCase(locale || this.locale)(value); + switch (plural) { + case Plural.Zero: + return 'zero'; + case Plural.One: + return 'one'; + case Plural.Two: + return 'two'; + case Plural.Few: + return 'few'; + case Plural.Many: + return 'many'; + default: + return 'other'; + } + } +} +NgLocaleLocalization.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +NgLocaleLocalization.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }, + { type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [DEPRECATED_PLURAL_FN,] }] } +]; +/** + * Returns the plural case based on the locale + * + * @deprecated from v5 the plural case function is in locale data files common/locales/*.ts + * \@publicApi + * @param {?} locale + * @param {?} nLike + * @return {?} + */ +function getPluralCase(locale, nLike) { + // TODO(vicb): lazy compute + if (typeof nLike === 'string') { + nLike = parseInt((/** @type {?} */ (nLike)), 10); + } + /** @type {?} */ + const n = (/** @type {?} */ (nLike)); + /** @type {?} */ + const nDecimal = n.toString().replace(/^[^.]*\.?/, ''); + /** @type {?} */ + const i = Math.floor(Math.abs(n)); + /** @type {?} */ + const v = nDecimal.length; + /** @type {?} */ + const f = parseInt(nDecimal, 10); + /** @type {?} */ + const t = parseInt(n.toString().replace(/^[^.]*\.?|0+$/g, ''), 10) || 0; + /** @type {?} */ + const lang = locale.split('-')[0].toLowerCase(); + switch (lang) { + case 'af': + case 'asa': + case 'az': + case 'bem': + case 'bez': + case 'bg': + case 'brx': + case 'ce': + case 'cgg': + case 'chr': + case 'ckb': + case 'ee': + case 'el': + case 'eo': + case 'es': + case 'eu': + case 'fo': + case 'fur': + case 'gsw': + case 'ha': + case 'haw': + case 'hu': + case 'jgo': + case 'jmc': + case 'ka': + case 'kk': + case 'kkj': + case 'kl': + case 'ks': + case 'ksb': + case 'ky': + case 'lb': + case 'lg': + case 'mas': + case 'mgo': + case 'ml': + case 'mn': + case 'nb': + case 'nd': + case 'ne': + case 'nn': + case 'nnh': + case 'nyn': + case 'om': + case 'or': + case 'os': + case 'ps': + case 'rm': + case 'rof': + case 'rwk': + case 'saq': + case 'seh': + case 'sn': + case 'so': + case 'sq': + case 'ta': + case 'te': + case 'teo': + case 'tk': + case 'tr': + case 'ug': + case 'uz': + case 'vo': + case 'vun': + case 'wae': + case 'xog': + if (n === 1) + return Plural.One; + return Plural.Other; + case 'ak': + case 'ln': + case 'mg': + case 'pa': + case 'ti': + if (n === Math.floor(n) && n >= 0 && n <= 1) + return Plural.One; + return Plural.Other; + case 'am': + case 'as': + case 'bn': + case 'fa': + case 'gu': + case 'hi': + case 'kn': + case 'mr': + case 'zu': + if (i === 0 || n === 1) + return Plural.One; + return Plural.Other; + case 'ar': + if (n === 0) + return Plural.Zero; + if (n === 1) + return Plural.One; + if (n === 2) + return Plural.Two; + if (n % 100 === Math.floor(n % 100) && n % 100 >= 3 && n % 100 <= 10) + return Plural.Few; + if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 99) + return Plural.Many; + return Plural.Other; + case 'ast': + case 'ca': + case 'de': + case 'en': + case 'et': + case 'fi': + case 'fy': + case 'gl': + case 'it': + case 'nl': + case 'sv': + case 'sw': + case 'ur': + case 'yi': + if (i === 1 && v === 0) + return Plural.One; + return Plural.Other; + case 'be': + if (n % 10 === 1 && !(n % 100 === 11)) + return Plural.One; + if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 4 && + !(n % 100 >= 12 && n % 100 <= 14)) + return Plural.Few; + if (n % 10 === 0 || n % 10 === Math.floor(n % 10) && n % 10 >= 5 && n % 10 <= 9 || + n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 14) + return Plural.Many; + return Plural.Other; + case 'br': + if (n % 10 === 1 && !(n % 100 === 11 || n % 100 === 71 || n % 100 === 91)) + return Plural.One; + if (n % 10 === 2 && !(n % 100 === 12 || n % 100 === 72 || n % 100 === 92)) + return Plural.Two; + if (n % 10 === Math.floor(n % 10) && (n % 10 >= 3 && n % 10 <= 4 || n % 10 === 9) && + !(n % 100 >= 10 && n % 100 <= 19 || n % 100 >= 70 && n % 100 <= 79 || + n % 100 >= 90 && n % 100 <= 99)) + return Plural.Few; + if (!(n === 0) && n % 1e6 === 0) + return Plural.Many; + return Plural.Other; + case 'bs': + case 'hr': + case 'sr': + if (v === 0 && i % 10 === 1 && !(i % 100 === 11) || f % 10 === 1 && !(f % 100 === 11)) + return Plural.One; + if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 && + !(i % 100 >= 12 && i % 100 <= 14) || + f % 10 === Math.floor(f % 10) && f % 10 >= 2 && f % 10 <= 4 && + !(f % 100 >= 12 && f % 100 <= 14)) + return Plural.Few; + return Plural.Other; + case 'cs': + case 'sk': + if (i === 1 && v === 0) + return Plural.One; + if (i === Math.floor(i) && i >= 2 && i <= 4 && v === 0) + return Plural.Few; + if (!(v === 0)) + return Plural.Many; + return Plural.Other; + case 'cy': + if (n === 0) + return Plural.Zero; + if (n === 1) + return Plural.One; + if (n === 2) + return Plural.Two; + if (n === 3) + return Plural.Few; + if (n === 6) + return Plural.Many; + return Plural.Other; + case 'da': + if (n === 1 || !(t === 0) && (i === 0 || i === 1)) + return Plural.One; + return Plural.Other; + case 'dsb': + case 'hsb': + if (v === 0 && i % 100 === 1 || f % 100 === 1) + return Plural.One; + if (v === 0 && i % 100 === 2 || f % 100 === 2) + return Plural.Two; + if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 || + f % 100 === Math.floor(f % 100) && f % 100 >= 3 && f % 100 <= 4) + return Plural.Few; + return Plural.Other; + case 'ff': + case 'fr': + case 'hy': + case 'kab': + if (i === 0 || i === 1) + return Plural.One; + return Plural.Other; + case 'fil': + if (v === 0 && (i === 1 || i === 2 || i === 3) || + v === 0 && !(i % 10 === 4 || i % 10 === 6 || i % 10 === 9) || + !(v === 0) && !(f % 10 === 4 || f % 10 === 6 || f % 10 === 9)) + return Plural.One; + return Plural.Other; + case 'ga': + if (n === 1) + return Plural.One; + if (n === 2) + return Plural.Two; + if (n === Math.floor(n) && n >= 3 && n <= 6) + return Plural.Few; + if (n === Math.floor(n) && n >= 7 && n <= 10) + return Plural.Many; + return Plural.Other; + case 'gd': + if (n === 1 || n === 11) + return Plural.One; + if (n === 2 || n === 12) + return Plural.Two; + if (n === Math.floor(n) && (n >= 3 && n <= 10 || n >= 13 && n <= 19)) + return Plural.Few; + return Plural.Other; + case 'gv': + if (v === 0 && i % 10 === 1) + return Plural.One; + if (v === 0 && i % 10 === 2) + return Plural.Two; + if (v === 0 && + (i % 100 === 0 || i % 100 === 20 || i % 100 === 40 || i % 100 === 60 || i % 100 === 80)) + return Plural.Few; + if (!(v === 0)) + return Plural.Many; + return Plural.Other; + case 'he': + if (i === 1 && v === 0) + return Plural.One; + if (i === 2 && v === 0) + return Plural.Two; + if (v === 0 && !(n >= 0 && n <= 10) && n % 10 === 0) + return Plural.Many; + return Plural.Other; + case 'is': + if (t === 0 && i % 10 === 1 && !(i % 100 === 11) || !(t === 0)) + return Plural.One; + return Plural.Other; + case 'ksh': + if (n === 0) + return Plural.Zero; + if (n === 1) + return Plural.One; + return Plural.Other; + case 'kw': + case 'naq': + case 'se': + case 'smn': + if (n === 1) + return Plural.One; + if (n === 2) + return Plural.Two; + return Plural.Other; + case 'lag': + if (n === 0) + return Plural.Zero; + if ((i === 0 || i === 1) && !(n === 0)) + return Plural.One; + return Plural.Other; + case 'lt': + if (n % 10 === 1 && !(n % 100 >= 11 && n % 100 <= 19)) + return Plural.One; + if (n % 10 === Math.floor(n % 10) && n % 10 >= 2 && n % 10 <= 9 && + !(n % 100 >= 11 && n % 100 <= 19)) + return Plural.Few; + if (!(f === 0)) + return Plural.Many; + return Plural.Other; + case 'lv': + case 'prg': + if (n % 10 === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19 || + v === 2 && f % 100 === Math.floor(f % 100) && f % 100 >= 11 && f % 100 <= 19) + return Plural.Zero; + if (n % 10 === 1 && !(n % 100 === 11) || v === 2 && f % 10 === 1 && !(f % 100 === 11) || + !(v === 2) && f % 10 === 1) + return Plural.One; + return Plural.Other; + case 'mk': + if (v === 0 && i % 10 === 1 || f % 10 === 1) + return Plural.One; + return Plural.Other; + case 'mt': + if (n === 1) + return Plural.One; + if (n === 0 || n % 100 === Math.floor(n % 100) && n % 100 >= 2 && n % 100 <= 10) + return Plural.Few; + if (n % 100 === Math.floor(n % 100) && n % 100 >= 11 && n % 100 <= 19) + return Plural.Many; + return Plural.Other; + case 'pl': + if (i === 1 && v === 0) + return Plural.One; + if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 && + !(i % 100 >= 12 && i % 100 <= 14)) + return Plural.Few; + if (v === 0 && !(i === 1) && i % 10 === Math.floor(i % 10) && i % 10 >= 0 && i % 10 <= 1 || + v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 || + v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 12 && i % 100 <= 14) + return Plural.Many; + return Plural.Other; + case 'pt': + if (n === Math.floor(n) && n >= 0 && n <= 2 && !(n === 2)) + return Plural.One; + return Plural.Other; + case 'ro': + if (i === 1 && v === 0) + return Plural.One; + if (!(v === 0) || n === 0 || + !(n === 1) && n % 100 === Math.floor(n % 100) && n % 100 >= 1 && n % 100 <= 19) + return Plural.Few; + return Plural.Other; + case 'ru': + case 'uk': + if (v === 0 && i % 10 === 1 && !(i % 100 === 11)) + return Plural.One; + if (v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 2 && i % 10 <= 4 && + !(i % 100 >= 12 && i % 100 <= 14)) + return Plural.Few; + if (v === 0 && i % 10 === 0 || + v === 0 && i % 10 === Math.floor(i % 10) && i % 10 >= 5 && i % 10 <= 9 || + v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 11 && i % 100 <= 14) + return Plural.Many; + return Plural.Other; + case 'shi': + if (i === 0 || n === 1) + return Plural.One; + if (n === Math.floor(n) && n >= 2 && n <= 10) + return Plural.Few; + return Plural.Other; + case 'si': + if (n === 0 || n === 1 || i === 0 && f === 1) + return Plural.One; + return Plural.Other; + case 'sl': + if (v === 0 && i % 100 === 1) + return Plural.One; + if (v === 0 && i % 100 === 2) + return Plural.Two; + if (v === 0 && i % 100 === Math.floor(i % 100) && i % 100 >= 3 && i % 100 <= 4 || !(v === 0)) + return Plural.Few; + return Plural.Other; + case 'tzm': + if (n === Math.floor(n) && n >= 0 && n <= 1 || n === Math.floor(n) && n >= 11 && n <= 99) + return Plural.One; + return Plural.Other; + // When there is no specification, the default is always "other" + // Spec: http://cldr.unicode.org/index/cldr-spec/plural-rules + // > other (required—general plural form — also used if the language only has a single form) + default: + return Plural.Other; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Register global data to be used internally by Angular. See the + * ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data. + * + * \@publicApi + * @param {?} data + * @param {?=} localeId + * @param {?=} extraData + * @return {?} + */ +// The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1 +function registerLocaleData(data, localeId, extraData) { + if (typeof localeId !== 'string') { + extraData = localeId; + localeId = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId]; + } + localeId = localeId.toLowerCase().replace(/_/g, '-'); + _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLOCALE_DATA"][localeId] = data; + if (extraData) { + _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLOCALE_DATA"][localeId][_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData] = extraData; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** + * @param {?} cookieStr + * @param {?} name + * @return {?} + */ +function parseCookieValue(cookieStr, name) { + name = encodeURIComponent(name); + for (const cookie of cookieStr.split(';')) { + /** @type {?} */ + const eqIndex = cookie.indexOf('='); + const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)]; + if (cookieName.trim() === name) { + return decodeURIComponent(cookieValue); + } + } + return null; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** + * Used to diff and convert ngStyle/ngClass instructions into [style] and [class] bindings. + * + * ngStyle and ngClass both accept various forms of input and behave differently than that + * of how [style] and [class] behave in Angular. + * + * The differences are: + * - ngStyle and ngClass both **watch** their binding values for changes each time CD runs + * while [style] and [class] bindings do not (they check for identity changes) + * - ngStyle allows for unit-based keys (e.g. `{'max-width.px':value}`) and [style] does not + * - ngClass supports arrays of class values and [class] only accepts map and string values + * - ngClass allows for multiple className keys (space-separated) within an array or map + * (as the * key) while [class] only accepts a simple key/value map object + * + * Having Angular understand and adapt to all the different forms of behavior is complicated + * and unnecessary. Instead, ngClass and ngStyle should have their input values be converted + * into something that the core-level [style] and [class] bindings understand. + * + * This [StylingDiffer] class handles this conversion by creating a new input value each time + * the inner representation of the binding value have changed. + * + * ## Why do we care about ngStyle/ngClass? + * The styling algorithm code (documented inside of `render3/interfaces/styling.ts`) needs to + * respect and understand the styling values emitted through ngStyle and ngClass (when they + * are present and used in a template). + * + * Instead of having these directives manage styling on their own, they should be included + * into the Angular styling algorithm that exists for [style] and [class] bindings. + * + * Here's why: + * + * - If ngStyle/ngClass is used in combination with [style]/[class] bindings then the + * styles and classes would fall out of sync and be applied and updated at + * inconsistent times + * - Both ngClass/ngStyle do not respect [class.name] and [style.prop] bindings + * (they will write over them given the right combination of events) + * + * ``` + * + *
...
+ * + * + *
...
+ * ``` + * - ngClass/ngStyle were written as a directives and made use of maps, closures and other + * expensive data structures which were evaluated each time CD runs + * @template T + */ +class StylingDiffer { + /** + * @param {?} _name + * @param {?} _options + */ + constructor(_name, _options) { + this._name = _name; + this._options = _options; + this.value = null; + this._lastSetValue = null; + this._lastSetValueType = 0 /* Null */; + this._lastSetValueIdentityChange = false; + } + /** + * Sets (updates) the styling value within the differ. + * + * Only when `hasValueChanged` is called then this new value will be evaluted + * and checked against the previous value. + * + * @param {?} value the new styling value provided from the ngClass/ngStyle binding + * @return {?} + */ + setValue(value) { + if (Array.isArray(value)) { + this._lastSetValueType = 4 /* Array */; + } + else if (value instanceof Set) { + this._lastSetValueType = 8 /* Set */; + } + else if (value && typeof value === 'string') { + if (!(this._options & 4 /* AllowStringValue */)) { + throw new Error(this._name + ' string values are not allowed'); + } + this._lastSetValueType = 1 /* String */; + } + else { + this._lastSetValueType = value ? 2 /* Map */ : 0 /* Null */; + } + this._lastSetValueIdentityChange = true; + this._lastSetValue = value || null; + } + /** + * Determines whether or not the value has changed. + * + * This function can be called right after `setValue()` is called, but it can also be + * called incase the existing value (if it's a collection) changes internally. If the + * value is indeed a collection it will do the necessary diffing work and produce a + * new object value as assign that to `value`. + * + * @return {?} whether or not the value has changed in some way. + */ + hasValueChanged() { + /** @type {?} */ + let valueHasChanged = this._lastSetValueIdentityChange; + if (!valueHasChanged && !(this._lastSetValueType & 14 /* Collection */)) + return false; + /** @type {?} */ + let finalValue = null; + /** @type {?} */ + const trimValues = (this._options & 1 /* TrimProperties */) ? true : false; + /** @type {?} */ + const parseOutUnits = (this._options & 8 /* AllowUnits */) ? true : false; + /** @type {?} */ + const allowSubKeys = (this._options & 2 /* AllowSubKeys */) ? true : false; + switch (this._lastSetValueType) { + // case 1: [input]="string" + case 1 /* String */: + /** @type {?} */ + const tokens = ((/** @type {?} */ (this._lastSetValue))).split(/\s+/g); + if (this._options & 16 /* ForceAsMap */) { + finalValue = {}; + tokens.forEach((/** + * @param {?} token + * @param {?} i + * @return {?} + */ + (token, i) => ((/** @type {?} */ (finalValue)))[token] = true)); + } + else { + finalValue = tokens.reduce((/** + * @param {?} str + * @param {?} token + * @param {?} i + * @return {?} + */ + (str, token, i) => str + (i ? ' ' : '') + token)); + } + break; + // case 2: [input]="{key:value}" + case 2 /* Map */: + /** @type {?} */ + const map = (/** @type {?} */ (this._lastSetValue)); + /** @type {?} */ + const keys = Object.keys(map); + if (!valueHasChanged) { + if (this.value) { + // we know that the classExp value exists and that it is + // a map (otherwise an identity change would have occurred) + valueHasChanged = mapHasChanged(keys, (/** @type {?} */ (this.value)), map); + } + else { + valueHasChanged = true; + } + } + if (valueHasChanged) { + finalValue = + bulidMapFromValues(this._name, trimValues, parseOutUnits, allowSubKeys, map, keys); + } + break; + // case 3a: [input]="[str1, str2, ...]" + // case 3b: [input]="Set" + case 4 /* Array */: + case 8 /* Set */: + /** @type {?} */ + const values = Array.from((/** @type {?} */ (this._lastSetValue))); + if (!valueHasChanged) { + /** @type {?} */ + const keys = Object.keys((/** @type {?} */ (this.value))); + valueHasChanged = !arrayEqualsArray(keys, values); + } + if (valueHasChanged) { + finalValue = + bulidMapFromValues(this._name, trimValues, parseOutUnits, allowSubKeys, values); + } + break; + // case 4: [input]="null|undefined" + default: + finalValue = null; + break; + } + if (valueHasChanged) { + ((/** @type {?} */ (this))).value = (/** @type {?} */ (finalValue)); + } + return valueHasChanged; + } +} +/** + * builds and returns a map based on the values input value + * + * If the `keys` param is provided then the `values` param is treated as a + * string map. Otherwise `values` is treated as a string array. + * @param {?} errorPrefix + * @param {?} trim + * @param {?} parseOutUnits + * @param {?} allowSubKeys + * @param {?} values + * @param {?=} keys + * @return {?} + */ +function bulidMapFromValues(errorPrefix, trim, parseOutUnits, allowSubKeys, values, keys) { + /** @type {?} */ + const map = {}; + if (keys) { + // case 1: map + for (let i = 0; i < keys.length; i++) { + /** @type {?} */ + let key = keys[i]; + key = trim ? key.trim() : key; + /** @type {?} */ + const value = ((/** @type {?} */ (values)))[key]; + setMapValues(map, key, value, parseOutUnits, allowSubKeys); + } + } + else { + // case 2: array + for (let i = 0; i < values.length; i++) { + /** @type {?} */ + let value = ((/** @type {?} */ (values)))[i]; + assertValidValue(errorPrefix, value); + value = trim ? value.trim() : value; + setMapValues(map, value, true, false, allowSubKeys); + } + } + return map; +} +/** + * @param {?} errorPrefix + * @param {?} value + * @return {?} + */ +function assertValidValue(errorPrefix, value) { + if (typeof value !== 'string') { + throw new Error(`${errorPrefix} can only toggle CSS classes expressed as strings, got ${value}`); + } +} +/** + * @param {?} map + * @param {?} key + * @param {?} value + * @param {?} parseOutUnits + * @param {?} allowSubKeys + * @return {?} + */ +function setMapValues(map, key, value, parseOutUnits, allowSubKeys) { + if (allowSubKeys && key.indexOf(' ') > 0) { + /** @type {?} */ + const innerKeys = key.split(/\s+/g); + for (let j = 0; j < innerKeys.length; j++) { + setIndividualMapValue(map, innerKeys[j], value, parseOutUnits); + } + } + else { + setIndividualMapValue(map, key, value, parseOutUnits); + } +} +/** + * @param {?} map + * @param {?} key + * @param {?} value + * @param {?} parseOutUnits + * @return {?} + */ +function setIndividualMapValue(map, key, value, parseOutUnits) { + if (parseOutUnits) { + /** @type {?} */ + const values = normalizeStyleKeyAndValue(key, value); + value = values.value; + key = values.key; + } + map[key] = value; +} +/** + * @param {?} key + * @param {?} value + * @return {?} + */ +function normalizeStyleKeyAndValue(key, value) { + /** @type {?} */ + const index = key.indexOf('.'); + if (index > 0) { + /** @type {?} */ + const unit = key.substr(index + 1); + key = key.substring(0, index); + if (value != null) { // we should not convert null values to string + value += unit; + } + } + return { key, value }; +} +/** + * @param {?} keys + * @param {?} a + * @param {?} b + * @return {?} + */ +function mapHasChanged(keys, a, b) { + /** @type {?} */ + const oldKeys = Object.keys(a); + /** @type {?} */ + const newKeys = keys; + // the keys are different which means the map changed + if (!arrayEqualsArray(oldKeys, newKeys)) { + return true; + } + for (let i = 0; i < newKeys.length; i++) { + /** @type {?} */ + const key = newKeys[i]; + if (a[key] !== b[key]) { + return true; + } + } + return false; +} +/** + * @param {?} a + * @param {?} b + * @return {?} + */ +function arrayEqualsArray(a, b) { + if (a && b) { + if (a.length !== b.length) + return false; + for (let i = 0; i < a.length; i++) { + if (b.indexOf(a[i]) === -1) + return false; + } + return true; + } + return false; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Used as a token for an injected service within the NgClass directive. + * + * NgClass behaves differenly whether or not VE is being used or not. If + * present then the legacy ngClass diffing algorithm will be used as an + * injected service. Otherwise the new diffing algorithm (which delegates + * to the `[class]` binding) will be used. This toggle behavior is done so + * via the ivy_switch mechanism. + * @abstract + */ +class NgClassImpl { +} +class NgClassR2Impl { + /** + * @param {?} _iterableDiffers + * @param {?} _keyValueDiffers + * @param {?} _ngEl + * @param {?} _renderer + */ + constructor(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) { + this._iterableDiffers = _iterableDiffers; + this._keyValueDiffers = _keyValueDiffers; + this._ngEl = _ngEl; + this._renderer = _renderer; + this._initialClasses = []; + } + /** + * @return {?} + */ + getValue() { return null; } + /** + * @param {?} value + * @return {?} + */ + setClass(value) { + this._removeClasses(this._initialClasses); + this._initialClasses = typeof value === 'string' ? value.split(/\s+/) : []; + this._applyClasses(this._initialClasses); + this._applyClasses(this._rawClass); + } + /** + * @param {?} value + * @return {?} + */ + setNgClass(value) { + this._removeClasses(this._rawClass); + this._applyClasses(this._initialClasses); + this._iterableDiffer = null; + this._keyValueDiffer = null; + this._rawClass = typeof value === 'string' ? value.split(/\s+/) : value; + if (this._rawClass) { + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisListLikeIterable"])(this._rawClass)) { + this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create(); + } + else { + this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create(); + } + } + } + /** + * @return {?} + */ + applyChanges() { + if (this._iterableDiffer) { + /** @type {?} */ + const iterableChanges = this._iterableDiffer.diff((/** @type {?} */ (this._rawClass))); + if (iterableChanges) { + this._applyIterableChanges(iterableChanges); + } + } + else if (this._keyValueDiffer) { + /** @type {?} */ + const keyValueChanges = this._keyValueDiffer.diff((/** @type {?} */ (this._rawClass))); + if (keyValueChanges) { + this._applyKeyValueChanges(keyValueChanges); + } + } + } + /** + * @private + * @param {?} changes + * @return {?} + */ + _applyKeyValueChanges(changes) { + changes.forEachAddedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._toggleClass(record.key, record.currentValue))); + changes.forEachChangedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._toggleClass(record.key, record.currentValue))); + changes.forEachRemovedItem((/** + * @param {?} record + * @return {?} + */ + (record) => { + if (record.previousValue) { + this._toggleClass(record.key, false); + } + })); + } + /** + * @private + * @param {?} changes + * @return {?} + */ + _applyIterableChanges(changes) { + changes.forEachAddedItem((/** + * @param {?} record + * @return {?} + */ + (record) => { + if (typeof record.item === 'string') { + this._toggleClass(record.item, true); + } + else { + throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(record.item)}`); + } + })); + changes.forEachRemovedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._toggleClass(record.item, false))); + } + /** + * Applies a collection of CSS classes to the DOM element. + * + * For argument of type Set and Array CSS class names contained in those collections are always + * added. + * For argument of type Map CSS class name in the map's key is toggled based on the value (added + * for truthy and removed for falsy). + * @private + * @param {?} rawClassVal + * @return {?} + */ + _applyClasses(rawClassVal) { + if (rawClassVal) { + if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { + ((/** @type {?} */ (rawClassVal))).forEach((/** + * @param {?} klass + * @return {?} + */ + (klass) => this._toggleClass(klass, true))); + } + else { + Object.keys(rawClassVal).forEach((/** + * @param {?} klass + * @return {?} + */ + klass => this._toggleClass(klass, !!rawClassVal[klass]))); + } + } + } + /** + * Removes a collection of CSS classes from the DOM element. This is mostly useful for cleanup + * purposes. + * @private + * @param {?} rawClassVal + * @return {?} + */ + _removeClasses(rawClassVal) { + if (rawClassVal) { + if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) { + ((/** @type {?} */ (rawClassVal))).forEach((/** + * @param {?} klass + * @return {?} + */ + (klass) => this._toggleClass(klass, false))); + } + else { + Object.keys(rawClassVal).forEach((/** + * @param {?} klass + * @return {?} + */ + klass => this._toggleClass(klass, false))); + } + } + } + /** + * @private + * @param {?} klass + * @param {?} enabled + * @return {?} + */ + _toggleClass(klass, enabled) { + klass = klass.trim(); + if (klass) { + klass.split(/\s+/g).forEach((/** + * @param {?} klass + * @return {?} + */ + klass => { + if (enabled) { + this._renderer.addClass(this._ngEl.nativeElement, klass); + } + else { + this._renderer.removeClass(this._ngEl.nativeElement, klass); + } + })); + } + } +} +NgClassR2Impl.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +NgClassR2Impl.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] } +]; +class NgClassR3Impl { + constructor() { + this._value = null; + this._ngClassDiffer = new StylingDiffer('NgClass', 1 /* TrimProperties */ | + 2 /* AllowSubKeys */ | + 4 /* AllowStringValue */ | 16 /* ForceAsMap */); + this._classStringDiffer = null; + } + /** + * @return {?} + */ + getValue() { return this._value; } + /** + * @param {?} value + * @return {?} + */ + setClass(value) { + // early exit incase the binding gets emitted as an empty value which + // means there is no reason to instantiate and diff the values... + if (!value && !this._classStringDiffer) + return; + this._classStringDiffer = this._classStringDiffer || + new StylingDiffer('class', 4 /* AllowStringValue */ | 16 /* ForceAsMap */); + this._classStringDiffer.setValue(value); + } + /** + * @param {?} value + * @return {?} + */ + setNgClass(value) { + this._ngClassDiffer.setValue(value); + } + /** + * @return {?} + */ + applyChanges() { + /** @type {?} */ + const classChanged = this._classStringDiffer ? this._classStringDiffer.hasValueChanged() : false; + /** @type {?} */ + const ngClassChanged = this._ngClassDiffer.hasValueChanged(); + if (classChanged || ngClassChanged) { + /** @type {?} */ + let value = this._ngClassDiffer.value; + if (this._classStringDiffer) { + /** @type {?} */ + let classValue = this._classStringDiffer.value; + if (classValue) { + value = value ? Object.assign({}, classValue, value) : classValue; + } + } + this._value = value; + } + } +} +NgClassR3Impl.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +// the implementation for both NgStyleR2Impl and NgStyleR3Impl are +// not ivy_switch'd away, instead they are only hooked up into the +// DI via NgStyle's directive's provider property. +/** @type {?} */ +const NgClassImplProvider__PRE_R3__ = { + provide: NgClassImpl, + useClass: NgClassR2Impl +}; +/** @type {?} */ +const NgClassImplProvider__POST_R3__ = { + provide: NgClassImpl, + useClass: NgClassR3Impl +}; +/** @type {?} */ +const NgClassImplProvider = NgClassImplProvider__PRE_R3__; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/* + * NgClass (as well as NgStyle) behaves differently when loaded in the VE and when not. + * + * If the VE is present (which is for older versions of Angular) then NgClass will inject + * the legacy diffing algorithm as a service and delegate all styling changes to that. + * + * If the VE is not present then NgStyle will normalize (through the injected service) and + * then write all styling changes to the `[style]` binding directly (through a host binding). + * Then Angular will notice the host binding change and treat the changes as styling + * changes and apply them via the core styling instructions that exist within Angular. + */ +// used when the VE is present +/** @type {?} */ +const ngClassDirectiveDef__PRE_R3__ = undefined; +// used when the VE is not present (note the directive will +// never be instantiated normally because it is apart of a +// base class) +const ɵ0 = /** + * @return {?} + */ +function () { }, ɵ1 = /** + * @return {?} + */ +() => { }, ɵ2 = /** + * @param {?} rf + * @param {?} ctx + * @param {?} elIndex + * @return {?} + */ +function (rf, ctx, elIndex) { + if (rf & 1 /* Create */) { + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyling"])(); + } + if (rf & 2 /* Update */) { + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵclassMap"])(ctx.getValue()); + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstylingApply"])(); + } +}; +/** @type {?} */ +const ngClassDirectiveDef__POST_R3__ = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"])({ + type: (/** @type {?} */ ((ɵ0))), + selectors: (/** @type {?} */ (null)), + factory: (ɵ1), + hostBindings: (ɵ2) +}); +/** @type {?} */ +const ngClassDirectiveDef = ngClassDirectiveDef__PRE_R3__; +/** + * Serves as the base non-VE container for NgClass. + * + * While this is a base class that NgClass extends from, the + * class itself acts as a container for non-VE code to setup + * a link to the `[class]` host binding (via the static + * `ngDirectiveDef` property on the class). + * + * Note that the `ngDirectiveDef` property's code is switched + * depending if VE is present or not (this allows for the + * binding code to be set only for newer versions of Angular). + * + * \@publicApi + */ +class NgClassBase { + /** + * @param {?} _delegate + */ + constructor(_delegate) { + this._delegate = _delegate; + } + /** + * @return {?} + */ + getValue() { return this._delegate.getValue(); } +} +/** @nocollapse */ NgClassBase.ngDirectiveDef = ngClassDirectiveDef; +/** + * \@ngModule CommonModule + * + * \@usageNotes + * ``` + * ... + * + * ... + * + * ... + * + * ... + * + * ... + * ``` + * + * \@description + * + * Adds and removes CSS classes on an HTML element. + * + * The CSS classes are updated as follows, depending on the type of the expression evaluation: + * - `string` - the CSS classes listed in the string (space delimited) are added, + * - `Array` - the CSS classes declared as Array elements are added, + * - `Object` - keys are CSS classes that get added when the expression given in the value + * evaluates to a truthy value, otherwise they are removed. + * + * \@publicApi + */ +class NgClass extends NgClassBase { + /** + * @param {?} delegate + */ + constructor(delegate) { super(delegate); } + /** + * @param {?} value + * @return {?} + */ + set klass(value) { this._delegate.setClass(value); } + /** + * @param {?} value + * @return {?} + */ + set ngClass(value) { + this._delegate.setNgClass(value); + } + /** + * @return {?} + */ + ngDoCheck() { this._delegate.applyChanges(); } +} +NgClass.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngClass]', providers: [NgClassImplProvider] },] } +]; +/** @nocollapse */ +NgClass.ctorParameters = () => [ + { type: NgClassImpl } +]; +NgClass.propDecorators = { + klass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['class',] }], + ngClass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngClass',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Instantiates a single {\@link Component} type and inserts its Host View into current View. + * `NgComponentOutlet` provides a declarative approach for dynamic component creation. + * + * `NgComponentOutlet` requires a component type, if a falsy value is set the view will clear and + * any existing component will get destroyed. + * + * \@usageNotes + * + * ### Fine tune control + * + * You can control the component creation process by using the following optional attributes: + * + * * `ngComponentOutletInjector`: Optional custom {\@link Injector} that will be used as parent for + * the Component. Defaults to the injector of the current view container. + * + * * `ngComponentOutletContent`: Optional list of projectable nodes to insert into the content + * section of the component, if exists. + * + * * `ngComponentOutletNgModuleFactory`: Optional module factory to allow dynamically loading other + * module, then load a component from that module. + * + * ### Syntax + * + * Simple + * ``` + * + * ``` + * + * Customized injector/content + * ``` + * + * + * ``` + * + * Customized ngModuleFactory + * ``` + * + * + * ``` + * + * ### A simple example + * + * {\@example common/ngComponentOutlet/ts/module.ts region='SimpleExample'} + * + * A more complete example with additional options: + * + * {\@example common/ngComponentOutlet/ts/module.ts region='CompleteExample'} + * + * \@publicApi + * \@ngModule CommonModule + */ +class NgComponentOutlet { + /** + * @param {?} _viewContainerRef + */ + constructor(_viewContainerRef) { + this._viewContainerRef = _viewContainerRef; + this._componentRef = null; + this._moduleRef = null; + } + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + this._viewContainerRef.clear(); + this._componentRef = null; + if (this.ngComponentOutlet) { + /** @type {?} */ + const elInjector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector; + if (changes['ngComponentOutletNgModuleFactory']) { + if (this._moduleRef) + this._moduleRef.destroy(); + if (this.ngComponentOutletNgModuleFactory) { + /** @type {?} */ + const parentModule = elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModuleRef"]); + this._moduleRef = this.ngComponentOutletNgModuleFactory.create(parentModule.injector); + } + else { + this._moduleRef = null; + } + } + /** @type {?} */ + const componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver : + elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ComponentFactoryResolver"]); + /** @type {?} */ + const componentFactory = componentFactoryResolver.resolveComponentFactory(this.ngComponentOutlet); + this._componentRef = this._viewContainerRef.createComponent(componentFactory, this._viewContainerRef.length, elInjector, this.ngComponentOutletContent); + } + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._moduleRef) + this._moduleRef.destroy(); + } +} +NgComponentOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngComponentOutlet]' },] } +]; +/** @nocollapse */ +NgComponentOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] } +]; +NgComponentOutlet.propDecorators = { + ngComponentOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngComponentOutletInjector: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngComponentOutletContent: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngComponentOutletNgModuleFactory: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@publicApi + * @template T + */ +class NgForOfContext { + /** + * @param {?} $implicit + * @param {?} ngForOf + * @param {?} index + * @param {?} count + */ + constructor($implicit, ngForOf, index, count) { + this.$implicit = $implicit; + this.ngForOf = ngForOf; + this.index = index; + this.count = count; + } + /** + * @return {?} + */ + get first() { return this.index === 0; } + /** + * @return {?} + */ + get last() { return this.index === this.count - 1; } + /** + * @return {?} + */ + get even() { return this.index % 2 === 0; } + /** + * @return {?} + */ + get odd() { return !this.even; } +} +/** + * A [structural directive](guide/structural-directives) that renders + * a template for each item in a collection. + * The directive is placed on an element, which becomes the parent + * of the cloned templates. + * + * The `ngForOf` directive is generally used in the + * [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`. + * In this form, the template to be rendered for each iteration is the content + * of an anchor element containing the directive. + * + * The following example shows the shorthand syntax with some options, + * contained in an `
  • ` element. + * + * ``` + *
  • ...
  • + * ``` + * + * The shorthand form expands into a long form that uses the `ngForOf` selector + * on an `` element. + * The content of the `` element is the `
  • ` element that held the + * short-form directive. + * + * Here is the expanded version of the short-form example. + * + * ``` + * + *
  • ...
  • + *
    + * ``` + * + * Angular automatically expands the shorthand syntax as it compiles the template. + * The context for each embedded view is logically merged to the current component + * context according to its lexical position. + * + * When using the shorthand syntax, Angular allows only [one structural directive + * on an element](guide/structural-directives#one-structural-directive-per-host-element). + * If you want to iterate conditionally, for example, + * put the `*ngIf` on a container element that wraps the `*ngFor` element. + * For futher discussion, see + * [Structural Directives](guide/structural-directives#one-per-element). + * + * \@usageNotes + * + * ### Local variables + * + * `NgForOf` provides exported values that can be aliased to local variables. + * For example: + * + * ``` + *
  • + * {{i}}/{{users.length}}. {{user}} default + *
  • + * ``` + * + * The following exported values can be aliased to local variables: + * + * - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`). + * - `ngForOf: NgIterable`: The value of the iterable expression. Useful when the expression is + * more complex then a property access, for example when using the async pipe (`userStreams | + * async`). + * - `index: number`: The index of the current item in the iterable. + * - `first: boolean`: True when the item is the first item in the iterable. + * - `last: boolean`: True when the item is the last item in the iterable. + * - `even: boolean`: True when the item has an even index in the iterable. + * - `odd: boolean`: True when the item has an odd index in the iterable. + * + * ### Change propagation + * + * When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM: + * + * * When an item is added, a new instance of the template is added to the DOM. + * * When an item is removed, its template instance is removed from the DOM. + * * When items are reordered, their respective templates are reordered in the DOM. + * + * Angular uses object identity to track insertions and deletions within the iterator and reproduce + * those changes in the DOM. This has important implications for animations and any stateful + * controls that are present, such as `` elements that accept user input. Inserted rows can + * be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state + * such as user input. + * For more on animations, see [Transitions and Triggers](guide/transition-and-triggers). + * + * The identities of elements in the iterator can change while the data does not. + * This can happen, for example, if the iterator is produced from an RPC to the server, and that + * RPC is re-run. Even if the data hasn't changed, the second response produces objects with + * different identities, and Angular must tear down the entire DOM and rebuild it (as if all old + * elements were deleted and all new elements inserted). + * + * To avoid this expensive operation, you can customize the default tracking algorithm. + * by supplying the `trackBy` option to `NgForOf`. + * `trackBy` takes a function that has two arguments: `index` and `item`. + * If `trackBy` is given, Angular tracks changes by the return value of the function. + * + * @see [Structural Directives](guide/structural-directives) + * \@ngModule CommonModule + * \@publicApi + * @template T + */ +class NgForOf { + /** + * @param {?} _viewContainer + * @param {?} _template + * @param {?} _differs + */ + constructor(_viewContainer, _template, _differs) { + this._viewContainer = _viewContainer; + this._template = _template; + this._differs = _differs; + this._ngForOfDirty = true; + this._differ = null; + } + /** + * The value of the iterable expression, which can be used as a + * [template input variable](guide/structural-directives#template-input-variable). + * @param {?} ngForOf + * @return {?} + */ + set ngForOf(ngForOf) { + this._ngForOf = ngForOf; + this._ngForOfDirty = true; + } + /** + * A function that defines how to track changes for items in the iterable. + * + * When items are added, moved, or removed in the iterable, + * the directive must re-render the appropriate DOM nodes. + * To minimize churn in the DOM, only nodes that have changed + * are re-rendered. + * + * By default, the change detector assumes that + * the object instance identifies the node in the iterable. + * When this function is supplied, the directive uses + * the result of calling this function to identify the item node, + * rather than the identity of the object itself. + * + * The function receives two inputs, + * the iteration index and the node object ID. + * @param {?} fn + * @return {?} + */ + set ngForTrackBy(fn) { + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["isDevMode"])() && fn != null && typeof fn !== 'function') { + // TODO(vicb): use a log service once there is a public one available + if ((/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) { + console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` + + `See https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#change-propagation for more information.`); + } + } + this._trackByFn = fn; + } + /** + * @return {?} + */ + get ngForTrackBy() { return this._trackByFn; } + /** + * A reference to the template that is stamped out for each item in the iterable. + * @see [template reference variable](guide/template-syntax#template-reference-variables--var-) + * @param {?} value + * @return {?} + */ + set ngForTemplate(value) { + // TODO(TS2.1): make TemplateRef>> once we move to TS v2.1 + // The current type is too restrictive; a template that just uses index, for example, + // should be acceptable. + if (value) { + this._template = value; + } + } + /** + * Applies the changes when needed. + * @return {?} + */ + ngDoCheck() { + if (this._ngForOfDirty) { + this._ngForOfDirty = false; + // React on ngForOf changes only once all inputs have been initialized + /** @type {?} */ + const value = this._ngForOf; + if (!this._differ && value) { + try { + this._differ = this._differs.find(value).create(this.ngForTrackBy); + } + catch (_a) { + throw new Error(`Cannot find a differ supporting object '${value}' of type '${getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`); + } + } + } + if (this._differ) { + /** @type {?} */ + const changes = this._differ.diff(this._ngForOf); + if (changes) + this._applyChanges(changes); + } + } + /** + * @private + * @param {?} changes + * @return {?} + */ + _applyChanges(changes) { + /** @type {?} */ + const insertTuples = []; + changes.forEachOperation((/** + * @param {?} item + * @param {?} adjustedPreviousIndex + * @param {?} currentIndex + * @return {?} + */ + (item, adjustedPreviousIndex, currentIndex) => { + if (item.previousIndex == null) { + /** @type {?} */ + const view = this._viewContainer.createEmbeddedView(this._template, new NgForOfContext((/** @type {?} */ (null)), this._ngForOf, -1, -1), currentIndex); + /** @type {?} */ + const tuple = new RecordViewTuple(item, view); + insertTuples.push(tuple); + } + else if (currentIndex == null) { + this._viewContainer.remove(adjustedPreviousIndex); + } + else { + /** @type {?} */ + const view = (/** @type {?} */ (this._viewContainer.get(adjustedPreviousIndex))); + this._viewContainer.move(view, currentIndex); + /** @type {?} */ + const tuple = new RecordViewTuple(item, (/** @type {?} */ (view))); + insertTuples.push(tuple); + } + })); + for (let i = 0; i < insertTuples.length; i++) { + this._perViewChange(insertTuples[i].view, insertTuples[i].record); + } + for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) { + /** @type {?} */ + const viewRef = (/** @type {?} */ (this._viewContainer.get(i))); + viewRef.context.index = i; + viewRef.context.count = ilen; + viewRef.context.ngForOf = this._ngForOf; + } + changes.forEachIdentityChange((/** + * @param {?} record + * @return {?} + */ + (record) => { + /** @type {?} */ + const viewRef = (/** @type {?} */ (this._viewContainer.get(record.currentIndex))); + viewRef.context.$implicit = record.item; + })); + } + /** + * @private + * @param {?} view + * @param {?} record + * @return {?} + */ + _perViewChange(view, record) { + view.context.$implicit = record.item; + } + /** + * Asserts the correct type of the context for the template that `NgForOf` will render. + * + * The presence of this method is a signal to the Ivy template type-check compiler that the + * `NgForOf` structural directive renders its template with a specific context type. + * @template T + * @param {?} dir + * @param {?} ctx + * @return {?} + */ + static ngTemplateContextGuard(dir, ctx) { + return true; + } +} +NgForOf.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngFor][ngForOf]' },] } +]; +/** @nocollapse */ +NgForOf.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] } +]; +NgForOf.propDecorators = { + ngForOf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngForTrackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngForTemplate: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +/** + * @template T + */ +class RecordViewTuple { + /** + * @param {?} record + * @param {?} view + */ + constructor(record, view) { + this.record = record; + this.view = view; + } +} +/** + * @param {?} type + * @return {?} + */ +function getTypeName(type) { + return type['name'] || typeof type; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A structural directive that conditionally includes a template based on the value of + * an expression coerced to Boolean. + * When the expression evaluates to true, Angular renders the template + * provided in a `then` clause, and when false or null, + * Angular renders the template provided in an optional `else` clause. The default + * template for the `else` clause is blank. + * + * A [shorthand form](guide/structural-directives#the-asterisk--prefix) of the directive, + * `*ngIf="condition"`, is generally used, provided + * as an attribute of the anchor element for the inserted template. + * Angular expands this into a more explicit version, in which the anchor element + * is contained in an `` element. + * + * Simple form with shorthand syntax: + * + * ``` + *
    Content to render when condition is true.
    + * ``` + * + * Simple form with expanded syntax: + * + * ``` + *
    Content to render when condition is + * true.
    + * ``` + * + * Form with an "else" block: + * + * ``` + *
    Content to render when condition is true.
    + * Content to render when condition is false. + * ``` + * + * Shorthand form with "then" and "else" blocks: + * + * ``` + *
    + * Content to render when condition is true. + * Content to render when condition is false. + * ``` + * + * Form with storing the value locally: + * + * ``` + *
    {{value}}
    + * Content to render when value is null. + * ``` + * + * \@usageNotes + * + * The `*ngIf` directive is most commonly used to conditionally show an inline template, + * as seen in the following example. + * The default `else` template is blank. + * + * {\@example common/ngIf/ts/module.ts region='NgIfSimple'} + * + * ### Showing an alternative template using `else` + * + * To display a template when `expression` evaluates to false, use an `else` template + * binding as shown in the following example. + * The `else` binding points to an `` element labeled `#elseBlock`. + * The template can be defined anywhere in the component view, but is typically placed right after + * `ngIf` for readability. + * + * {\@example common/ngIf/ts/module.ts region='NgIfElse'} + * + * ### Using an external `then` template + * + * In the previous example, the then-clause template is specified inline, as the content of the + * tag that contains the `ngIf` directive. You can also specify a template that is defined + * externally, by referencing a labeled `` element. When you do this, you can + * change which template to use at runtime, as shown in the following example. + * + * {\@example common/ngIf/ts/module.ts region='NgIfThenElse'} + * + * ### Storing a conditional result in a variable + * + * You might want to show a set of properties from the same object. If you are waiting + * for asynchronous data, the object can be undefined. + * In this case, you can use `ngIf` and store the result of the condition in a local + * variable as shown in the the following example. + * + * {\@example common/ngIf/ts/module.ts region='NgIfAs'} + * + * This code uses only one `AsyncPipe`, so only one subscription is created. + * The conditional statement stores the result of `userStream|async` in the local variable `user`. + * You can then bind the local `user` repeatedly. + * + * The conditional displays the data only if `userStream` returns a value, + * so you don't need to use the + * [safe-navigation-operator](guide/template-syntax#safe-navigation-operator) (`?.`) + * to guard against null values when accessing properties. + * You can display an alternative template while waiting for the data. + * + * ### Shorthand syntax + * + * The shorthand syntax `*ngIf` expands into two separate template specifications + * for the "then" and "else" clauses. For example, consider the following shorthand statement, + * that is meant to show a loading page while waiting for data to be loaded. + * + * ``` + *
    + * ... + *
    + * + * + *
    Loading...
    + *
    + * ``` + * + * You can see that the "else" clause references the `` + * with the `#loading` label, and the template for the "then" clause + * is provided as the content of the anchor element. + * + * However, when Angular expands the shorthand syntax, it creates + * another `` tag, with `ngIf` and `ngIfElse` directives. + * The anchor element containing the template for the "then" clause becomes + * the content of this unlabeled `` tag. + * + * ``` + * + *
    + * ... + *
    + *
    + * + * + *
    Loading...
    + *
    + * ``` + * + * The presence of the implicit template object has implications for the nesting of + * structural directives. For more on this subject, see + * [Structural Directives](https://angular.io/guide/structural-directives#one-per-element). + * + * \@ngModule CommonModule + * \@publicApi + */ +class NgIf { + /** + * @param {?} _viewContainer + * @param {?} templateRef + */ + constructor(_viewContainer, templateRef) { + this._viewContainer = _viewContainer; + this._context = new NgIfContext(); + this._thenTemplateRef = null; + this._elseTemplateRef = null; + this._thenViewRef = null; + this._elseViewRef = null; + this._thenTemplateRef = templateRef; + } + /** + * The Boolean expression to evaluate as the condition for showing a template. + * @param {?} condition + * @return {?} + */ + set ngIf(condition) { + this._context.$implicit = this._context.ngIf = condition; + this._updateView(); + } + /** + * A template to show if the condition expression evaluates to true. + * @param {?} templateRef + * @return {?} + */ + set ngIfThen(templateRef) { + assertTemplate('ngIfThen', templateRef); + this._thenTemplateRef = templateRef; + this._thenViewRef = null; // clear previous view if any. + this._updateView(); + } + /** + * A template to show if the condition expression evaluates to false. + * @param {?} templateRef + * @return {?} + */ + set ngIfElse(templateRef) { + assertTemplate('ngIfElse', templateRef); + this._elseTemplateRef = templateRef; + this._elseViewRef = null; // clear previous view if any. + this._updateView(); + } + /** + * @private + * @return {?} + */ + _updateView() { + if (this._context.$implicit) { + if (!this._thenViewRef) { + this._viewContainer.clear(); + this._elseViewRef = null; + if (this._thenTemplateRef) { + this._thenViewRef = + this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context); + } + } + } + else { + if (!this._elseViewRef) { + this._viewContainer.clear(); + this._thenViewRef = null; + if (this._elseTemplateRef) { + this._elseViewRef = + this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context); + } + } + } + } +} +NgIf.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngIf]' },] } +]; +/** @nocollapse */ +NgIf.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] } +]; +NgIf.propDecorators = { + ngIf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngIfThen: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngIfElse: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +/** + * \@publicApi + */ +class NgIfContext { + constructor() { + this.$implicit = null; + this.ngIf = null; + } +} +/** + * @param {?} property + * @param {?} templateRef + * @return {?} + */ +function assertTemplate(property, templateRef) { + /** @type {?} */ + const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView); + if (!isTemplateRefOrNull) { + throw new Error(`${property} must be a TemplateRef, but received '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(templateRef)}'.`); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class SwitchView { + /** + * @param {?} _viewContainerRef + * @param {?} _templateRef + */ + constructor(_viewContainerRef, _templateRef) { + this._viewContainerRef = _viewContainerRef; + this._templateRef = _templateRef; + this._created = false; + } + /** + * @return {?} + */ + create() { + this._created = true; + this._viewContainerRef.createEmbeddedView(this._templateRef); + } + /** + * @return {?} + */ + destroy() { + this._created = false; + this._viewContainerRef.clear(); + } + /** + * @param {?} created + * @return {?} + */ + enforceState(created) { + if (created && !this._created) { + this.create(); + } + else if (!created && this._created) { + this.destroy(); + } + } +} +/** + * \@ngModule CommonModule + * + * \@description A structural directive that adds or removes templates (displaying or hiding views) + * when the next match expression matches the switch expression. + * + * The `[ngSwitch]` directive on a container specifies an expression to match against. + * The expressions to match are provided by `ngSwitchCase` directives on views within the container. + * - Every view that matches is rendered. + * - If there are no matches, a view with the `ngSwitchDefault` directive is rendered. + * - Elements within the `[NgSwitch]` statement but outside of any `NgSwitchCase` + * or `ngSwitchDefault` directive are preserved at the location. + * + * \@usageNotes + * Define a container element for the directive, and specify the switch expression + * to match against as an attribute: + * + * ``` + * + * ``` + * + * Within the container, `*ngSwitchCase` statements specify the match expressions + * as attributes. Include `*ngSwitchDefault` as the final case. + * + * ``` + * + * ... + * ... + * ... + * + * ``` + * + * ### Usage Examples + * + * The following example shows how to use more than one case to display the same view: + * + * ``` + * + * + * ... + * ... + * ... + * + * ... + * + * ``` + * + * The following example shows how cases can be nested: + * ``` + * + * ... + * ... + * ... + * + * + * + * + * + * ... + * + * ``` + * + * \@publicApi + * @see `NgSwitchCase` + * @see `NgSwitchDefault` + * @see [Structural Directives](guide/structural-directives) + * + */ +class NgSwitch { + constructor() { + this._defaultUsed = false; + this._caseCount = 0; + this._lastCaseCheckIndex = 0; + this._lastCasesMatched = false; + } + /** + * @param {?} newValue + * @return {?} + */ + set ngSwitch(newValue) { + this._ngSwitch = newValue; + if (this._caseCount === 0) { + this._updateDefaultCases(true); + } + } + /** + * \@internal + * @return {?} + */ + _addCase() { return this._caseCount++; } + /** + * \@internal + * @param {?} view + * @return {?} + */ + _addDefault(view) { + if (!this._defaultViews) { + this._defaultViews = []; + } + this._defaultViews.push(view); + } + /** + * \@internal + * @param {?} value + * @return {?} + */ + _matchCase(value) { + /** @type {?} */ + const matched = value == this._ngSwitch; + this._lastCasesMatched = this._lastCasesMatched || matched; + this._lastCaseCheckIndex++; + if (this._lastCaseCheckIndex === this._caseCount) { + this._updateDefaultCases(!this._lastCasesMatched); + this._lastCaseCheckIndex = 0; + this._lastCasesMatched = false; + } + return matched; + } + /** + * @private + * @param {?} useDefault + * @return {?} + */ + _updateDefaultCases(useDefault) { + if (this._defaultViews && useDefault !== this._defaultUsed) { + this._defaultUsed = useDefault; + for (let i = 0; i < this._defaultViews.length; i++) { + /** @type {?} */ + const defaultView = this._defaultViews[i]; + defaultView.enforceState(useDefault); + } + } + } +} +NgSwitch.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitch]' },] } +]; +NgSwitch.propDecorators = { + ngSwitch: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +/** + * \@ngModule CommonModule + * + * \@description + * Provides a switch case expression to match against an enclosing `ngSwitch` expression. + * When the expressions match, the given `NgSwitchCase` template is rendered. + * If multiple match expressions match the switch expression value, all of them are displayed. + * + * \@usageNotes + * + * Within a switch container, `*ngSwitchCase` statements specify the match expressions + * as attributes. Include `*ngSwitchDefault` as the final case. + * + * ``` + * + * ... + * ... + * ... + * + * ``` + * + * Each switch-case statement contains an in-line HTML template or template reference + * that defines the subtree to be selected if the value of the match expression + * matches the value of the switch expression. + * + * Unlike JavaScript, which uses strict equality, Angular uses loose equality. + * This means that the empty string, `""` matches 0. + * + * \@publicApi + * @see `NgSwitch` + * @see `NgSwitchDefault` + * + */ +class NgSwitchCase { + /** + * @param {?} viewContainer + * @param {?} templateRef + * @param {?} ngSwitch + */ + constructor(viewContainer, templateRef, ngSwitch) { + this.ngSwitch = ngSwitch; + ngSwitch._addCase(); + this._view = new SwitchView(viewContainer, templateRef); + } + /** + * Performs case matching. For internal use only. + * @return {?} + */ + ngDoCheck() { this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase)); } +} +NgSwitchCase.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitchCase]' },] } +]; +/** @nocollapse */ +NgSwitchCase.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] } +]; +NgSwitchCase.propDecorators = { + ngSwitchCase: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +/** + * \@ngModule CommonModule + * + * \@description + * + * Creates a view that is rendered when no `NgSwitchCase` expressions + * match the `NgSwitch` expression. + * This statement should be the final case in an `NgSwitch`. + * + * \@publicApi + * @see `NgSwitch` + * @see `NgSwitchCase` + * + */ +class NgSwitchDefault { + /** + * @param {?} viewContainer + * @param {?} templateRef + * @param {?} ngSwitch + */ + constructor(viewContainer, templateRef, ngSwitch) { + ngSwitch._addDefault(new SwitchView(viewContainer, templateRef)); + } +} +NgSwitchDefault.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngSwitchDefault]' },] } +]; +/** @nocollapse */ +NgSwitchDefault.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * + * \@usageNotes + * ``` + * + * there is nothing + * there is one + * there are a few + * + * ``` + * + * \@description + * + * Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization. + * + * Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees + * that match the switch expression's pluralization category. + * + * To use this directive you must provide a container element that sets the `[ngPlural]` attribute + * to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their + * expression: + * - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value + * matches the switch expression exactly, + * - otherwise, the view will be treated as a "category match", and will only display if exact + * value matches aren't found and the value maps to its category for the defined locale. + * + * See http://cldr.unicode.org/index/cldr-spec/plural-rules + * + * \@publicApi + */ +class NgPlural { + /** + * @param {?} _localization + */ + constructor(_localization) { + this._localization = _localization; + this._caseViews = {}; + } + /** + * @param {?} value + * @return {?} + */ + set ngPlural(value) { + this._switchValue = value; + this._updateView(); + } + /** + * @param {?} value + * @param {?} switchView + * @return {?} + */ + addCase(value, switchView) { this._caseViews[value] = switchView; } + /** + * @private + * @return {?} + */ + _updateView() { + this._clearViews(); + /** @type {?} */ + const cases = Object.keys(this._caseViews); + /** @type {?} */ + const key = getPluralCategory(this._switchValue, cases, this._localization); + this._activateView(this._caseViews[key]); + } + /** + * @private + * @return {?} + */ + _clearViews() { + if (this._activeView) + this._activeView.destroy(); + } + /** + * @private + * @param {?} view + * @return {?} + */ + _activateView(view) { + if (view) { + this._activeView = view; + this._activeView.create(); + } + } +} +NgPlural.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngPlural]' },] } +]; +/** @nocollapse */ +NgPlural.ctorParameters = () => [ + { type: NgLocalization } +]; +NgPlural.propDecorators = { + ngPlural: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; +/** + * \@ngModule CommonModule + * + * \@description + * + * Creates a view that will be added/removed from the parent {\@link NgPlural} when the + * given expression matches the plural expression according to CLDR rules. + * + * \@usageNotes + * ``` + * + * ... + * ... + * + * ``` + * + * See {\@link NgPlural} for more details and example. + * + * \@publicApi + */ +class NgPluralCase { + /** + * @param {?} value + * @param {?} template + * @param {?} viewContainer + * @param {?} ngPlural + */ + constructor(value, template, viewContainer, ngPlural) { + this.value = value; + /** @type {?} */ + const isANumber = !isNaN(Number(value)); + ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template)); + } +} +NgPluralCase.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngPluralCase]' },] } +]; +/** @nocollapse */ +NgPluralCase.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Attribute"], args: ['ngPluralCase',] }] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, + { type: NgPlural, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Used as a token for an injected service within the NgStyle directive. + * + * NgStyle behaves differenly whether or not VE is being used or not. If + * present then the legacy ngClass diffing algorithm will be used as an + * injected service. Otherwise the new diffing algorithm (which delegates + * to the `[style]` binding) will be used. This toggle behavior is done so + * via the ivy_switch mechanism. + * @abstract + */ +class NgStyleImpl { +} +class NgStyleR2Impl { + /** + * @param {?} _ngEl + * @param {?} _differs + * @param {?} _renderer + */ + constructor(_ngEl, _differs, _renderer) { + this._ngEl = _ngEl; + this._differs = _differs; + this._renderer = _renderer; + } + /** + * @return {?} + */ + getValue() { return null; } + /** + * A map of style properties, specified as colon-separated + * key-value pairs. + * * The key is a style name, with an optional `.` suffix + * (such as 'top.px', 'font-style.em'). + * * The value is an expression to be evaluated. + * @param {?} values + * @return {?} + */ + setNgStyle(values) { + this._ngStyle = values; + if (!this._differ && values) { + this._differ = this._differs.find(values).create(); + } + } + /** + * Applies the new styles if needed. + * @return {?} + */ + applyChanges() { + if (this._differ) { + /** @type {?} */ + const changes = this._differ.diff(this._ngStyle); + if (changes) { + this._applyChanges(changes); + } + } + } + /** + * @private + * @param {?} changes + * @return {?} + */ + _applyChanges(changes) { + changes.forEachRemovedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._setStyle(record.key, null))); + changes.forEachAddedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._setStyle(record.key, record.currentValue))); + changes.forEachChangedItem((/** + * @param {?} record + * @return {?} + */ + (record) => this._setStyle(record.key, record.currentValue))); + } + /** + * @private + * @param {?} nameAndUnit + * @param {?} value + * @return {?} + */ + _setStyle(nameAndUnit, value) { + const [name, unit] = nameAndUnit.split('.'); + value = value != null && unit ? `${value}${unit}` : value; + if (value != null) { + this._renderer.setStyle(this._ngEl.nativeElement, name, (/** @type {?} */ (value))); + } + else { + this._renderer.removeStyle(this._ngEl.nativeElement, name); + } + } +} +NgStyleR2Impl.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +NgStyleR2Impl.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] } +]; +class NgStyleR3Impl { + constructor() { + this._differ = new StylingDiffer('NgStyle', 8 /* AllowUnits */); + this._value = null; + } + /** + * @return {?} + */ + getValue() { return this._value; } + /** + * @param {?} value + * @return {?} + */ + setNgStyle(value) { this._differ.setValue(value); } + /** + * @return {?} + */ + applyChanges() { + if (this._differ.hasValueChanged()) { + this._value = this._differ.value; + } + } +} +NgStyleR3Impl.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +// the implementation for both NgClassR2Impl and NgClassR3Impl are +// not ivy_switch'd away, instead they are only hooked up into the +// DI via NgStyle's directive's provider property. +/** @type {?} */ +const NgStyleImplProvider__PRE_R3__ = { + provide: NgStyleImpl, + useClass: NgStyleR2Impl +}; +/** @type {?} */ +const NgStyleImplProvider__POST_R3__ = { + provide: NgStyleImpl, + useClass: NgStyleR3Impl +}; +/** @type {?} */ +const NgStyleImplProvider = NgStyleImplProvider__PRE_R3__; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/* + * NgStyle (as well as NgClass) behaves differently when loaded in the VE and when not. + * + * If the VE is present (which is for older versions of Angular) then NgStyle will inject + * the legacy diffing algorithm as a service and delegate all styling changes to that. + * + * If the VE is not present then NgStyle will normalize (through the injected service) and + * then write all styling changes to the `[style]` binding directly (through a host binding). + * Then Angular will notice the host binding change and treat the changes as styling + * changes and apply them via the core styling instructions that exist within Angular. + */ +// used when the VE is present +/** @type {?} */ +const ngStyleDirectiveDef__PRE_R3__ = undefined; +// used when the VE is not present (note the directive will +// never be instantiated normally because it is apart of a +// base class) +const ɵ0$1 = /** + * @return {?} + */ +function () { }, ɵ1$1 = /** + * @return {?} + */ +() => { }, ɵ2$1 = /** + * @param {?} rf + * @param {?} ctx + * @param {?} elIndex + * @return {?} + */ +function (rf, ctx, elIndex) { + if (rf & 1 /* Create */) { + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyling"])(); + } + if (rf & 2 /* Update */) { + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstyleMap"])(ctx.getValue()); + Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵstylingApply"])(); + } +}; +/** @type {?} */ +const ngStyleDirectiveDef__POST_R3__ = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"])({ + type: (/** @type {?} */ ((ɵ0$1))), + selectors: (/** @type {?} */ (null)), + factory: (ɵ1$1), + hostBindings: (ɵ2$1) +}); +/** @type {?} */ +const ngStyleDirectiveDef = ngStyleDirectiveDef__PRE_R3__; +/** + * Serves as the base non-VE container for NgStyle. + * + * While this is a base class that NgStyle extends from, the + * class itself acts as a container for non-VE code to setup + * a link to the `[style]` host binding (via the static + * `ngDirectiveDef` property on the class). + * + * Note that the `ngDirectiveDef` property's code is switched + * depending if VE is present or not (this allows for the + * binding code to be set only for newer versions of Angular). + * + * \@publicApi + */ +class NgStyleBase { + /** + * @param {?} _delegate + */ + constructor(_delegate) { + this._delegate = _delegate; + } + /** + * @return {?} + */ + getValue() { return this._delegate.getValue(); } +} +/** @nocollapse */ NgStyleBase.ngDirectiveDef = ngStyleDirectiveDef; +/** + * \@ngModule CommonModule + * + * \@usageNotes + * + * Set the font of the containing element to the result of an expression. + * + * ``` + * ... + * ``` + * + * Set the width of the containing element to a pixel value returned by an expression. + * + * ``` + * ... + * ``` + * + * Set a collection of style values using an expression that returns key-value pairs. + * + * ``` + * ... + * ``` + * + * \@description + * + * An attribute directive that updates styles for the containing HTML element. + * Sets one or more style properties, specified as colon-separated key-value pairs. + * The key is a style name, with an optional `.` suffix + * (such as 'top.px', 'font-style.em'). + * The value is an expression to be evaluated. + * The resulting non-null value, expressed in the given unit, + * is assigned to the given style property. + * If the result of evaluation is null, the corresponding style is removed. + * + * \@publicApi + */ +class NgStyle extends NgStyleBase { + /** + * @param {?} delegate + */ + constructor(delegate) { super(delegate); } + /** + * @param {?} value + * @return {?} + */ + set ngStyle(value) { this._delegate.setNgStyle(value); } + /** + * @return {?} + */ + ngDoCheck() { this._delegate.applyChanges(); } +} +NgStyle.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngStyle]', providers: [NgStyleImplProvider] },] } +]; +/** @nocollapse */ +NgStyle.ctorParameters = () => [ + { type: NgStyleImpl } +]; +NgStyle.propDecorators = { + ngStyle: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngStyle',] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * + * \@description + * + * Inserts an embedded view from a prepared `TemplateRef`. + * + * You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`. + * `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding + * by the local template `let` declarations. + * + * \@usageNotes + * ``` + * + * ``` + * + * Using the key `$implicit` in the context object will set its value as default. + * + * ### Example + * + * {\@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'} + * + * \@publicApi + */ +class NgTemplateOutlet { + /** + * @param {?} _viewContainerRef + */ + constructor(_viewContainerRef) { + this._viewContainerRef = _viewContainerRef; + this._viewRef = null; + /** + * A context object to attach to the {\@link EmbeddedViewRef}. This should be an + * object, the object's keys will be available for binding by the local template `let` + * declarations. + * Using the key `$implicit` in the context object will set its value as default. + */ + this.ngTemplateOutletContext = null; + /** + * A string defining the template reference and optionally the context object for the template. + */ + this.ngTemplateOutlet = null; + } + /** + * @param {?} changes + * @return {?} + */ + ngOnChanges(changes) { + /** @type {?} */ + const recreateView = this._shouldRecreateView(changes); + if (recreateView) { + if (this._viewRef) { + this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._viewRef)); + } + if (this.ngTemplateOutlet) { + this._viewRef = this._viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, this.ngTemplateOutletContext); + } + } + else { + if (this._viewRef && this.ngTemplateOutletContext) { + this._updateExistingContext(this.ngTemplateOutletContext); + } + } + } + /** + * We need to re-create existing embedded view if: + * - templateRef has changed + * - context has changes + * + * We mark context object as changed when the corresponding object + * shape changes (new properties are added or existing properties are removed). + * In other words we consider context with the same properties as "the same" even + * if object reference changes (see https://github.com/angular/angular/issues/13407). + * @private + * @param {?} changes + * @return {?} + */ + _shouldRecreateView(changes) { + /** @type {?} */ + const ctxChange = changes['ngTemplateOutletContext']; + return !!changes['ngTemplateOutlet'] || (ctxChange && this._hasContextShapeChanged(ctxChange)); + } + /** + * @private + * @param {?} ctxChange + * @return {?} + */ + _hasContextShapeChanged(ctxChange) { + /** @type {?} */ + const prevCtxKeys = Object.keys(ctxChange.previousValue || {}); + /** @type {?} */ + const currCtxKeys = Object.keys(ctxChange.currentValue || {}); + if (prevCtxKeys.length === currCtxKeys.length) { + for (let propName of currCtxKeys) { + if (prevCtxKeys.indexOf(propName) === -1) { + return true; + } + } + return false; + } + else { + return true; + } + } + /** + * @private + * @param {?} ctx + * @return {?} + */ + _updateExistingContext(ctx) { + for (let propName of Object.keys(ctx)) { + ((/** @type {?} */ ((/** @type {?} */ (this._viewRef)).context)))[propName] = ((/** @type {?} */ (this.ngTemplateOutletContext)))[propName]; + } + } +} +NgTemplateOutlet.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"], args: [{ selector: '[ngTemplateOutlet]' },] } +]; +/** @nocollapse */ +NgTemplateOutlet.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] } +]; +NgTemplateOutlet.propDecorators = { + ngTemplateOutletContext: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }], + ngTemplateOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }] +}; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A collection of Angular directives that are likely to be used in each and every Angular + * application. + * @type {?} + */ +const COMMON_DIRECTIVES = [ + NgClass, + NgComponentOutlet, + NgForOf, + NgIf, + NgTemplateOutlet, + NgStyle, + NgSwitch, + NgSwitchCase, + NgSwitchDefault, + NgPlural, + NgPluralCase, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @param {?} type + * @param {?} value + * @return {?} + */ +function invalidPipeArgumentError(type, value) { + return Error(`InvalidPipeArgument: '${value}' for pipe '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(type)}'`); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class NumberFormatter { + /** + * @param {?} num + * @param {?} locale + * @param {?} style + * @param {?=} opts + * @return {?} + */ + static format(num, locale, style, opts = {}) { + const { minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, currency, currencyAsSymbol = false } = opts; + /** @type {?} */ + const options = { + minimumIntegerDigits, + minimumFractionDigits, + maximumFractionDigits, + style: NumberFormatStyle[style].toLowerCase() + }; + if (style == NumberFormatStyle.Currency) { + options.currency = typeof currency == 'string' ? currency : undefined; + options.currencyDisplay = currencyAsSymbol ? 'symbol' : 'code'; + } + return new Intl.NumberFormat(locale, options).format(num); + } +} +/** @type {?} */ +const DATE_FORMATS_SPLIT$1 = /((?:[^yMLdHhmsazZEwGjJ']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|J+|j+|m+|s+|a|z|Z|G+|w+))(.*)/; +/** @type {?} */ +const PATTERN_ALIASES = { + // Keys are quoted so they do not get renamed during closure compilation. + 'yMMMdjms': datePartGetterFactory(combine([ + digitCondition('year', 1), + nameCondition('month', 3), + digitCondition('day', 1), + digitCondition('hour', 1), + digitCondition('minute', 1), + digitCondition('second', 1), + ])), + 'yMdjm': datePartGetterFactory(combine([ + digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1), + digitCondition('hour', 1), digitCondition('minute', 1) + ])), + 'yMMMMEEEEd': datePartGetterFactory(combine([ + digitCondition('year', 1), nameCondition('month', 4), nameCondition('weekday', 4), + digitCondition('day', 1) + ])), + 'yMMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 4), digitCondition('day', 1)])), + 'yMMMd': datePartGetterFactory(combine([digitCondition('year', 1), nameCondition('month', 3), digitCondition('day', 1)])), + 'yMd': datePartGetterFactory(combine([digitCondition('year', 1), digitCondition('month', 1), digitCondition('day', 1)])), + 'jms': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('second', 1), digitCondition('minute', 1)])), + 'jm': datePartGetterFactory(combine([digitCondition('hour', 1), digitCondition('minute', 1)])) +}; +/** @type {?} */ +const DATE_FORMATS$1 = { + // Keys are quoted so they do not get renamed. + 'yyyy': datePartGetterFactory(digitCondition('year', 4)), + 'yy': datePartGetterFactory(digitCondition('year', 2)), + 'y': datePartGetterFactory(digitCondition('year', 1)), + 'MMMM': datePartGetterFactory(nameCondition('month', 4)), + 'MMM': datePartGetterFactory(nameCondition('month', 3)), + 'MM': datePartGetterFactory(digitCondition('month', 2)), + 'M': datePartGetterFactory(digitCondition('month', 1)), + 'LLLL': datePartGetterFactory(nameCondition('month', 4)), + 'L': datePartGetterFactory(nameCondition('month', 1)), + 'dd': datePartGetterFactory(digitCondition('day', 2)), + 'd': datePartGetterFactory(digitCondition('day', 1)), + 'HH': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), false)))), + 'H': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), false))), + 'hh': digitModifier(hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 2), true)))), + 'h': hourExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))), + 'jj': datePartGetterFactory(digitCondition('hour', 2)), + 'j': datePartGetterFactory(digitCondition('hour', 1)), + 'mm': digitModifier(datePartGetterFactory(digitCondition('minute', 2))), + 'm': datePartGetterFactory(digitCondition('minute', 1)), + 'ss': digitModifier(datePartGetterFactory(digitCondition('second', 2))), + 's': datePartGetterFactory(digitCondition('second', 1)), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit + // fractions + 'sss': datePartGetterFactory(digitCondition('second', 3)), + 'EEEE': datePartGetterFactory(nameCondition('weekday', 4)), + 'EEE': datePartGetterFactory(nameCondition('weekday', 3)), + 'EE': datePartGetterFactory(nameCondition('weekday', 2)), + 'E': datePartGetterFactory(nameCondition('weekday', 1)), + 'a': hourClockExtractor(datePartGetterFactory(hour12Modify(digitCondition('hour', 1), true))), + 'Z': timeZoneGetter$1('short'), + 'z': timeZoneGetter$1('long'), + 'ww': datePartGetterFactory({}), + // Week of year, padded (00-53). Week 01 is the week with the + // first Thursday of the year. not support ? + 'w': datePartGetterFactory({}), + // Week of year (0-53). Week 1 is the week with the first Thursday + // of the year not support ? + 'G': datePartGetterFactory(nameCondition('era', 1)), + 'GG': datePartGetterFactory(nameCondition('era', 2)), + 'GGG': datePartGetterFactory(nameCondition('era', 3)), + 'GGGG': datePartGetterFactory(nameCondition('era', 4)) +}; +/** + * @param {?} inner + * @return {?} + */ +function digitModifier(inner) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { + /** @type {?} */ + const result = inner(date, locale); + return result.length == 1 ? '0' + result : result; + }); +} +/** + * @param {?} inner + * @return {?} + */ +function hourClockExtractor(inner) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { return inner(date, locale).split(' ')[1]; }); +} +/** + * @param {?} inner + * @return {?} + */ +function hourExtractor(inner) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { return inner(date, locale).split(' ')[0]; }); +} +/** + * @param {?} date + * @param {?} locale + * @param {?} options + * @return {?} + */ +function intlDateFormat(date, locale, options) { + return new Intl.DateTimeFormat(locale, options).format(date).replace(/[\u200e\u200f]/g, ''); +} +/** + * @param {?} timezone + * @return {?} + */ +function timeZoneGetter$1(timezone) { + // To workaround `Intl` API restriction for single timezone let format with 24 hours + /** @type {?} */ + const options = { hour: '2-digit', hour12: false, timeZoneName: timezone }; + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + function (date, locale) { + /** @type {?} */ + const result = intlDateFormat(date, locale, options); + // Then extract first 3 letters that related to hours + return result ? result.substring(3) : ''; + }); +} +/** + * @param {?} options + * @param {?} value + * @return {?} + */ +function hour12Modify(options, value) { + options.hour12 = value; + return options; +} +/** + * @param {?} prop + * @param {?} len + * @return {?} + */ +function digitCondition(prop, len) { + /** @type {?} */ + const result = {}; + result[prop] = len === 2 ? '2-digit' : 'numeric'; + return result; +} +/** + * @param {?} prop + * @param {?} len + * @return {?} + */ +function nameCondition(prop, len) { + /** @type {?} */ + const result = {}; + if (len < 4) { + result[prop] = len > 1 ? 'short' : 'narrow'; + } + else { + result[prop] = 'long'; + } + return result; +} +/** + * @param {?} options + * @return {?} + */ +function combine(options) { + return options.reduce((/** + * @param {?} merged + * @param {?} opt + * @return {?} + */ + (merged, opt) => (Object.assign({}, merged, opt))), {}); +} +/** + * @param {?} ret + * @return {?} + */ +function datePartGetterFactory(ret) { + return (/** + * @param {?} date + * @param {?} locale + * @return {?} + */ + (date, locale) => intlDateFormat(date, locale, ret)); +} +/** @type {?} */ +const DATE_FORMATTER_CACHE = new Map(); +/** + * @param {?} format + * @param {?} date + * @param {?} locale + * @return {?} + */ +function dateFormatter(format, date, locale) { + /** @type {?} */ + const fn = PATTERN_ALIASES[format]; + if (fn) + return fn(date, locale); + /** @type {?} */ + const cacheKey = format; + /** @type {?} */ + let parts = DATE_FORMATTER_CACHE.get(cacheKey); + if (!parts) { + parts = []; + /** @type {?} */ + let match; + DATE_FORMATS_SPLIT$1.exec(format); + /** @type {?} */ + let _format = format; + while (_format) { + match = DATE_FORMATS_SPLIT$1.exec(_format); + if (match) { + parts = parts.concat(match.slice(1)); + _format = (/** @type {?} */ (parts.pop())); + } + else { + parts.push(_format); + _format = null; + } + } + DATE_FORMATTER_CACHE.set(cacheKey, parts); + } + return parts.reduce((/** + * @param {?} text + * @param {?} part + * @return {?} + */ + (text, part) => { + /** @type {?} */ + const fn = DATE_FORMATS$1[part]; + return text + (fn ? fn(date, locale) : partToTime(part)); + }), ''); +} +/** + * @param {?} part + * @return {?} + */ +function partToTime(part) { + return part === '\'\'' ? '\'' : part.replace(/(^'|'$)/g, '').replace(/''/g, '\''); +} +class DateFormatter { + /** + * @param {?} date + * @param {?} locale + * @param {?} pattern + * @return {?} + */ + static format(date, locale, pattern) { + return dateFormatter(pattern, date, locale); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * \@description + * + * Formats a date according to locale rules. + * + * Where: + * - `expression` is a date object or a number (milliseconds since UTC epoch) or an ISO string + * (https://www.w3.org/TR/NOTE-datetime). + * - `format` indicates which date/time components to include. The format can be predefined as + * shown below or custom as shown in the table. + * - `'medium'`: equivalent to `'yMMMdjms'` (e.g. `Sep 3, 2010, 12:05:08 PM` for `en-US`) + * - `'short'`: equivalent to `'yMdjm'` (e.g. `9/3/2010, 12:05 PM` for `en-US`) + * - `'fullDate'`: equivalent to `'yMMMMEEEEd'` (e.g. `Friday, September 3, 2010` for `en-US`) + * - `'longDate'`: equivalent to `'yMMMMd'` (e.g. `September 3, 2010` for `en-US`) + * - `'mediumDate'`: equivalent to `'yMMMd'` (e.g. `Sep 3, 2010` for `en-US`) + * - `'shortDate'`: equivalent to `'yMd'` (e.g. `9/3/2010` for `en-US`) + * - `'mediumTime'`: equivalent to `'jms'` (e.g. `12:05:08 PM` for `en-US`) + * - `'shortTime'`: equivalent to `'jm'` (e.g. `12:05 PM` for `en-US`) + * + * + * | Component | Symbol | Narrow | Short Form | Long Form | Numeric | 2-digit | + * |-----------|:------:|--------|--------------|-------------------|-----------|-----------| + * | era | G | G (A) | GGG (AD) | GGGG (Anno Domini)| - | - | + * | year | y | - | - | - | y (2015) | yy (15) | + * | month | M | L (S) | MMM (Sep) | MMMM (September) | M (9) | MM (09) | + * | day | d | - | - | - | d (3) | dd (03) | + * | weekday | E | E (S) | EEE (Sun) | EEEE (Sunday) | - | - | + * | hour | j | - | - | - | j (13) | jj (13) | + * | hour12 | h | - | - | - | h (1 PM) | hh (01 PM)| + * | hour24 | H | - | - | - | H (13) | HH (13) | + * | minute | m | - | - | - | m (5) | mm (05) | + * | second | s | - | - | - | s (9) | ss (09) | + * | timezone | z | - | - | z (Pacific Standard Time)| - | - | + * | timezone | Z | - | Z (GMT-8:00) | - | - | - | + * | timezone | a | - | a (PM) | - | - | - | + * + * In javascript, only the components specified will be respected (not the ordering, + * punctuations, ...) and details of the formatting will be dependent on the locale. + * + * Timezone of the formatted text will be the local system timezone of the end-user's machine. + * + * When the expression is a ISO string without time (e.g. 2016-09-19) the time zone offset is not + * applied and the formatted text will have the same day, month and year of the expression. + * + * WARNINGS: + * - this pipe is marked as pure hence it will not be re-evaluated when the input is mutated. + * Instead users should treat the date as an immutable object and change the reference when the + * pipe needs to re-run (this is to avoid reformatting the date on every change detection run + * which would be an expensive operation). + * - this pipe uses the Internationalization API. Therefore it is only reliable in Chrome and Opera + * browsers. + * + * \@usageNotes + * + * ### Examples + * + * Assuming `dateObj` is (year: 2010, month: 9, day: 3, hour: 12 PM, minute: 05, second: 08) + * in the _local_ time and locale is 'en-US': + * + * {\@example common/pipes/ts/date_pipe.ts region='DeprecatedDatePipe'} + * + * \@publicApi + */ +class DeprecatedDatePipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * @param {?} value + * @param {?=} pattern + * @return {?} + */ + transform(value, pattern = 'mediumDate') { + if (value == null || value === '' || value !== value) + return null; + /** @type {?} */ + let date; + if (typeof value === 'string') { + value = value.trim(); + } + if (isDate$1(value)) { + date = value; + } + else if (!isNaN(value - parseFloat(value))) { + date = new Date(parseFloat(value)); + } + else if (typeof value === 'string' && /^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) { + /** + * For ISO Strings without time the day, month and year must be extracted from the ISO String + * before Date creation to avoid time offset and errors in the new Date. + * If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new + * date, some browsers (e.g. IE 9) will throw an invalid Date error + * If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the + * timeoffset + * is applied + * Note: ISO months are 0 for January, 1 for February, ... + */ + const [y, m, d] = value.split('-').map((/** + * @param {?} val + * @return {?} + */ + (val) => parseInt(val, 10))); + date = new Date(y, m - 1, d); + } + else { + date = new Date(value); + } + if (!isDate$1(date)) { + /** @type {?} */ + let match; + if ((typeof value === 'string') && (match = value.match(ISO8601_DATE_REGEX))) { + date = isoStringToDate(match); + } + else { + throw invalidPipeArgumentError(DeprecatedDatePipe, value); + } + } + return DateFormatter.format(date, this._locale, DeprecatedDatePipe._ALIASES[pattern] || pattern); + } +} +/** + * \@internal + */ +DeprecatedDatePipe._ALIASES = { + 'medium': 'yMMMdjms', + 'short': 'yMdjm', + 'fullDate': 'yMMMMEEEEd', + 'longDate': 'yMMMMd', + 'mediumDate': 'yMMMd', + 'shortDate': 'yMd', + 'mediumTime': 'jms', + 'shortTime': 'jm' +}; +DeprecatedDatePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'date', pure: true },] } +]; +/** @nocollapse */ +DeprecatedDatePipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * @param {?} value + * @return {?} + */ +function isDate$1(value) { + return value instanceof Date && !isNaN(value.valueOf()); +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @param {?} pipe + * @param {?} locale + * @param {?} value + * @param {?} style + * @param {?=} digits + * @param {?=} currency + * @param {?=} currencyAsSymbol + * @return {?} + */ +function formatNumber$1(pipe, locale, value, style, digits, currency = null, currencyAsSymbol = false) { + if (value == null) + return null; + // Convert strings to numbers + value = typeof value === 'string' && !isNaN(+value - parseFloat(value)) ? +value : value; + if (typeof value !== 'number') { + throw invalidPipeArgumentError(pipe, value); + } + /** @type {?} */ + let minInt; + /** @type {?} */ + let minFraction; + /** @type {?} */ + let maxFraction; + if (style !== NumberFormatStyle.Currency) { + // rely on Intl default for currency + minInt = 1; + minFraction = 0; + maxFraction = 3; + } + if (digits) { + /** @type {?} */ + const parts = digits.match(NUMBER_FORMAT_REGEXP); + if (parts === null) { + throw new Error(`${digits} is not a valid digit info for number pipes`); + } + if (parts[1] != null) { // min integer digits + minInt = parseIntAutoRadix(parts[1]); + } + if (parts[3] != null) { // min fraction digits + minFraction = parseIntAutoRadix(parts[3]); + } + if (parts[5] != null) { // max fraction digits + maxFraction = parseIntAutoRadix(parts[5]); + } + } + return NumberFormatter.format((/** @type {?} */ (value)), locale, style, { + minimumIntegerDigits: minInt, + minimumFractionDigits: minFraction, + maximumFractionDigits: maxFraction, + currency: currency, + currencyAsSymbol: currencyAsSymbol, + }); +} +/** + * Formats a number as text. Group sizing and separator and other locale-specific + * configurations are based on the active locale. + * + * where `expression` is a number: + * - `digitInfo` is a `string` which has a following format:
    + * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits} + * - `minIntegerDigits` is the minimum number of integer digits to use. Defaults to `1`. + * - `minFractionDigits` is the minimum number of digits after fraction. Defaults to `0`. + * - `maxFractionDigits` is the maximum number of digits after fraction. Defaults to `3`. + * + * For more information on the acceptable range for each of these numbers and other + * details see your native internationalization library. + * + * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers + * and may require a polyfill. See [Browser Support](guide/browser-support) for details. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/pipes/ts/number_pipe.ts region='DeprecatedNumberPipe'} + * + * \@ngModule CommonModule + * \@publicApi + */ +class DeprecatedDecimalPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * @param {?} value + * @param {?=} digits + * @return {?} + */ + transform(value, digits) { + return formatNumber$1(DeprecatedDecimalPipe, this._locale, value, NumberFormatStyle.Decimal, digits); + } +} +DeprecatedDecimalPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'number' },] } +]; +/** @nocollapse */ +DeprecatedDecimalPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * \@ngModule CommonModule + * + * \@description + * + * Formats a number as percentage according to locale rules. + * + * - `digitInfo` See {\@link DecimalPipe} for detailed description. + * + * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers + * and may require a polyfill. See [Browser Support](guide/browser-support) for details. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/pipes/ts/percent_pipe.ts region='DeprecatedPercentPipe'} + * + * \@publicApi + */ +class DeprecatedPercentPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * @param {?} value + * @param {?=} digits + * @return {?} + */ + transform(value, digits) { + return formatNumber$1(DeprecatedPercentPipe, this._locale, value, NumberFormatStyle.Percent, digits); + } +} +DeprecatedPercentPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'percent' },] } +]; +/** @nocollapse */ +DeprecatedPercentPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * \@ngModule CommonModule + * \@description + * + * Formats a number as currency using locale rules. + * + * Use `currency` to format a number as currency. + * + * - `currencyCode` is the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, such + * as `USD` for the US dollar and `EUR` for the euro. + * - `symbolDisplay` is a boolean indicating whether to use the currency symbol or code. + * - `true`: use symbol (e.g. `$`). + * - `false`(default): use code (e.g. `USD`). + * - `digitInfo` See {\@link DecimalPipe} for detailed description. + * + * WARNING: this pipe uses the Internationalization API which is not yet available in all browsers + * and may require a polyfill. See [Browser Support](guide/browser-support) for details. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/pipes/ts/currency_pipe.ts region='DeprecatedCurrencyPipe'} + * + * \@publicApi + */ +class DeprecatedCurrencyPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * @param {?} value + * @param {?=} currencyCode + * @param {?=} symbolDisplay + * @param {?=} digits + * @return {?} + */ + transform(value, currencyCode = 'USD', symbolDisplay = false, digits) { + return formatNumber$1(DeprecatedCurrencyPipe, this._locale, value, NumberFormatStyle.Currency, digits, currencyCode, symbolDisplay); + } +} +DeprecatedCurrencyPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'currency' },] } +]; +/** @nocollapse */ +DeprecatedCurrencyPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A collection of deprecated i18n pipes that require intl api + * + * @deprecated from v5 + * @type {?} + */ +const COMMON_DEPRECATED_I18N_PIPES = [DeprecatedDecimalPipe, DeprecatedPercentPipe, DeprecatedCurrencyPipe, DeprecatedDatePipe]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +class ObservableStrategy { + /** + * @param {?} async + * @param {?} updateLatestValue + * @return {?} + */ + createSubscription(async, updateLatestValue) { + return async.subscribe({ next: updateLatestValue, error: (/** + * @param {?} e + * @return {?} + */ + (e) => { throw e; }) }); + } + /** + * @param {?} subscription + * @return {?} + */ + dispose(subscription) { subscription.unsubscribe(); } + /** + * @param {?} subscription + * @return {?} + */ + onDestroy(subscription) { subscription.unsubscribe(); } +} +class PromiseStrategy { + /** + * @param {?} async + * @param {?} updateLatestValue + * @return {?} + */ + createSubscription(async, updateLatestValue) { + return async.then(updateLatestValue, (/** + * @param {?} e + * @return {?} + */ + e => { throw e; })); + } + /** + * @param {?} subscription + * @return {?} + */ + dispose(subscription) { } + /** + * @param {?} subscription + * @return {?} + */ + onDestroy(subscription) { } +} +/** @type {?} */ +const _promiseStrategy = new PromiseStrategy(); +/** @type {?} */ +const _observableStrategy = new ObservableStrategy(); +/** + * \@ngModule CommonModule + * \@description + * + * Unwraps a value from an asynchronous primitive. + * + * The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has + * emitted. When a new value is emitted, the `async` pipe marks the component to be checked for + * changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid + * potential memory leaks. + * + * \@usageNotes + * + * ### Examples + * + * This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the + * promise. + * + * {\@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'} + * + * It's also possible to use `async` with Observables. The example below binds the `time` Observable + * to the view. The Observable continuously updates the view with the current time. + * + * {\@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'} + * + * \@publicApi + */ +class AsyncPipe { + /** + * @param {?} _ref + */ + constructor(_ref) { + this._ref = _ref; + this._latestValue = null; + this._latestReturnedValue = null; + this._subscription = null; + this._obj = null; + this._strategy = (/** @type {?} */ (null)); + } + /** + * @return {?} + */ + ngOnDestroy() { + if (this._subscription) { + this._dispose(); + } + } + /** + * @param {?} obj + * @return {?} + */ + transform(obj) { + if (!this._obj) { + if (obj) { + this._subscribe(obj); + } + this._latestReturnedValue = this._latestValue; + return this._latestValue; + } + if (obj !== this._obj) { + this._dispose(); + return this.transform((/** @type {?} */ (obj))); + } + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵlooseIdentical"])(this._latestValue, this._latestReturnedValue)) { + return this._latestReturnedValue; + } + this._latestReturnedValue = this._latestValue; + return _angular_core__WEBPACK_IMPORTED_MODULE_0__["WrappedValue"].wrap(this._latestValue); + } + /** + * @private + * @param {?} obj + * @return {?} + */ + _subscribe(obj) { + this._obj = obj; + this._strategy = this._selectStrategy(obj); + this._subscription = this._strategy.createSubscription(obj, (/** + * @param {?} value + * @return {?} + */ + (value) => this._updateLatestValue(obj, value))); + } + /** + * @private + * @param {?} obj + * @return {?} + */ + _selectStrategy(obj) { + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(obj)) { + return _promiseStrategy; + } + if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(obj)) { + return _observableStrategy; + } + throw invalidPipeArgumentError(AsyncPipe, obj); + } + /** + * @private + * @return {?} + */ + _dispose() { + this._strategy.dispose((/** @type {?} */ (this._subscription))); + this._latestValue = null; + this._latestReturnedValue = null; + this._subscription = null; + this._obj = null; + } + /** + * @private + * @param {?} async + * @param {?} value + * @return {?} + */ + _updateLatestValue(async, value) { + if (async === this._obj) { + this._latestValue = value; + this._ref.markForCheck(); + } + } +} +AsyncPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'async', pure: false },] } +]; +/** @nocollapse */ +AsyncPipe.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Transforms text to all lower case. + * + * @see `UpperCasePipe` + * @see `TitleCasePipe` + * \@usageNotes + * + * The following example defines a view that allows the user to enter + * text, and then uses the pipe to convert the input text to all lower case. + * + * + * + * \@ngModule CommonModule + * \@publicApi + */ +class LowerCasePipe { + /** + * @param {?} value The string to transform to lower case. + * @return {?} + */ + transform(value) { + if (!value) + return value; + if (typeof value !== 'string') { + throw invalidPipeArgumentError(LowerCasePipe, value); + } + return value.toLowerCase(); + } +} +LowerCasePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'lowercase' },] } +]; +// +// Regex below matches any Unicode word and compatible with ES5. In ES2018 the same result +// can be achieved by using /\p{L}\S*/gu and also known as Unicode Property Escapes +// (http://2ality.com/2017/07/regexp-unicode-property-escapes.html). Since there is no +// transpilation of this functionality down to ES5 without external tool, the only solution is +// to use already transpiled form. Example can be found here - +// https://mothereff.in/regexpu#input=var+regex+%3D+/%5Cp%7BL%7D/u%3B&unicodePropertyEscape=1 +// +/** @type {?} */ +const unicodeWordMatch = /(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])\S*/g; +/** + * Transforms text to title case. + * Capitalizes the first letter of each word, and transforms the + * rest of the word to lower case. + * Words are delimited by any whitespace character, such as a space, tab, or line-feed character. + * + * @see `LowerCasePipe` + * @see `UpperCasePipe` + * + * \@usageNotes + * The following example shows the result of transforming various strings into title case. + * + * + * + * \@ngModule CommonModule + * \@publicApi + */ +class TitleCasePipe { + /** + * @param {?} value The string to transform to title case. + * @return {?} + */ + transform(value) { + if (!value) + return value; + if (typeof value !== 'string') { + throw invalidPipeArgumentError(TitleCasePipe, value); + } + return value.replace(unicodeWordMatch, ((/** + * @param {?} txt + * @return {?} + */ + txt => txt[0].toUpperCase() + txt.substr(1).toLowerCase()))); + } +} +TitleCasePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'titlecase' },] } +]; +/** + * Transforms text to all upper case. + * @see `LowerCasePipe` + * @see `TitleCasePipe` + * + * \@ngModule CommonModule + * \@publicApi + */ +class UpperCasePipe { + /** + * @param {?} value The string to transform to upper case. + * @return {?} + */ + transform(value) { + if (!value) + return value; + if (typeof value !== 'string') { + throw invalidPipeArgumentError(UpperCasePipe, value); + } + return value.toUpperCase(); + } +} +UpperCasePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'uppercase' },] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// clang-format off +/** + * \@ngModule CommonModule + * \@description + * + * Formats a date value according to locale rules. + * + * Only the `en-US` locale data comes with Angular. To localize dates + * in another language, you must import the corresponding locale data. + * See the [I18n guide](guide/i18n#i18n-pipes) for more information. + * + * @see `formatDate()` + * + * + * \@usageNotes + * + * The result of this pipe is not reevaluated when the input is mutated. To avoid the need to + * reformat the date on every change-detection cycle, treat the date as an immutable object + * and change the reference when the pipe needs to run again. + * + * ### Pre-defined format options + * + * Examples are given in `en-US` locale. + * + * - `'short'`: equivalent to `'M/d/yy, h:mm a'` (`6/15/15, 9:03 AM`). + * - `'medium'`: equivalent to `'MMM d, y, h:mm:ss a'` (`Jun 15, 2015, 9:03:01 AM`). + * - `'long'`: equivalent to `'MMMM d, y, h:mm:ss a z'` (`June 15, 2015 at 9:03:01 AM + * GMT+1`). + * - `'full'`: equivalent to `'EEEE, MMMM d, y, h:mm:ss a zzzz'` (`Monday, June 15, 2015 at + * 9:03:01 AM GMT+01:00`). + * - `'shortDate'`: equivalent to `'M/d/yy'` (`6/15/15`). + * - `'mediumDate'`: equivalent to `'MMM d, y'` (`Jun 15, 2015`). + * - `'longDate'`: equivalent to `'MMMM d, y'` (`June 15, 2015`). + * - `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` (`Monday, June 15, 2015`). + * - `'shortTime'`: equivalent to `'h:mm a'` (`9:03 AM`). + * - `'mediumTime'`: equivalent to `'h:mm:ss a'` (`9:03:01 AM`). + * - `'longTime'`: equivalent to `'h:mm:ss a z'` (`9:03:01 AM GMT+1`). + * - `'fullTime'`: equivalent to `'h:mm:ss a zzzz'` (`9:03:01 AM GMT+01:00`). + * + * ### Custom format options + * + * You can construct a format string using symbols to specify the components + * of a date-time value, as described in the following table. + * Format details depend on the locale. + * Fields marked with (*) are only available in the extra data set for the given locale. + * + * | Field type | Format | Description | Example Value | + * |--------------------|-------------|---------------------------------------------------------------|------------------------------------------------------------| + * | Era | G, GG & GGG | Abbreviated | AD | + * | | GGGG | Wide | Anno Domini | + * | | GGGGG | Narrow | A | + * | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 | + * | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 | + * | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 | + * | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 | + * | Month | M | Numeric: 1 digit | 9, 12 | + * | | MM | Numeric: 2 digits + zero padded | 09, 12 | + * | | MMM | Abbreviated | Sep | + * | | MMMM | Wide | September | + * | | MMMMM | Narrow | S | + * | Month standalone | L | Numeric: 1 digit | 9, 12 | + * | | LL | Numeric: 2 digits + zero padded | 09, 12 | + * | | LLL | Abbreviated | Sep | + * | | LLLL | Wide | September | + * | | LLLLL | Narrow | S | + * | Week of year | w | Numeric: minimum digits | 1... 53 | + * | | ww | Numeric: 2 digits + zero padded | 01... 53 | + * | Week of month | W | Numeric: 1 digit | 1... 5 | + * | Day of month | d | Numeric: minimum digits | 1 | + * | | dd | Numeric: 2 digits + zero padded | 01 | + * | Week day | E, EE & EEE | Abbreviated | Tue | + * | | EEEE | Wide | Tuesday | + * | | EEEEE | Narrow | T | + * | | EEEEEE | Short | Tu | + * | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM | + * | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem | + * | | aaaaa | Narrow | a/p | + * | Period* | B, BB & BBB | Abbreviated | mid. | + * | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | + * | | BBBBB | Narrow | md | + * | Period standalone* | b, bb & bbb | Abbreviated | mid. | + * | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night | + * | | bbbbb | Narrow | md | + * | Hour 1-12 | h | Numeric: minimum digits | 1, 12 | + * | | hh | Numeric: 2 digits + zero padded | 01, 12 | + * | Hour 0-23 | H | Numeric: minimum digits | 0, 23 | + * | | HH | Numeric: 2 digits + zero padded | 00, 23 | + * | Minute | m | Numeric: minimum digits | 8, 59 | + * | | mm | Numeric: 2 digits + zero padded | 08, 59 | + * | Second | s | Numeric: minimum digits | 0... 59 | + * | | ss | Numeric: 2 digits + zero padded | 00... 59 | + * | Fractional seconds | S | Numeric: 1 digit | 0... 9 | + * | | SS | Numeric: 2 digits + zero padded | 00... 99 | + * | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 | + * | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 | + * | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 | + * | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 | + * | | ZZZZ | Long localized GMT format | GMT-8:00 | + * | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 | + * | | O, OO & OOO | Short localized GMT format | GMT-8 | + * | | OOOO | Long localized GMT format | GMT-08:00 | + * + * Note that timezone correction is not applied to an ISO string that has no time component, such as "2016-09-19" + * + * ### Format examples + * + * These examples transform a date into various formats, + * assuming that `dateObj` is a JavaScript `Date` object for + * year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11, + * given in the local time for the `en-US` locale. + * + * ``` + * {{ dateObj | date }} // output is 'Jun 15, 2015' + * {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM' + * {{ dateObj | date:'shortTime' }} // output is '9:43 PM' + * {{ dateObj | date:'mm:ss' }} // output is '43:11' + * ``` + * + * ### Usage example + * + * The following component uses a date pipe to display the current date in different formats. + * + * ``` + * \@Component({ + * selector: 'date-pipe', + * template: `
    + *

    Today is {{today | date}}

    + *

    Or if you prefer, {{today | date:'fullDate'}}

    + *

    The time is {{today | date:'h:mm a z'}}

    + *
    ` + * }) + * // Get the current date and time as a date-time value. + * export class DatePipeComponent { + * today: number = Date.now(); + * } + * ``` + * + * \@publicApi + */ +// clang-format on +class DatePipe { + /** + * @param {?} locale + */ + constructor(locale) { + this.locale = locale; + } + /** + * @param {?} value The date expression: a `Date` object, a number + * (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime). + * @param {?=} format The date/time components to include, using predefined options or a + * custom format string. + * @param {?=} timezone A timezone offset (such as `'+0430'`), or a standard + * UTC/GMT or continental US timezone abbreviation. Default is + * the local system timezone of the end-user's machine. + * @param {?=} locale A locale code for the locale format rules to use. + * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. + * See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app). + * @return {?} A date string in the desired format. + */ + transform(value, format = 'mediumDate', timezone, locale) { + if (value == null || value === '' || value !== value) + return null; + try { + return formatDate(value, format, locale || this.locale, timezone); + } + catch (error) { + throw invalidPipeArgumentError(DatePipe, error.message); + } + } +} +DatePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'date', pure: true },] } +]; +/** @nocollapse */ +DatePipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @type {?} */ +const _INTERPOLATION_REGEXP = /#/g; +/** + * \@ngModule CommonModule + * \@description + * + * Maps a value to a string that pluralizes the value according to locale rules. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/pipes/ts/i18n_pipe.ts region='I18nPluralPipeComponent'} + * + * \@publicApi + */ +class I18nPluralPipe { + /** + * @param {?} _localization + */ + constructor(_localization) { + this._localization = _localization; + } + /** + * @param {?} value the number to be formatted + * @param {?} pluralMap an object that mimics the ICU format, see + * http://userguide.icu-project.org/formatparse/messages. + * @param {?=} locale a `string` defining the locale to use (uses the current {\@link LOCALE_ID} by + * default). + * @return {?} + */ + transform(value, pluralMap, locale) { + if (value == null) + return ''; + if (typeof pluralMap !== 'object' || pluralMap === null) { + throw invalidPipeArgumentError(I18nPluralPipe, pluralMap); + } + /** @type {?} */ + const key = getPluralCategory(value, Object.keys(pluralMap), this._localization, locale); + return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString()); + } +} +I18nPluralPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'i18nPlural', pure: true },] } +]; +/** @nocollapse */ +I18nPluralPipe.ctorParameters = () => [ + { type: NgLocalization } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * \@description + * + * Generic selector that displays the string that matches the current value. + * + * If none of the keys of the `mapping` match the `value`, then the content + * of the `other` key is returned when present, otherwise an empty string is returned. + * + * \@usageNotes + * + * ### Example + * + * {\@example common/pipes/ts/i18n_pipe.ts region='I18nSelectPipeComponent'} + * + * \@publicApi + */ +class I18nSelectPipe { + /** + * @param {?} value a string to be internationalized. + * @param {?} mapping an object that indicates the text that should be displayed + * for different values of the provided `value`. + * @return {?} + */ + transform(value, mapping) { + if (value == null) + return ''; + if (typeof mapping !== 'object' || typeof value !== 'string') { + throw invalidPipeArgumentError(I18nSelectPipe, mapping); + } + if (mapping.hasOwnProperty(value)) { + return mapping[value]; + } + if (mapping.hasOwnProperty('other')) { + return mapping['other']; + } + return ''; + } +} +I18nSelectPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'i18nSelect', pure: true },] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * \@description + * + * Converts a value into its JSON-format representation. Useful for debugging. + * + * \@usageNotes + * + * The following component uses a JSON pipe to convert an object + * to JSON format, and displays the string in both formats for comparison. + * + * {\@example common/pipes/ts/json_pipe.ts region='JsonPipe'} + * + * \@publicApi + */ +class JsonPipe { + /** + * @param {?} value A value of any type to convert into a JSON-format string. + * @return {?} + */ + transform(value) { return JSON.stringify(value, null, 2); } +} +JsonPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'json', pure: false },] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @template K, V + * @param {?} key + * @param {?} value + * @return {?} + */ +function makeKeyValuePair(key, value) { + return { key: key, value: value }; +} +/** + * \@ngModule CommonModule + * \@description + * + * Transforms Object or Map into an array of key value pairs. + * + * The output array will be ordered by keys. + * By default the comparator will be by Unicode point value. + * You can optionally pass a compareFn if your keys are complex types. + * + * \@usageNotes + * ### Examples + * + * This examples show how an Object or a Map can be iterated by ngFor with the use of this keyvalue + * pipe. + * + * {\@example common/pipes/ts/keyvalue_pipe.ts region='KeyValuePipe'} + * + * \@publicApi + */ +class KeyValuePipe { + /** + * @param {?} differs + */ + constructor(differs) { + this.differs = differs; + this.keyValues = []; + } + /** + * @template K, V + * @param {?} input + * @param {?=} compareFn + * @return {?} + */ + transform(input, compareFn = defaultComparator) { + if (!input || (!(input instanceof Map) && typeof input !== 'object')) { + return null; + } + if (!this.differ) { + // make a differ for whatever type we've been passed in + this.differ = this.differs.find(input).create(); + } + /** @type {?} */ + const differChanges = this.differ.diff((/** @type {?} */ (input))); + if (differChanges) { + this.keyValues = []; + differChanges.forEachItem((/** + * @param {?} r + * @return {?} + */ + (r) => { + this.keyValues.push(makeKeyValuePair(r.key, (/** @type {?} */ (r.currentValue)))); + })); + this.keyValues.sort(compareFn); + } + return this.keyValues; + } +} +KeyValuePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'keyvalue', pure: false },] } +]; +/** @nocollapse */ +KeyValuePipe.ctorParameters = () => [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] } +]; +/** + * @template K, V + * @param {?} keyValueA + * @param {?} keyValueB + * @return {?} + */ +function defaultComparator(keyValueA, keyValueB) { + /** @type {?} */ + const a = keyValueA.key; + /** @type {?} */ + const b = keyValueB.key; + // if same exit with 0; + if (a === b) + return 0; + // make sure that undefined are at the end of the sort. + if (a === undefined) + return 1; + if (b === undefined) + return -1; + // make sure that nulls are at the end of the sort. + if (a === null) + return 1; + if (b === null) + return -1; + if (typeof a == 'string' && typeof b == 'string') { + return a < b ? -1 : 1; + } + if (typeof a == 'number' && typeof b == 'number') { + return a - b; + } + if (typeof a == 'boolean' && typeof b == 'boolean') { + return a < b ? -1 : 1; + } + // `a` and `b` are of different types. Compare their string values. + /** @type {?} */ + const aString = String(a); + /** @type {?} */ + const bString = String(b); + return aString == bString ? 0 : aString < bString ? -1 : 1; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * \@description + * + * Transforms a number into a string, + * formatted according to locale rules that determine group sizing and + * separator, decimal-point character, and other locale-specific + * configurations. + * + * If no parameters are specified, the function rounds off to the nearest value using this + * [rounding method](https://en.wikibooks.org/wiki/Arithmetic/Rounding). + * The behavior differs from that of the JavaScript ```Math.round()``` function. + * In the following case for example, the pipe rounds down where + * ```Math.round()``` rounds up: + * + * ```html + * -2.5 | number:'1.0-0' + * > -3 + * Math.round(-2.5) + * > -2 + * ``` + * + * @see `formatNumber()` + * + * \@usageNotes + * The following code shows how the pipe transforms numbers + * into text strings, according to various format specifications, + * where the caller's default locale is `en-US`. + * + * ### Example + * + * + * + * \@publicApi + */ +class DecimalPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * @param {?} value The number to be formatted. + * @param {?=} digitsInfo Decimal representation options, specified by a string + * in the following format:
    + * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}. + * - `minIntegerDigits`: The minimum number of integer digits before the decimal point. + * Default is `1`. + * - `minFractionDigits`: The minimum number of digits after the decimal point. + * Default is `0`. + * - `maxFractionDigits`: The maximum number of digits after the decimal point. + * Default is `3`. + * @param {?=} locale A locale code for the locale format rules to use. + * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. + * See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app). + * @return {?} + */ + transform(value, digitsInfo, locale) { + if (isEmpty(value)) + return null; + locale = locale || this._locale; + try { + /** @type {?} */ + const num = strToNumber(value); + return formatNumber(num, locale, digitsInfo); + } + catch (error) { + throw invalidPipeArgumentError(DecimalPipe, error.message); + } + } +} +DecimalPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'number' },] } +]; +/** @nocollapse */ +DecimalPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * \@ngModule CommonModule + * \@description + * + * Transforms a number to a percentage + * string, formatted according to locale rules that determine group sizing and + * separator, decimal-point character, and other locale-specific + * configurations. + * + * @see `formatPercent()` + * + * \@usageNotes + * The following code shows how the pipe transforms numbers + * into text strings, according to various format specifications, + * where the caller's default locale is `en-US`. + * + * + * + * \@publicApi + */ +class PercentPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * + * @param {?} value The number to be formatted as a percentage. + * @param {?=} digitsInfo Decimal representation options, specified by a string + * in the following format:
    + * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}. + * - `minIntegerDigits`: The minimum number of integer digits before the decimal point. + * Default is `1`. + * - `minFractionDigits`: The minimum number of digits after the decimal point. + * Default is `0`. + * - `maxFractionDigits`: The maximum number of digits after the decimal point. + * Default is `0`. + * @param {?=} locale A locale code for the locale format rules to use. + * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. + * See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app). + * @return {?} + */ + transform(value, digitsInfo, locale) { + if (isEmpty(value)) + return null; + locale = locale || this._locale; + try { + /** @type {?} */ + const num = strToNumber(value); + return formatPercent(num, locale, digitsInfo); + } + catch (error) { + throw invalidPipeArgumentError(PercentPipe, error.message); + } + } +} +PercentPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'percent' },] } +]; +/** @nocollapse */ +PercentPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * \@ngModule CommonModule + * \@description + * + * Transforms a number to a currency string, formatted according to locale rules + * that determine group sizing and separator, decimal-point character, + * and other locale-specific configurations. + * + * @see `getCurrencySymbol()` + * @see `formatCurrency()` + * + * \@usageNotes + * The following code shows how the pipe transforms numbers + * into text strings, according to various format specifications, + * where the caller's default locale is `en-US`. + * + * + * + * \@publicApi + */ +class CurrencyPipe { + /** + * @param {?} _locale + */ + constructor(_locale) { + this._locale = _locale; + } + /** + * + * @param {?} value The number to be formatted as currency. + * @param {?=} currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code, + * such as `USD` for the US dollar and `EUR` for the euro. + * @param {?=} display The format for the currency indicator. One of the following: + * - `code`: Show the code (such as `USD`). + * - `symbol`(default): Show the symbol (such as `$`). + * - `symbol-narrow`: Use the narrow symbol for locales that have two symbols for their + * currency. + * For example, the Canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`. If the + * locale has no narrow symbol, uses the standard symbol for the locale. + * - String: Use the given string value instead of a code or a symbol. + * For example, an empty string will suppress the currency & symbol. + * - Boolean (marked deprecated in v5): `true` for symbol and false for `code`. + * + * @param {?=} digitsInfo Decimal representation options, specified by a string + * in the following format:
    + * {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}. + * - `minIntegerDigits`: The minimum number of integer digits before the decimal point. + * Default is `1`. + * - `minFractionDigits`: The minimum number of digits after the decimal point. + * Default is `2`. + * - `maxFractionDigits`: The maximum number of digits after the decimal point. + * Default is `2`. + * If not provided, the number will be formatted with the proper amount of digits, + * depending on what the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) specifies. + * For example, the Canadian dollar has 2 digits, whereas the Chilean peso has none. + * @param {?=} locale A locale code for the locale format rules to use. + * When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default. + * See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app). + * @return {?} + */ + transform(value, currencyCode, display = 'symbol', digitsInfo, locale) { + if (isEmpty(value)) + return null; + locale = locale || this._locale; + if (typeof display === 'boolean') { + if ((/** @type {?} */ (console)) && (/** @type {?} */ (console.warn))) { + console.warn(`Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".`); + } + display = display ? 'symbol' : 'code'; + } + /** @type {?} */ + let currency = currencyCode || 'USD'; + if (display !== 'code') { + if (display === 'symbol' || display === 'symbol-narrow') { + currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale); + } + else { + currency = display; + } + } + try { + /** @type {?} */ + const num = strToNumber(value); + return formatCurrency(num, locale, currency, currencyCode, digitsInfo); + } + catch (error) { + throw invalidPipeArgumentError(CurrencyPipe, error.message); + } + } +} +CurrencyPipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'currency' },] } +]; +/** @nocollapse */ +CurrencyPipe.ctorParameters = () => [ + { type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] } +]; +/** + * @param {?} value + * @return {?} + */ +function isEmpty(value) { + return value == null || value === '' || value !== value; +} +/** + * Transforms a string into a number (if needed). + * @param {?} value + * @return {?} + */ +function strToNumber(value) { + // Convert strings to numbers + if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) { + return Number(value); + } + if (typeof value !== 'number') { + throw new Error(`${value} is not a number`); + } + return value; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@ngModule CommonModule + * \@description + * + * Creates a new `Array` or `String` containing a subset (slice) of the elements. + * + * \@usageNotes + * + * All behavior is based on the expected behavior of the JavaScript API `Array.prototype.slice()` + * and `String.prototype.slice()`. + * + * When operating on an `Array`, the returned `Array` is always a copy even when all + * the elements are being returned. + * + * When operating on a blank value, the pipe returns the blank value. + * + * ### List Example + * + * This `ngFor` example: + * + * {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_list'} + * + * produces the following: + * + * ```html + *
  • b
  • + *
  • c
  • + * ``` + * + * ### String Examples + * + * {\@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'} + * + * \@publicApi + */ +class SlicePipe { + /** + * @param {?} value + * @param {?} start + * @param {?=} end + * @return {?} + */ + transform(value, start, end) { + if (value == null) + return value; + if (!this.supports(value)) { + throw invalidPipeArgumentError(SlicePipe, value); + } + return value.slice(start, end); + } + /** + * @private + * @param {?} obj + * @return {?} + */ + supports(obj) { return typeof obj === 'string' || Array.isArray(obj); } +} +SlicePipe.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] }, + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"], args: [{ name: 'slice', pure: false },] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A collection of Angular pipes that are likely to be used in each and every application. + * @type {?} + */ +const COMMON_PIPES = [ + AsyncPipe, + UpperCasePipe, + LowerCasePipe, + JsonPipe, + SlicePipe, + DecimalPipe, + PercentPipe, + TitleCasePipe, + CurrencyPipe, + DatePipe, + I18nPluralPipe, + I18nSelectPipe, + KeyValuePipe, +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// Note: This does not contain the location providers, +// as they need some platform specific implementations to work. +/** + * Exports all the basic Angular directives and pipes, + * such as `NgIf`, `NgForOf`, `DecimalPipe`, and so on. + * Re-exported by `BrowserModule`, which is included automatically in the root + * `AppModule` when you create a new app with the CLI `new` command. + * + * * The `providers` options configure the NgModule's injector to provide + * localization dependencies to members. + * * The `exports` options make the declared directives and pipes available for import + * by other NgModules. + * + * \@publicApi + */ +class CommonModule { +} +CommonModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + declarations: [COMMON_DIRECTIVES, COMMON_PIPES], + exports: [COMMON_DIRECTIVES, COMMON_PIPES], + providers: [ + { provide: NgLocalization, useClass: NgLocaleLocalization }, + ], + },] } +]; +const ɵ0$2 = getPluralCase; +/** + * A module that contains the deprecated i18n pipes. + * + * @deprecated from v5 + * \@publicApi + */ +class DeprecatedI18NPipesModule { +} +DeprecatedI18NPipesModule.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"], args: [{ + declarations: [COMMON_DEPRECATED_I18N_PIPES], + exports: [COMMON_DEPRECATED_I18N_PIPES], + providers: [{ provide: DEPRECATED_PLURAL_FN, useValue: ɵ0$2 }], + },] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A DI Token representing the main rendering context. In a browser this is the DOM Document. + * + * Note: Document might not be available in the Application Context when Application and Rendering + * Contexts are not the same (e.g. when running the application into a Web Worker). + * + * \@publicApi + * @type {?} + */ +const DOCUMENT = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('DocumentToken'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** @type {?} */ +const PLATFORM_BROWSER_ID = 'browser'; +/** @type {?} */ +const PLATFORM_SERVER_ID = 'server'; +/** @type {?} */ +const PLATFORM_WORKER_APP_ID = 'browserWorkerApp'; +/** @type {?} */ +const PLATFORM_WORKER_UI_ID = 'browserWorkerUi'; +/** + * Returns whether a platform id represents a browser platform. + * \@publicApi + * @param {?} platformId + * @return {?} + */ +function isPlatformBrowser(platformId) { + return platformId === PLATFORM_BROWSER_ID; +} +/** + * Returns whether a platform id represents a server platform. + * \@publicApi + * @param {?} platformId + * @return {?} + */ +function isPlatformServer(platformId) { + return platformId === PLATFORM_SERVER_ID; +} +/** + * Returns whether a platform id represents a web worker app platform. + * \@publicApi + * @param {?} platformId + * @return {?} + */ +function isPlatformWorkerApp(platformId) { + return platformId === PLATFORM_WORKER_APP_ID; +} +/** + * Returns whether a platform id represents a web worker UI platform. + * \@publicApi + * @param {?} platformId + * @return {?} + */ +function isPlatformWorkerUi(platformId) { + return platformId === PLATFORM_WORKER_UI_ID; +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * \@publicApi + * @type {?} + */ +const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Version"]('8.1.2'); + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Defines a scroll position manager. Implemented by `BrowserViewportScroller`. + * + * \@publicApi + * @abstract + */ +class ViewportScroller { +} +// De-sugared tree-shakable injection +// See #23917 +/** @nocollapse */ +/** @nocollapse */ ViewportScroller.ngInjectableDef = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ + token: ViewportScroller, + providedIn: 'root', + factory: (/** + * @nocollapse @return {?} + */ + () => new BrowserViewportScroller(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT), window, Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ErrorHandler"]))) +}); +/** + * Manages the scroll position for a browser window. + */ +class BrowserViewportScroller { + /** + * @param {?} document + * @param {?} window + * @param {?} errorHandler + */ + constructor(document, window, errorHandler) { + this.document = document; + this.window = window; + this.errorHandler = errorHandler; + this.offset = (/** + * @return {?} + */ + () => [0, 0]); + } + /** + * Configures the top offset used when scrolling to an anchor. + * @param {?} offset A position in screen coordinates (a tuple with x and y values) + * or a function that returns the top offset position. + * + * @return {?} + */ + setOffset(offset) { + if (Array.isArray(offset)) { + this.offset = (/** + * @return {?} + */ + () => offset); + } + else { + this.offset = offset; + } + } + /** + * Retrieves the current scroll position. + * @return {?} The position in screen coordinates. + */ + getScrollPosition() { + if (this.supportScrollRestoration()) { + return [this.window.scrollX, this.window.scrollY]; + } + else { + return [0, 0]; + } + } + /** + * Sets the scroll position. + * @param {?} position The new position in screen coordinates. + * @return {?} + */ + scrollToPosition(position) { + if (this.supportScrollRestoration()) { + this.window.scrollTo(position[0], position[1]); + } + } + /** + * Scrolls to an anchor element. + * @param {?} anchor The ID of the anchor element. + * @return {?} + */ + scrollToAnchor(anchor) { + if (this.supportScrollRestoration()) { + // Escape anything passed to `querySelector` as it can throw errors and stop the application + // from working if invalid values are passed. + if (this.window.CSS && this.window.CSS.escape) { + anchor = this.window.CSS.escape(anchor); + } + else { + anchor = anchor.replace(/(\"|\'\ |:|\.|\[|\]|,|=)/g, '\\$1'); + } + try { + /** @type {?} */ + const elSelectedById = this.document.querySelector(`#${anchor}`); + if (elSelectedById) { + this.scrollToElement(elSelectedById); + return; + } + /** @type {?} */ + const elSelectedByName = this.document.querySelector(`[name='${anchor}']`); + if (elSelectedByName) { + this.scrollToElement(elSelectedByName); + return; + } + } + catch (e) { + this.errorHandler.handleError(e); + } + } + } + /** + * Disables automatic scroll restoration provided by the browser. + * @param {?} scrollRestoration + * @return {?} + */ + setHistoryScrollRestoration(scrollRestoration) { + if (this.supportScrollRestoration()) { + /** @type {?} */ + const history = this.window.history; + if (history && history.scrollRestoration) { + history.scrollRestoration = scrollRestoration; + } + } + } + /** + * @private + * @param {?} el + * @return {?} + */ + scrollToElement(el) { + /** @type {?} */ + const rect = el.getBoundingClientRect(); + /** @type {?} */ + const left = rect.left + this.window.pageXOffset; + /** @type {?} */ + const top = rect.top + this.window.pageYOffset; + /** @type {?} */ + const offset = this.offset(); + this.window.scrollTo(left - offset[0], top - offset[1]); + } + /** + * We only support scroll restoration when we can get a hold of window. + * This means that we do not support this behavior when running in a web worker. + * + * Lifting this restriction right now would require more changes in the dom adapter. + * Since webworkers aren't widely used, we will lift it once RouterScroller is + * battle-tested. + * @private + * @return {?} + */ + supportScrollRestoration() { + try { + return !!this.window && !!this.window.scrollTo; + } + catch (_a) { + return false; + } + } +} +/** + * Provides an empty implementation of the viewport scroller. This will + * live in \@angular/common as it will be used by both platform-server and platform-webworker. + */ +class NullViewportScroller { + /** + * Empty implementation + * @param {?} offset + * @return {?} + */ + setOffset(offset) { } + /** + * Empty implementation + * @return {?} + */ + getScrollPosition() { return [0, 0]; } + /** + * Empty implementation + * @param {?} position + * @return {?} + */ + scrollToPosition(position) { } + /** + * Empty implementation + * @param {?} anchor + * @return {?} + */ + scrollToAnchor(anchor) { } + /** + * Empty implementation + * @param {?} scrollRestoration + * @return {?} + */ + setHistoryScrollRestoration(scrollRestoration) { } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ + +/** + * Generated bundle index. Do not edit. + */ + + +//# sourceMappingURL=common.js.map + + +/***/ }), + +/***/ "./node_modules/@angular/common/fesm2015/http.js": +/*!*******************************************************!*\ + !*** ./node_modules/@angular/common/fesm2015/http.js ***! + \*******************************************************/ +/*! exports provided: ɵangular_packages_common_http_http_a, ɵangular_packages_common_http_http_b, ɵangular_packages_common_http_http_c, ɵangular_packages_common_http_http_d, ɵangular_packages_common_http_http_g, ɵangular_packages_common_http_http_h, ɵangular_packages_common_http_http_e, ɵangular_packages_common_http_http_f, HttpBackend, HttpHandler, HttpClient, HttpHeaders, HTTP_INTERCEPTORS, JsonpClientBackend, JsonpInterceptor, HttpClientJsonpModule, HttpClientModule, HttpClientXsrfModule, ɵHttpInterceptingHandler, HttpParams, HttpUrlEncodingCodec, HttpRequest, HttpErrorResponse, HttpEventType, HttpHeaderResponse, HttpResponse, HttpResponseBase, HttpXhrBackend, XhrFactory, HttpXsrfTokenExtractor */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_a", function() { return NoopInterceptor; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_b", function() { return JsonpCallbackContext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_c", function() { return jsonpCallbackContext; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_d", function() { return BrowserXhr; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_g", function() { return HttpXsrfCookieExtractor; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_h", function() { return HttpXsrfInterceptor; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_e", function() { return XSRF_COOKIE_NAME; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_http_http_f", function() { return XSRF_HEADER_NAME; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpBackend", function() { return HttpBackend; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpHandler", function() { return HttpHandler; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpClient", function() { return HttpClient; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpHeaders", function() { return HttpHeaders; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HTTP_INTERCEPTORS", function() { return HTTP_INTERCEPTORS; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JsonpClientBackend", function() { return JsonpClientBackend; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JsonpInterceptor", function() { return JsonpInterceptor; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpClientJsonpModule", function() { return HttpClientJsonpModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpClientModule", function() { return HttpClientModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpClientXsrfModule", function() { return HttpClientXsrfModule; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵHttpInterceptingHandler", function() { return HttpInterceptingHandler; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpParams", function() { return HttpParams; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpUrlEncodingCodec", function() { return HttpUrlEncodingCodec; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpRequest", function() { return HttpRequest; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpErrorResponse", function() { return HttpErrorResponse; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpEventType", function() { return HttpEventType; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpHeaderResponse", function() { return HttpHeaderResponse; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpResponse", function() { return HttpResponse; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpResponseBase", function() { return HttpResponseBase; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpXhrBackend", function() { return HttpXhrBackend; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "XhrFactory", function() { return XhrFactory; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HttpXsrfTokenExtractor", function() { return HttpXsrfTokenExtractor; }); +/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/fesm2015/core.js"); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! rxjs */ "./node_modules/rxjs/_esm2015/index.js"); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! rxjs/operators */ "./node_modules/rxjs/_esm2015/operators/index.js"); +/* harmony import */ var _angular_common__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/common */ "./node_modules/@angular/common/fesm2015/common.js"); +/** + * @license Angular v8.1.2 + * (c) 2010-2019 Google LLC. https://angular.io/ + * License: MIT + */ + + + + + + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/** + * Transforms an `HttpRequest` into a stream of `HttpEvent`s, one of which will likely be a + * `HttpResponse`. + * + * `HttpHandler` is injectable. When injected, the handler instance dispatches requests to the + * first interceptor in the chain, which dispatches to the second, etc, eventually reaching the + * `HttpBackend`. + * + * In an `HttpInterceptor`, the `HttpHandler` parameter is the next interceptor in the chain. + * + * \@publicApi + * @abstract + */ +class HttpHandler { +} +/** + * A final `HttpHandler` which will dispatch the request via browser HTTP APIs to a backend. + * + * Interceptors sit between the `HttpClient` interface and the `HttpBackend`. + * + * When injected, `HttpBackend` dispatches requests directly to the backend, without going + * through the interceptor chain. + * + * \@publicApi + * @abstract + */ +class HttpBackend { +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * `HttpHeaders` class represents the header configuration options for an HTTP request. + * Instances should be assumed immutable with lazy parsing. + * + * \@publicApi + */ +class HttpHeaders { + /** + * Constructs a new HTTP header object with the given values. + * @param {?=} headers + */ + constructor(headers) { + /** + * Internal map of lowercased header names to the normalized + * form of the name (the form seen first). + */ + this.normalizedNames = new Map(); + /** + * Queued updates to be materialized the next initialization. + */ + this.lazyUpdate = null; + if (!headers) { + this.headers = new Map(); + } + else if (typeof headers === 'string') { + this.lazyInit = (/** + * @return {?} + */ + () => { + this.headers = new Map(); + headers.split('\n').forEach((/** + * @param {?} line + * @return {?} + */ + line => { + /** @type {?} */ + const index = line.indexOf(':'); + if (index > 0) { + /** @type {?} */ + const name = line.slice(0, index); + /** @type {?} */ + const key = name.toLowerCase(); + /** @type {?} */ + const value = line.slice(index + 1).trim(); + this.maybeSetNormalizedName(name, key); + if (this.headers.has(key)) { + (/** @type {?} */ (this.headers.get(key))).push(value); + } + else { + this.headers.set(key, [value]); + } + } + })); + }); + } + else { + this.lazyInit = (/** + * @return {?} + */ + () => { + this.headers = new Map(); + Object.keys(headers).forEach((/** + * @param {?} name + * @return {?} + */ + name => { + /** @type {?} */ + let values = headers[name]; + /** @type {?} */ + const key = name.toLowerCase(); + if (typeof values === 'string') { + values = [values]; + } + if (values.length > 0) { + this.headers.set(key, values); + this.maybeSetNormalizedName(name, key); + } + })); + }); + } + } + /** + * Checks for existence of a header by a given name. + * + * @param {?} name The header name to check for existence. + * + * @return {?} Whether the header exits. + */ + has(name) { + this.init(); + return this.headers.has(name.toLowerCase()); + } + /** + * Returns the first header value that matches a given name. + * + * @param {?} name The header name to retrieve. + * + * @return {?} A string if the header exists, null otherwise + */ + get(name) { + this.init(); + /** @type {?} */ + const values = this.headers.get(name.toLowerCase()); + return values && values.length > 0 ? values[0] : null; + } + /** + * Returns the names of the headers. + * + * @return {?} A list of header names. + */ + keys() { + this.init(); + return Array.from(this.normalizedNames.values()); + } + /** + * Returns a list of header values for a given header name. + * + * @param {?} name The header name from which to retrieve the values. + * + * @return {?} A string of values if the header exists, null otherwise. + */ + getAll(name) { + this.init(); + return this.headers.get(name.toLowerCase()) || null; + } + /** + * Appends a new header value to the existing set of + * header values. + * + * @param {?} name The header name for which to append the values. + * + * @param {?} value + * @return {?} A clone of the HTTP header object with the value appended. + */ + append(name, value) { + return this.clone({ name, value, op: 'a' }); + } + /** + * Sets a header value for a given name. If the header name already exists, + * its value is replaced with the given value. + * + * @param {?} name The header name. + * @param {?} value Provides the value to set or overide for a given name. + * + * @return {?} A clone of the HTTP header object with the newly set header value. + */ + set(name, value) { + return this.clone({ name, value, op: 's' }); + } + /** + * Deletes all header values for a given name. + * + * @param {?} name The header name. + * @param {?=} value The header values to delete for a given name. + * + * @return {?} A clone of the HTTP header object. + */ + delete(name, value) { + return this.clone({ name, value, op: 'd' }); + } + /** + * @private + * @param {?} name + * @param {?} lcName + * @return {?} + */ + maybeSetNormalizedName(name, lcName) { + if (!this.normalizedNames.has(lcName)) { + this.normalizedNames.set(lcName, name); + } + } + /** + * @private + * @return {?} + */ + init() { + if (!!this.lazyInit) { + if (this.lazyInit instanceof HttpHeaders) { + this.copyFrom(this.lazyInit); + } + else { + this.lazyInit(); + } + this.lazyInit = null; + if (!!this.lazyUpdate) { + this.lazyUpdate.forEach((/** + * @param {?} update + * @return {?} + */ + update => this.applyUpdate(update))); + this.lazyUpdate = null; + } + } + } + /** + * @private + * @param {?} other + * @return {?} + */ + copyFrom(other) { + other.init(); + Array.from(other.headers.keys()).forEach((/** + * @param {?} key + * @return {?} + */ + key => { + this.headers.set(key, (/** @type {?} */ (other.headers.get(key)))); + this.normalizedNames.set(key, (/** @type {?} */ (other.normalizedNames.get(key)))); + })); + } + /** + * @private + * @param {?} update + * @return {?} + */ + clone(update) { + /** @type {?} */ + const clone = new HttpHeaders(); + clone.lazyInit = + (!!this.lazyInit && this.lazyInit instanceof HttpHeaders) ? this.lazyInit : this; + clone.lazyUpdate = (this.lazyUpdate || []).concat([update]); + return clone; + } + /** + * @private + * @param {?} update + * @return {?} + */ + applyUpdate(update) { + /** @type {?} */ + const key = update.name.toLowerCase(); + switch (update.op) { + case 'a': + case 's': + /** @type {?} */ + let value = (/** @type {?} */ (update.value)); + if (typeof value === 'string') { + value = [value]; + } + if (value.length === 0) { + return; + } + this.maybeSetNormalizedName(update.name, key); + /** @type {?} */ + const base = (update.op === 'a' ? this.headers.get(key) : undefined) || []; + base.push(...value); + this.headers.set(key, base); + break; + case 'd': + /** @type {?} */ + const toDelete = (/** @type {?} */ (update.value)); + if (!toDelete) { + this.headers.delete(key); + this.normalizedNames.delete(key); + } + else { + /** @type {?} */ + let existing = this.headers.get(key); + if (!existing) { + return; + } + existing = existing.filter((/** + * @param {?} value + * @return {?} + */ + value => toDelete.indexOf(value) === -1)); + if (existing.length === 0) { + this.headers.delete(key); + this.normalizedNames.delete(key); + } + else { + this.headers.set(key, existing); + } + } + break; + } + } + /** + * \@internal + * @param {?} fn + * @return {?} + */ + forEach(fn) { + this.init(); + Array.from(this.normalizedNames.keys()) + .forEach((/** + * @param {?} key + * @return {?} + */ + key => fn((/** @type {?} */ (this.normalizedNames.get(key))), (/** @type {?} */ (this.headers.get(key)))))); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * A class that uses `encodeURIComponent` and `decodeURIComponent` to + * serialize and parse URL parameter keys and values. If you pass URL query parameters + * without encoding, the query parameters can get misinterpreted at the receiving end. + * Use the `HttpParameterCodec` class to encode and decode the query-string values. + * + * \@publicApi + */ +class HttpUrlEncodingCodec { + /** + * @param {?} key + * @return {?} + */ + encodeKey(key) { return standardEncoding(key); } + /** + * @param {?} value + * @return {?} + */ + encodeValue(value) { return standardEncoding(value); } + /** + * @param {?} key + * @return {?} + */ + decodeKey(key) { return decodeURIComponent(key); } + /** + * @param {?} value + * @return {?} + */ + decodeValue(value) { return decodeURIComponent(value); } +} +/** + * @param {?} rawParams + * @param {?} codec + * @return {?} + */ +function paramParser(rawParams, codec) { + /** @type {?} */ + const map = new Map(); + if (rawParams.length > 0) { + /** @type {?} */ + const params = rawParams.split('&'); + params.forEach((/** + * @param {?} param + * @return {?} + */ + (param) => { + /** @type {?} */ + const eqIdx = param.indexOf('='); + const [key, val] = eqIdx == -1 ? + [codec.decodeKey(param), ''] : + [codec.decodeKey(param.slice(0, eqIdx)), codec.decodeValue(param.slice(eqIdx + 1))]; + /** @type {?} */ + const list = map.get(key) || []; + list.push(val); + map.set(key, list); + })); + } + return map; +} +/** + * @param {?} v + * @return {?} + */ +function standardEncoding(v) { + return encodeURIComponent(v) + .replace(/%40/gi, '@') + .replace(/%3A/gi, ':') + .replace(/%24/gi, '$') + .replace(/%2C/gi, ',') + .replace(/%3B/gi, ';') + .replace(/%2B/gi, '+') + .replace(/%3D/gi, '=') + .replace(/%3F/gi, '?') + .replace(/%2F/gi, '/'); +} +/** + * An HTTP request/response body that represents serialized parameters, + * per the MIME type `application/x-www-form-urlencoded`. + * + * This class is immutable - all mutation operations return a new instance. + * + * \@publicApi + */ +class HttpParams { + /** + * @param {?=} options + */ + constructor(options = (/** @type {?} */ ({}))) { + this.updates = null; + this.cloneFrom = null; + this.encoder = options.encoder || new HttpUrlEncodingCodec(); + if (!!options.fromString) { + if (!!options.fromObject) { + throw new Error(`Cannot specify both fromString and fromObject.`); + } + this.map = paramParser(options.fromString, this.encoder); + } + else if (!!options.fromObject) { + this.map = new Map(); + Object.keys(options.fromObject).forEach((/** + * @param {?} key + * @return {?} + */ + key => { + /** @type {?} */ + const value = ((/** @type {?} */ (options.fromObject)))[key]; + (/** @type {?} */ (this.map)).set(key, Array.isArray(value) ? value : [value]); + })); + } + else { + this.map = null; + } + } + /** + * Check whether the body has one or more values for the given parameter name. + * @param {?} param + * @return {?} + */ + has(param) { + this.init(); + return (/** @type {?} */ (this.map)).has(param); + } + /** + * Get the first value for the given parameter name, or `null` if it's not present. + * @param {?} param + * @return {?} + */ + get(param) { + this.init(); + /** @type {?} */ + const res = (/** @type {?} */ (this.map)).get(param); + return !!res ? res[0] : null; + } + /** + * Get all values for the given parameter name, or `null` if it's not present. + * @param {?} param + * @return {?} + */ + getAll(param) { + this.init(); + return (/** @type {?} */ (this.map)).get(param) || null; + } + /** + * Get all the parameter names for this body. + * @return {?} + */ + keys() { + this.init(); + return Array.from((/** @type {?} */ (this.map)).keys()); + } + /** + * Construct a new body with an appended value for the given parameter name. + * @param {?} param + * @param {?} value + * @return {?} + */ + append(param, value) { return this.clone({ param, value, op: 'a' }); } + /** + * Construct a new body with a new value for the given parameter name. + * @param {?} param + * @param {?} value + * @return {?} + */ + set(param, value) { return this.clone({ param, value, op: 's' }); } + /** + * Construct a new body with either the given value for the given parameter + * removed, if a value is given, or all values for the given parameter removed + * if not. + * @param {?} param + * @param {?=} value + * @return {?} + */ + delete(param, value) { return this.clone({ param, value, op: 'd' }); } + /** + * Serialize the body to an encoded string, where key-value pairs (separated by `=`) are + * separated by `&`s. + * @return {?} + */ + toString() { + this.init(); + return this.keys() + .map((/** + * @param {?} key + * @return {?} + */ + key => { + /** @type {?} */ + const eKey = this.encoder.encodeKey(key); + return (/** @type {?} */ ((/** @type {?} */ (this.map)).get(key))).map((/** + * @param {?} value + * @return {?} + */ + value => eKey + '=' + this.encoder.encodeValue(value))) + .join('&'); + })) + .join('&'); + } + /** + * @private + * @param {?} update + * @return {?} + */ + clone(update) { + /** @type {?} */ + const clone = new HttpParams((/** @type {?} */ ({ encoder: this.encoder }))); + clone.cloneFrom = this.cloneFrom || this; + clone.updates = (this.updates || []).concat([update]); + return clone; + } + /** + * @private + * @return {?} + */ + init() { + if (this.map === null) { + this.map = new Map(); + } + if (this.cloneFrom !== null) { + this.cloneFrom.init(); + this.cloneFrom.keys().forEach((/** + * @param {?} key + * @return {?} + */ + key => (/** @type {?} */ (this.map)).set(key, (/** @type {?} */ ((/** @type {?} */ ((/** @type {?} */ (this.cloneFrom)).map)).get(key)))))); + (/** @type {?} */ (this.updates)).forEach((/** + * @param {?} update + * @return {?} + */ + update => { + switch (update.op) { + case 'a': + case 's': + /** @type {?} */ + const base = (update.op === 'a' ? (/** @type {?} */ (this.map)).get(update.param) : undefined) || []; + base.push((/** @type {?} */ (update.value))); + (/** @type {?} */ (this.map)).set(update.param, base); + break; + case 'd': + if (update.value !== undefined) { + /** @type {?} */ + let base = (/** @type {?} */ (this.map)).get(update.param) || []; + /** @type {?} */ + const idx = base.indexOf(update.value); + if (idx !== -1) { + base.splice(idx, 1); + } + if (base.length > 0) { + (/** @type {?} */ (this.map)).set(update.param, base); + } + else { + (/** @type {?} */ (this.map)).delete(update.param); + } + } + else { + (/** @type {?} */ (this.map)).delete(update.param); + break; + } + } + })); + this.cloneFrom = this.updates = null; + } + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Determine whether the given HTTP method may include a body. + * @param {?} method + * @return {?} + */ +function mightHaveBody(method) { + switch (method) { + case 'DELETE': + case 'GET': + case 'HEAD': + case 'OPTIONS': + case 'JSONP': + return false; + default: + return true; + } +} +/** + * Safely assert whether the given value is an ArrayBuffer. + * + * In some execution environments ArrayBuffer is not defined. + * @param {?} value + * @return {?} + */ +function isArrayBuffer(value) { + return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer; +} +/** + * Safely assert whether the given value is a Blob. + * + * In some execution environments Blob is not defined. + * @param {?} value + * @return {?} + */ +function isBlob(value) { + return typeof Blob !== 'undefined' && value instanceof Blob; +} +/** + * Safely assert whether the given value is a FormData instance. + * + * In some execution environments FormData is not defined. + * @param {?} value + * @return {?} + */ +function isFormData(value) { + return typeof FormData !== 'undefined' && value instanceof FormData; +} +/** + * An outgoing HTTP request with an optional typed body. + * + * `HttpRequest` represents an outgoing request, including URL, method, + * headers, body, and other request configuration options. Instances should be + * assumed to be immutable. To modify a `HttpRequest`, the `clone` + * method should be used. + * + * \@publicApi + * @template T + */ +class HttpRequest { + /** + * @param {?} method + * @param {?} url + * @param {?=} third + * @param {?=} fourth + */ + constructor(method, url, third, fourth) { + this.url = url; + /** + * The request body, or `null` if one isn't set. + * + * Bodies are not enforced to be immutable, as they can include a reference to any + * user-defined data type. However, interceptors should take care to preserve + * idempotence by treating them as such. + */ + this.body = null; + /** + * Whether this request should be made in a way that exposes progress events. + * + * Progress events are expensive (change detection runs on each event) and so + * they should only be requested if the consumer intends to monitor them. + */ + this.reportProgress = false; + /** + * Whether this request should be sent with outgoing credentials (cookies). + */ + this.withCredentials = false; + /** + * The expected response type of the server. + * + * This is used to parse the response appropriately before returning it to + * the requestee. + */ + this.responseType = 'json'; + this.method = method.toUpperCase(); + // Next, need to figure out which argument holds the HttpRequestInit + // options, if any. + /** @type {?} */ + let options; + // Check whether a body argument is expected. The only valid way to omit + // the body argument is to use a known no-body method like GET. + if (mightHaveBody(this.method) || !!fourth) { + // Body is the third argument, options are the fourth. + this.body = (third !== undefined) ? (/** @type {?} */ (third)) : null; + options = fourth; + } + else { + // No body required, options are the third argument. The body stays null. + options = (/** @type {?} */ (third)); + } + // If options have been passed, interpret them. + if (options) { + // Normalize reportProgress and withCredentials. + this.reportProgress = !!options.reportProgress; + this.withCredentials = !!options.withCredentials; + // Override default response type of 'json' if one is provided. + if (!!options.responseType) { + this.responseType = options.responseType; + } + // Override headers if they're provided. + if (!!options.headers) { + this.headers = options.headers; + } + if (!!options.params) { + this.params = options.params; + } + } + // If no headers have been passed in, construct a new HttpHeaders instance. + if (!this.headers) { + this.headers = new HttpHeaders(); + } + // If no parameters have been passed in, construct a new HttpUrlEncodedParams instance. + if (!this.params) { + this.params = new HttpParams(); + this.urlWithParams = url; + } + else { + // Encode the parameters to a string in preparation for inclusion in the URL. + /** @type {?} */ + const params = this.params.toString(); + if (params.length === 0) { + // No parameters, the visible URL is just the URL given at creation time. + this.urlWithParams = url; + } + else { + // Does the URL already have query parameters? Look for '?'. + /** @type {?} */ + const qIdx = url.indexOf('?'); + // There are 3 cases to handle: + // 1) No existing parameters -> append '?' followed by params. + // 2) '?' exists and is followed by existing query string -> + // append '&' followed by params. + // 3) '?' exists at the end of the url -> append params directly. + // This basically amounts to determining the character, if any, with + // which to join the URL and parameters. + /** @type {?} */ + const sep = qIdx === -1 ? '?' : (qIdx < url.length - 1 ? '&' : ''); + this.urlWithParams = url + sep + params; + } + } + } + /** + * Transform the free-form body into a serialized format suitable for + * transmission to the server. + * @return {?} + */ + serializeBody() { + // If no body is present, no need to serialize it. + if (this.body === null) { + return null; + } + // Check whether the body is already in a serialized form. If so, + // it can just be returned directly. + if (isArrayBuffer(this.body) || isBlob(this.body) || isFormData(this.body) || + typeof this.body === 'string') { + return this.body; + } + // Check whether the body is an instance of HttpUrlEncodedParams. + if (this.body instanceof HttpParams) { + return this.body.toString(); + } + // Check whether the body is an object or array, and serialize with JSON if so. + if (typeof this.body === 'object' || typeof this.body === 'boolean' || + Array.isArray(this.body)) { + return JSON.stringify(this.body); + } + // Fall back on toString() for everything else. + return ((/** @type {?} */ (this.body))).toString(); + } + /** + * Examine the body and attempt to infer an appropriate MIME type + * for it. + * + * If no such type can be inferred, this method will return `null`. + * @return {?} + */ + detectContentTypeHeader() { + // An empty body has no content type. + if (this.body === null) { + return null; + } + // FormData bodies rely on the browser's content type assignment. + if (isFormData(this.body)) { + return null; + } + // Blobs usually have their own content type. If it doesn't, then + // no type can be inferred. + if (isBlob(this.body)) { + return this.body.type || null; + } + // Array buffers have unknown contents and thus no type can be inferred. + if (isArrayBuffer(this.body)) { + return null; + } + // Technically, strings could be a form of JSON data, but it's safe enough + // to assume they're plain strings. + if (typeof this.body === 'string') { + return 'text/plain'; + } + // `HttpUrlEncodedParams` has its own content-type. + if (this.body instanceof HttpParams) { + return 'application/x-www-form-urlencoded;charset=UTF-8'; + } + // Arrays, objects, and numbers will be encoded as JSON. + if (typeof this.body === 'object' || typeof this.body === 'number' || + Array.isArray(this.body)) { + return 'application/json'; + } + // No type could be inferred. + return null; + } + /** + * @param {?=} update + * @return {?} + */ + clone(update = {}) { + // For method, url, and responseType, take the current value unless + // it is overridden in the update hash. + /** @type {?} */ + const method = update.method || this.method; + /** @type {?} */ + const url = update.url || this.url; + /** @type {?} */ + const responseType = update.responseType || this.responseType; + // The body is somewhat special - a `null` value in update.body means + // whatever current body is present is being overridden with an empty + // body, whereas an `undefined` value in update.body implies no + // override. + /** @type {?} */ + const body = (update.body !== undefined) ? update.body : this.body; + // Carefully handle the boolean options to differentiate between + // `false` and `undefined` in the update args. + /** @type {?} */ + const withCredentials = (update.withCredentials !== undefined) ? update.withCredentials : this.withCredentials; + /** @type {?} */ + const reportProgress = (update.reportProgress !== undefined) ? update.reportProgress : this.reportProgress; + // Headers and params may be appended to if `setHeaders` or + // `setParams` are used. + /** @type {?} */ + let headers = update.headers || this.headers; + /** @type {?} */ + let params = update.params || this.params; + // Check whether the caller has asked to add headers. + if (update.setHeaders !== undefined) { + // Set every requested header. + headers = + Object.keys(update.setHeaders) + .reduce((/** + * @param {?} headers + * @param {?} name + * @return {?} + */ + (headers, name) => headers.set(name, (/** @type {?} */ (update.setHeaders))[name])), headers); + } + // Check whether the caller has asked to set params. + if (update.setParams) { + // Set every requested param. + params = Object.keys(update.setParams) + .reduce((/** + * @param {?} params + * @param {?} param + * @return {?} + */ + (params, param) => params.set(param, (/** @type {?} */ (update.setParams))[param])), params); + } + // Finally, construct the new HttpRequest using the pieces from above. + return new HttpRequest(method, url, body, { + params, headers, reportProgress, responseType, withCredentials, + }); + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** @enum {number} */ +const HttpEventType = { + /** + * The request was sent out over the wire. + */ + Sent: 0, + /** + * An upload progress event was received. + */ + UploadProgress: 1, + /** + * The response status code and headers were received. + */ + ResponseHeader: 2, + /** + * A download progress event was received. + */ + DownloadProgress: 3, + /** + * The full response including the body was received. + */ + Response: 4, + /** + * A custom event from an interceptor or a backend. + */ + User: 5, +}; +HttpEventType[HttpEventType.Sent] = 'Sent'; +HttpEventType[HttpEventType.UploadProgress] = 'UploadProgress'; +HttpEventType[HttpEventType.ResponseHeader] = 'ResponseHeader'; +HttpEventType[HttpEventType.DownloadProgress] = 'DownloadProgress'; +HttpEventType[HttpEventType.Response] = 'Response'; +HttpEventType[HttpEventType.User] = 'User'; +/** + * Base class for both `HttpResponse` and `HttpHeaderResponse`. + * + * \@publicApi + * @abstract + */ +class HttpResponseBase { + /** + * Super-constructor for all responses. + * + * The single parameter accepted is an initialization hash. Any properties + * of the response passed there will override the default values. + * @param {?} init + * @param {?=} defaultStatus + * @param {?=} defaultStatusText + */ + constructor(init, defaultStatus = 200, defaultStatusText = 'OK') { + // If the hash has values passed, use them to initialize the response. + // Otherwise use the default values. + this.headers = init.headers || new HttpHeaders(); + this.status = init.status !== undefined ? init.status : defaultStatus; + this.statusText = init.statusText || defaultStatusText; + this.url = init.url || null; + // Cache the ok value to avoid defining a getter. + this.ok = this.status >= 200 && this.status < 300; + } +} +/** + * A partial HTTP response which only includes the status and header data, + * but no response body. + * + * `HttpHeaderResponse` is a `HttpEvent` available on the response + * event stream, only when progress events are requested. + * + * \@publicApi + */ +class HttpHeaderResponse extends HttpResponseBase { + /** + * Create a new `HttpHeaderResponse` with the given parameters. + * @param {?=} init + */ + constructor(init = {}) { + super(init); + this.type = HttpEventType.ResponseHeader; + } + /** + * Copy this `HttpHeaderResponse`, overriding its contents with the + * given parameter hash. + * @param {?=} update + * @return {?} + */ + clone(update = {}) { + // Perform a straightforward initialization of the new HttpHeaderResponse, + // overriding the current parameters with new ones if given. + return new HttpHeaderResponse({ + headers: update.headers || this.headers, + status: update.status !== undefined ? update.status : this.status, + statusText: update.statusText || this.statusText, + url: update.url || this.url || undefined, + }); + } +} +/** + * A full HTTP response, including a typed response body (which may be `null` + * if one was not returned). + * + * `HttpResponse` is a `HttpEvent` available on the response event + * stream. + * + * \@publicApi + * @template T + */ +class HttpResponse extends HttpResponseBase { + /** + * Construct a new `HttpResponse`. + * @param {?=} init + */ + constructor(init = {}) { + super(init); + this.type = HttpEventType.Response; + this.body = init.body !== undefined ? init.body : null; + } + /** + * @param {?=} update + * @return {?} + */ + clone(update = {}) { + return new HttpResponse({ + body: (update.body !== undefined) ? update.body : this.body, + headers: update.headers || this.headers, + status: (update.status !== undefined) ? update.status : this.status, + statusText: update.statusText || this.statusText, + url: update.url || this.url || undefined, + }); + } +} +/** + * A response that represents an error or failure, either from a + * non-successful HTTP status, an error while executing the request, + * or some other failure which occurred during the parsing of the response. + * + * Any error returned on the `Observable` response stream will be + * wrapped in an `HttpErrorResponse` to provide additional context about + * the state of the HTTP layer when the error occurred. The error property + * will contain either a wrapped Error object or the error response returned + * from the server. + * + * \@publicApi + */ +class HttpErrorResponse extends HttpResponseBase { + /** + * @param {?} init + */ + constructor(init) { + // Initialize with a default status of 0 / Unknown Error. + super(init, 0, 'Unknown Error'); + this.name = 'HttpErrorResponse'; + /** + * Errors are never okay, even when the status code is in the 2xx success range. + */ + this.ok = false; + // If the response was successful, then this was a parse error. Otherwise, it was + // a protocol-level failure of some sort. Either the request failed in transit + // or the server returned an unsuccessful status code. + if (this.status >= 200 && this.status < 300) { + this.message = `Http failure during parsing for ${init.url || '(unknown url)'}`; + } + else { + this.message = + `Http failure response for ${init.url || '(unknown url)'}: ${init.status} ${init.statusText}`; + } + this.error = init.error || null; + } +} + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * Constructs an instance of `HttpRequestOptions` from a source `HttpMethodOptions` and + * the given `body`. This function clones the object and adds the body. + * @template T + * @param {?} options + * @param {?} body + * @return {?} + */ +function addBody(options, body) { + return { + body, + headers: options.headers, + observe: options.observe, + params: options.params, + reportProgress: options.reportProgress, + responseType: options.responseType, + withCredentials: options.withCredentials, + }; +} +/** + * Performs HTTP requests. + * + * `HttpClient` is available as an injectable class, with methods to perform HTTP requests. + * Each request method has multiple signatures, and the return type varies based on + * the signature that is called (mainly the values of `observe` and `responseType`). + * + * + * @see [HTTP Guide](guide/http) + * + * + * \@usageNotes + * Sample HTTP requests for the [Tour of Heroes](/tutorial/toh-pt0) application. + * + * ### HTTP Request Example + * + * ``` + * // GET heroes whose name contains search term + * searchHeroes(term: string): observable{ + * + * const params = new HttpParams({fromString: 'name=term'}); + * return this.httpClient.request('GET', this.heroesUrl, {responseType:'json', params}); + * } + * ``` + * ### JSONP Example + * ``` + * requestJsonp(url, callback = 'callback') { + * return this.httpClient.jsonp(this.heroesURL, callback); + * } + * ``` + * + * + * ### PATCH Example + * ``` + * // PATCH one of the heroes' name + * patchHero (id: number, heroName: string): Observable<{}> { + * const url = `${this.heroesUrl}/${id}`; // PATCH api/heroes/42 + * return this.httpClient.patch(url, {name: heroName}, httpOptions) + * .pipe(catchError(this.handleError('patchHero'))); + * } + * ``` + * + * \@publicApi + */ +class HttpClient { + /** + * @param {?} handler + */ + constructor(handler) { + this.handler = handler; + } + /** + * Constructs an observable for a generic HTTP request that, when subscribed, + * fires the request through the chain of registered interceptors and on to the + * server. + * + * You can pass an `HttpRequest` directly as the only parameter. In this case, + * the call returns an observable of the raw `HttpEvent` stream. + * + * Alternatively you can pass an HTTP method as the first parameter, + * a URL string as the second, and an options hash containing the request body as the third. + * See `addBody()`. In this case, the specified `responseType` and `observe` options determine the + * type of returned observable. + * * The `responseType` value determines how a successful response body is parsed. + * * If `responseType` is the default `json`, you can pass a type interface for the resulting + * object as a type parameter to the call. + * + * The `observe` value determines the return type, according to what you are interested in + * observing. + * * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including + * progress events by default. + * * An `observe` value of response returns an observable of `HttpResponse`, + * where the `T` parameter depends on the `responseType` and any optionally provided type + * parameter. + * * An `observe` value of body returns an observable of `` with the same `T` body type. + * + * @param {?} first + * @param {?=} url + * @param {?=} options + * @return {?} + */ + request(first, url, options = {}) { + /** @type {?} */ + let req; + // First, check whether the primary argument is an instance of `HttpRequest`. + if (first instanceof HttpRequest) { + // It is. The other arguments must be undefined (per the signatures) and can be + // ignored. + req = (/** @type {?} */ (first)); + } + else { + // It's a string, so it represents a URL. Construct a request based on it, + // and incorporate the remaining arguments (assuming `GET` unless a method is + // provided. + // Figure out the headers. + /** @type {?} */ + let headers = undefined; + if (options.headers instanceof HttpHeaders) { + headers = options.headers; + } + else { + headers = new HttpHeaders(options.headers); + } + // Sort out parameters. + /** @type {?} */ + let params = undefined; + if (!!options.params) { + if (options.params instanceof HttpParams) { + params = options.params; + } + else { + params = new HttpParams((/** @type {?} */ ({ fromObject: options.params }))); + } + } + // Construct the request. + req = new HttpRequest(first, (/** @type {?} */ (url)), (options.body !== undefined ? options.body : null), { + headers, + params, + reportProgress: options.reportProgress, + // By default, JSON is assumed to be returned for all calls. + responseType: options.responseType || 'json', + withCredentials: options.withCredentials, + }); + } + // Start with an Observable.of() the initial request, and run the handler (which + // includes all interceptors) inside a concatMap(). This way, the handler runs + // inside an Observable chain, which causes interceptors to be re-run on every + // subscription (this also makes retries re-run the handler, including interceptors). + /** @type {?} */ + const events$ = Object(rxjs__WEBPACK_IMPORTED_MODULE_1__["of"])(req).pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["concatMap"])((/** + * @param {?} req + * @return {?} + */ + (req) => this.handler.handle(req)))); + // If coming via the API signature which accepts a previously constructed HttpRequest, + // the only option is to get the event stream. Otherwise, return the event stream if + // that is what was requested. + if (first instanceof HttpRequest || options.observe === 'events') { + return events$; + } + // The requested stream contains either the full response or the body. In either + // case, the first step is to filter the event stream to extract a stream of + // responses(s). + /** @type {?} */ + const res$ = (/** @type {?} */ (events$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["filter"])((/** + * @param {?} event + * @return {?} + */ + (event) => event instanceof HttpResponse))))); + // Decide which stream to return. + switch (options.observe || 'body') { + case 'body': + // The requested stream is the body. Map the response stream to the response + // body. This could be done more simply, but a misbehaving interceptor might + // transform the response body into a different format and ignore the requested + // responseType. Guard against this by validating that the response is of the + // requested type. + switch (req.responseType) { + case 'arraybuffer': + return res$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["map"])((/** + * @param {?} res + * @return {?} + */ + (res) => { + // Validate that the body is an ArrayBuffer. + if (res.body !== null && !(res.body instanceof ArrayBuffer)) { + throw new Error('Response is not an ArrayBuffer.'); + } + return res.body; + }))); + case 'blob': + return res$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["map"])((/** + * @param {?} res + * @return {?} + */ + (res) => { + // Validate that the body is a Blob. + if (res.body !== null && !(res.body instanceof Blob)) { + throw new Error('Response is not a Blob.'); + } + return res.body; + }))); + case 'text': + return res$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["map"])((/** + * @param {?} res + * @return {?} + */ + (res) => { + // Validate that the body is a string. + if (res.body !== null && typeof res.body !== 'string') { + throw new Error('Response is not a string.'); + } + return res.body; + }))); + case 'json': + default: + // No validation needed for JSON responses, as they can be of any type. + return res$.pipe(Object(rxjs_operators__WEBPACK_IMPORTED_MODULE_2__["map"])((/** + * @param {?} res + * @return {?} + */ + (res) => res.body))); + } + case 'response': + // The response stream was requested directly, so return it. + return res$; + default: + // Guard against new future observe types being added. + throw new Error(`Unreachable: unhandled observe type ${options.observe}}`); + } + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `DELETE` request to execute on the server. See the individual overloads for + * details on the return type. + * + * @param {?} url The endpoint URL. + * @param {?=} options The HTTP options to send with the request. + * + * @return {?} + */ + delete(url, options = {}) { + return this.request('DELETE', url, (/** @type {?} */ (options))); + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `GET` request to execute on the server. See the individual overloads for + * details on the return type. + * @param {?} url + * @param {?=} options + * @return {?} + */ + get(url, options = {}) { + return this.request('GET', url, (/** @type {?} */ (options))); + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `HEAD` request to execute on the server. The `HEAD` method returns + * meta information about the resource without transferring the + * resource itself. See the individual overloads for + * details on the return type. + * @param {?} url + * @param {?=} options + * @return {?} + */ + head(url, options = {}) { + return this.request('HEAD', url, (/** @type {?} */ (options))); + } + /** + * Constructs an `Observable` that, when subscribed, causes a request with the special method + * `JSONP` to be dispatched via the interceptor pipeline. + * The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain + * API endpoints that don't support newer, + * and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol. + * JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the + * requests even if the API endpoint is not located on the same domain (origin) as the client-side + * application making the request. + * The endpoint API must support JSONP callback for JSONP requests to work. + * The resource API returns the JSON response wrapped in a callback function. + * You can pass the callback function name as one of the query parameters. + * Note that JSONP requests can only be used with `GET` requests. + * + * @template T + * @param {?} url The resource URL. + * @param {?} callbackParam The callback function name. + * + * @return {?} + */ + jsonp(url, callbackParam) { + return this.request('JSONP', url, { + params: new HttpParams().append(callbackParam, 'JSONP_CALLBACK'), + observe: 'body', + responseType: 'json', + }); + } + /** + * Constructs an `Observable` that, when subscribed, causes the configured + * `OPTIONS` request to execute on the server. This method allows the client + * to determine the supported HTTP methods and other capabilites of an endpoint, + * without implying a resource action. See the individual overloads for + * details on the return type. + * @param {?} url + * @param {?=} options + * @return {?} + */ + options(url, options = {}) { + return this.request('OPTIONS', url, (/** @type {?} */ (options))); + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `PATCH` request to execute on the server. See the individual overloads for + * details on the return type. + * @param {?} url + * @param {?} body + * @param {?=} options + * @return {?} + */ + patch(url, body, options = {}) { + return this.request('PATCH', url, addBody(options, body)); + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `POST` request to execute on the server. The server responds with the location of + * the replaced resource. See the individual overloads for + * details on the return type. + * @param {?} url + * @param {?} body + * @param {?=} options + * @return {?} + */ + post(url, body, options = {}) { + return this.request('POST', url, addBody(options, body)); + } + /** + * Constructs an observable that, when subscribed, causes the configured + * `PUT` request to execute on the server. The `PUT` method replaces an existing resource + * with a new set of values. + * See the individual overloads for details on the return type. + * @param {?} url + * @param {?} body + * @param {?=} options + * @return {?} + */ + put(url, body, options = {}) { + return this.request('PUT', url, addBody(options, body)); + } +} +HttpClient.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; +/** @nocollapse */ +HttpClient.ctorParameters = () => [ + { type: HttpHandler } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +/** + * `HttpHandler` which applies an `HttpInterceptor` to an `HttpRequest`. + * + * + */ +class HttpInterceptorHandler { + /** + * @param {?} next + * @param {?} interceptor + */ + constructor(next, interceptor) { + this.next = next; + this.interceptor = interceptor; + } + /** + * @param {?} req + * @return {?} + */ + handle(req) { + return this.interceptor.intercept(req, this.next); + } +} +/** + * A multi-provider token which represents the array of `HttpInterceptor`s that + * are registered. + * + * \@publicApi + * @type {?} + */ +const HTTP_INTERCEPTORS = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('HTTP_INTERCEPTORS'); +class NoopInterceptor { + /** + * @param {?} req + * @param {?} next + * @return {?} + */ + intercept(req, next) { + return next.handle(req); + } +} +NoopInterceptor.decorators = [ + { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"] } +]; + +/** + * @fileoverview added by tsickle + * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc + */ +// Every request made through JSONP needs a callback name that's unique across the +// whole page. Each request is assigned an id and the callback name is constructed +// from that. The next id to be assigned is tracked in a global variable here that +// is shared among all applications on the page. +/** @type {?} */ +let nextRequestId = 0; +// Error text given when a JSONP script is injected, but doesn't invoke the callback +// passed in its URL. +/** @type {?} */ +const JSONP_ERR_NO_CALLBACK = 'JSONP injected script did not invoke callback.'; +// Error text given when a request is passed to the JsonpClientBackend that doesn't +// have a request method JSONP. +/** @type {?} */ +const JSONP_ERR_WRONG_METHOD = 'JSONP requests must use JSONP request method.'; +/** @type {?} */ +const JSONP_ERR_WRONG_RESPONSE_TYPE = 'JSONP requests must use Json response type.'; +/** + * DI token/abstract type representing a map of JSONP callbacks. + * + * In the browser, this should always be the `window` object. + * + * + * @abstract + */ +class JsonpCallbackContext { +} +/** + * `HttpBackend` that only processes `HttpRequest` with the JSONP method, + * by performing JSONP style requests. + * + * \@publicApi + */ +class JsonpClientBackend { + /** + * @param {?} callbackMap + * @param {?} document + */ + constructor(callbackMap, document) { + this.callbackMap = callbackMap; + this.document = document; + } + /** + * Get the name of the next callback method, by incrementing the global `nextRequestId`. + * @private + * @return {?} + */ + nextCallback() { return `ng_jsonp_callback_${nextRequestId++}`; } + /** + * Process a JSONP request and return an event stream of the results. + * @param {?} req + * @return {?} + */ + handle(req) { + // Firstly, check both the method and response type. If either doesn't match + // then the request was improperly routed here and cannot be handled. + if (req.method !== 'JSONP') { + throw new Error(JSONP_ERR_WRONG_METHOD); + } + else if (req.responseType !== 'json') { + throw new Error(JSONP_ERR_WRONG_RESPONSE_TYPE); + } + // Everything else happens inside the Observable boundary. + return new rxjs__WEBPACK_IMPORTED_MODULE_1__["Observable"]((/** + * @param {?} observer + * @return {?} + */ + (observer) => { + // The first step to make a request is to generate the callback name, and replace the + // callback placeholder in the URL with the name. Care has to be taken here to ensure + // a trailing &, if matched, gets inserted back into the URL in the correct place. + /** @type {?} */ + const callback = this.nextCallback(); + /** @type {?} */ + const url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`); + // Construct the + + + + + + + diff --git a/web/kepek/cadillac_700_400.jpg b/web/kepek/cadillac_700_400.jpg new file mode 100644 index 0000000..3e70aa2 Binary files /dev/null and b/web/kepek/cadillac_700_400.jpg differ diff --git a/web/kepek/delorean_700_400.jpg b/web/kepek/delorean_700_400.jpg new file mode 100644 index 0000000..0287aaa Binary files /dev/null and b/web/kepek/delorean_700_400.jpg differ diff --git a/web/kepek/favicon.png b/web/kepek/favicon.png new file mode 100644 index 0000000..23b30a5 Binary files /dev/null and b/web/kepek/favicon.png differ diff --git a/web/kepek/ferrari_700_400.jpg b/web/kepek/ferrari_700_400.jpg new file mode 100644 index 0000000..11a73ad Binary files /dev/null and b/web/kepek/ferrari_700_400.jpg differ diff --git a/web/kepek/lada_fejlec_900_350.jpg b/web/kepek/lada_fejlec_900_350.jpg new file mode 100644 index 0000000..7941263 Binary files /dev/null and b/web/kepek/lada_fejlec_900_350.jpg differ diff --git a/web/kepek/moszkvics_700_400.jpg b/web/kepek/moszkvics_700_400.jpg new file mode 100644 index 0000000..81bb48f Binary files /dev/null and b/web/kepek/moszkvics_700_400.jpg differ diff --git a/web/kepek/moszkvics_fejlec_900_350.jpg b/web/kepek/moszkvics_fejlec_900_350.jpg new file mode 100644 index 0000000..dacae76 Binary files /dev/null and b/web/kepek/moszkvics_fejlec_900_350.jpg differ diff --git a/web/kepek/mustang_700_400.jpg b/web/kepek/mustang_700_400.jpg new file mode 100644 index 0000000..8956136 Binary files /dev/null and b/web/kepek/mustang_700_400.jpg differ diff --git a/web/kepek/polszki_fejlec_900_350.jpg b/web/kepek/polszki_fejlec_900_350.jpg new file mode 100644 index 0000000..34f28bb Binary files /dev/null and b/web/kepek/polszki_fejlec_900_350.jpg differ diff --git a/web/kepek/trabant_700_400.jpg b/web/kepek/trabant_700_400.jpg new file mode 100644 index 0000000..f3ba178 Binary files /dev/null and b/web/kepek/trabant_700_400.jpg differ diff --git a/web/oldtimer.css b/web/oldtimer.css new file mode 100644 index 0000000..ca738d4 --- /dev/null +++ b/web/oldtimer.css @@ -0,0 +1,37 @@ +body { + padding-top: 56px; + font-family: sans-serif; +} + +.anchor { + display: block; + position: relative; + top: -56px; +} + +section { + padding-bottom: 25px; + border-bottom: 2px solid #9696969c; +} + +#diasor { + border-bottom: none; + padding-bottom: 0; +} + +h2 { + margin-top: 25px; + margin-bottom: 25px; +} + +li{ + color:white; +} + +.dia-elem-szovegdoboz { + background-color: #1714149c; +} + +nav { + font-weight: 600; +} diff --git a/web/oldtimer.js b/web/oldtimer.js new file mode 100644 index 0000000..1ce1030 --- /dev/null +++ b/web/oldtimer.js @@ -0,0 +1,34 @@ +document.getElementById('nem-elerheto').textContent = 'Jelenleg minden autó elérhet ő!' +fetch('api/nemelerheto') + .then(res => { + res.json() + .then(json => { + document.getElementById('nem-elerheto').textContent = json.nemElerhetoAutok.toString() + }) + .catch(console.error) + }) + .catch(console.error) + +function velemenyKuldes() { + const val = document.getElementById('velemenyInput').value + fetch('api/velemeny', { + method: 'POST', + body: JSON.stringify({ + velemeny: val, + }), + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + }) + .then(res => { + res.json() + .then(json => { + console.log(json) + document.getElementById('velemenyInput').value = '' + alert('Véleménye fontos számunkra!') + }) + .catch(console.error) + }) + .catch(console.error) +} \ No newline at end of file
    + {{headerText}} + + {{dataAccessor(data, name)}} +