UNPKG

@hxui/angular

Version:

An Angular library based on the [HXUI design system](https://hxui.io).

1 lines 644 kB
{"version":3,"file":"hxui-angular.mjs","sources":["../../../projects/hx-ui/src/lib/accordion/accordion.body.ts","../../../projects/hx-ui/src/lib/accordion/accordion.component.ts","../../../projects/hx-ui/src/lib/accordion/accordion.container.component.ts","../../../projects/hx-ui/src/lib/accordion/accordion.header.component.ts","../../../projects/hx-ui/src/lib/accordion/accordion.module.ts","../../../projects/hx-ui/src/lib/auto-grow/auto-grow.directive.ts","../../../projects/hx-ui/src/lib/auto-grow/auto-grow.module.ts","../../../projects/hx-ui/src/lib/utils/trigger.class.ts","../../../projects/hx-ui/src/lib/utils/triggers.ts","../../../projects/hx-ui/src/lib/component-loader/content-ref.class.ts","../../../projects/hx-ui/src/lib/component-loader/component-loader.class.ts","../../../projects/hx-ui/src/lib/positioning/ng-positioning.ts","../../../projects/hx-ui/src/lib/positioning/positioning.service.ts","../../../projects/hx-ui/src/lib/component-loader/component-loader.factory.ts","../../../projects/hx-ui/src/lib/component-loader/hx-component-ref.class.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker.model.ts","../../../projects/hx-ui/src/lib/text-input/text-input.directive.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker.config.ts","../../../projects/hx-ui/src/lib/tabs/tab.directive.ts","../../../projects/hx-ui/src/lib/tabs/tabset.config.ts","../../../projects/hx-ui/src/lib/tabs/ng-transclude.directive.ts","../../../projects/hx-ui/src/lib/tabs/tabset.component.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker-interval.component.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker-interval.component.html","../../../projects/hx-ui/src/lib/enums.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker.model.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker.component.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker.component.html","../../../projects/hx-ui/src/lib/datepicker/datepicker-form.component.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker-form.component.html","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker-custom/date-range-picker-custom.component.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker-custom/date-range-picker-custom.component.html","../../../projects/hx-ui/src/lib/date-range-picker/interval-option-model.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker-interval/date-range-picker-interval.component.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker-interval/date-range-picker-interval.component.html","../../../projects/hx-ui/src/lib/dropdown/dropdown-menu.directive.ts","../../../projects/hx-ui/src/lib/dropdown/dropdown.config.ts","../../../projects/hx-ui/src/lib/dropdown/dropdown.directive.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker.config.ts","../../../projects/hx-ui/src/lib/dropdown/dropdown-toggle.directive.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker.component.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker.component.html","../../../projects/hx-ui/src/lib/tabs/tab-heading.directive.ts","../../../projects/hx-ui/src/lib/tabs/tabs.module.ts","../../../projects/hx-ui/src/lib/text-input/text-input.module.ts","../../../projects/hx-ui/src/lib/datepicker/datepicker.module.ts","../../../projects/hx-ui/src/lib/dropdown/dropdown-item.directive.ts","../../../projects/hx-ui/src/lib/dropdown/dropdown.module.ts","../../../projects/hx-ui/src/lib/date-range-picker/date-range-picker.module.ts","../../../projects/hx-ui/src/lib/dialog/dialog-overlay.ref.ts","../../../projects/hx-ui/src/lib/dialog/dialog.service.ts","../../../projects/hx-ui/src/lib/dialog/dialog.module.ts","../../../projects/hx-ui/src/lib/empty-state/empty-state.config.ts","../../../projects/hx-ui/src/lib/empty-state/empty-state.component.ts","../../../projects/hx-ui/src/lib/empty-state/empty-state.component.html","../../../projects/hx-ui/src/lib/empty-state/empty-state.module.ts","../../../projects/hx-ui/src/lib/filters/filters-type.enum.ts","../../../projects/hx-ui/src/lib/filters/filters-collapsed.component.ts","../../../projects/hx-ui/src/lib/filters/filters-collapsed.component.html","../../../projects/hx-ui/src/lib/filters/filters.config.ts","../../../projects/hx-ui/src/lib/filters/filters.model.ts","../../../projects/hx-ui/src/lib/filters/filters.component.ts","../../../projects/hx-ui/src/lib/filters/filters.component.html","../../../projects/hx-ui/src/lib/filters/filters.module.ts","../../../projects/hx-ui/src/lib/inspector/inspector-size.enum.ts","../../../projects/hx-ui/src/lib/inspector/inspector-location.enum.ts","../../../projects/hx-ui/src/lib/inspector/inspector.component.ts","../../../projects/hx-ui/src/lib/inspector/inspector.component.html","../../../projects/hx-ui/src/lib/inspector/inspector-overlay.ref.ts","../../../projects/hx-ui/src/lib/inspector/inspector.service.ts","../../../projects/hx-ui/src/lib/inspector/inspector.module.ts","../../../projects/hx-ui/src/lib/line-clamp/line-clamp.component.ts","../../../projects/hx-ui/src/lib/line-clamp/line-clamp.module.ts","../../../projects/hx-ui/src/lib/loaders/loaders.component.ts","../../../projects/hx-ui/src/lib/loaders/loaders.component.html","../../../projects/hx-ui/src/lib/loaders/loaders.module.ts","../../../projects/hx-ui/src/lib/modal/modal.annotation.ts","../../../projects/hx-ui/src/lib/modal/modal-backdrop.component.ts","../../../projects/hx-ui/src/lib/modal/modal.service.ts","../../../projects/hx-ui/src/lib/modal/modal-placeholder.component.ts","../../../projects/hx-ui/src/lib/modal/modal.module.ts","../../../projects/hx-ui/src/lib/pagination/pagination.config.ts","../../../projects/hx-ui/src/lib/pagination/pager.component.ts","../../../projects/hx-ui/src/lib/pagination/pagination.component.ts","../../../projects/hx-ui/src/lib/pagination/pagination.module.ts","../../../projects/hx-ui/src/lib/tooltip/tooltip-content.component.ts","../../../projects/hx-ui/src/lib/tooltip/tooltip-dynamic-content.directive.ts","../../../projects/hx-ui/src/lib/tooltip/tooltip.config.ts","../../../projects/hx-ui/src/lib/tooltip/tooltip.directive.ts","../../../projects/hx-ui/src/lib/tooltip/tooltip.module.ts","../../../projects/hx-ui/src/lib/utils/pipes/simple-search.pipe.ts","../../../projects/hx-ui/src/lib/tabular/tabular-content.service.ts","../../../projects/hx-ui/src/lib/tabular/tabular-column.interface.ts","../../../projects/hx-ui/src/lib/tabular/tabular-sort-by.service.ts","../../../projects/hx-ui/src/lib/tabular/tabular-config.interface.ts","../../../projects/hx-ui/src/lib/tabular/actions-config.interface.ts","../../../projects/hx-ui/src/lib/tabular/tabular-size.enum.ts","../../../projects/hx-ui/src/lib/tabular/tabular.config.ts","../../../projects/hx-ui/src/lib/tabular/tabular-theme.enum.ts","../../../projects/hx-ui/src/lib/tabular/tabular.component.ts","../../../projects/hx-ui/src/lib/tabular/tabular.component.html","../../../projects/hx-ui/src/lib/tabular/tabular.module.ts","../../../projects/hx-ui/src/lib/utils/util.ts","../../../projects/hx-ui/src/lib/time-picker/hxa-time.ts","../../../projects/hx-ui/src/lib/time-picker/hxa-time-adapter.ts","../../../projects/hx-ui/src/lib/time-picker/timepicker-config.ts","../../../projects/hx-ui/src/lib/time-picker/timepicker-i18n.ts","../../../projects/hx-ui/src/lib/time-picker/timepicker.ts","../../../projects/hx-ui/src/lib/time-picker/timepicker.module.ts","../../../projects/hx-ui/src/lib/toastr/hxa-toastr.component.ts","../../../projects/hx-ui/src/lib/toastr/hxa-toastr.module.ts","../../../projects/hx-ui/src/lib/typeahead/latin-map.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead-utils.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead-container.component.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead-match.class.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead.directive.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead-highlight.component.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead.module.ts","../../../projects/hx-ui/src/lib/utils/services/online-status.service.ts","../../../projects/hx-ui/src/lib/hx-ui.module.ts","../../../projects/hx-ui/src/lib/positioning/positioning.options.ts","../../../projects/hx-ui/src/lib/tabular/tabular-column.model.ts","../../../projects/hx-ui/src/lib/typeahead/typeahead-options.class.ts","../../../projects/hx-ui/src/lib/utils/decorators.ts","../../../projects/hx-ui/src/lib/utils/facade/browser.ts","../../../projects/hx-ui/src/lib/utils/linked-list.class.ts","../../../projects/hx-ui/src/lib/utils/utils.class.ts","../../../projects/hx-ui/src/public_api.ts","../../../projects/hx-ui/src/hxui-angular.ts"],"sourcesContent":["import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'hx-accordion-body, hxa-accordion-body',\r\n template: `<ng-content></ng-content>`\r\n})\r\nexport class AccordionBodyComponent {}\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'hx-accordion, hxa-accordion',\r\n template: `\r\n <div class=\"hxui-reset\">\r\n <ul class=\"hx-accordion\" [ngClass]=\"cssClass\">\r\n <ng-content></ng-content>\r\n </ul>\r\n </div>\r\n `\r\n})\r\nexport class AccordionComponent {\r\n @Input() cssClass?: string = null;\r\n}\r\n","import {\r\n animate,\r\n state,\r\n style,\r\n transition,\r\n trigger\r\n} from '@angular/animations';\r\nimport {\r\n ChangeDetectorRef,\r\n Component,\r\n EventEmitter,\r\n Input,\r\n Output\r\n} from '@angular/core';\r\n\r\n/**\r\n * TODO: !BREAKING! align accordion markup for accessibility,\r\n * consider using attribute selector\r\n * @see {@link https://www.w3.org/TR/wai-aria-practices/#accordion}\r\n * @see {@link https://medium.com/javascript-everyday/when-to-use-an-attribute-selector-for-angular-components-7e788ba1bfe7}\r\n */\r\n@Component({\r\n selector: 'hx-accordion-container, hxa-accordion-container',\r\n template: `\r\n <li\r\n class=\"hx-accordion-container\"\r\n [class.is-active]=\"expanded && !disabled\"\r\n >\r\n <a\r\n class=\"hx-accordion-header\"\r\n [class.is-disabled]=\"!empty && disabled\"\r\n (click)=\"toggle()\"\r\n >\r\n <div class=\"header-title\">\r\n <ng-content\r\n select=\"hx-accordion-header, hxa-accordion-header\"\r\n ></ng-content>\r\n </div>\r\n <div class=\"header-icon\" *ngIf=\"empty\">\r\n <i class=\"hx-icon icon-angle-down\" *ngIf=\"!expanded || disabled\"></i>\r\n <i class=\"hx-icon icon-angle-up\" *ngIf=\"expanded && !disabled\"></i>\r\n </div>\r\n </a>\r\n <div\r\n class=\"hx-accordion-body\"\r\n [@slideIn]=\"expanded && !disabled\"\r\n *ngIf=\"expanded && !disabled\"\r\n >\r\n <div class=\"hx-accordion-body-wrapper\">\r\n <ng-content\r\n select=\"hx-accordion-body, hxa-accordion-body\"\r\n ></ng-content>\r\n </div>\r\n </div>\r\n </li>\r\n `,\r\n styleUrls: ['./accordian.container.scss'],\r\n animations: [\r\n trigger('slideIn', [\r\n state('*', style({ 'overflow-y': 'hidden' })),\r\n state('void', style({ 'overflow-y': 'hidden' })),\r\n transition('* => void', [\r\n style({ height: '*' }),\r\n animate('0.25s ease-out', style({ height: 0, opacity: 0 }))\r\n ]),\r\n transition('void => *', [\r\n style({ height: '0' }),\r\n animate('0.25s ease-out', style({ height: '*', opacity: 1 }))\r\n ])\r\n ])\r\n ]\r\n})\r\nexport class AccordionContainerComponent {\r\n @Input() expanded = true;\r\n @Input() index: number = null;\r\n @Input() disabled = false;\r\n @Input() empty = true;\r\n @Output() headerClick: EventEmitter<number> = new EventEmitter<number>();\r\n\r\n constructor(private _changeDetectionRef: ChangeDetectorRef) {}\r\n\r\n public toggle(): void {\r\n if (this.index !== null) {\r\n this.headerClick.emit(this.index);\r\n }\r\n this.expanded = !this.expanded;\r\n this._changeDetectionRef.markForCheck();\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'hx-accordion-header, hxa-accordion-header',\r\n template: `<ng-content></ng-content>`\r\n})\r\nexport class AccordionHeaderComponent {}\r\n","import { CommonModule } from '@angular/common';\r\nimport { NgModule } from '@angular/core';\r\nimport { AccordionBodyComponent } from './accordion.body';\r\nimport { AccordionComponent } from './accordion.component';\r\nimport { AccordionContainerComponent } from './accordion.container.component';\r\nimport { AccordionHeaderComponent } from './accordion.header.component';\r\n\r\n@NgModule({\r\n imports: [CommonModule],\r\n declarations: [\r\n AccordionComponent,\r\n AccordionContainerComponent,\r\n AccordionHeaderComponent,\r\n AccordionBodyComponent\r\n ],\r\n exports: [\r\n AccordionComponent,\r\n AccordionContainerComponent,\r\n AccordionHeaderComponent,\r\n AccordionBodyComponent\r\n ]\r\n})\r\nexport class AccordionModule {}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n HostListener,\r\n AfterViewInit\r\n} from '@angular/core';\r\n\r\n@Directive({\r\n selector: 'textarea[autogrow]'\r\n})\r\nexport class AutoGrowDirective\r\n implements AfterViewInit {\r\n\r\n @HostListener('input', ['$event.target'])\r\n public onInput() {\r\n this.resize();\r\n }\r\n\r\n constructor(public element: ElementRef) {}\r\n\r\n public ngAfterViewInit() {\r\n const style = this.element.nativeElement.style;\r\n style.overflow = 'hidden';\r\n style.height = 'auto';\r\n }\r\n\r\n public resize() {\r\n const el = this.element.nativeElement;\r\n\r\n if (el.style.height === el.scrollHeight + 'px') {\r\n return;\r\n }\r\n\r\n el.style.overflow = 'hidden';\r\n el.style.height = 'auto';\r\n el.style.height = `${el.scrollHeight}px`;\r\n }\r\n}\r\n","import { ModuleWithProviders, NgModule } from '@angular/core';\r\nimport { AutoGrowDirective } from './auto-grow.directive';\r\n\r\n@NgModule({\r\n declarations: [AutoGrowDirective],\r\n exports: [AutoGrowDirective]\r\n})\r\nexport class AutoGrowModule {\r\n public static forRoot(): ModuleWithProviders<AutoGrowModule> {\r\n return {\r\n ngModule: AutoGrowModule,\r\n providers: []\r\n };\r\n }\r\n}\r\n","/**\r\n * @copyright Valor Software\r\n * @copyright Angular ng-bootstrap team\r\n */\r\n\r\nexport class Trigger {\r\n public open: string;\r\n public close?: string;\r\n\r\n public constructor(open: string, close?: string) {\r\n this.open = open;\r\n this.close = close || open;\r\n }\r\n\r\n public isManual(): boolean { return this.open === 'manual' || this.close === 'manual'; }\r\n}\r\n","\r\nimport { Renderer2 } from '@angular/core';\r\nimport { Trigger } from './trigger.class';\r\n\r\nconst DEFAULT_ALIASES = {\r\n hover: ['mouseenter', 'mouseleave'],\r\n focus: ['focusin', 'focusout']\r\n};\r\n\r\nexport function parseTriggers(triggers: string, aliases: any = DEFAULT_ALIASES): Trigger[] {\r\n const trimmedTriggers = (triggers || '').trim();\r\n\r\n if (trimmedTriggers.length === 0) {\r\n return [];\r\n }\r\n\r\n const parsedTriggers = trimmedTriggers.split(/\\s+/)\r\n .map((trigger: string) => trigger.split(':'))\r\n .map((triggerPair: string[]) => {\r\n const alias = aliases[triggerPair[0]] || triggerPair;\r\n return new Trigger(alias[0], alias[1]);\r\n });\r\n\r\n const manualTriggers = parsedTriggers\r\n .filter((triggerPair: Trigger) => triggerPair.isManual());\r\n\r\n if (manualTriggers.length > 1) {\r\n throw new Error('Triggers parse error: only one manual trigger is allowed');\r\n }\r\n\r\n if (manualTriggers.length === 1 && parsedTriggers.length > 1) {\r\n throw new Error('Triggers parse error: manual trigger can\\'t be mixed with other triggers');\r\n }\r\n\r\n return parsedTriggers;\r\n}\r\n\r\nexport function listenToTriggers(renderer: Renderer2, target: any, triggers: any,\r\n showFn: (event: any) => boolean | void, hideFn: (event: any) => boolean | void, toggleFn: (event: any) => boolean | void): Function {\r\n const parsedTriggers = parseTriggers(triggers);\r\n const listeners: any[] = [];\r\n\r\n if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {\r\n return Function.prototype;\r\n }\r\n\r\n parsedTriggers.forEach((trigger: Trigger) => {\r\n if (trigger.open === trigger.close) {\r\n listeners.push(renderer.listen(target, trigger.open, toggleFn));\r\n return;\r\n }\r\n\r\n listeners.push(\r\n renderer.listen(target, <any>trigger.open, showFn),\r\n renderer.listen(target, <any>trigger.close, hideFn));\r\n });\r\n\r\n return () => { listeners.forEach((unsubscribeFn: Function) => <any>unsubscribeFn()); };\r\n}\r\n","\r\nimport { ComponentRef, ViewRef } from '@angular/core';\r\n\r\nexport class ContentRef {\r\n public nodes: any[];\r\n public viewRef?: ViewRef;\r\n public componentRef?: ComponentRef<any>;\r\n\r\n public constructor( nodes: any[], viewRef?: ViewRef, componentRef?: ComponentRef<any>) {\r\n this.nodes = nodes;\r\n this.viewRef = viewRef;\r\n this.componentRef = componentRef;\r\n }\r\n}\r\n","// todo: add delay support\r\n// todo: merge events onShow, onShown, etc...\r\n// todo: add global positioning configuration?\r\nimport {\r\n ComponentFactory,\r\n ComponentFactoryResolver,\r\n ComponentRef,\r\n ElementRef,\r\n EventEmitter,\r\n Injector,\r\n NgZone,\r\n Provider,\r\n ReflectiveInjector,\r\n Renderer2,\r\n TemplateRef,\r\n Type,\r\n ViewContainerRef\r\n} from '@angular/core';\r\nimport { PositioningOptions } from '../positioning/positioning.options';\r\nimport { PositioningService } from '../positioning/positioning.service';\r\nimport { listenToTriggers } from '../utils/triggers';\r\nimport { ContentRef } from './content-ref.class';\r\n\r\nexport interface ListenOptions {\r\n target?: ElementRef;\r\n triggers?: string;\r\n show?: any;\r\n hide?: any;\r\n toggle?: any;\r\n}\r\n\r\nexport class ComponentLoader<T> {\r\n public onBeforeShow: EventEmitter<any> = new EventEmitter();\r\n public onShown: EventEmitter<any> = new EventEmitter();\r\n public onBeforeHide: EventEmitter<any> = new EventEmitter();\r\n public onHidden: EventEmitter<any> = new EventEmitter();\r\n\r\n public instance: T;\r\n public _componentRef: ComponentRef<T>;\r\n\r\n private _providers: Provider[] = [];\r\n private _componentFactory: ComponentFactory<T>;\r\n private _elementRef: ElementRef;\r\n private _zoneSubscription: any;\r\n private _contentRef: ContentRef;\r\n private _viewContainerRef: ViewContainerRef;\r\n private _injector: Injector;\r\n private _renderer: Renderer2;\r\n private _ngZone: NgZone;\r\n private _componentFactoryResolver: ComponentFactoryResolver;\r\n private _posService: PositioningService;\r\n\r\n // eslint-disable-next-line @typescript-eslint/ban-types\r\n private _unregisterListenersFn: Function;\r\n\r\n public get isShown(): boolean {\r\n return !!this._componentRef;\r\n }\r\n\r\n /**\r\n * Placement of a component. Accepts: \"top\", \"bottom\", \"left\", \"right\"\r\n */\r\n private attachment: string;\r\n\r\n /**\r\n * A selector specifying the element the popover should be appended to.\r\n * Currently only supports \"body\".\r\n */\r\n private container: string | ElementRef | any;\r\n\r\n /**\r\n * Specifies events that should trigger. Supports a space separated list of\r\n * event names.\r\n */\r\n private triggers: string;\r\n\r\n /**\r\n * Do not use this directly, it should be instanced via\r\n * `ComponentLoadFactory.attach`\r\n * @internal\r\n * @param _viewContainerRef\r\n * @param _elementRef\r\n * @param _injector\r\n * @param _renderer\r\n * @param _componentFactoryResolver\r\n * @param _ngZone\r\n * @param _posService\r\n */\r\n // eslint-disable-next-line\r\n public constructor(\r\n _viewContainerRef: ViewContainerRef,\r\n _renderer: Renderer2,\r\n _elementRef: ElementRef,\r\n _injector: Injector,\r\n _componentFactoryResolver: ComponentFactoryResolver,\r\n _ngZone: NgZone,\r\n _posService: PositioningService\r\n ) {\r\n this._ngZone = _ngZone;\r\n this._injector = _injector;\r\n this._renderer = _renderer;\r\n this._elementRef = _elementRef;\r\n this._posService = _posService;\r\n this._viewContainerRef = _viewContainerRef;\r\n this._componentFactoryResolver = _componentFactoryResolver;\r\n }\r\n\r\n public attach(compType: Type<T>): ComponentLoader<T> {\r\n this._componentFactory =\r\n this._componentFactoryResolver.resolveComponentFactory<T>(compType);\r\n return this;\r\n }\r\n\r\n // todo: add behaviour: to target element, `body`, custom element\r\n public to(container?: string): ComponentLoader<T> {\r\n this.container = container || this.container;\r\n return this;\r\n }\r\n\r\n public position(opts?: PositioningOptions): ComponentLoader<T> {\r\n this.attachment = opts.attachment || this.attachment;\r\n this._elementRef = (opts.target as ElementRef) || this._elementRef;\r\n return this;\r\n }\r\n\r\n public provide(provider: Provider): ComponentLoader<T> {\r\n this._providers.push(provider);\r\n return this;\r\n }\r\n\r\n public show(\r\n opts: { content?: string | TemplateRef<any>; [key: string]: any } = {}\r\n ): ComponentRef<T> {\r\n this._subscribePositioning();\r\n\r\n if (!this._componentRef) {\r\n this.onBeforeShow.emit();\r\n this._contentRef = this._getContentRef(opts.content);\r\n const injector = ReflectiveInjector.resolveAndCreate(\r\n this._providers,\r\n this._injector\r\n );\r\n this._componentRef = this._viewContainerRef.createComponent(\r\n this._componentFactory,\r\n 0,\r\n injector,\r\n this._contentRef.nodes\r\n );\r\n this.instance = this._componentRef.instance;\r\n\r\n Object.assign(this._componentRef.instance, opts);\r\n\r\n if (this.container === 'body' && typeof document !== 'undefined') {\r\n document\r\n .querySelector(this.container as string)\r\n .appendChild(this._componentRef.location.nativeElement);\r\n }\r\n\r\n // we need to manually invoke change detection since events registered\r\n // via\r\n // Renderer::listen() are not picked up by change detection with the\r\n // OnPush strategy\r\n this._componentRef.changeDetectorRef.markForCheck();\r\n this.onShown.emit(this._componentRef.instance);\r\n }\r\n return this._componentRef;\r\n }\r\n\r\n public hide(): ComponentLoader<T> {\r\n if (this._componentRef) {\r\n this.onBeforeHide.emit(this._componentRef.instance);\r\n this._viewContainerRef.remove(\r\n this._viewContainerRef.indexOf(this._componentRef.hostView)\r\n );\r\n this._componentRef = null;\r\n\r\n if (this._contentRef.viewRef) {\r\n this._viewContainerRef.remove(\r\n this._viewContainerRef.indexOf(this._contentRef.viewRef)\r\n );\r\n this._contentRef = null;\r\n }\r\n\r\n this._componentRef = null;\r\n this.onHidden.emit();\r\n }\r\n return this;\r\n }\r\n\r\n public toggle(): void {\r\n if (this.isShown) {\r\n this.hide();\r\n return;\r\n }\r\n\r\n this.show();\r\n }\r\n\r\n public dispose(): void {\r\n if (this.isShown) {\r\n this.hide();\r\n }\r\n\r\n this._unsubscribePositioning();\r\n\r\n if (this._unregisterListenersFn) {\r\n this._unregisterListenersFn();\r\n }\r\n }\r\n\r\n public listen(listenOpts: ListenOptions): ComponentLoader<T> {\r\n this.triggers = listenOpts.triggers || this.triggers;\r\n\r\n listenOpts.target = listenOpts.target || this._elementRef;\r\n listenOpts.show = listenOpts.show || (() => this.show());\r\n listenOpts.hide = listenOpts.hide || (() => this.hide());\r\n listenOpts.toggle =\r\n listenOpts.toggle ||\r\n (() => (this.isShown ? listenOpts.hide() : listenOpts.show()));\r\n\r\n this._unregisterListenersFn = listenToTriggers(\r\n this._renderer,\r\n listenOpts.target.nativeElement,\r\n this.triggers,\r\n listenOpts.show,\r\n listenOpts.hide,\r\n listenOpts.toggle\r\n );\r\n\r\n return this;\r\n }\r\n\r\n private _subscribePositioning(): void {\r\n if (this._zoneSubscription || !this.attachment) {\r\n return;\r\n }\r\n\r\n this._zoneSubscription = this._ngZone.onStable.subscribe(() => {\r\n if (!this._componentRef) {\r\n return;\r\n }\r\n this._posService.position({\r\n element: this._componentRef.location,\r\n target: this._elementRef,\r\n attachment: this.attachment,\r\n appendToBody: this.container === 'body'\r\n });\r\n });\r\n }\r\n\r\n private _unsubscribePositioning(): void {\r\n if (!this._zoneSubscription) {\r\n return;\r\n }\r\n this._zoneSubscription.unsubscribe();\r\n this._zoneSubscription = null;\r\n }\r\n\r\n private _getContentRef(content: string | TemplateRef<any>): ContentRef {\r\n if (!content) {\r\n return new ContentRef([]);\r\n }\r\n\r\n if (content instanceof TemplateRef) {\r\n const viewRef =\r\n this._viewContainerRef.createEmbeddedView<TemplateRef<T>>(content);\r\n return new ContentRef([viewRef.rootNodes], viewRef);\r\n }\r\n\r\n return new ContentRef([[this._renderer.createText(`${content}`)]]);\r\n }\r\n}\r\n","/**\r\n * @copyright Valor Software\r\n * @copyright Angular ng-bootstrap team\r\n */\r\n\r\n// previous version:\r\n// https://github.com/angular-ui/bootstrap/blob/07c31d0731f7cb068a1932b8e01d2312b796b4ec/src/position/position.js\r\n\r\nexport class Positioning {\r\n public position(element: HTMLElement, round = true): Record<string, number> {\r\n let elPosition: Record<string, number>;\r\n let parentOffset: Record<string, number> = {\r\n width: 0,\r\n height: 0,\r\n top: 0,\r\n bottom: 0,\r\n left: 0,\r\n right: 0\r\n };\r\n\r\n if (this.getStyle(element, 'position') === 'fixed') {\r\n const tempPos = element.getBoundingClientRect() as unknown;\r\n elPosition = tempPos as Record<string, number>;\r\n } else {\r\n const offsetParentEl = this.offsetParent(element);\r\n\r\n elPosition = this.offset(element, false);\r\n\r\n if (offsetParentEl !== document.documentElement) {\r\n parentOffset = this.offset(offsetParentEl, false);\r\n }\r\n\r\n parentOffset.top += offsetParentEl.clientTop;\r\n parentOffset.left += offsetParentEl.clientLeft;\r\n }\r\n\r\n elPosition.top -= parentOffset.top;\r\n elPosition.bottom -= parentOffset.top;\r\n elPosition.left -= parentOffset.left;\r\n elPosition.right -= parentOffset.left;\r\n\r\n if (round) {\r\n elPosition.top = Math.round(elPosition.top);\r\n elPosition.bottom = Math.round(elPosition.bottom);\r\n elPosition.left = Math.round(elPosition.left);\r\n elPosition.right = Math.round(elPosition.right);\r\n }\r\n\r\n return elPosition;\r\n }\r\n\r\n public offset(element: HTMLElement, round = true): Record<string, number> {\r\n const elBcr = element.getBoundingClientRect();\r\n const viewportOffset = {\r\n top: window.pageYOffset - document.documentElement.clientTop,\r\n left: window.pageXOffset - document.documentElement.clientLeft\r\n };\r\n\r\n const elOffset = {\r\n height: elBcr.height || element.offsetHeight,\r\n width: elBcr.width || element.offsetWidth,\r\n top: elBcr.top + viewportOffset.top,\r\n bottom: elBcr.bottom + viewportOffset.top,\r\n left: elBcr.left + viewportOffset.left,\r\n right: elBcr.right + viewportOffset.left\r\n };\r\n\r\n if (round) {\r\n elOffset.height = Math.round(elOffset.height);\r\n elOffset.width = Math.round(elOffset.width);\r\n elOffset.top = Math.round(elOffset.top);\r\n elOffset.bottom = Math.round(elOffset.bottom);\r\n elOffset.left = Math.round(elOffset.left);\r\n elOffset.right = Math.round(elOffset.right);\r\n }\r\n\r\n return elOffset;\r\n }\r\n\r\n public positionElements(\r\n hostElement: HTMLElement,\r\n targetElement: HTMLElement,\r\n placement: string,\r\n appendToBody?: boolean\r\n ): Record<string, number> {\r\n const hostElPosition = appendToBody\r\n ? this.offset(hostElement, false)\r\n : this.position(hostElement, false);\r\n const shiftWidth: any = {\r\n left: hostElPosition.left,\r\n center:\r\n hostElPosition.left +\r\n hostElPosition.width / 2 -\r\n targetElement.offsetWidth / 2,\r\n right: hostElPosition.left + hostElPosition.width\r\n };\r\n const shiftHeight: any = {\r\n top: hostElPosition.top,\r\n center:\r\n hostElPosition.top +\r\n hostElPosition.height / 2 -\r\n targetElement.offsetHeight / 2,\r\n bottom: hostElPosition.top + hostElPosition.height\r\n };\r\n const targetElBCR = targetElement.getBoundingClientRect();\r\n const placementPrimary = placement.split(' ')[0] || 'top';\r\n const placementSecondary = placement.split(' ')[1] || 'center';\r\n\r\n const targetElPosition: Record<string, number> = {\r\n height: targetElBCR.height || targetElement.offsetHeight,\r\n width: targetElBCR.width || targetElement.offsetWidth,\r\n top: 0,\r\n bottom: targetElBCR.height || targetElement.offsetHeight,\r\n left: 0,\r\n right: targetElBCR.width || targetElement.offsetWidth\r\n };\r\n\r\n switch (placementPrimary) {\r\n case 'top':\r\n targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;\r\n targetElPosition.bottom +=\r\n hostElPosition.top - targetElement.offsetHeight;\r\n targetElPosition.left = shiftWidth[placementSecondary];\r\n targetElPosition.right += shiftWidth[placementSecondary];\r\n break;\r\n case 'bottom':\r\n targetElPosition.top = shiftHeight[placementPrimary];\r\n targetElPosition.bottom += shiftHeight[placementPrimary];\r\n targetElPosition.left = shiftWidth[placementSecondary];\r\n targetElPosition.right += shiftWidth[placementSecondary];\r\n break;\r\n case 'left':\r\n targetElPosition.top = shiftHeight[placementSecondary];\r\n targetElPosition.bottom += shiftHeight[placementSecondary];\r\n targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;\r\n targetElPosition.right +=\r\n hostElPosition.left - targetElement.offsetWidth;\r\n break;\r\n case 'right':\r\n targetElPosition.top = shiftHeight[placementSecondary];\r\n targetElPosition.bottom += shiftHeight[placementSecondary];\r\n targetElPosition.left = shiftWidth[placementPrimary];\r\n targetElPosition.right += shiftWidth[placementPrimary];\r\n break;\r\n }\r\n\r\n targetElPosition.top = Math.round(targetElPosition.top);\r\n targetElPosition.bottom = Math.round(targetElPosition.bottom);\r\n targetElPosition.left = Math.round(targetElPosition.left);\r\n targetElPosition.right = Math.round(targetElPosition.right);\r\n\r\n return targetElPosition;\r\n }\r\n\r\n private getStyle(element: HTMLElement, prop: string): string {\r\n return (window.getComputedStyle(element) as any)[prop];\r\n }\r\n\r\n private isStaticPositioned(element: HTMLElement): boolean {\r\n return (this.getStyle(element, 'position') || 'static') === 'static';\r\n }\r\n\r\n private offsetParent(element: HTMLElement): HTMLElement {\r\n let offsetParentEl =\r\n <HTMLElement>element.offsetParent || document.documentElement;\r\n\r\n while (\r\n offsetParentEl &&\r\n offsetParentEl !== document.documentElement &&\r\n this.isStaticPositioned(offsetParentEl)\r\n ) {\r\n offsetParentEl = <HTMLElement>offsetParentEl.offsetParent;\r\n }\r\n\r\n return offsetParentEl || document.documentElement;\r\n }\r\n}\r\n\r\nconst positionService = new Positioning();\r\n\r\nexport function positionElements(\r\n hostElement: HTMLElement,\r\n targetElement: HTMLElement,\r\n placement: string,\r\n appendToBody?: boolean\r\n): void {\r\n const pos = positionService.positionElements(\r\n hostElement,\r\n targetElement,\r\n placement,\r\n appendToBody\r\n );\r\n\r\n targetElement.style.top = `${pos.top}px`;\r\n targetElement.style.left = `${pos.left}px`;\r\n}\r\n","import { Injectable, ElementRef } from '@angular/core';\r\nimport { positionElements } from './ng-positioning';\r\nimport {PositioningOptions} from './positioning.options';\r\n\r\n\r\n@Injectable()\r\nexport class PositioningService {\r\n public position(options: PositioningOptions): void {\r\n const {element, target, attachment, appendToBody} = options;\r\n positionElements(\r\n this._getHtmlElement(target),\r\n this._getHtmlElement(element),\r\n <any>attachment,\r\n appendToBody);\r\n }\r\n\r\n public isElementBelowTheFold(element: HTMLElement): boolean {\r\n const rect = element.getBoundingClientRect();\r\n return ((rect.top + rect.height) > document.body.clientHeight) ;\r\n }\r\n\r\n private _getHtmlElement(element: any): HTMLElement {\r\n // it means that we got a selector\r\n if (typeof element === 'string') {\r\n return document.querySelector(element) as HTMLElement;\r\n }\r\n\r\n if (element instanceof ElementRef) {\r\n return element.nativeElement;\r\n }\r\n\r\n return element as HTMLElement;\r\n }\r\n}\r\n","import {\r\n Injectable, NgZone, ViewContainerRef, ComponentFactoryResolver, Injector,\r\n Renderer2, ElementRef\r\n} from '@angular/core';\r\nimport { ComponentLoader } from './component-loader.class';\r\nimport { PositioningService } from '../positioning/positioning.service';\r\n\r\n@Injectable()\r\nexport class ComponentLoaderFactory {\r\n private _componentFactoryResolver: ComponentFactoryResolver;\r\n private _ngZone: NgZone;\r\n private _injector: Injector;\r\n private _posService: PositioningService;\r\n\r\n public constructor(componentFactoryResolver: ComponentFactoryResolver, ngZone: NgZone,\r\n injector: Injector, posService: PositioningService) {\r\n this._ngZone = ngZone;\r\n this._injector = injector;\r\n this._posService = posService;\r\n this._componentFactoryResolver = componentFactoryResolver;\r\n }\r\n\r\n public createLoader<T>(_elementRef: ElementRef, _viewContainerRef: ViewContainerRef, _renderer: Renderer2): ComponentLoader<T> {\r\n return new ComponentLoader<T>(_viewContainerRef, _renderer, _elementRef,\r\n this._injector, this._componentFactoryResolver, this._ngZone, this._posService);\r\n }\r\n}\r\n","import { TemplateRef, ViewContainerRef } from '@angular/core';\r\n\r\nexport class HxComponentRef<T> {\r\n templateRef: TemplateRef<T>;\r\n viewContainer: ViewContainerRef;\r\n}\r\n","export enum DisplayMode {\r\n showTab = 1,\r\n showCustomOnly,\r\n showIntervalOnly\r\n}\r\n\r\nexport interface DateRange {\r\n fromDate: Date;\r\n toDate: Date;\r\n}\r\n\r\n//expanded when more tabs be added\r\nexport enum DateSelectionType {\r\n interval,\r\n custom\r\n}\r\n","import {Directive, HostListener, ElementRef, HostBinding} from '@angular/core';\r\n\r\n@Directive({\r\n selector: '[hxaTextInput]'\r\n})\r\nexport class TextInputDirective {\r\n\r\n @HostBinding('class.has-label-placeholder') isPlaceholder: boolean;\r\n @HostBinding('class.has-label-floating') isLabel: boolean;\r\n\r\n constructor(private el: ElementRef) {\r\n this.styleLabel();\r\n }\r\n\r\n @HostListener('focus')\r\n onFocus() {\r\n this.styleLabelAsFloating();\r\n }\r\n\r\n @HostListener('blur')\r\n onBlur() {\r\n this.styleLabel();\r\n }\r\n\r\n styleLabel(floatingLabel?: boolean) {\r\n // If the element is empty, style the label like a placeholder otherwise float the label above the input\r\n if (!floatingLabel && this.el.nativeElement.value.trim().length === 0 && this.el.nativeElement.placeholder.trim().length === 0 ) {\r\n this.styleLabelAsPlaceholder();\r\n } else {\r\n this.styleLabelAsFloating();\r\n }\r\n }\r\n\r\n styleLabelAsPlaceholder() {\r\n this.isPlaceholder = true;\r\n this.isLabel = false;\r\n }\r\n\r\n styleLabelAsFloating() {\r\n this.isPlaceholder = false;\r\n this.isLabel = true;\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n/** Default values provider for calendar */\r\n@Injectable()\r\nexport class DatepickerConfig {\r\n /** dropdown overlay placement */\r\n public placement: 'top' | 'bottom' | 'left' | 'right' = 'bottom';\r\n /** delay in ms before showing the calendar after show is called */\r\n public showDelay = 0;\r\n /** delay in ms before hiding the calendar after hide is called */\r\n public hideDelay = 0;\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n EventEmitter,\r\n HostBinding,\r\n Input,\r\n OnDestroy,\r\n Output,\r\n TemplateRef,\r\n} from '@angular/core';\r\nimport { TabsetComponent } from './tabset.component';\r\n\r\n// eslint-disable-next-line @angular-eslint/directive-selector\r\n@Directive({ selector: 'hx-tab, [hx-tab]' })\r\nexport class TabDirective implements OnDestroy {\r\n /** tab header text */\r\n @Input() heading: string;\r\n /** tab id */\r\n @Input() id: string;\r\n /** if true tab can not be activated */\r\n @Input() disabled: boolean;\r\n /** if true tab can be removable, additional button will appear */\r\n @Input() removable: boolean;\r\n /** if set, will be added to the tab's class atribute */\r\n @Input() customClass: string;\r\n\r\n @Input()\r\n get active(): boolean {\r\n return this._active;\r\n }\r\n\r\n set active(active: boolean) {\r\n if ((this.disabled && active) || !active) {\r\n if (!active) {\r\n this._active = active;\r\n }\r\n\r\n this.deselect.emit(this);\r\n return;\r\n }\r\n\r\n this._active = active;\r\n this.select.emit(this);\r\n }\r\n\r\n /** tab active state toggle */\r\n @HostBinding('class.is-active')\r\n get _() {\r\n return !!this._active;\r\n }\r\n\r\n /** fired when tab became active, $event:Tab equals to selected instance of Tab component */\r\n // TODO: change output name\r\n // eslint-disable-next-line @angular-eslint/no-output-native\r\n @Output() public select: EventEmitter<TabDirective> = new EventEmitter();\r\n /** fired when tab became inactive, $event:Tab equals to deselected instance of Tab component */\r\n @Output() public deselect: EventEmitter<TabDirective> = new EventEmitter();\r\n /** fired before tab will be removed, $event:Tab equals to instance of removed tab */\r\n @Output() public removed: EventEmitter<TabDirective> = new EventEmitter();\r\n\r\n @HostBinding('class.hx-tab-pane') addClasn = true;\r\n\r\n headingRef: TemplateRef<any>;\r\n tabset: TabsetComponent;\r\n protected _active: boolean;\r\n\r\n // TODO: refactor so that ref to parent 'TabsetComponent' is removed, causing circular refs\r\n constructor(tabset: TabsetComponent, public elementRef: ElementRef) {\r\n this.tabset = tabset;\r\n this.tabset.addTab(this);\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.tabset.removeTab(this, { reselect: false, emit: false });\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n@Injectable()\r\nexport class TabsetConfig {\r\n /** provides default navigation context class */\r\n public type: 'tabs' | 'pills' = 'tabs';\r\n}\r\n","import {\r\n Directive, Input, TemplateRef, ViewContainerRef\r\n} from '@angular/core';\r\n\r\n@Directive({\r\n selector: '[ngTransclude]'\r\n})\r\nexport class NgTranscludeDirective {\r\n public viewRef: ViewContainerRef;\r\n\r\n protected _viewRef: ViewContainerRef;\r\n protected _ngTransclude: TemplateRef<any>;\r\n\r\n @Input()\r\n public set ngTransclude(templateRef: TemplateRef<any>) {\r\n this._ngTransclude = templateRef;\r\n if (templateRef) {\r\n this.viewRef.createEmbeddedView(templateRef);\r\n }\r\n }\r\n\r\n public get ngTransclude(): TemplateRef<any> {\r\n return this._ngTransclude;\r\n }\r\n\r\n public constructor(viewRef: ViewContainerRef) {\r\n this.viewRef = viewRef;\r\n }\r\n}\r\n","import {\r\n AfterContentInit,\r\n Component,\r\n ContentChildren,\r\n forwardRef,\r\n Input,\r\n OnDestroy,\r\n QueryList,\r\n} from '@angular/core';\r\nimport { TabDirective } from './tab.directive';\r\nimport { TabsetConfig } from './tabset.config';\r\n\r\n@Component({\r\n selector: 'hx-tabset',\r\n host: {\r\n class: 'hx-tab-container',\r\n },\r\n template: `\r\n <ul\r\n class=\"hx-nav hx-nav-{{ type }}\"\r\n [ngStyle]=\"{\r\n position: getStickyHeaderPosition(),\r\n 'top.rem': stickyHeaderOffset\r\n }\"\r\n [class.is-vertical]=\"vertical\"\r\n [class.is-justified]=\"justified\"\r\n [class.has-info]=\"hasInfo\"\r\n >\r\n <li\r\n *ngFor=\"let tab of tabs\"\r\n [ngClass]=\"['hx-nav-item', tab.customClass || '']\"\r\n [class.is-active]=\"!!tab?.active\"\r\n [class.is-disabled]=\"!!tab?.disabled\"\r\n [class.is-button]=\"tag === 'button'\"\r\n >\r\n <button\r\n *ngIf=\"tag === 'button'\"\r\n class=\"hx-nav-link\"\r\n [class.is-active]=\"!!tab?.active\"\r\n [class.is-disabled]=\"!!tab?.disabled\"\r\n [attr.disabled]=\"!!tab?.disabled ? '' : null\"\r\n (click)=\"selectTab(tab)\"\r\n >\r\n <span [ngTransclude]=\"tab.headingRef\">{{ tab.heading }}</span>\r\n <span *ngIf=\"tab.removable\">\r\n <span\r\n (click)=\"removeTab(tab)\"\r\n class=\"icon close-outline is-small\"\r\n ></span>\r\n </span>\r\n </button>\r\n <a\r\n *ngIf=\"tag === 'link'\"\r\n class=\"hx-nav-link\"\r\n [class.is-active]=\"!!tab?.active\"\r\n [class.is-disabled]=\"!!tab?.disabled\"\r\n [attr.disabled]=\"!!tab?.disabled ? '' : null\"\r\n (click)=\"selectTab(tab)\"\r\n >\r\n <span [ngTransclude]=\"tab.headingRef\">{{ tab.heading }}</span>\r\n <span *ngIf=\"tab.removable\">\r\n <span\r\n (click)=\"removeTab(tab)\"\r\n class=\"icon close-outline is-small\"\r\n ></span>\r\n </span>\r\n </a>\r\n </li>\r\n </ul>\r\n <div class=\"hx-tab-content {{ contentCustomClass }}\">\r\n <ng-content></ng-content>\r\n </div>\r\n `,\r\n styles: [\r\n `\r\n :host,\r\n ul.hx-nav {\r\n background-color: inherit;\r\n }\r\n\r\n button.hx-nav-link {\r\n border-width: 0;\r\n border-bottom-width: 1px;\r\n border-color: transparent;\r\n background-color: transparent;\r\n line-height: 1.5;\r\n cursor: pointer;\r\n }\r\n\r\n :where(.is-justified) .is-button.hx-nav-item {\r\n display: flex;\r\n }\r\n\r\n :where(.is-justified .is-button) button.hx-nav-link {\r\n display: flex;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class TabsetComponent implements OnDestroy, AfterContentInit {\r\n /** if true tabs will be placed vertically */\r\n @Input() vertical = false;\r\n\r\n /** if true tabs fill the container and have a consistent width */\r\n @Input() justified = false;\r\n\r\n @Input() hasInfo = false;\r\n\r\n /** navigation context class: 'tabs' or 'pills' */\r\n @Input()\r\n get type(): string {\r\n return this._type;\r\n }\r\n set type(value: string) {\r\n this._type = value;\r\n }\r\n\r\n @Input() contentCustomClass: string;\r\n @Input() stickyHeader = false;\r\n @Input() stickyHeaderOffset = 0;\r\n\r\n @Input() tag: 'link' | 'button' = 'link';\r\n\r\n @Input()\r\n changeFn = async () => true;\r\n\r\n @ContentChildren(forwardRef(() => TabDirective))\r\n private _tabList: QueryList<TabDirective>;\r\n\r\n tabs: TabDirective[] = [];\r\n\r\n protected isDestroyed: boolean;\r\n protected _type: string;\r\n\r\n constructor(config: TabsetConfig) {\r\n Object.assign(this, config);\r\n }\r\n\r\n ngAfterContentInit() {\r\n // get all active tabs\r\n const activeTabs = this._tabList.filter(tab => tab.active);\r\n\r\n // if there is no active tab set, activate the first\r\n if (activeTabs.length === 0) {\r\n this._selectTab(this._tabList.last);\r\n }\r\n }\r\n\r\n private _selectTab(tab: TabDirective) {\r\n // deactivate all tabs\r\n this._tabList.toArray().forEach(tab => (tab.active = false));\r\n\r\n // activate the tab the user has clicked on.\r\n tab.active = true;\r\n }\r\n\r\n selectTab(tab: TabDirective) {\r\n this.changeFn().then(res => !!res && this._selectTab(tab));\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.isDestroyed = true;\r\n }\r\n\r\n addTab(tab: TabDirective): void {\r\n this.tabs.push(tab);\r\n tab.active = this.tabs.length === 1 && tab.active !== false;\r\n }\r\n\r\n removeTab(tab: TabDirective, options = { reselect: true, emit: true }): void {\r\n const index = this.tabs.indexOf(tab);\r\n if (index === -1 || this.isDestroyed) {\r\n return;\r\n }\r\n // Select a new tab if the tab to be removed is selected and not destroyed\r\n if (options.reselect && tab.active && this.hasAvailableTabs(index)) {\r\n const newActiveIndex = this.getClosestTabIndex(index);\r\n this.tabs[newActiveIndex].active = true;\r\n }\r\n if (options.emit) {\r\n tab.removed.emit(tab);\r\n }\r\n this.tabs.splice(index, 1);\r\n if (tab.elementRef.nativeElement && tab.elementRef.nativeElement.remove) {\r\n tab.elementRef.nativeElement.remove();\r\n }\r\n }\r\n\r\n getStickyHeaderPosition(): string {\r\n return this.stickyHeader ? 'sticky' : 'relative';\r\n }\r\n\r\n protected getClosestTabIndex(index: number): number {\r\n const tabsLength = this.tabs.length;\r\n if (!tabsLength) {\r\n return -1;\r\n }\r\n\r\n for (let step = 1; step <= tabsLength; step += 1) {\r\n const prevIndex = index - step;\r\n const nextIndex = index + step;\r\n if (this.tabs[prevIndex] && !this.tabs[prevIndex].disabled) {\r\n return prevIndex;\r\n }\r\n if (this.tabs[nextIndex] && !this.tabs[nextIndex].disabled) {\r\n return nextIndex;\r\n }\r\n }\r\n return -1;\r\n }\r\n\r\n protected hasAvailableTabs(index: number): boolean {\r\n const tabsLength = this.tabs.length;\r\n if (!tabsLength) {\r\n return false;\r\n }\r\n\r\n for (let i = 0; i < tabsLength; i += 1) {\r\n if (!this.tabs[i].disabled && i !== index) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n}\r\n","import {\r\n Component,\r\n EventEmitter,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n} from '@angular/core';\r\nimport { FormBuilder, FormGroup, Validators } from '@angular/forms';\r\nimport moment from 'moment';\r\nimport { Subscription } from 'rxjs';\r\nimport { DatePickerInterval } from './datepicker.model';\r\n\r\n@Component({\r\n selector: 'hxa-datepicker-interval',\r\n templateUrl: './datepicker-interval.component.html',\r\n styleUrls: ['./datepicker-interval.component.scss'],\r\n host: {\r\n class: 'hx-card hxa-datepicker-interval',\r\n },\r\n})\r\nexport class DatepickerIntervalComponent implements OnInit, OnDestroy {\r\n durationOptions = ['day', 'week', 'month', 'year'];\r\n duration = 'days';\r\n increment = 0;\r\n text: moment.Moment;\r\n dateLabel: string;\r\n public _dueDatestring: string;\r\n\r\n private value$: Subscription = new Subscription();\r\n form: FormGroup;\r\n\r\n @Input()\r\n selectedDate: Date;\r\n\r\n @Input()\r\n selectedInterval: DatePickerInterval;\r\n\r\n @Output()\r\n update = new EventEmitter<DatePickerInterval & { date: Date }>();\r\n\r\n @Output()\r\n cancel = new EventEmitter<void>();\r\n\r\n constructor(private _fb: FormBuilder) {}\r\n\r\n ngOnInit(): void {\r\n // date selected from interval\r\n if (\r\n this.selectedInterval &&\r\n this.selectedInterval.isSelectedFromInterval &&\r\n this.selectedInterval.interval\r\n ) {\r\n const intervalArr = this.selectedInterval.interval.split(' ');\r\n\r\n if (intervalArr && intervalArr.length > 1) {\r\n this.increment = parseInt(intervalArr[0], 10);\r\n this.duration = this.normaliseDurationString(intervalArr[1]);\r\n }\r\n\r\n // date is typed or calendar picker\r\n } else if (this.selectedDate) {\r\n const selected = moment(this.selectedDate);\r\n const today = moment().startOf('day');\r\n const duration = 'days';\r\n\r\n const daysBetween: number = selected.diff(today, duration);\r\n\r\n if (daysBetween && daysBetween > 0) {\r\n this.increment = daysBetween;\r\n this.duration = duration;\r\n }\r\n }\r\n\r\n this.onSelectoptions(this.increment, this.duration);\r\n\r\n this.form = this._fb.group({\r\n number: [this.increment, Validators.min(0)],\r\n duration: [this.duration],\r\n });\r\n\r\n this.onValueChanges();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.value$.unsubscribe();\r\n }\r\n\r\n onValueChanges(): void {\r\n this.value$ = this.form.valueChanges.subscribe(val => {\r\n this.onSelectoptions(val.number, val.duration);\r\n });\r\n }\r\n\r\n /** on cancel of interval form */\r\n onCancel(): void {\r\n this.cancel.e