@universal-material/angular
Version:
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.1.0.
1 lines • 269 kB
Source Map (JSON)
{"version":3,"file":"universal-material-angular.mjs","sources":["../../../../src/ripple/ripple.directive.ts","../../../../src/ripple/ripple.module.ts","../../../../src/coercion/boolean.coercion.ts","../../../../src/form-field/form-field.component.ts","../../../../src/form-field/form-field.component.html","../../../../src/shared/text-input-base.ts","../../../../src/text-field/text-input.directive.ts","../../../../src/text-field/text-field.module.ts","../../../../src/util/scrollable-container-wrapper.ts","../../../../src/util/scroll-behavior.ts","../../../../src/dialog/dialog-body.directive.ts","../../../../src/util/animations/animation-events.ts","../../../../src/dialog/dialog-config.model.ts","../../../../src/dialog/dialog-base.component.ts","../../../../src/dialog/dialog.component.ts","../../../../src/dialog/dialog.component.html","../../../../src/dialog/progress-dialog/progress-dialog.component.ts","../../../../src/dialog/progress-dialog/progress-dialog.component.html","../../../../src/dialog/dialog-injector.ts","../../../../src/util/key.ts","../../../../src/dialog/dialog-stack.service.ts","../../../../src/dialog/dialog.service.ts","../../../../src/dialog/confirm-dialog/confirm-dialog-config.model.ts","../../../../src/dialog/confirm-dialog/confirm-dialog.component.ts","../../../../src/dialog/progress-dialog/progress-dialog.service.ts","../../../../src/dialog/dialog.module.ts","../../../../src/util/util.ts","../../../../src/typeahead/highlight.ts","../../../../src/typeahead/typeahead-window.ts","../../../../src/util/autoclose.ts","../../../../src/util/transition/util.ts","../../../../src/util/transition/transition.ts","../../../../src/util/popup.ts","../../../../src/util/positioning.ts","../../../../src/typeahead/typeahead-config.ts","../../../../src/util/accessibility/live.ts","../../../../src/typeahead/typeahead.ts","../../../../src/typeahead/typeahead.module.ts","../../../../src/floating-action-behavior/floating-action-behavior.directive.ts","../../../../src/floating-action-behavior/floating-action-behavior.module.ts","../../../../src/form-field/label.directive.ts","../../../../src/form-field/form-field.module.ts","../../../../src/dropdown/dropdown-toggle.directive.ts","../../../../src/dropdown/dropdown-menu.directive.ts","../../../../src/dropdown/dropdown.directive.ts","../../../../src/dropdown/dropdown.module.ts","../../../../src/datepicker/datepicker-config.model.ts","../../../../src/datepicker/datepicker-adapter.ts","../../../../src/datepicker/default-datepicker-adapter.ts","../../../../src/datepicker/datepicker-base.component.ts","../../../../src/datepicker/datepicker-state.model.ts","../../../../src/datepicker/datepicker-content/datepicker-content.component.ts","../../../../src/datepicker/datepicker-content/datepicker-content.component.html","../../../../src/datepicker/datepicker.component.ts","../../../../src/datepicker/datepicker.component.html","../../../../src/datepicker/datepicker-input/datepicker-input.component.ts","../../../../src/datepicker/datepicker-input/datepicker-input.component.html","../../../../src/datepicker/datepicker.module.ts","../../../../src/collapse/collapse.component.ts","../../../../src/collapse/collapse.component.html","../../../../src/collapse/collapse.module.ts","../../../../src/expansion-panel/expansion-panel.component.ts","../../../../src/expansion-panel/expansion-panel.component.html","../../../../src/expansion-panel/expansion-panel-container/expansion-panel-container.component.ts","../../../../src/expansion-panel/expansion-panel-container/expansion-panel-container.component.html","../../../../src/expansion-panel/expansion-panel.module.ts","../../../../src/slider/slider.component.ts","../../../../src/slider/slider.component.html","../../../../src/slider/slider.module.ts","../../../../src/value-accessors/radio-control-value-accessor.ts","../../../../src/value-accessors/check-control-value-accessor.ts","../../../../src/value-accessors/chip-field-control-value-accessor.ts","../../../../src/value-accessors/default-control-value-accessor.ts","../../../../src/value-accessors/typeahead-control-value-accessor.ts","../../../../src/value-accessors/select-control-value-accessor.ts","../../../../src/tab-bar/tab-bar.directive.ts","../../../../src/dialog/confirm-dialog/confirm-dialog.service.ts","../../../../src/snackbar/snackbar-config.model.ts","../../../../src/snackbar/snackbar-duration.ts","../../../../src/snackbar/snackbar.service.ts","../../../../src/index.ts","../../../../src/universal-material-angular.ts"],"sourcesContent":["import { AfterViewInit, Directive, ElementRef, HostListener, Inject, Input } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nimport { RippleConfig } from './ripple-config.model';\n\n@Directive({\n selector: '[uRipple]',\n standalone: false,\n})\nexport class RippleDirective implements AfterViewInit {\n\n @Input() rippleConfig: RippleConfig = {};\n @Input('rippleDisabled') disabled = false;\n\n isTouching = false;\n\n constructor(protected readonly _elementRef: ElementRef<HTMLElement>,\n @Inject(DOCUMENT) private document: any) {\n }\n\n private static _setElementSquareSizeAndCenter(element: HTMLElement, size: number) {\n element.style.top = '50%';\n element.style.left = '50%';\n element.style.width = `${size}px`;\n element.style.height = `${size}px`;\n element.style.marginLeft = `${-size / 2}px`;\n element.style.marginTop = `${-size / 2}px`;\n }\n\n @HostListener('mousedown', ['$event']) _mousedown = (e: MouseEvent) => {\n if (this.disabled ||\n this._elementRef.nativeElement.hasAttribute('disabled') ||\n this._elementRef.nativeElement.classList.contains('disabled')) {\n return;\n }\n\n if (!this.isTouching) {\n this.createRipple('mouseup', null, e.clientX, e.clientY);\n }\n }\n\n @HostListener('touchstart', ['$event']) _touchstart = (e: TouchEvent) => {\n if (this.disabled ||\n this._elementRef.nativeElement.hasAttribute('disabled') ||\n this._elementRef.nativeElement.classList.contains('disabled')) {\n return;\n }\n\n this.isTouching = true;\n this.createRipple('touchend', () => {\n setTimeout(() => this.isTouching = false, 100);\n }, e.touches[0].clientX, e.touches[0].clientY);\n }\n\n ngAfterViewInit(): void {\n const {position} = document.defaultView!.getComputedStyle(this._elementRef.nativeElement);\n\n if (position !== 'absolute' &&\n position !== 'fixed' &&\n (!this.rippleConfig || !this.rippleConfig.dontChangePositioning)) {\n this._elementRef.nativeElement.style.position = 'relative';\n }\n }\n\n createRipple(releaseEventName: string, releaseCallback: Function | null, pageX: number, pageY: number) {\n if (this.disabled ||\n this._elementRef.nativeElement.hasAttribute('disabled') ||\n this._elementRef.nativeElement.classList.contains('disabled')) {\n return;\n }\n\n let release: () => void;\n\n const cancelRippleIfNecessary = () => {\n\n this._elementRef.nativeElement.removeEventListener(\"touchmove\", cancelRippleIfNecessary);\n window.removeEventListener(releaseEventName, cancelRippleIfNecessary);\n\n if (release) {\n release();\n }\n };\n\n this._elementRef.nativeElement.addEventListener(\"touchmove\", cancelRippleIfNecessary);\n window.addEventListener(releaseEventName, cancelRippleIfNecessary);\n\n const rippleWrapper = document.createElement('DIV');\n rippleWrapper.classList.add('u-ripple-wrapper');\n\n const ripple = document.createElement('DIV');\n ripple.classList.add('u-ripple');\n rippleWrapper.appendChild(ripple);\n this._elementRef.nativeElement.insertAdjacentElement('afterbegin', rippleWrapper);\n\n if (this.rippleConfig.size) {\n RippleDirective._setElementSquareSizeAndCenter(rippleWrapper, this.rippleConfig.size);\n }\n\n if (this.rippleConfig.borderRadius) {\n rippleWrapper.style.borderRadius = this.rippleConfig.borderRadius;\n }\n\n release = () => {\n\n if (ripple.classList.contains('dismiss')) {\n return;\n }\n\n ripple.classList.add('dismiss');\n\n ripple.addEventListener('transitionend', () => {\n this._elementRef.nativeElement.removeChild(rippleWrapper);\n this._elementRef.nativeElement.removeEventListener('touchend', release);\n this._elementRef.nativeElement.removeEventListener('mouseleave', release);\n this._elementRef.nativeElement.removeEventListener('mouseup', release);\n });\n\n if (releaseCallback) {\n releaseCallback();\n releaseCallback = null;\n }\n };\n\n this._elementRef.nativeElement.addEventListener('touchend', release);\n this._elementRef.nativeElement.addEventListener('mouseleave', release);\n this._elementRef.nativeElement.addEventListener('mouseup', release);\n\n requestAnimationFrame(() => {\n const clientRect = this._elementRef.nativeElement.getBoundingClientRect();\n const largestDimensionSize = Math.max(rippleWrapper.clientWidth, rippleWrapper.clientHeight);\n const rippleSize = this.rippleConfig.size || largestDimensionSize * 2;\n RippleDirective._setElementSquareSizeAndCenter(ripple, rippleSize);\n ripple.style.transitionDuration = `${1080 * Math.pow(rippleSize, 0.3)}ms, 750ms`;\n\n const x = (pageX - clientRect.left) + ((rippleSize - this._elementRef.nativeElement.clientWidth) / 2);\n const y = (pageY - clientRect.top) + ((rippleSize - this._elementRef.nativeElement.clientHeight) / 2);\n\n ripple.style.transformOrigin = `${x}px ${y}px`;\n ripple.classList.add('show');\n });\n }\n}\n","import {NgModule} from '@angular/core';\r\nimport {RippleDirective} from './ripple.directive';\r\n\r\n@NgModule({\r\n declarations: [RippleDirective],\r\n exports: [RippleDirective]\r\n})\r\nexport class RippleModule {\r\n\r\n}\r\n","/**\r\n * @license\r\n * Copyright Google LLC All Rights Reserved.\r\n *\r\n * Use of this source code is governed by an MIT-style license that can be\r\n * found in the LICENSE file at https://angular.io/license\r\n */\r\n\r\n/** Coerces a data-bound value (typically a string) to a boolean. */\r\nexport function coerceBooleanProperty(value: any): boolean {\r\n return value != null && `${value}` !== 'false';\r\n}\r\n","import {\n Component,\n ContentChild,\n ElementRef,\n EventEmitter,\n HostBinding,\n HostListener,\n Inject,\n InjectionToken,\n Input,\n Optional,\n Output,\n ViewChild\n} from '@angular/core';\nimport { LabelDirective } from './label.directive';\nimport { InputBaseComponent } from '../shared/input-base.component';\nimport { FormFieldAppearance } from './form-field-appearance';\n\nexport const FORM_FIELD_DEFAULT_APPEARANCE = new InjectionToken('FORM_FIELD_DEFAULT_APPEARANCE');\n\n@Component({\n selector: 'u-form-field',\n templateUrl: './form-field.component.html',\n styleUrls: ['./form-field.component.scss'],\n standalone: false,\n})\nexport class FormFieldComponent {\n\n _appearanceClass!: string;\n _appearance!: FormFieldAppearance;\n _defaultAppearance: FormFieldAppearance;\n _input: InputBaseComponent | null = null;\n _hasLabel = false;\n\n @HostBinding('class.u-form-field-selection')\n @Input() selectionField = false;\n\n set labelWidth(width: number) {\n this._elementRef.nativeElement.style.setProperty('--u-text-field-label-width', `${width}px`);\n this._elementRef.nativeElement.style.setProperty('--u-text-field-label-half-width', `${width / 2}px`);\n }\n\n @HostBinding('style.margin-bottom')\n get removeMarginStyle() {\n return this.removeMargin ? '0' : '';\n }\n\n @Input() invalid = false;\n @Input() removeMargin = false;\n @Input() supportingText: string | null = null;\n @Input() errorText: string | null = null;\n @Output() activated = new EventEmitter<void>();\n\n @Input()\n get appearance(): FormFieldAppearance {\n return this._appearance;\n }\n set appearance(value: FormFieldAppearance) {\n this._appearance = value;\n\n if (!value || value === 'default') {\n value = this._defaultAppearance;\n }\n\n if (value.indexOf('search') > -1) {\n this._appearanceClass = 'u-search-field';\n return;\n }\n\n this._appearanceClass = `u-text-field-${value}`;\n }\n\n constructor(readonly _elementRef: ElementRef,\n @Optional() @Inject(FORM_FIELD_DEFAULT_APPEARANCE) defaultAppearance: FormFieldAppearance) {\n this._defaultAppearance = defaultAppearance || 'box';\n this.appearance = this._defaultAppearance;\n _elementRef.nativeElement.classList.add('u-form-field');\n }\n\n click(): void {\n\n if (!this._input?.disabled) {\n this._input?.focus();\n this.activated.next();\n }\n }\n\n @HostListener('mousedown', ['$event'])\n mouseDown(e: MouseEvent): void {\n if (!this._input?.disabled) {\n e.preventDefault();\n }\n }\n}\n","<div class=\"u-text-field\"\n tabindex=\"-1\"\n [ngClass]=\"_appearanceClass\"\n [class.u-text-field-hidden-label]=\"!_hasLabel\"\n [class.invalid]=\"invalid\"\n [class.disabled]=\"_input?.disabled\"\n [class.focus]=\"_input?.focused\"\n [class.empty]=\"_input?.empty\"\n (click)=\"click()\">\n <div\n uRipple\n [rippleDisabled]=\"_input?.disabled || !selectionField\"\n class=\"u-text-field-state\"></div>\n <ng-content></ng-content>\n\n</div>\n\n<ng-container *ngIf=\"invalid && (errorText || errorTextContainer.children.length); else supportingTextTemplate\">\n <div class=\"u-text-field-supporting-text\">{{errorText}}</div>\n</ng-container>\n<div class=\"u-text-field-supporting-text\"\n [class.d-none]=\"!invalid || !errorTextContainer.children.length\"\n #errorTextContainer>\n <ng-content select=\"[uErrorText]\"></ng-content>\n</div>\n\n<ng-template #supportingTextTemplate>\n <div\n *ngIf=\"supportingText\"\n class=\"u-text-field-supporting-text\">{{supportingText}}</div>\n <div class=\"u-text-field-supporting-text\"\n [class.d-none]=\"!supportingTextContainer.children.length\"\n #supportingTextContainer>\n <ng-content select=\"[uSupportingText]\"></ng-content>\n </div>\n</ng-template>\n","import { Directive, ElementRef, HostBinding, HostListener, Input } from '@angular/core';\r\nimport { NgControl } from '@angular/forms';\r\n\r\nimport { FormFieldComponent } from '../form-field/form-field.component';\r\nimport { coerceBooleanProperty } from '../coercion/boolean.coercion';\r\n\r\n@Directive()\r\nexport abstract class TextInputBase {\r\n focused = false;\r\n\r\n @Input()\r\n get disabled(): boolean {\r\n if (this.ngControl && this.ngControl.disabled !== null) {\r\n return this.ngControl.disabled;\r\n }\r\n return this._disabled;\r\n }\r\n set disabled(value: boolean) {\r\n this._disabled = (value as any === '') || value;\r\n\r\n // Browsers may not fire the blur event if the input is disabled too quickly.\r\n // Reset from here to ensure that the element doesn't become stuck.\r\n if (this.focused) {\r\n this.focused = false;\r\n }\r\n }\r\n\r\n protected _disabled = false;\r\n static ngAcceptInputType_disabled: boolean | '';\r\n\r\n /** Whether the element is readonly. */\r\n @Input()\r\n get readonly(): boolean { return this._readonly; }\r\n set readonly(value: boolean) { this._readonly = coerceBooleanProperty(value); }\r\n private _readonly = false;\r\n\r\n get empty(): boolean {\r\n return !this._elementRef.nativeElement.value;\r\n }\r\n\r\n @HostListener('blur') _blur = () => this._focusChanged(false);\r\n @HostListener('focus') _focus = () => this._focusChanged(true);\r\n @HostBinding('attr.disabled') get _disabledAttribute() {\r\n return this.disabled ? true : null;\r\n }\r\n\r\n protected constructor(readonly ngControl: NgControl | null,\r\n formField: FormFieldComponent | null,\r\n protected readonly _elementRef: ElementRef) {\r\n\r\n if (formField) {\r\n formField._input = this;\r\n }\r\n }\r\n\r\n focus(): void {\r\n if (document.activeElement !== this._elementRef.nativeElement) {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n }\r\n\r\n /** Callback for the cases where the focused state of the input changes. */\r\n _focusChanged(focused: boolean) {\r\n if (focused !== this.focused && (!this.readonly || !focused)) {\r\n this.focused = focused;\r\n }\r\n }\r\n\r\n @HostListener('mousedown', ['$event'])\r\n mouseDown(e: MouseEvent): void {\r\n e.stopPropagation();\r\n }\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n forwardRef,\r\n HostBinding,\r\n HostListener,\r\n Inject,\r\n Input,\r\n Optional,\r\n Self\r\n} from '@angular/core';\r\nimport { NgControl } from '@angular/forms';\r\n\r\nimport { TextInputBase } from '../shared/text-input-base';\r\nimport { FormFieldComponent } from '../form-field/form-field.component';\r\n\r\n@Directive({\r\n selector: '[uTextInput]',\r\n standalone: false,\r\n})\r\nexport class TextInputDirective extends TextInputBase {\r\n\r\n @Input()\r\n @HostBinding('class.u-text-input')\r\n setInputClass = true;\r\n\r\n constructor(@Optional() @Self() override readonly ngControl: NgControl,\r\n @Optional() @Inject(forwardRef(() => FormFieldComponent)) formField: FormFieldComponent,\r\n elementRef: ElementRef) {\r\n super(ngControl, formField, elementRef);\r\n elementRef.nativeElement.addEventListener('click', (e: Event) => e.stopPropagation());\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nimport { TextInputDirective } from './text-input.directive';\r\n\r\n@NgModule({\r\n imports: [\r\n CommonModule\r\n ],\r\n declarations: [\r\n TextInputDirective\r\n ],\r\n exports: [\r\n TextInputDirective\r\n ]\r\n})\r\nexport class TextFieldModule {\r\n\r\n}\r\n","import { BehaviorSubject, Observable } from \"rxjs\";\nimport { distinctUntilChanged } from \"rxjs/operators\";\n\nexport class ScrollableContainerWrapper {\n private _container: EventTarget | any;\n defaultTarget: EventTarget | any;\n\n _innerScrollTop = new BehaviorSubject<number | null>(null);\n\n scrollTop: number | null = null;\n scrollTop$: Observable<number | null> = this._innerScrollTop.pipe(distinctUntilChanged());\n\n private _emitScroll = () => {\n this.scrollTop = this._getScrollTop();\n this._innerScrollTop.next(this.scrollTop);\n };\n\n private _getScrollTop(): number | null{\n if (typeof this._container.scrollY === 'number') {\n return this._container.scrollY;\n }\n\n if (typeof this._container.scrollTop === 'number') {\n return this._container.scrollTop;\n }\n\n if (this._container.body && typeof this._container.body.scrollTop === 'number') {\n return this._container.body.scrollTop;\n }\n\n return null;\n }\n\n get container(): EventTarget | any {\n return this._container;\n }\n\n set container(value: EventTarget | any) {\n value = value || this.defaultTarget;\n if (value === this._container) {\n return;\n }\n\n if (this._container) {\n this._container.removeEventListener('scroll', this._emitScroll);\n }\n\n this._container = value;\n\n if (this._container) {\n this._container.addEventListener('scroll', this._emitScroll);\n }\n\n this._emitScroll();\n }\n}\n","import { AfterContentInit, Directive, Input, OnChanges, SimpleChanges } from '@angular/core';\r\n\r\nimport { ScrollableContainerWrapper } from './scrollable-container-wrapper';\r\n\r\n@Directive()\r\nexport abstract class ScrollBehavior implements AfterContentInit, OnChanges {\r\n @Input() scrollContainer: HTMLElement | null = null;\r\n protected _scrollableWrapper: ScrollableContainerWrapper | null = null;\r\n\r\n protected abstract _processBehavior: (scrollTop: number | null) => void;\r\n protected defaultTarget: EventTarget | any;\r\n\r\n protected _setScrollWrapper() {\r\n this._scrollableWrapper = new ScrollableContainerWrapper();\r\n this._scrollableWrapper.defaultTarget = this.defaultTarget;\r\n this._scrollableWrapper.container = this.scrollContainer;\r\n this._scrollableWrapper.scrollTop$.subscribe(this._processBehavior.bind(this));\r\n }\r\n\r\n ngAfterContentInit(): void {\r\n this._setScrollWrapper();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['scrollContainer'] && this._scrollableWrapper) {\r\n this._scrollableWrapper.container = this.scrollContainer;\r\n }\r\n }\r\n}\r\n","import { Directive, ElementRef } from '@angular/core';\n\nimport { ScrollBehavior } from '../util/scroll-behavior';\n\n@Directive({\n selector: '[uDialogBody]'\n})\nexport class DialogBodyDirective extends ScrollBehavior {\n dialog: any;\n\n constructor(_elementRef: ElementRef) {\n super();\n this.defaultTarget = _elementRef.nativeElement\n }\n\n _processBehavior = () => {\n\n if (!this.dialog || !this._scrollableWrapper) {\n return;\n }\n\n const scrollTop = this._scrollableWrapper.scrollTop;\n this.dialog.scrollTopDivider = !!scrollTop;\n\n if (scrollTop === null) {\n this.dialog.scrollBottomDivider = false;\n return;\n }\n\n const scrollBottom = scrollTop + this._scrollableWrapper.container.offsetHeight;\n this.dialog.scrollBottomDivider = scrollBottom !== this._scrollableWrapper.container.scrollHeight\n }\n}\n","export class AnimationEvents {\n private static readonly _animationEndEvents = ['webkitAnimationEnd', 'oanimationend', 'msAnimationEnd', 'animationend'];\n\n static attachAnimationEndEvents(element: Element, listener: EventListenerOrEventListenerObject) {\n AnimationEvents\n ._animationEndEvents\n .forEach(eventName => {\n element.addEventListener(eventName, listener);\n });\n }\n}\n","import { InjectionToken } from '@angular/core';\n\nexport const DIALOG_DEFAULT_OPTIONS = new InjectionToken('DIALOG_DEFAULT_OPTIONS');\n\nexport interface DialogConfig {\n closeOnBackdropClick?: boolean;\n closeOnEsc?: boolean;\n}\n","import {\n AfterContentInit,\n ContentChild,\n Directive,\n ElementRef,\n EventEmitter,\n HostBinding,\n Inject,\n Input,\n Optional,\n Output,\n ViewChild\n} from '@angular/core';\n\nimport { DialogBodyDirective } from \"./dialog-body.directive\";\nimport { AnimationEvents } from '../util/animations/animation-events';\nimport { DIALOG_DEFAULT_OPTIONS, DialogConfig } from './dialog-config.model';\n\nexport const DefaultDialogConfig: DialogConfig = {\n closeOnBackdropClick: true,\n closeOnEsc: true\n};\n\n@Directive()\nexport class DialogBaseComponent implements AfterContentInit {\n private _contentInitialized = false;\n\n _dialogConfig: DialogConfig;\n\n @HostBinding('class.hide') _hiding = false;\n @HostBinding('class.show') @Input() show = false;\n @Output() showChange = new EventEmitter<boolean>();\n @Output() afterClose = new EventEmitter();\n @Output() closedFromBackdrop = new EventEmitter();\n\n @ContentChild(DialogBodyDirective)\n set _contentChildBody(dialogBody: DialogBodyDirective) {\n this.setDialogBody(dialogBody);\n }\n\n @ViewChild(DialogBodyDirective)\n set _viewChildBody(dialogBody: DialogBodyDirective) {\n this.setDialogBody(dialogBody);\n }\n\n dialogBody: DialogBodyDirective | null = null;\n\n @HostBinding('tabindex') _tabIndex = -1;\n\n @HostBinding('class.u-dialog-scroll-top-divider') scrollTopDivider = false;\n @HostBinding('class.u-dialog-scroll-bottom-divider') scrollBottomDivider = false;\n\n constructor(protected readonly _elementRef: ElementRef,\n @Optional() @Inject(DIALOG_DEFAULT_OPTIONS) defaultOptions?: DialogConfig | undefined) {\n this._dialogConfig = {...DefaultDialogConfig, ...defaultOptions};\n _elementRef.nativeElement.classList.add('u-dialog');\n }\n\n private addAnimationEndEvents() {\n AnimationEvents.attachAnimationEndEvents(this._elementRef.nativeElement, this.onAnimationEnd.bind(this));\n }\n\n private onAnimationEnd = (event: Event) => {\n this._elementRef.nativeElement.removeEventListener(event.type, this.onAnimationEnd);\n this._hiding = false;\n this.afterClose.emit();\n }\n\n private setDialogBody(dialogBody: DialogBodyDirective): void {\n this.dialogBody = dialogBody;\n\n if (!this.dialogBody) {\n return;\n }\n\n this.dialogBody.dialog = this;\n this.dialogBody._processBehavior();\n }\n\n backdropClick() {\n if (this._dialogConfig.closeOnBackdropClick) {\n this.close();\n this.closedFromBackdrop.emit();\n }\n }\n\n close() {\n\n if (!this.show) {\n return;\n }\n\n this.show = false;\n this.showChange.emit(false);\n this._hiding = true;\n this.addAnimationEndEvents();\n }\n\n ngAfterContentInit(): void {\n setTimeout(() => this._contentInitialized = true, 100);\n }\n}\n","import { Component } from '@angular/core';\n\nimport { DialogBaseComponent } from './dialog-base.component';\n\n@Component({\n selector: 'u-legacy-dialog',\n templateUrl: './dialog.component.html',\n styleUrls: ['./dialog.component.scss']\n})\nexport class DialogComponent extends DialogBaseComponent {\n\n}\n","<div class=\"u-dialog-backdrop\" (click)=\"backdropClick()\"></div>\n<ng-content></ng-content>\n","import { Component, ElementRef } from '@angular/core';\n\nimport { DialogComponent } from '../dialog.component';\n\n@Component({\n templateUrl: './progress-dialog.component.html'\n})\nexport class ProgressDialogComponent extends DialogComponent {\n message: string | null = null;\n\n constructor(_elementRef: ElementRef) {\n super (_elementRef, {\n closeOnBackdropClick: false,\n closeOnEsc: false\n });\n _elementRef.nativeElement.classList.add('u-dialog-progress');\n }\n}\n","<div class=\"u-dialog-backdrop\"></div>\n<div class=\"u-dialog-content\">\n <div class=\"u-dialog-body\">\n <div class=\"preloader-wrapper\">\n <div class=\"spinner-layer\">\n <div class=\"circle-clipper left\">\n <div class=\"circle\"></div>\n </div>\n <div class=\"gap-patch\">\n <div class=\"circle\"></div>\n </div>\n <div class=\"circle-clipper right\">\n <div class=\"circle\"></div>\n </div>\n </div>\n </div>\n <div class=\"u-dialog-progress-message u-headline6 u-text-low-contrast u-text-nowrap\">{{message}}</div>\n </div>\n</div>\n","import { Injector } from '@angular/core';\n\nexport class DialogInjector implements Injector {\n constructor(\n private _parentInjector: Injector,\n private _customTokens: WeakMap<any, any>\n ) {}\n\n get(token: any, notFoundValue?: any): any {\n const value = this._customTokens.get(token);\n\n if (typeof value !== 'undefined') {\n return value;\n }\n\n return this._parentInjector.get<any>(token, notFoundValue);\n }\n\n}\n","export enum Key {\n Tab = 9,\n Enter = 13,\n Escape = 27,\n Space = 32,\n PageUp = 33,\n PageDown = 34,\n End = 35,\n Home = 36,\n ArrowLeft = 37,\n ArrowUp = 38,\n ArrowRight = 39,\n ArrowDown = 40\n}\n","import { Inject, Injectable } from '@angular/core';\nimport { first } from 'rxjs/operators';\n\nimport { DialogComponent } from './dialog.component';\nimport { DOCUMENT } from '@angular/common';\nimport { Key } from '../util/key';\n\n@Injectable({providedIn: 'root'})\nexport class DialogStackService {\n private static _dialogStack: DialogComponent[] = [];\n\n constructor(@Inject(DOCUMENT) private readonly _document: any) {\n this._document.body.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.keyCode === Key.Escape) {\n this.closeTopMostDialog();\n }\n });\n }\n\n removeDialog(dialog: DialogComponent) {\n const index = DialogStackService._dialogStack.indexOf(dialog);\n\n if (index < 0) {\n return;\n }\n\n DialogStackService._dialogStack.splice(index, 1);\n }\n\n addDialog(dialog: DialogComponent) {\n const index = DialogStackService._dialogStack.indexOf(dialog);\n\n if (index < 0) {\n return;\n }\n\n DialogStackService._dialogStack.unshift(dialog);\n }\n\n add(dialog: DialogComponent) {\n\n if (dialog.show) {\n this.addDialog(dialog);\n } else {\n dialog.showChange\n .pipe(first())\n .subscribe(show => {\n if (show) {\n this.addDialog(dialog);\n }\n });\n }\n\n dialog.afterClose\n .pipe(first())\n .subscribe(() => this.removeDialog(dialog));\n\n DialogStackService._dialogStack.unshift(dialog);\n }\n\n closeTopMostDialog() {\n for (const dialog of DialogStackService._dialogStack) {\n if (dialog._dialogConfig && dialog._dialogConfig.closeOnEsc) {\n dialog.close();\n break;\n }\n }\n }\n}\n","import { ApplicationRef, ComponentFactoryResolver, Injectable, InjectionToken, Injector, Type } from '@angular/core';\n\nimport { DialogInjector } from './dialog-injector';\nimport { DialogStackService } from './dialog-stack.service';\nimport { DialogComponent } from './dialog.component';\n\nexport const DIALOG_DATA = new InjectionToken<any>('DIALOG_DATA');\n\n@Injectable({\n providedIn: 'root'\n})\nexport class DialogService {\n\n constructor(private readonly _componentFactoryResolver: ComponentFactoryResolver,\n private readonly _appRef: ApplicationRef,\n private readonly _injector: Injector,\n private readonly _dialogStackService: DialogStackService) {\n\n }\n\n _internalOpen<T extends DialogComponent>(dialogType: Type<T>, customInjectionTokens: WeakMap<any, any>): T {\n const dialogComponent = this._componentFactoryResolver.resolveComponentFactory(dialogType);\n\n const dialogComponentRef = dialogComponent.create(new DialogInjector(this._injector, customInjectionTokens));\n\n dialogComponentRef.instance.afterClose.subscribe(() => {\n this._appRef.detachView(dialogComponentRef.hostView);\n dialogComponentRef.destroy();\n });\n\n this._appRef.attachView(dialogComponentRef.hostView);\n\n this._dialogStackService.add(dialogComponentRef.instance);\n\n document\n .querySelector('body')!\n .appendChild(dialogComponentRef.location.nativeElement);\n\n return dialogComponentRef.instance;\n }\n\n open<T extends DialogComponent>(dialogType: Type<T>, data?: any): T {\n return this._internalOpen(dialogType, new WeakMap(data && [[DIALOG_DATA, data]]));\n }\n}\n","import { InjectionToken } from '@angular/core';\n\nimport { DialogConfig } from '../dialog-config.model';\nimport { DefaultDialogConfig } from '../dialog-base.component';\nimport { UmButtonColor, UmButtonVariant } from '@universal-material/web';\n\nexport const CONFIRM_DIALOG_DEFAULT_OPTIONS = new InjectionToken<any>('CONFIRM_DIALOG_DEFAULT_OPTIONS');\n\nexport const DefaultConfirmDialogConfig: ConfirmDialogConfig = {\n ...DefaultDialogConfig,\n confirmButton: {\n text: 'OK',\n variant: 'text'\n },\n cancelButton: {\n text: 'Cancel',\n variant: 'text'\n },\n};\n\nexport interface ConfirmDialogButtonConfig {\n text?: string;\n variant?: UmButtonVariant;\n color?: UmButtonColor;\n}\n\nexport class ConfirmDialogConfig implements DialogConfig {\n title?: string;\n confirmButton?: ConfirmDialogButtonConfig;\n cancelButton?: ConfirmDialogButtonConfig;\n closeOnBackdropClick?: boolean;\n closeOnEsc?: boolean;\n}\n","import { Component, Directive, ElementRef, Inject, Optional, SecurityContext, ViewChild } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Subject } from 'rxjs';\n\nimport { DialogComponent } from '../dialog.component';\nimport {\n CONFIRM_DIALOG_DEFAULT_OPTIONS,\n ConfirmDialogConfig,\n DefaultConfirmDialogConfig\n} from './confirm-dialog-config.model';\nimport { DialogBodyDirective } from '../dialog-body.directive';\n\n@Component({\n template: '',\n})\nexport abstract class ConfirmDialogComponent extends DialogComponent {\n safeMessage: string | null = null;\n\n set message(value: string) {\n this.safeMessage = this.sanitizer.sanitize(SecurityContext.HTML, value);\n }\n\n private _closed = false;\n readonly _confirmDialogConfig: ConfirmDialogConfig;\n\n onCancel = new Subject<void>();\n onConfirm = new Subject<void>();\n confirmed = false;\n\n @ViewChild(DialogBodyDirective) override dialogBody!: DialogBodyDirective;\n\n constructor(elementRef: ElementRef,\n private readonly sanitizer: DomSanitizer,\n @Optional() confirmDialogConfig: ConfirmDialogConfig,\n @Optional() @Inject(CONFIRM_DIALOG_DEFAULT_OPTIONS) defaultOptions: ConfirmDialogConfig) {\n super(elementRef);\n this._confirmDialogConfig = DefaultConfirmDialogConfig;\n this._confirmDialogConfig = this._assignConfig(this._confirmDialogConfig, defaultOptions);\n this._confirmDialogConfig = this._assignConfig(this._confirmDialogConfig, confirmDialogConfig);\n\n this._dialogConfig = this._confirmDialogConfig;\n }\n\n private _assignConfig(baseConfig: ConfirmDialogConfig, partialConfig: ConfirmDialogConfig): ConfirmDialogConfig {\n\n if (partialConfig) {\n baseConfig.confirmButton = {...baseConfig.confirmButton, ...partialConfig.confirmButton};\n baseConfig.cancelButton = {...baseConfig.cancelButton, ...partialConfig.cancelButton};\n delete partialConfig.confirmButton;\n delete partialConfig.cancelButton;\n }\n\n return {...baseConfig, ...partialConfig};\n }\n\n override close() {\n super.close();\n this._closed = true;\n }\n\n _cancelClick() {\n if (this._closed) {\n return;\n }\n\n this.close();\n this.onCancel.next();\n }\n\n _confirmClick() {\n if (this._closed) {\n return;\n }\n\n this.close();\n this.confirmed = true;\n this.onConfirm.next();\n }\n}\n","import { Injectable } from '@angular/core';\n\nimport { ProgressDialogComponent } from './progress-dialog.component';\nimport { DialogService } from '../dialog.service';\n\n@Injectable({providedIn: 'root'})\nexport class ProgressDialogService {\n constructor(private readonly _dialogService: DialogService) {\n\n }\n\n open(message: string | null = null): ProgressDialogComponent {\n const progressDialog = this._dialogService.open(ProgressDialogComponent);\n progressDialog.message = message;\n progressDialog.show = true;\n\n return progressDialog;\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\n\nimport { DialogComponent } from './dialog.component';\nimport { DialogBodyDirective } from './dialog-body.directive';\nimport { ProgressDialogComponent } from './progress-dialog/progress-dialog.component';\n\nexport { DialogBaseComponent } from './dialog-base.component';\nexport { DialogConfig, DIALOG_DEFAULT_OPTIONS } from './dialog-config.model';\nexport { DialogComponent } from './dialog.component';\nexport { DialogBodyDirective } from './dialog-body.directive';\nexport { DialogService, DIALOG_DATA } from './dialog.service';\n\nexport { ConfirmDialogConfig, CONFIRM_DIALOG_DEFAULT_OPTIONS } from './confirm-dialog/confirm-dialog-config.model';\nexport { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component';\n\nexport { ProgressDialogComponent } from './progress-dialog/progress-dialog.component';\nexport { ProgressDialogService } from './progress-dialog/progress-dialog.service';\n\n@NgModule({\n imports: [\n CommonModule\n ],\n declarations: [\n DialogComponent,\n DialogBodyDirective,\n ProgressDialogComponent\n ],\n exports: [\n DialogComponent,\n DialogBodyDirective\n ]\n})\nexport class DialogModule {\n}\n","import { NgZone } from '@angular/core';\nimport { OperatorFunction, Observable } from 'rxjs';\n\nexport function toInteger(value: any): number {\n return parseInt(`${value}`, 10);\n}\n\nexport function toString(value: any): string {\n return (value !== undefined && value !== null) ? `${value}` : '';\n}\n\nexport function getValueInRange(value: number, max: number, min = 0): number {\n return Math.max(Math.min(value, max), min);\n}\n\nexport function isString(value: any): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: any): value is number {\n return !isNaN(toInteger(value));\n}\n\nexport function isInteger(value: any): value is number {\n return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;\n}\n\nexport function isDefined(value: any): boolean {\n return value !== undefined && value !== null;\n}\n\nexport function padNumber(value: number) {\n if (isNumber(value)) {\n return `0${value}`.slice(-2);\n } else {\n return '';\n }\n}\n\nexport function regExpEscape(text: string) {\n return text.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&');\n}\n\nexport function closest(element: HTMLElement, selector?: string): HTMLElement | null {\n if (!selector) {\n return null;\n }\n\n /*\n * In certain browsers (e.g. Edge 44.18362.449.0) HTMLDocument does\n * not support `Element.prototype.closest`. To emulate the correct behaviour\n * we return null when the method is missing.\n *\n * Note that in evergreen browsers `closest(document.documentElement, 'html')`\n * will return the document element whilst in Edge null will be returned. This\n * compromise was deemed good enough.\n */\n if (typeof element.closest === 'undefined') {\n return null;\n }\n\n return element.closest(selector);\n}\n\nexport function runInZone<T>(zone: NgZone): OperatorFunction<T, T> {\n return (source) => {\n return new Observable(observer => {\n const onNext = (value: T) => zone.run(() => observer.next(value));\n const onError = (e: any) => zone.run(() => observer.error(e));\n const onComplete = () => zone.run(() => observer.complete());\n return source.subscribe(onNext, onError, onComplete);\n });\n };\n}\n","import {Component, Input, OnChanges, ChangeDetectionStrategy, SimpleChanges} from '@angular/core';\nimport {regExpEscape, toString} from '../util/util';\n\n/**\n * A component that can be used inside a custom result template in order to highlight the term inside the text of the\n * result\n */\n@Component({\n selector: 'u-legacy-highlight',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `<ng-template ngFor [ngForOf]=\"parts\" let-part let-isOdd=\"odd\">` +\n `<span *ngIf=\"isOdd; else even\" [class]=\"highlightClass\">{{part}}</span><ng-template #even>{{part}}</ng-template>` +\n `</ng-template>`, // template needs to be formatted in a certain way so we don't add empty text nodes\n styleUrls: ['./highlight.scss'],\n standalone: false,\n})\nexport class Highlight implements OnChanges {\n parts!: string[];\n\n /**\n * The CSS class of the span elements wrapping the term inside the result\n */\n @Input() highlightClass = 'u-highlight';\n\n /**\n * The result text to display. If the term is found inside this text, it's highlighted\n */\n @Input() result?: string | null;\n\n /**\n * The searched term\n */\n @Input() term!: string | readonly string[];\n\n ngOnChanges(changes: SimpleChanges) {\n const resultStr = toString(this.result);\n const resultLC = resultStr.toLowerCase();\n const termLC = toString(this.term).toLowerCase();\n let currentIdx = 0;\n\n if (termLC.length > 0) {\n this.parts = resultLC.split(new RegExp(`(${regExpEscape(termLC)})`)).map((part) => {\n const originalPart = resultStr.substr(currentIdx, part.length);\n currentIdx += part.length;\n return originalPart;\n });\n } else {\n this.parts = [resultStr];\n }\n }\n}\n","import {Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewEncapsulation} from '@angular/core';\n\nimport {toString} from '../util/util';\n\n/**\n * The context for the typeahead result template in case you want to override the default one.\n */\nexport interface ResultTemplateContext {\n /**\n * Your typeahead result item.\n */\n result: any;\n\n /**\n * Search term from the `<input>` used to get current result.\n */\n term: string;\n\n /**\n * The function which transforms the result into a string\n */\n formatter: (result: any) => string;\n}\n\n@Component({\n selector: 'u-typeahead-window',\n exportAs: 'TypeaheadWindow',\n encapsulation: ViewEncapsulation.None,\n host: {\n '(mousedown)': '$event.preventDefault()',\n '[class]': '\"u-dropdown-menu show\" + (popupClass ? \" \" + popupClass : \"\")',\n 'role': 'listbox',\n '[id]': 'id'\n },\n template: `\n <ng-template #rt let-result=\"result\" let-term=\"term\" let-formatter=\"formatter\">\n <u-highlight [attr.result]=\"formatter(result)\" [attr.term]=\"term\"></u-highlight>\n </ng-template>\n <ng-template ngFor [ngForOf]=\"results\" let-result let-idx=\"index\">\n <button type=\"button\" uRipple class=\"u-dropdown-item\" role=\"option\"\n [id]=\"id + '-' + idx\"\n [class.active]=\"idx === activeIdx\"\n (mouseenter)=\"markActive(idx)\"\n (click)=\"select(result)\">\n <ng-template\n [ngTemplateOutlet]=\"resultTemplate || rt\"\n [ngTemplateOutletContext]=\"{result: result, term: term, formatter: formatter}\"></ng-template>\n </button>\n </ng-template>\n `\n})\nexport class TypeaheadWindow implements OnInit {\n activeIdx = 0;\n\n /**\n * The id for the typeahead window. The id should be unique and the same\n * as the associated typeahead's id.\n */\n @Input() id: string | null = null;\n\n /**\n * Flag indicating if the first row should be active initially\n */\n @Input() focusFirst = true;\n\n /**\n * Typeahead match results to be displayed\n */\n @Input() results!: readonly any[];\n\n /**\n * Search term used to get current results\n */\n @Input() term!: string;\n\n /**\n * A function used to format a given result before display. This function should return a formatted string without any\n * HTML markup\n */\n @Input() formatter = toString;\n\n /**\n * A template to override a matching result default display\n */\n @Input() resultTemplate!: TemplateRef<ResultTemplateContext>;\n\n /**\n * A custom class to append to the typeahead window\n *\n * @since 9.1.0\n */\n @Input() popupClass: string | null = null;\n\n /**\n * Event raised when user selects a particular result row\n */\n @Output('select') selectEvent = new EventEmitter();\n\n @Output('activeChange') activeChangeEvent = new EventEmitter();\n\n hasActive() { return this.activeIdx > -1 && this.activeIdx < this.results.length; }\n\n getActive() { return this.results[this.activeIdx]; }\n\n markActive(activeIdx: number) {\n this.activeIdx = activeIdx;\n this._activeChanged();\n }\n\n next() {\n if (this.activeIdx === this.results.length - 1) {\n this.activeIdx = this.focusFirst ? (this.activeIdx + 1) % this.results.length : -1;\n } else {\n this.activeIdx++;\n }\n this._activeChanged();\n }\n\n prev() {\n if (this.activeIdx < 0) {\n this.activeIdx = this.results.length - 1;\n } else if (this.activeIdx === 0) {\n this.activeIdx = this.focusFirst ? this.results.length - 1 : -1;\n } else {\n this.activeIdx--;\n }\n this._activeChanged();\n }\n\n resetActive() {\n this.activeIdx = this.focusFirst ? 0 : -1;\n this._activeChanged();\n }\n\n select(item: any) { this.selectEvent.emit(item); }\n\n ngOnInit() { this.resetActive(); }\n\n private _activeChanged() {\n this.activeChangeEvent.emit(this.activeIdx >= 0 ? this.id + '-' + this.activeIdx : undefined);\n }\n}\n","import {NgZone} from '@angular/core';\r\nimport {fromEvent, Observable, race} from 'rxjs';\r\nimport {delay, filter, map, takeUntil, tap, withLatestFrom} from 'rxjs/operators';\r\nimport {Key} from './key';\r\nimport {closest} from './util';\r\n\r\nconst isContainedIn = (element: HTMLElement, array?: HTMLElement[]) =>\r\n array ? array.some(item => item.contains(element)) : false;\r\n\r\nconst matchesSelectorIfAny = (element: HTMLElement, selector?: string) =>\r\n !selector || closest(element, selector) != null;\r\n\r\n// we have to add a more significant delay to avoid re-opening when handling (click) on a toggling element\r\n// TODO: use proper Angular platform detection when NgbAutoClose becomes a service and we can inject PLATFORM_ID\r\nconst isMobile = (() => {\r\n const isIOS = () => /iPad|iPhone|iPod/.test(navigator.userAgent) ||\r\n (/Macintosh/.test(navigator.userAgent) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);\r\n const isAndroid = () => /Android/.test(navigator.userAgent);\r\n\r\n return typeof navigator !== 'undefined' ? !!navigator.userAgent && (isIOS() || isAndroid()) : false;\r\n})();\r\n\r\n// setting 'ngbAutoClose' synchronously on mobile results in immediate popup closing\r\n// when tapping on the triggering element\r\nconst wrapAsyncForMobile = (fn: any) => isMobile ? () => setTimeout(() => fn(), 100) : fn;\r\n\r\nexport const enum SOURCE {ESCAPE, CLICK}\r\n\r\nexport function AutoClose(\r\n zone: NgZone, document: any, type: boolean | 'inside' | 'outside', close: (source: SOURCE) => void,\r\n closed$: Observable<any>, insideElements: HTMLElement[], ignoreElements?: HTMLElement[], insideSelector?: string) {\r\n // closing on ESC and outside clicks\r\n if (type) {\r\n zone.runOutsideAngular(wrapAsyncForMobile(() => {\r\n\r\n const shouldCloseOnClick = (event: MouseEvent) => {\r\n const element = event.target as HTMLElement;\r\n if (event.button === 2 || isContainedIn(element, ignoreElements)) {\r\n return false;\r\n }\r\n if (type === 'inside') {\r\n return isContainedIn(element, insideElements) && matchesSelectorIfAny(element, insideSelector);\r\n } else if (type === 'outside') {\r\n return !isContainedIn(element, insideElements);\r\n } else /* if (type === true) */ {\r\n return matchesSelectorIfAny(element, insideSelector) || !isContainedIn(element, insideElements);\r\n }\r\n };\r\n\r\n const escapes$ = fromEvent<KeyboardEvent>(document, 'keydown')\r\n .pipe(\r\n takeUntil(closed$),\r\n // tslint:disable-next-line:deprecation\r\n filter(e => e.which === Key.Escape), tap(e => e.preventDefault()));\r\n\r\n\r\n // we have to pre-calculate 'shouldCloseOnClick' on 'mousedown',\r\n // because on 'mouseup' DOM nodes might be detached\r\n const mouseDowns$ =\r\n fromEvent<MouseEvent>(document, 'mousedown').pipe(map(shouldCloseOnClick), takeUntil(closed$));\r\n\r\n const closeableClicks$ = fromEvent<MouseEvent>(document, 'mouseup')\r\n .pipe(\r\n withLatestFrom(mouseDowns$), filter(([_, shouldClose]) => shouldClose), delay(0),\r\n takeUntil(closed$)) as any as Observable<MouseEvent>;\r\n\r\n\r\n race([\r\n escapes$.pipe(map(_ => SOURCE.ESCAPE)), closeableClicks$.pipe(map(_ => SOURCE.CLICK))\r\n ]).subscribe({\r\n next: source => zone.run(() => close(source))\r\n });\r\n }));\r\n }\r\n}\r\n","export function getTransitionDurationMs(element: HTMLElement) {\r\n const {transitionDelay, transitionDuration} = window.getComputedStyle(element);\r\n const transitionDelaySec = parseFloat(transitionDelay);\r\n const transitionDurationSec = parseFloat(transitionDuration);\r\n\r\n return (transitionDelaySec + transitionDurationSec) * 1000;\r\n}\r\n","import {NgZone} from '@angular/core';\r\nimport {EMPTY, fromEvent, Observable, of, race, Subject, timer} from 'rxjs';\r\nimport {endWith, filter, takeUntil} from 'rxjs/operators';\r\nimport {getTransitionDurationMs} from './util';\r\nimport {runInZone} from '../util';\r\n\r\nexport const environment = {\r\n animation: true,\r\n transitionTimerDelayMs: 5,\r\n};\r\n\r\nexport type TransitionStartFn<T = any> = (element: HTMLElement, animation: boolean, context: T) =>\r\n TransitionEndFn | void;\r\nexport type TransitionEndFn = () => void;\r\n\r\nexport interface TransitionOptions<T> {\r\n animation: boolean;\r\n runningTransition: 'continue' | 'stop';\r\n context?: T;\r\n}\r\n\r\nexport interface NgbTransitionCtx<T> {\r\n transition$: Subject<any>;\r\n complete: () => void;\r\n context: T;\r\n}\r\n\r\nconst noopFn: TransitionEndFn = () => {};\r\n\r\nconst {transitionTimerDelayMs} = environment;\r\nconst runningTransitions = new Map<HTMLElement, NgbTransitionCtx<any>>();\r\n\r\nexport const runTransition =\r\n <T>(zone: NgZone, element: HTMLElement, startFn: TransitionStartFn<T>, options: TransitionOptions<T>):\r\n Observable<void> => {\r\n\r\n // Getting initial context from options\r\n let context = options.context || <T>{};\r\n\r\n // Checking if there are already running transitions on the given element.\r\n const running = runningTransitions.get(element);\r\n if (running) {\r\n switch (options.runningTransition) {\r\n // If there is one running and we want for it to 'continue' to run, we have to cancel the new one.\r\n // We're not emitting any values, but simply completing the observable (EMPTY).\r\n case 'continue':\r\n return EMPTY;\r\n // If there is one running and we want for it to 'stop', we have to complete the running one.\r\n // We're simply completing the running one and not emitting any values and merging newly provided context\r\n // with the one coming from currently running transition.\r\n case 'stop':\r\n zone.run(() => running.transition$.complete());\r\n context = Object.assign(running.context, context);\r\n runningTransitions.delete(element);\r\n }\r\n }\r\n\r\n // Running the s