UNPKG

@angular-mdl/core

Version:

Angular components, directives and styles based on material design lite https://getmdl.io.

1 lines 362 kB
{"version":3,"file":"angular-mdl-core.mjs","sources":["../../../../projects/core/src/lib/common/append-view-container-ref-directive.ts","../../../../projects/core/src/lib/common/animations.ts","../../../../projects/core/src/lib/common/boolean-property.ts","../../../../projects/core/src/lib/common/mdl-error.ts","../../../../projects/core/src/lib/common/native-support.ts","../../../../projects/core/src/lib/common/noop.ts","../../../../projects/core/src/lib/common/number.property.ts","../../../../projects/core/src/lib/common/mdl-common.module.ts","../../../../projects/core/src/lib/layout/mdl-layout-mediator.service.ts","../../../../projects/core/src/lib/ripple/ripple.vendor.ts","../../../../projects/core/src/lib/ripple/mdl-ripple.directive.ts","../../../../projects/core/src/lib/layout/mdl-layout-header.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-drawer.component.ts","../../../../projects/core/src/lib/tabs/mdl-tab-panel-title.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-tab-panel.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-content.component.ts","../../../../projects/core/src/lib/icon/mdl-icon.component.ts","../../../../projects/core/src/lib/layout/mdl-layout.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-header-transparent.directive.ts","../../../../projects/core/src/lib/layout/mdl-layout-header-row.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-title.component.ts","../../../../projects/core/src/lib/layout/mdl-layout-spacer.component.ts","../../../../projects/core/src/lib/icon/mdl-icon.module.ts","../../../../projects/core/src/lib/tabs/mdl-tab-panel.component.ts","../../../../projects/core/src/lib/tabs/mdl-tabs.component.ts","../../../../projects/core/src/lib/ripple/mdl-ripple.module.ts","../../../../projects/core/src/lib/tabs/mdl-tabs.module.ts","../../../../projects/core/src/lib/layout/mdl-layout.module.ts","../../../../projects/core/src/lib/badge/mdl-badge.directive.ts","../../../../projects/core/src/lib/badge/mdl-badge.module.ts","../../../../projects/core/src/lib/button/mdl-button.component.ts","../../../../projects/core/src/lib/button/mdl-button.module.ts","../../../../projects/core/src/lib/card/mdl-card.component.ts","../../../../projects/core/src/lib/card/mdl-card.module.ts","../../../../projects/core/src/lib/checkbox/mdl-checkbox.component.ts","../../../../projects/core/src/lib/checkbox/mdl-checkbox.module.ts","../../../../projects/core/src/lib/chips/mdl-chip.component.ts","../../../../projects/core/src/lib/chips/mdl-chip-contact.directive.ts","../../../../projects/core/src/lib/chips/mdl-chip.module.ts","../../../../projects/core/src/lib/dialog/config.ts","../../../../projects/core/src/lib/dialog/mdl-dialog-reference.ts","../../../../projects/core/src/lib/dialog/mdl-simple-dialog.component.ts","../../../../projects/core/src/lib/dialog/internal-dialog-reference.ts","../../../../projects/core/src/lib/dialog/mdl-dialog-host.component.ts","../../../../projects/core/src/lib/dialog-outlet/mdl-backdrop-overlay.component.ts","../../../../projects/core/src/lib/dialog-outlet/mdl-dialog-outlet.component.ts","../../../../projects/core/src/lib/dialog-outlet/mdl-dialog-outlet.service.ts","../../../../projects/core/src/lib/dialog/mdl-dialog.service.ts","../../../../projects/core/src/lib/dialog/mdl-dialog.component.ts","../../../../projects/core/src/lib/dialog/mdl-alert.component.ts","../../../../projects/core/src/lib/dialog-outlet/mdl-dialog-inner-outlet.component.ts","../../../../projects/core/src/lib/dialog-outlet/mdl-dialog-outlet.module.ts","../../../../projects/core/src/lib/dialog/mdl-dialog.module.ts","../../../../projects/core/src/lib/icon-toggle/mdl-icon-toggle.component.ts","../../../../projects/core/src/lib/icon-toggle/mdl-icon-toggle.module.ts","../../../../projects/core/src/lib/list/mdl-list.component.ts","../../../../projects/core/src/lib/list/mdl-list.module.ts","../../../../projects/core/src/lib/menu/mdl-menu.component.ts","../../../../projects/core/src/lib/menu/mdl-menu-item.component.ts","../../../../projects/core/src/lib/menu/mdl-menu-item.directive.ts","../../../../projects/core/src/lib/menu/mdl-toggle-menu.directive.ts","../../../../projects/core/src/lib/menu/mdl-menu.module.ts","../../../../projects/core/src/lib/progress/mdl-progress.component.ts","../../../../projects/core/src/lib/progress/mdl-progress.module.ts","../../../../projects/core/src/lib/radio/mdl-radio.component.ts","../../../../projects/core/src/lib/radio/mdl-radio.module.ts","../../../../projects/core/src/lib/shadow/mdl-shadow.directive.ts","../../../../projects/core/src/lib/shadow/mdl-shadow.module.ts","../../../../projects/core/src/lib/slider/mdl-slider.component.ts","../../../../projects/core/src/lib/slider/mdl-slider.module.ts","../../../../projects/core/src/lib/snackbar/mdl-snackbar.service.ts","../../../../projects/core/src/lib/snackbar/mdl-snackbar.module.ts","../../../../projects/core/src/lib/spinner/mdl-spinner.component.ts","../../../../projects/core/src/lib/spinner/mdl-spinner.module.ts","../../../../projects/core/src/lib/switch/mdl-switch.component.ts","../../../../projects/core/src/lib/switch/mdl-switch.module.ts","../../../../projects/core/src/lib/table/mdl-table.component.ts","../../../../projects/core/src/lib/table/mdl-table.module.ts","../../../../projects/core/src/lib/textfield/mdl-textfield.component.ts","../../../../projects/core/src/lib/textfield/mdl-textfield.module.ts","../../../../projects/core/src/lib/tooltip/mdl-tooltip-position.service.ts","../../../../projects/core/src/lib/tooltip/mdl-tooltip.component.ts","../../../../projects/core/src/lib/tooltip/mdl-tooltip.directive.ts","../../../../projects/core/src/lib/tooltip/mdl-tooltip.module.ts","../../../../projects/core/src/lib/core.module.ts","../../../../projects/core/src/public-api.ts","../../../../projects/core/src/angular-mdl-core.ts"],"sourcesContent":["import {\n AfterViewInit,\n Directive,\n Input,\n Renderer2,\n ViewContainerRef,\n} from \"@angular/core\";\n\n@Directive({\n // eslint-disable-next-line\n selector: \"[append-view-container-ref]\",\n})\nexport class AppendViewContainerRefDirective implements AfterViewInit {\n @Input(\"append-view-container-ref\")\n viewContainerRefToAppend: ViewContainerRef | undefined;\n\n constructor(private viewRef: ViewContainerRef, private renderer: Renderer2) {}\n\n ngAfterViewInit(): void {\n this.renderer.appendChild(\n this.viewRef.element.nativeElement,\n this.viewContainerRefToAppend?.element.nativeElement\n );\n }\n}\n","export interface AnimationPlayer {\n onDone(fn: () => void): void;\n\n play(): void;\n}\n\nexport class NativeWebAnimationPlayer implements AnimationPlayer {\n private onDoneCallback: (() => void)[] = [];\n\n constructor(\n private element: HTMLElement,\n private keyframes: { [key: string]: string | number }[],\n private duration: number,\n private easing: string\n ) {}\n\n onDone(fn: () => void): void {\n this.onDoneCallback.push(fn);\n }\n\n play(): void {\n const animation = this.element.animate(this.keyframes, {\n duration: this.duration,\n easing: this.easing,\n fill: \"forwards\",\n });\n\n animation.addEventListener(\"finish\", () =>\n this.onDoneCallback.forEach((fn) => fn())\n );\n }\n}\n\nexport class NoopAnimationPlayer implements AnimationPlayer {\n private onDoneCallback: (() => void)[] = [];\n\n onDone(fn: () => void): void {\n this.onDoneCallback.push(fn);\n }\n\n play(): void {\n this.onDoneCallback.forEach((fn) => fn());\n }\n}\n\nexport abstract class Animations {\n abstract animate(\n element: HTMLElement,\n keyframes: { [key: string]: string | number }[],\n duration: number,\n easing: string\n ): AnimationPlayer;\n}\n\nexport class NativeWebAnimations implements Animations {\n public animate(\n element: HTMLElement,\n keyframes: { [key: string]: string | number }[],\n duration: number,\n easing: string\n ): AnimationPlayer {\n return new NativeWebAnimationPlayer(element, keyframes, duration, easing);\n }\n}\n\nexport class NoopWebAnimations implements Animations {\n public animate(): AnimationPlayer {\n return new NoopAnimationPlayer();\n }\n}\n","export const toBoolean = (value: unknown): boolean =>\n value != null && `${value}` !== \"false\";\n","/**\n * Wrapper for mdl error messages.\n */\nexport class MdlError extends Error {\n constructor(value: string) {\n /* istanbul ignore next */\n super(value);\n }\n}\n\nexport class MdlStructureError extends MdlError {\n constructor(child: string, requiredParent: string) {\n /* istanbul ignore next */\n super(`\"${child}\" requires \"${requiredParent}\" as a parent.`);\n }\n}\n","export const callNative = (\n el: Element,\n method: string,\n arg: any | null = null // eslint-disable-line @typescript-eslint/no-explicit-any\n): void => {\n /* istanbul ignore next */ // if this code runs in browser this is allways true!\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (el[method]) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n el[method](arg);\n }\n};\n","/* istanbul ignore next */\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nexport const noop = (): void => {};\n","export const toNumber = (\n value: number | string | undefined | null\n): number | null | undefined => {\n if (typeof value === \"undefined\") {\n return null;\n } else if (typeof value === \"string\") {\n return parseInt(value, 10);\n }\n return value;\n};\n","import { NgModule } from \"@angular/core\";\nimport { AppendViewContainerRefDirective } from \"./append-view-container-ref-directive\";\nimport {\n Animations,\n NativeWebAnimations,\n NoopWebAnimations,\n} from \"./animations\";\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nfunction isWebAnimationsSupported() {\n return (\n typeof Element !== \"undefined\" &&\n typeof Element.prototype.animate === \"function\"\n );\n}\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\nexport function instantiateSupportedAnimationDriver(): Animations {\n /* istanbul ignore next */\n if (isWebAnimationsSupported()) {\n return new NativeWebAnimations();\n }\n /* istanbul ignore next */\n return new NoopWebAnimations();\n}\n\n@NgModule({\n imports: [],\n exports: [AppendViewContainerRefDirective],\n declarations: [AppendViewContainerRefDirective],\n providers: [\n { provide: Animations, useFactory: instantiateSupportedAnimationDriver },\n ],\n})\nexport class MdlCommonsModule {}\n\nexport * from \"./animations\";\nexport * from \"./boolean-property\";\nexport * from \"./mdl-error\";\nexport * from \"./append-view-container-ref-directive\";\nexport * from \"./native-support\";\nexport * from \"./noop\";\nexport * from \"./number.property\";\n","import { Injectable } from \"@angular/core\";\nimport { MdlLayoutTabPanelComponent } from \"./mdl-layout-tab-panel.component\";\nimport { Observable, Subject } from \"rxjs\";\n\n@Injectable({\n providedIn: \"root\",\n})\nexport class MdlLayoutMediatorService {\n private tabMouseoverSubject = new Subject<MdlLayoutTabPanelComponent>();\n private tabMouseoutSubject = new Subject<MdlLayoutTabPanelComponent>();\n private tabSelectedSubject = new Subject<MdlLayoutTabPanelComponent>();\n\n onTabMouseover(): Observable<MdlLayoutTabPanelComponent> {\n return this.tabMouseoverSubject.asObservable();\n }\n\n tabMouseover(tab: MdlLayoutTabPanelComponent): void {\n this.tabMouseoverSubject.next(tab);\n }\n\n onTabMouseOut(): Observable<MdlLayoutTabPanelComponent> {\n return this.tabMouseoutSubject.asObservable();\n }\n\n tabMouseout(tab: MdlLayoutTabPanelComponent): void {\n this.tabMouseoutSubject.next(tab);\n }\n\n onTabSelected(): Observable<MdlLayoutTabPanelComponent> {\n return this.tabSelectedSubject.asObservable();\n }\n\n tabSelected(tab: MdlLayoutTabPanelComponent): void {\n this.tabSelectedSubject.next(tab);\n }\n}\n","/**\n * @license\n * Copyright 2015 Google Inc. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/* eslint-disable */\n/* istanbul ignore file */\n// @ts-nocheck\n\"use strict\";\n\n/**\n * Class constructor for Ripple MDL component.\n * Implements MDL component design pattern defined at:\n * https://github.com/jasonmayes/mdl-component-design-pattern\n *\n */\nexport function MaterialRipple(renderer, element): void {\n this.renderer_ = renderer;\n this.element_ = element;\n\n // Initialize instance.\n this.init();\n}\n\n/**\n * Store constants in one place so they can be updated easily.\n */\nMaterialRipple.prototype.Constant_ = {\n INITIAL_SCALE: \"scale(0.0001, 0.0001)\",\n INITIAL_SIZE: \"1px\",\n INITIAL_OPACITY: \"0.4\",\n FINAL_OPACITY: \"0\",\n FINAL_SCALE: \"\",\n};\n\n/**\n * Store strings for class names defined by this component that are used in\n * JavaScript. This allows us to simply change it in one place should we\n * decide to modify at a later date.\n */\nMaterialRipple.prototype.CssClasses_ = {\n RIPPLE_CENTER: \"mdl-ripple--center\",\n RIPPLE_EFFECT_IGNORE_EVENTS: \"mdl-js-ripple-effect--ignore-events\",\n RIPPLE: \"mdl-ripple\",\n IS_ANIMATING: \"is-animating\",\n IS_VISIBLE: \"is-visible\",\n};\n\n/**\n * Handle mouse / finger down on element.\n *\n */\n// eslint-disable-next-line\nMaterialRipple.prototype.downHandler_ = function (event) {\n if (!this.rippleElement_.style.width && !this.rippleElement_.style.height) {\n const rect = this.element_.getBoundingClientRect();\n this.boundHeight = rect.height;\n this.boundWidth = rect.width;\n this.rippleSize_ =\n Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2;\n this.rippleElement_.style.width = this.rippleSize_ + \"px\";\n this.rippleElement_.style.height = this.rippleSize_ + \"px\";\n }\n\n this.renderer_.addClass(this.rippleElement_, this.CssClasses_.IS_VISIBLE);\n\n if (event.type === \"mousedown\" && this.ignoringMouseDown_) {\n this.ignoringMouseDown_ = false;\n } else {\n if (event.type === \"touchstart\") {\n this.ignoringMouseDown_ = true;\n }\n const frameCount = this.getFrameCount();\n if (frameCount > 0) {\n return;\n }\n this.setFrameCount(1);\n const bound = event.currentTarget.getBoundingClientRect();\n let x;\n let y;\n // Check if we are handling a keyboard click.\n if (event.clientX === 0 && event.clientY === 0) {\n x = Math.round(bound.width / 2);\n y = Math.round(bound.height / 2);\n } else {\n const clientX =\n event.clientX !== undefined ? event.clientX : event.touches[0].clientX;\n const clientY =\n event.clientY !== undefined ? event.clientY : event.touches[0].clientY;\n x = Math.round(clientX - bound.left);\n y = Math.round(clientY - bound.top);\n }\n this.setRippleXY(x, y);\n this.setRippleStyles(true);\n window.requestAnimationFrame(this.animFrameHandler.bind(this));\n }\n};\n\n/**\n * Handle mouse / finger up on element.\n *\n */\n// eslint-disable-next-line\nMaterialRipple.prototype.upHandler_ = function (event) {\n // Don't fire for the artificial \"mouseup\" generated by a double-click.\n if (event && event.detail !== 2) {\n // Allow a repaint to occur before removing this class, so the animation\n // shows for tap events, which seem to trigger a mouseup too soon after\n // mousedown.\n // eslint-disable-next-line\n setTimeout(\n function () {\n this.renderer_.removeClass(\n this.rippleElement_,\n this.CssClasses_.IS_VISIBLE\n );\n }.bind(this),\n 0\n );\n }\n};\n\n/**\n * Initialize element.\n */\n// eslint-disable-next-line\nMaterialRipple.prototype.init = function () {\n if (this.element_) {\n const recentering = this.element_.classList.contains(\n this.CssClasses_.RIPPLE_CENTER\n );\n if (\n !this.element_.classList.contains(\n this.CssClasses_.RIPPLE_EFFECT_IGNORE_EVENTS\n )\n ) {\n this.rippleElement_ = this.element_.querySelector(\n \".\" + this.CssClasses_.RIPPLE\n );\n this.frameCount_ = 0;\n this.rippleSize_ = 0;\n this.x_ = 0;\n this.y_ = 0;\n\n // Touch start produces a compat mouse down event, which would cause a\n // second ripples. To avoid that, we use this property to ignore the first\n // mouse down after a touch start.\n this.ignoringMouseDown_ = false;\n\n this.boundDownHandler = this.downHandler_.bind(this);\n this.element_.addEventListener(\"mousedown\", this.boundDownHandler);\n this.element_.addEventListener(\"touchstart\", this.boundDownHandler);\n\n this.boundUpHandler = this.upHandler_.bind(this);\n this.element_.addEventListener(\"mouseup\", this.boundUpHandler);\n this.element_.addEventListener(\"mouseleave\", this.boundUpHandler);\n this.element_.addEventListener(\"touchend\", this.boundUpHandler);\n this.element_.addEventListener(\"blur\", this.boundUpHandler);\n\n // eslint-disable-next-line\n this.getFrameCount = function () {\n return this.frameCount_;\n };\n\n // eslint-disable-next-line\n this.setFrameCount = function (fC) {\n this.frameCount_ = fC;\n };\n\n // eslint-disable-next-line\n this.getRippleElement = function () {\n return this.rippleElement_;\n };\n\n // eslint-disable-next-line\n this.setRippleXY = function (newX, newY) {\n this.x_ = newX;\n this.y_ = newY;\n };\n\n // eslint-disable-next-line\n this.setRippleStyles = function (start) {\n if (this.rippleElement_ !== null) {\n let transformString;\n let scale;\n let size;\n let offset = \"translate(\" + this.x_ + \"px, \" + this.y_ + \"px)\";\n\n if (start) {\n scale = this.Constant_.INITIAL_SCALE;\n size = this.Constant_.INITIAL_SIZE;\n } else {\n scale = this.Constant_.FINAL_SCALE;\n size = this.rippleSize_ + \"px\";\n if (recentering) {\n offset =\n \"translate(\" +\n this.boundWidth / 2 +\n \"px, \" +\n this.boundHeight / 2 +\n \"px)\";\n }\n }\n\n transformString = \"translate(-50%, -50%) \" + offset + scale;\n\n this.rippleElement_.style.webkitTransform = transformString;\n this.rippleElement_.style.msTransform = transformString;\n this.rippleElement_.style.transform = transformString;\n\n if (start) {\n this.renderer_.removeClass(\n this.rippleElement_,\n this.CssClasses_.IS_ANIMATING\n );\n } else {\n this.renderer_.addClass(\n this.rippleElement_,\n this.CssClasses_.IS_ANIMATING\n );\n }\n }\n };\n\n /**\n * Handles an animation frame.\n */\n // eslint-disable-next-line\n this.animFrameHandler = function () {\n if (this.frameCount_-- > 0) {\n window.requestAnimationFrame(this.animFrameHandler.bind(this));\n } else {\n this.setRippleStyles(false);\n }\n };\n }\n }\n};\n","import {\n Directive,\n ElementRef,\n Input,\n OnChanges,\n Renderer2,\n} from \"@angular/core\";\nimport { MaterialRipple } from \"./ripple.vendor\";\n\nconst RIPPLE = \"mdl-ripple\";\n\n// known bugs: https://github.com/google/material-design-lite/issues/4215\n@Directive()\nexport class MdlRippleDirective implements OnChanges {\n public el: HTMLElement;\n rippleActive: boolean | string = true;\n\n private rippleContainer: HTMLElement | undefined;\n private ripple: (() => void) | undefined;\n\n constructor(\n private elementRef: ElementRef,\n public renderer: Renderer2,\n private cssContainerClasses: string[]\n ) {\n this.el = elementRef.nativeElement;\n }\n\n ngOnChanges(): void {\n // remove any existing ripple container\n if (this.rippleContainer) {\n this.el.removeChild(this.rippleContainer);\n delete this.rippleContainer;\n delete this.ripple;\n }\n\n // if used as mdl-ripple without property binding it is an empty string\n // otherwise (e.g. [mdl-ripple] it is a boolean - may be with the default value true.\n if (this.rippleActive === \"\" || this.rippleActive) {\n this.rippleContainer = this.renderer.createElement(\"span\");\n this.cssContainerClasses.forEach((cssClass) => {\n this.renderer.addClass(this.rippleContainer, cssClass);\n });\n const rippleElement = this.renderer.createElement(\"span\");\n this.renderer.addClass(rippleElement, RIPPLE);\n this.rippleContainer?.appendChild(rippleElement);\n if (this.rippleContainer) {\n this.el.appendChild(this.rippleContainer);\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.ripple = new MaterialRipple(this.renderer, this.el);\n }\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-button[mdl-ripple], button[mdl-ripple]\",\n})\nexport class MdlButtonRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\"mdl-button__ripple-container\"]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-checkbox[mdl-ripple]\",\n})\nexport class MdlCheckboxRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\n \"mdl-checkbox__ripple-container\",\n \"mdl-ripple--center\",\n ]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-radio[mdl-ripple]\",\n})\nexport class MdlRadioRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\n \"mdl-radio__ripple-container\",\n \"mdl-ripple--center\",\n ]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-icon-toggle[mdl-ripple]\",\n})\nexport class MdlIconToggleRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\n \"mdl-icon-toggle__ripple-container\",\n \"mdl-ripple--center\",\n ]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-switch[mdl-ripple]\",\n})\nexport class MdlSwitchRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\n \"mdl-switch__ripple-container\",\n \"mdl-ripple--center\",\n ]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"mdl-menu-item[mdl-ripple]\",\n})\nexport class MdlMenuItemRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\"mdl-menu__item--ripple-container\"]);\n }\n}\n\n@Directive({\n // eslint-disable-next-line\n selector: \"a[mdl-ripple],div[mdl-ripple]\",\n})\nexport class MdlAnchorRippleDirective extends MdlRippleDirective {\n // eslint-disable-next-line\n @Input(\"mdl-ripple\") public override rippleActive: boolean | string = true;\n\n constructor(elementRef: ElementRef, renderer: Renderer2) {\n super(elementRef, renderer, [\n \"mdl-tabs__ripple-container\",\n \"mdl-layout__tab-ripple-container\",\n ]);\n }\n}\n","import {\n Component,\n ElementRef,\n HostBinding,\n HostListener,\n QueryList,\n ViewEncapsulation,\n} from \"@angular/core\";\nimport { MdlLayoutTabPanelComponent } from \"./mdl-layout-tab-panel.component\";\nimport { MdlLayoutMediatorService } from \"./mdl-layout-mediator.service\";\n\n@Component({\n selector: \"mdl-layout-header\",\n template: `\n <ng-content></ng-content>\n <div\n *ngIf=\"tabs?.toArray() && tabs.toArray().length > 0\"\n class=\"mdl-layout__tab-bar-container\"\n >\n <div class=\"mdl-layout__tab-bar is-casting-shadow\">\n <div\n *ngFor=\"let tab of tabs.toArray()\"\n class=\"mdl-layout__tab\"\n [ngClass]=\"{ 'is-active': tab.isActive }\"\n (mouseover)=\"onTabMouseover(tab)\"\n (mouseout)=\"onTabMouseout(tab)\"\n >\n <div\n *ngIf=\"tab.titleComponent\"\n (click)=\"tabSelected(tab)\"\n [mdl-ripple]=\"isRipple\"\n [append-view-container-ref]=\"tab.titleComponent.vcRef\"\n ></div>\n <a\n *ngIf=\"!tab.titleComponent\"\n href=\"javascript:void(0)\"\n (click)=\"tabSelected(tab)\"\n class=\"mdl-layout__tab\"\n [ngClass]=\"{ 'is-active': tab.isActive }\"\n [mdl-ripple]=\"isRipple\"\n >{{ tab.title }}</a\n >\n </div>\n </div>\n </div>\n `,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutHeaderComponent {\n @HostBinding(\"class.mdl-layout__header--seamed\")\n isSeamed = false;\n @HostBinding(\"class.mdl-layout__header\")\n isLayoutHeader = true;\n @HostBinding(\"class.is-compact\")\n isCompact = false;\n\n isAnimating = false;\n\n isRipple = true;\n // set from MdlLayoutComponent\n mode: string | undefined;\n el: HTMLElement;\n\n // will be set from mdllayoutcomponent\n tabs: QueryList<MdlLayoutTabPanelComponent> =\n new QueryList<MdlLayoutTabPanelComponent>();\n\n constructor(\n private elementRef: ElementRef,\n private layoutMediatorService: MdlLayoutMediatorService\n ) {\n this.el = elementRef.nativeElement;\n }\n\n @HostBinding(\"class.mdl-layout__header--waterfall\")\n get isWaterfall(): boolean {\n return this.mode === \"waterfall\";\n }\n\n @HostBinding(\"class.is-casting-shadow\") get isCastingShadow(): boolean {\n return this.mode === \"standard\" || this.isCompact;\n }\n\n @HostBinding(\"class.mdl-layout__header--scroll\")\n get isHeaderScroll(): boolean {\n return this.mode === \"scroll\";\n }\n\n @HostListener(\"transitionend\")\n onTransitionEnd(): void {\n this.isAnimating = false;\n }\n\n @HostListener(\"click\")\n onClick(): void {\n if (this.isCompact) {\n this.isCompact = false;\n this.isAnimating = true;\n }\n }\n\n onTabMouseover(tab: MdlLayoutTabPanelComponent): void {\n this.layoutMediatorService.tabMouseover(tab);\n }\n\n onTabMouseout(tab: MdlLayoutTabPanelComponent): void {\n this.layoutMediatorService.tabMouseout(tab);\n }\n\n tabSelected(tab: MdlLayoutTabPanelComponent): void {\n this.layoutMediatorService.tabSelected(tab);\n }\n}\n","import { Component, HostBinding, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-layout-drawer\",\n template: ` <ng-content></ng-content>`,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutDrawerComponent {\n @HostBinding(\"class.mdl-layout__drawer\")\n isDrawer = true;\n\n @HostBinding(\"class.is-visible\")\n isDrawerVisible = false;\n}\n","import { Component, ViewContainerRef, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-tab-panel-title\",\n template: ` <ng-content></ng-content> `,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlTabPanelTitleComponent {\n constructor(public vcRef: ViewContainerRef) {}\n}\n","import {\n Component,\n ContentChild,\n HostBinding,\n Input,\n ViewEncapsulation,\n} from \"@angular/core\";\nimport { MdlTabPanelTitleComponent } from \"../tabs/mdl-tab-panel-title.component\";\n\n@Component({\n selector: \"mdl-layout-tab-panel\",\n template: `\n <ng-content\n *ngIf=\"titleComponent\"\n select=\"mdl-tab-panel-content\"\n ></ng-content>\n <ng-content *ngIf=\"!titleComponent\"></ng-content>\n `,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutTabPanelComponent {\n @ContentChild(MdlTabPanelTitleComponent, { static: true })\n titleComponent: MdlTabPanelTitleComponent | undefined;\n // eslint-disable-next-line @angular-eslint/no-input-rename\n @Input(\"mdl-layout-tab-panel-title\")\n title: string | undefined;\n\n @HostBinding(\"class.mdl-layout__tab-panel\")\n isLayoutTabPanel = true;\n\n @HostBinding(\"class.is-active\")\n isActive = false;\n}\n","import {\n Component,\n ContentChildren,\n ElementRef,\n HostBinding,\n QueryList,\n ViewEncapsulation,\n} from \"@angular/core\";\nimport { MdlLayoutTabPanelComponent } from \"./mdl-layout-tab-panel.component\";\n\n@Component({\n selector: \"mdl-layout-content\",\n template: ` <ng-content></ng-content>`,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutContentComponent {\n @HostBinding(\"class.mdl-layout__content\")\n isContent = true;\n @ContentChildren(MdlLayoutTabPanelComponent)\n tabs: QueryList<MdlLayoutTabPanelComponent> = new QueryList<MdlLayoutTabPanelComponent>();\n\n el: HTMLElement;\n\n constructor(private elRef: ElementRef) {\n this.el = elRef.nativeElement;\n }\n}\n","import { Component, HostBinding, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-icon\",\n template: \"<ng-content></ng-content>\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlIconComponent {\n @HostBinding(\"class.material-icons\")\n isMatIcon = true;\n}\n","import {\n AfterContentInit,\n Component,\n ContentChild,\n ContentChildren,\n ElementRef,\n EventEmitter,\n Inject,\n Injectable,\n InjectionToken,\n Input,\n NgZone,\n OnChanges,\n OnDestroy,\n Optional,\n Output,\n QueryList,\n Renderer2,\n SimpleChanges,\n ViewEncapsulation,\n} from \"@angular/core\";\nimport { EventManager } from \"@angular/platform-browser\";\nimport { MdlLayoutHeaderComponent } from \"./mdl-layout-header.component\";\nimport { MdlLayoutDrawerComponent } from \"./mdl-layout-drawer.component\";\nimport { MdlLayoutContentComponent } from \"./mdl-layout-content.component\";\nimport { BehaviorSubject, Observable, Subject, Subscription } from \"rxjs\";\nimport { toBoolean } from \"../common/boolean-property\";\nimport { toNumber } from \"../common/number.property\";\nimport { MdlError } from \"../common/mdl-error\";\nimport { MdlLayoutMediatorService } from \"./mdl-layout-mediator.service\";\nimport { MdlLayoutTabPanelComponent } from \"./mdl-layout-tab-panel.component\";\n\nconst ESCAPE = 27;\n\nconst STANDARD = \"standard\";\nconst WATERFALL = \"waterfall\";\nconst SCROLL = \"scroll\";\n\n/**\n * The LAYOUT_SCREEN_SIZE_THRESHOLD can be changed at the root module. Just provide a value for this InjectionToken:\n *\n * providers: [\n * {provide:LAYOUT_SCREEN_SIZE_THRESHOLD, useValue: 768 }\n * ]\n *\n * you also need to change the scss variable to the same value: $layout-screen-size-threshold: 768px.\n *\n * It should be clear that this can only be used if you are using the scss and not the pre compiled css from getmdl.io.\n *\n */\nexport const LAYOUT_SCREEN_SIZE_THRESHOLD = new InjectionToken<number>(\n \"layoutScreenSizeThreshold\"\n);\n\nexport class MdLUnsupportedLayoutTypeError extends MdlError {\n constructor(type: string) {\n /* istanbul ignore next */\n super(\n `Layout type \"${type}\" isn't supported by mdl-layout (allowed: standard, waterfall, scroll).`\n );\n }\n}\n\n@Injectable({\n providedIn: \"root\",\n})\nexport class MdlScreenSizeService {\n private sizesSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(\n false\n );\n\n private windowMediaQueryListener: (() => void) | null = null;\n\n constructor(\n ngZone: NgZone,\n @Optional()\n @Inject(LAYOUT_SCREEN_SIZE_THRESHOLD)\n public layoutScreenSizeThreshold: number\n ) {\n // if no value is injected the default size wil be used. same as $layout-screen-size-threshold in scss\n if (!this.layoutScreenSizeThreshold) {\n this.layoutScreenSizeThreshold = 1024;\n }\n\n // do not try to access the window object if rendered on the server\n if (typeof window === \"object\" && \"matchMedia\" in window) {\n const query: MediaQueryList = window.matchMedia(\n `(max-width: ${this.layoutScreenSizeThreshold}px)`\n );\n\n const queryListener = () => {\n ngZone.run(() => {\n this.sizesSubject.next(query.matches);\n });\n };\n // - addEventListener not working in Safari\n // eslint-disable-next-line\n query.addListener(queryListener);\n this.windowMediaQueryListener = () => {\n // eslint-disable-next-line\n query.removeListener(queryListener);\n };\n // set the initial state\n this.sizesSubject.next(query.matches);\n }\n }\n\n public isSmallScreen(): boolean {\n return this.sizesSubject.value;\n }\n\n public sizes(): Observable<boolean> {\n return this.sizesSubject.asObservable();\n }\n\n destroy(): void {\n if (this.windowMediaQueryListener) {\n this.windowMediaQueryListener();\n this.windowMediaQueryListener = null;\n }\n }\n}\n\n@Component({\n selector: \"mdl-layout\",\n template: `\n <div\n class=\"mdl-layout__container\"\n [ngClass]=\"{ 'has-scrolling-header': mode === 'scroll' }\"\n >\n <div\n class=\"mdl-layout is-upgraded\"\n [ngClass]=\"{\n 'is-small-screen': isSmallScreen,\n 'mdl-layout--fixed-drawer': isFixedDrawer,\n 'mdl-layout--fixed-header': isFixedHeader,\n 'mdl-layout--fixed-tabs': 'tabs.toArray().length > 0'\n }\"\n >\n <ng-content select=\"mdl-layout-header\"></ng-content>\n <ng-content select=\"mdl-layout-drawer\"></ng-content>\n <div\n *ngIf=\"drawers.length > 0 && isNoDrawer === false\"\n class=\"mdl-layout__drawer-button\"\n (click)=\"toggleDrawer()\"\n >\n <mdl-icon>&#xE5D2;</mdl-icon>\n </div>\n <ng-content select=\"mdl-layout-content\"></ng-content>\n <div\n class=\"mdl-layout__obfuscator\"\n [ngClass]=\"{ 'is-visible': isDrawerVisible }\"\n (click)=\"toggleDrawer()\"\n (keydown)=\"obfuscatorKeyDown($event)\"\n ></div>\n </div>\n </div>\n `,\n exportAs: \"mdlLayout\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutComponent\n implements AfterContentInit, OnDestroy, OnChanges\n{\n @ContentChild(MdlLayoutHeaderComponent)\n header: MdlLayoutHeaderComponent | undefined;\n // will be set to undefined, if not a direct child or not present in 2.0.0 i\n // n 2.0.1 it is now the grand child drawer again :(\n @ContentChildren(MdlLayoutDrawerComponent, { descendants: false })\n drawers: QueryList<MdlLayoutDrawerComponent> = new QueryList<MdlLayoutDrawerComponent>();\n @ContentChild(MdlLayoutContentComponent, { static: true })\n content: MdlLayoutContentComponent | undefined;\n\n // eslint-disable-next-line\n @Input(\"mdl-layout-mode\")\n mode: string = STANDARD;\n // eslint-disable-next-line\n @Output(\"mdl-layout-tab-active-changed\")\n selectedTabEmitter = new EventEmitter();\n // eslint-disable-next-line\n @Output(\"mdl-layout-tab-mouseover\")\n mouseoverTabEmitter = new EventEmitter();\n // eslint-disable-next-line\n @Output(\"mdl-layout-tab-mouseout\")\n mouseoutTabEmitter = new EventEmitter();\n // eslint-disable-next-line\n @Output(\"open\")\n // eslint-disable-next-line @angular-eslint/no-output-on-prefix\n onOpen = new EventEmitter<void>();\n // eslint-disable-next-line\n @Output(\"close\")\n // eslint-disable-next-line @angular-eslint/no-output-on-prefix\n onClose = new EventEmitter<void>();\n isDrawerVisible = false;\n isSmallScreen = false;\n private scrollListener:\n | ((\n target?: \"window\" | \"document\" | \"body\" | unknown,\n eventName?: string,\n callback?: (event: Event) => boolean | void\n ) => void)\n | undefined;\n private isFixedDrawerIntern = false;\n private isFixedHeaderIntern = false;\n private isSeamedIntern = false;\n private selectedIndexIntern: number | null | undefined = 0;\n private isNoDrawerIntern = false;\n\n private subscriptions: Subscription[] = [];\n\n constructor(\n private renderer: Renderer2,\n private evm: EventManager,\n private el: ElementRef,\n private screenSizeService: MdlScreenSizeService,\n private layoutMediatorService: MdlLayoutMediatorService\n ) {}\n\n @Input(\"mdl-layout-fixed-drawer\")\n get isFixedDrawer(): boolean {\n return this.isFixedDrawerIntern;\n }\n\n set isFixedDrawer(value: boolean | string) {\n this.isFixedDrawerIntern = toBoolean(value);\n }\n\n @Input(\"mdl-layout-fixed-header\")\n get isFixedHeader(): boolean {\n return this.isFixedHeaderIntern;\n }\n\n set isFixedHeader(value: boolean | string) {\n this.isFixedHeaderIntern = toBoolean(value);\n }\n\n @Input(\"mdl-layout-header-seamed\")\n get isSeamed(): boolean {\n return this.isSeamedIntern;\n }\n\n set isSeamed(value: boolean | string) {\n this.isSeamedIntern = toBoolean(value);\n }\n\n @Input(\"mdl-layout-tab-active-index\")\n get selectedIndex(): number {\n return this.selectedIndexIntern ? this.selectedIndexIntern : 0;\n }\n\n set selectedIndex(value: number | undefined) {\n this.selectedIndexIntern = toNumber(value);\n }\n\n @Input(\"mdl-layout-no-drawer-button\")\n get isNoDrawer(): boolean {\n return this.isNoDrawerIntern;\n }\n\n set isNoDrawer(value: boolean | string) {\n this.isNoDrawerIntern = toBoolean(value);\n }\n\n ngAfterContentInit(): void {\n this.validateMode();\n\n if (this.header && this.content && this.content.tabs) {\n this.header.tabs = this.content.tabs;\n this.updateSelectedTabIndex();\n }\n\n if (this.header && this.header.tabs) {\n this.subscriptions.push(\n this.layoutMediatorService\n .onTabMouseOut()\n .subscribe((tab: MdlLayoutTabPanelComponent) => {\n this.onTabMouseout(tab);\n })\n );\n\n this.subscriptions.push(\n this.layoutMediatorService\n .onTabMouseover()\n .subscribe((tab: MdlLayoutTabPanelComponent) => {\n this.onTabMouseover(tab);\n })\n );\n\n this.subscriptions.push(\n this.layoutMediatorService\n .onTabSelected()\n .subscribe((tab: MdlLayoutTabPanelComponent) => {\n this.tabSelected(tab);\n })\n );\n }\n }\n\n public ngOnChanges(changes: SimpleChanges): void {\n if (changes[\"selectedIndex\"]) {\n this.updateSelectedTabIndex();\n }\n }\n\n toggleDrawer(): void {\n this.isDrawerVisible = !this.isDrawerVisible;\n if (this.drawers && this.drawers.length > 0) {\n this.setDrawerVisible(this.isDrawerVisible);\n }\n }\n\n closeDrawer(): void {\n this.isDrawerVisible = false;\n if (this.drawers && this.drawers.length > 0) {\n this.setDrawerVisible(false);\n }\n }\n\n openDrawer(): void {\n this.isDrawerVisible = true;\n if (this.drawers && this.drawers.length > 0) {\n this.setDrawerVisible(true);\n }\n }\n\n obfuscatorKeyDown($event: KeyboardEvent): void {\n if ($event.keyCode === ESCAPE) {\n this.toggleDrawer();\n }\n }\n\n ngOnDestroy(): void {\n if (this.scrollListener) {\n this.scrollListener();\n this.scrollListener = undefined;\n }\n this.subscriptions.forEach((sub) => sub.unsubscribe());\n }\n\n closeDrawerOnSmallScreens(): void {\n if (this.isSmallScreen && this.isDrawerVisible) {\n this.closeDrawer();\n }\n }\n\n openDrawerOnSmallScreens(): void {\n if (this.isSmallScreen && !this.isDrawerVisible) {\n this.openDrawer();\n }\n }\n\n hasDrawer(): boolean {\n return !!(this.drawers && this.drawers.length > 0);\n }\n\n private tabSelected(tab: MdlLayoutTabPanelComponent) {\n const index = this.header?.tabs.toArray().indexOf(tab);\n if (index !== this.selectedIndex) {\n this.selectedIndex = index;\n this.updateSelectedTabIndex();\n this.selectedTabEmitter.emit({ index: this.selectedIndex });\n }\n }\n\n private onTabMouseover(tab: MdlLayoutTabPanelComponent) {\n const index = this.header?.tabs.toArray().indexOf(tab);\n this.mouseoverTabEmitter.emit({ index });\n }\n\n private onTabMouseout(tab: MdlLayoutTabPanelComponent) {\n const index = this.header?.tabs.toArray().indexOf(tab);\n this.mouseoutTabEmitter.emit({ index });\n }\n\n private updateSelectedTabIndex() {\n if (this.header && this.header.tabs) {\n this.header.tabs.forEach((tab) => (tab.isActive = false));\n if (\n this.header.tabs.toArray().length > 0 &&\n this.selectedIndex < this.header.tabs.toArray().length &&\n this.selectedIndex !== -1\n ) {\n this.header.tabs.toArray()[this.selectedIndex].isActive = true;\n }\n }\n }\n\n private validateMode() {\n if (this.mode === \"\") {\n this.mode = STANDARD;\n }\n if ([STANDARD, WATERFALL, SCROLL].indexOf(this.mode) === -1) {\n throw new MdLUnsupportedLayoutTypeError(this.mode);\n }\n\n if (this.header) {\n // inform the header about the mode\n this.header.mode = this.mode;\n this.header.isSeamed = this.isSeamed;\n }\n\n if (this.content) {\n this.scrollListener = this.renderer.listen(\n this.content.el,\n \"scroll\",\n () => {\n this.onScroll(this.content?.el.scrollTop);\n return true;\n }\n );\n\n this.screenSizeService.sizes().subscribe((isSmall: boolean) => {\n this.onQueryChange(isSmall);\n });\n }\n }\n\n private onScroll(scrollTop: number | undefined) {\n if (this.mode !== WATERFALL) {\n return;\n }\n\n if (this.header?.isAnimating) {\n return;\n }\n\n const headerVisible = !this.isSmallScreen || this.isFixedHeader;\n if (this.header) {\n if (scrollTop != null && scrollTop > 0 && !this.header.isCompact) {\n this.header.isCompact = true;\n if (headerVisible) {\n this.header.isAnimating = true;\n }\n } else if (scrollTop != null && scrollTop <= 0 && this.header.isCompact) {\n this.header.isCompact = false;\n if (headerVisible) {\n this.header.isAnimating = true;\n }\n }\n }\n }\n\n private onQueryChange(isSmall: boolean) {\n if (isSmall) {\n this.isSmallScreen = true;\n } else {\n this.isSmallScreen = false;\n this.closeDrawer();\n }\n }\n\n private setDrawerVisible(visible: boolean) {\n this.drawers.first.isDrawerVisible = visible;\n if (this.drawers.first.isDrawerVisible) {\n this.onOpen.emit();\n } else {\n this.onClose.emit();\n }\n }\n}\n","import { Directive, HostBinding } from \"@angular/core\";\n\n@Directive({\n // eslint-disable-next-line\n selector: 'mdl-layout-header[mdl-layout-header-transparent]'\n})\nexport class MdlLayoutHeaderTransparentDirective {\n @HostBinding(\"class.mdl-layout__header--transparent\")\n isTransparent = true;\n}\n","import { Component, HostBinding, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-layout-header-row\",\n template: \"<ng-content></ng-content>\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutHeaderRowComponent {\n @HostBinding(\"class.mdl-layout__header-row\")\n isHeaderRow = true;\n}\n","import { Component, HostBinding, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-layout-title\",\n template: \"<ng-content></ng-content>\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutTitleComponent {\n @HostBinding(\"class.mdl-layout-title\")\n isLayoutTitle = true;\n}\n","import { Component, HostBinding, ViewEncapsulation } from \"@angular/core\";\n\n@Component({\n selector: \"mdl-layout-spacer\",\n template: \"\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlLayoutSpacerComponent {\n @HostBinding(\"class.mdl-layout-spacer\")\n isLayoutSpacer = true;\n}\n","import { ModuleWithProviders, NgModule } from \"@angular/core\";\nimport { MdlIconComponent } from \"./mdl-icon.component\";\n\nexport * from \"./mdl-icon.component\";\n\nconst MDL_ICON_DIRECTIVES = [MdlIconComponent];\n\n@NgModule({\n imports: [],\n exports: MDL_ICON_DIRECTIVES,\n declarations: MDL_ICON_DIRECTIVES,\n})\nexport class MdlIconModule {\n static forRoot(): ModuleWithProviders<MdlIconModule> {\n return {\n ngModule: MdlIconModule,\n providers: [],\n };\n }\n}\n","import {\n Component,\n ContentChild,\n HostBinding,\n Input,\n ViewEncapsulation,\n} from \"@angular/core\";\nimport { MdlTabPanelTitleComponent } from \"./mdl-tab-panel-title.component\";\n\n@Component({\n selector: \"mdl-tab-panel-content\",\n template: \"<ng-content></ng-content>\",\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlTabPanelContentComponent {}\n\n@Component({\n selector: \"mdl-tab-panel\",\n template: `\n <ng-content\n *ngIf=\"titleComponent\"\n select=\"mdl-tab-panel-content\"\n ></ng-content>\n <ng-content *ngIf=\"!titleComponent\"></ng-content>\n `,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlTabPanelComponent {\n @ContentChild(MdlTabPanelTitleComponent, { static: true })\n titleComponent: MdlTabPanelTitleComponent | undefined;\n // eslint-disable-next-line\n @Input(\"mdl-tab-panel-title\")\n title: string | undefined;\n // eslint-disable-next-line\n @Input(\"disabled\")\n disabled: boolean | undefined;\n @HostBinding(\"class.mdl-tabs__panel\")\n isTabPanel = true;\n @HostBinding(\"class.is-active\")\n isActive = false;\n}\n","import {\n AfterContentInit,\n Component,\n ContentChildren,\n EventEmitter,\n HostBinding,\n Input,\n OnChanges,\n Output,\n QueryList,\n SimpleChanges,\n ViewEncapsulation,\n} from \"@angular/core\";\n\nimport { MdlTabPanelComponent } from \"./mdl-tab-panel.component\";\nimport { toNumber } from \"../common/number.property\";\nimport { toBoolean } from \"../common/boolean-property\";\n\n@Component({\n selector: \"mdl-tabs\",\n template: `\n <div class=\"mdl-tabs__tab-bar\">\n <div *ngFor=\"let tab of tabs.toArray()\">\n <div\n *ngIf=\"tab.titleComponent\"\n class=\"mdl-tabs__tab\"\n (click)=\"tabSelected(tab)\"\n [mdl-ripple]=\"isRipple && !tab.disabled\"\n [ngClass]=\"{ 'is-active': tab.isActive, disabled: tab.disabled }\"\n [append-view-container-ref]=\"tab.titleComponent.vcRef\"\n ></div>\n <a\n *ngIf=\"!tab.titleComponent\"\n href=\"javascript:void(0)\"\n (click)=\"tabSelected(tab)\"\n class=\"mdl-tabs__tab\"\n [mdl-ripple]=\"isRipple && !tab.disabled\"\n [ngClass]=\"{ 'is-active': tab.isActive, disabled: tab.disabled }\"\n >{{ tab.title }}</a\n >\n </div>\n </div>\n <ng-content></ng-content>\n `,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MdlTabsComponent implements AfterContentInit, OnChanges {\n // eslint-disable-next-line\n @Output(\"mdl-tab-active-changed\")\n selectedTabEmitter = new EventEmitter();\n @ContentChildren(MdlTabPanelComponent)\n tabs: QueryList<MdlTabPanelComponent> = new QueryList<MdlTabPanelComponent>();\n\n @HostBinding(\"class.mdl-tabs\")\n isTabs = true;\n @HostBinding(\"class.is-upgraded\")\n isUpgraded = true;\n\n private selectedIndexIntern = 0;\n private isRippleIntern = false;\n\n @Input(\"mdl-tab-active-index\")\n get selectedIndex(): number {\n return this.selectedIndexIntern;\n }\n\n set selectedIndex(value: number | string) {\n this.selectedIndexIntern = toNumber(value) ?? 0;\n }\n\n @Input(\"mdl-ripple\")\n get isRipple(): boolean {\n return this.isRippleIntern;\n }\n\n set isRipple(value: boolean | string) {\n this.isRippleIntern = toBoolean(value);\n }\n\n ngAfterContentInit(): void {\n // the initial tabs\n this.updateSelectedTabIndex();\n // listen to tab changes - this would not be necessary if this would be fixed:\n // https://github.com/angular/angular/issues/12818\n this.tabs.changes.subscribe(() => {\n this.updateSelectedTabIndex();\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes[\"selectedIndex\"]) {\n this.updateSelectedTabInd