@js-smart/ng-kit
Version:
Reusable Angular components built with Angular Material and Bootstrap 5.x, Utility classes/functions for Date, Form and String operations
773 lines (765 loc) • 187 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, ChangeDetectorRef, input, signal, output, effect, ChangeDetectionStrategy, Component, viewChild, computed, forwardRef, ElementRef, Renderer2, DestroyRef, ApplicationRef, EnvironmentInjector, createComponent, Directive, DOCUMENT, HostListener, Input, Injectable, ViewContainerRef, Inject, InjectionToken, makeEnvironmentProviders, untracked } from '@angular/core';
import * as i1 from '@angular/material/progress-spinner';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { NgClass } from '@angular/common';
import * as i1$1 from '@angular/forms';
import { FormControl, ReactiveFormsModule, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import * as i2 from '@angular/material/autocomplete';
import { MatAutocompleteTrigger, MatAutocomplete, MatAutocompleteModule } from '@angular/material/autocomplete';
import * as i1$2 from '@angular/material/button';
import { MatButtonModule, MatIconButton, MatAnchor, MatButton } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i2$1 from '@angular/material/icon';
import { MatIconModule, MatIcon, MatIconRegistry } from '@angular/material/icon';
import * as i3 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import { Subject, throttleTime } from 'rxjs';
import { DomSanitizer } from '@angular/platform-browser';
import * as i1$3 from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import * as i3$1 from '@angular/material/divider';
import { MatDividerModule } from '@angular/material/divider';
import * as i1$4 from '@angular/material/snack-bar';
import { MAT_SNACK_BAR_DATA, MatSnackBar } from '@angular/material/snack-bar';
import { QueryClient, MutationObserver, QueryObserver } from '@tanstack/query-core';
/**
* Boostrap Alert component that can be used to alert messages to the user
*
* @author Pavan Kumar Jadda
* @since 12.0.0
*/
class AlertComponent {
constructor() {
this.cdr = inject(ChangeDetectorRef);
/**
* Type of the BootStrap Alert. Following values are supported. See BootStrap docs for more information
*/
this.type = input('info', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
/**
* Is alert visible or open
*/
this.isOpen = input(true, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
/**
* Writable signal for isOpen
*/
this.open = signal(this.isOpen(), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
/**
* If set, displays an inline “Close” button
*/
this.dismissible = input(true, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
/**
* If set, dismisses the alert after Dismiss Timeout
*/
this.dismissOnTimeout = input(true, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "dismissOnTimeout" }] : /* istanbul ignore next */ []));
/**
* Number in milliseconds, after which alert will be closed. Default value is 5000 ms
*/
this.dismissTimeout = input(5000, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "dismissTimeout" }] : /* istanbul ignore next */ []));
/**
* Additional classes to be added to the alert. This can be used to add custom styles to the alert
*/
this.class = input('', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
/**
* Emits when the alert is closed.
*/
this.closed = output();
// React to isOpen input changes
effect(() => {
this.open.set(this.isOpen());
});
}
/**
* Initialize the component and settings
*
* @author Pavan Kumar Jadda
* @since 12.0.0
*/
ngOnInit() {
if (this.dismissOnTimeout()) {
setTimeout(() => {
this.closeAlert();
this.cdr.markForCheck();
}, this.dismissTimeout());
}
}
/**
* Closes BootStrap Alert if not open
*
* @author Pavan Kumar Jadda
* @since 12.0.0
*/
closeAlert() {
if (!this.open()) {
return;
}
this.open.set(false);
this.closed.emit();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: AlertComponent, isStandalone: true, selector: "lib-alert, alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, dismissOnTimeout: { classPropertyName: "dismissOnTimeout", publicName: "dismissOnTimeout", isSignal: true, isRequired: false, transformFunction: null }, dismissTimeout: { classPropertyName: "dismissTimeout", publicName: "dismissTimeout", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "@if (open()) {\n\t<div class=\"row {{ class() }}\">\n\t\t<div class=\"col-xs-12 col-sm-12 col-md-auto mx-auto\">\n\t\t\t<div class=\"alert alert-{{ type() }} alert-dismissible alert_div\" role=\"alert\" aria-live=\"polite\">\n\t\t\t\t<ng-content></ng-content>\n\t\t\t\t@if (dismissible()) {\n\t\t\t\t\t<button (click)=\"closeAlert()\" aria-label=\"Close\" class=\"btn-close\" data-bs-dismiss=\"alert\" type=\"button\"></button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n}\n", styles: [".alert_div{display:flex;align-items:center;justify-content:center}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AlertComponent, decorators: [{
type: Component,
args: [{ selector: 'lib-alert, alert', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open()) {\n\t<div class=\"row {{ class() }}\">\n\t\t<div class=\"col-xs-12 col-sm-12 col-md-auto mx-auto\">\n\t\t\t<div class=\"alert alert-{{ type() }} alert-dismissible alert_div\" role=\"alert\" aria-live=\"polite\">\n\t\t\t\t<ng-content></ng-content>\n\t\t\t\t@if (dismissible()) {\n\t\t\t\t\t<button (click)=\"closeAlert()\" aria-label=\"Close\" class=\"btn-close\" data-bs-dismiss=\"alert\" type=\"button\"></button>\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>\n\t</div>\n}\n", styles: [".alert_div{display:flex;align-items:center;justify-content:center}\n"] }]
}], ctorParameters: () => [], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissOnTimeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissOnTimeout", required: false }] }], dismissTimeout: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissTimeout", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
class SpinnerComponent {
constructor() {
/**
* Use Boostrap Spinner. Default `true`
*/
this.bootstrapSpinner = input(true, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "bootstrapSpinner" }] : /* istanbul ignore next */ []));
/**
* Diameter of the Angular Material spinner
*/
this.diameter = input(50, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "diameter" }] : /* istanbul ignore next */ []));
/**
* Color of the Angular Material spinner
*/
this.color = input('primary', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
/**
* Stroke Width of the Angular Material spinner
*/
this.strokeWidth = input(5, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "strokeWidth" }] : /* istanbul ignore next */ []));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: SpinnerComponent, isStandalone: true, selector: "spinner,lib-spinner", inputs: { bootstrapSpinner: { classPropertyName: "bootstrapSpinner", publicName: "bootstrapSpinner", isSignal: true, isRequired: false, transformFunction: null }, diameter: { classPropertyName: "diameter", publicName: "diameter", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<!-- Angular Material Spinner -->\n@if (!bootstrapSpinner()) {\n\t<mat-spinner [color]=\"color()\" [diameter]=\"diameter()\" [strokeWidth]=\"strokeWidth()\" class=\"mx-auto\"> </mat-spinner>\n}\n\n<!-- Bootstrap Spinner -->\n@if (bootstrapSpinner()) {\n\t<div class=\"d-flex justify-content-center\">\n\t\t<div class=\"spinner-border bs-spinner\" role=\"status\"></div>\n\t</div>\n}\n", styles: [".bs-spinner-sm{color:#3f51b5;margin-bottom:20px}.bs-spinner{color:#3f51b5;width:3rem;height:3rem;margin-bottom:20px}.bs-spinner-lg{color:#3f51b5;width:5rem;height:5rem;margin-bottom:20px}\n"], dependencies: [{ kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: SpinnerComponent, decorators: [{
type: Component,
args: [{ selector: 'spinner,lib-spinner', imports: [MatProgressSpinnerModule], changeDetection: ChangeDetectionStrategy.Eager, template: "<!-- Angular Material Spinner -->\n@if (!bootstrapSpinner()) {\n\t<mat-spinner [color]=\"color()\" [diameter]=\"diameter()\" [strokeWidth]=\"strokeWidth()\" class=\"mx-auto\"> </mat-spinner>\n}\n\n<!-- Bootstrap Spinner -->\n@if (bootstrapSpinner()) {\n\t<div class=\"d-flex justify-content-center\">\n\t\t<div class=\"spinner-border bs-spinner\" role=\"status\"></div>\n\t</div>\n}\n", styles: [".bs-spinner-sm{color:#3f51b5;margin-bottom:20px}.bs-spinner{color:#3f51b5;width:3rem;height:3rem;margin-bottom:20px}.bs-spinner-lg{color:#3f51b5;width:5rem;height:5rem;margin-bottom:20px}\n"] }]
}], propDecorators: { bootstrapSpinner: [{ type: i0.Input, args: [{ isSignal: true, alias: "bootstrapSpinner", required: false }] }], diameter: [{ type: i0.Input, args: [{ isSignal: true, alias: "diameter", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }] } });
/**
* Reusable Auto Complete component that extends MatAutoComplete to show Clear icon and Arrow buttons
*
* @author Pavan Kumar Jadda
* @since 12.0.0
*/
class AutocompleteComponent {
constructor() {
/** Gets reference to the MatAutocompleteTrigger to programmatically open/close the panel */
this.autocompleteTrigger = viewChild.required(MatAutocompleteTrigger);
/** MatAutocomplete instance (used to scroll the selected option into view when the panel opens) */
this.matAutocomplete = viewChild.required(MatAutocomplete);
/** Gets reference to the input element for re-focusing after clear */
this.inputElement = viewChild.required('inputEl');
/** Label of the autocomplete form field */
this.label = input('Select Value', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
/** Placeholder text displayed inside the input when empty */
this.placeholder = input('', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
/** Appearance of the form field. Defaults to `outline` */
this.appearance = input('outline', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
/** List of CSS classes to apply to the form field */
this.classes = input('', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
/** List of options to display in the dropdown */
this.options = input([], /* @ts-ignore */
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
/**
* Function that maps an option to its display string.
* Used for rendering options in the dropdown and showing the selected value in the input.
* Defaults to `String(value)` which works for primitive string options.
*/
this.displayWith = input((value) => String(value), /* @ts-ignore */
...(ngDevMode ? [{ debugName: "displayWith" }] : /* istanbul ignore next */ []));
/** Whether the autocomplete is in a loading state. Shows a spinner instead of options */
this.loading = input(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
/** Text displayed when the autocomplete is in a loading state. Defaults to 'Loading...' */
this.loadingText = input('Loading...', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "loadingText" }] : /* istanbul ignore next */ []));
/** Text displayed when no options match the filter input. Defaults to 'No values found' */
this.noOptionsText = input('No values found', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "noOptionsText" }] : /* istanbul ignore next */ []));
/** Emits the selected value when an option is picked from the dropdown */
this.selectionChange = output();
/** Emits the raw text in the input on each keystroke (filter text while typing) */
this.onInputChange = output();
/** Internal form control for the autocomplete input */
this.control = new FormControl(null);
/** Signal that tracks whether the autocomplete panel is currently open */
this.isExpanded = signal(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
/** Signal that tracks the current filter text typed by the user */
this.filterText = signal('', /* @ts-ignore */
...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
/**
* Computed signal that filters options based on the current filter text.
* Uses the `displayWith` function to extract searchable text from each option.
* Returns all options when filter text is empty.
*/
this.filteredOptions = computed(() => {
const filterValue = this.filterText().toLowerCase();
const displayFn = this.displayWith();
return this.options().filter((option) => displayFn(option).toLowerCase().includes(filterValue));
}, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
/**
* Display function passed to mat-autocomplete's [displayWith] to render the
* selected value in the input field. Returns empty string for null/undefined values.
*/
this.displayFn = (value) => {
if (value == null || value === '') {
return '';
}
return this.displayWith()(value);
};
/** Callback function registered by the parent form to propagate value changes */
this.onChange = (_) => {
/* noop */
};
/** Callback function registered by the parent form to propagate touched state */
this.onTouched = () => {
/* noop */
};
}
/**
* Writes a new value to the internal control. Called by the parent form
* when the form control value is set programmatically.
*/
writeValue(value) {
// Use null (not '') so MatAutocompleteTrigger clears mat-option selection and stays in sync with the parent CVA.
const internal = value == null ? null : value;
this.control.setValue(internal, { emitEvent: false });
}
/**
* Registers a callback function that is called when the control's value
* changes in the UI (option selected or input cleared).
*/
registerOnChange(fn) {
this.onChange = fn;
}
/**
* Registers a callback function that is called when the control is
* first interacted with (blur or selection).
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Sets the disabled state of the internal control. Called by the parent form
* when `control.disable()` or `control.enable()` is invoked.
*/
setDisabledState(isDisabled) {
if (isDisabled) {
this.control.disable();
}
else {
this.control.enable();
}
}
/** Updates the filter text signal as the user types in the input */
onInput(event) {
const value = event.target.value;
this.filterText.set(value);
this.onInputChange.emit(value);
}
/**
* Clears the input value, resets the filter, notifies the parent form,
* and re-focuses the input element.
*/
clearInput(event) {
event.preventDefault();
event.stopPropagation();
this.autocompleteTrigger().closePanel();
this.control.setValue(null, { emitEvent: false });
this.filterText.set('');
this.onChange(null);
this.onTouched();
queueMicrotask(() => this.inputElement().nativeElement.focus());
}
/** Runs when the autocomplete overlay opens: keep expanded state and scroll the selected option into view. */
onPanelOpened() {
this.isExpanded.set(true);
this.scrollSelectedOptionIntoView();
}
scrollSelectedOptionIntoView() {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
const panelEl = this.matAutocomplete().panel?.nativeElement;
if (!panelEl) {
return;
}
const selected = panelEl.querySelector('.mat-mdc-option.mdc-list-item--selected');
selected?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
});
});
}
/** Opens the autocomplete panel programmatically */
openPanel() {
this.autocompleteTrigger().openPanel();
}
/**
* Handles option selection from the dropdown. Resets the filter text,
* notifies the parent form of the new value, and emits the selectionChange output.
*/
onOptionSelected(value) {
this.filterText.set('');
this.onChange(value);
this.onTouched();
this.selectionChange.emit(value);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: AutocompleteComponent, isStandalone: true, selector: "autocomplete, lib-autocomplete", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, noOptionsText: { classPropertyName: "noOptionsText", publicName: "noOptionsText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", onInputChange: "onInputChange" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AutocompleteComponent),
multi: true,
},
], viewQueries: [{ propertyName: "autocompleteTrigger", first: true, predicate: MatAutocompleteTrigger, descendants: true, isSignal: true }, { propertyName: "matAutocomplete", first: true, predicate: MatAutocomplete, descendants: true, isSignal: true }, { propertyName: "inputElement", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-form-field\n\t#origin=\"matAutocompleteOrigin\"\n\t[appearance]=\"appearance()\"\n\t[ngClass]=\"classes()\"\n\tmatAutocompleteOrigin\n\tsubscriptSizing=\"dynamic\">\n\t<mat-label>{{ label() }}</mat-label>\n\n\t<input\n\t\t#inputEl\n\t\t#trigger=\"matAutocompleteTrigger\"\n\t\t(click)=\"trigger.openPanel()\"\n\t\t(input)=\"onInput($event)\"\n\t\t[formControl]=\"control\"\n\t\t[matAutocompleteConnectedTo]=\"origin\"\n\t\t[matAutocomplete]=\"auto\"\n\t\t[placeholder]=\"placeholder()\"\n\t\tmatInput\n\t\ttype=\"text\" />\n\n\t<div class=\"autocomplete-suffix\" matSuffix>\n\t\t@if (control.value && !control.disabled) {\n\t\t\t<button type=\"button\" (click)=\"clearInput($event)\" aria-label=\"Clear value\" class=\"suffix-action-btn\" mat-icon-button>\n\t\t\t\t<mat-icon>close</mat-icon>\n\t\t\t</button>\n\t\t} @else if (!control.disabled) {\n\t\t\t<span aria-hidden=\"true\" class=\"suffix-placeholder\"></span>\n\t\t}\n\t\t@if (!control.disabled) {\n\t\t\t<button\n\t\t\t\t(click)=\"trigger.panelOpen ? trigger.closePanel() : trigger.openPanel(); $event.stopPropagation()\"\n\t\t\t\t[attr.aria-label]=\"trigger.panelOpen ? 'Close options' : 'Open options'\"\n\t\t\t\tclass=\"suffix-action-btn\"\n\t\t\t\tmat-icon-button\n\t\t\t\ttype=\"button\">\n\t\t\t\t@if (isExpanded()) {\n\t\t\t\t\t<mat-icon>arrow_drop_up</mat-icon>\n\t\t\t\t} @else {\n\t\t\t\t\t<mat-icon>arrow_drop_down</mat-icon>\n\t\t\t\t}\n\t\t\t</button>\n\t\t}\n\t</div>\n\n\t<mat-autocomplete\n\t\t#auto=\"matAutocomplete\"\n\t\t(closed)=\"isExpanded.set(false)\"\n\t\t(opened)=\"onPanelOpened()\"\n\t\t(optionSelected)=\"onOptionSelected($event.option.value)\"\n\t\t[displayWith]=\"displayFn\">\n\t\t@if (loading()) {\n\t\t\t<mat-option disabled>\n\t\t\t\t<div style=\"display: flex; align-items: center; gap: 8px\">\n\t\t\t\t\t<mat-spinner diameter=\"20\"></mat-spinner>\n\t\t\t\t\t<span>{{ loadingText() }}</span>\n\t\t\t\t</div>\n\t\t\t</mat-option>\n\t\t} @else {\n\t\t\t@for (option of filteredOptions(); track option) {\n\t\t\t\t<mat-option [value]=\"option\">{{ displayWith()(option) }}</mat-option>\n\t\t\t} @empty {\n\t\t\t\t<mat-option disabled>{{ noOptionsText() }}</mat-option>\n\t\t\t}\n\t\t}\n\t</mat-autocomplete>\n</mat-form-field>\n", styles: [".autocomplete-suffix{display:flex;align-items:center}.suffix-action-btn{width:40px;height:40px;padding:0}.suffix-placeholder{display:inline-block;width:40px}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "directive", type: i2.MatAutocompleteOrigin, selector: "[matAutocompleteOrigin]", exportAs: ["matAutocompleteOrigin"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteComponent, decorators: [{
type: Component,
args: [{ selector: 'autocomplete, lib-autocomplete', imports: [
NgClass,
ReactiveFormsModule,
MatAutocompleteModule,
MatInputModule,
MatFormFieldModule,
MatIconModule,
MatButtonModule,
MatProgressSpinnerModule,
], changeDetection: ChangeDetectionStrategy.Eager, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AutocompleteComponent),
multi: true,
},
], template: "<mat-form-field\n\t#origin=\"matAutocompleteOrigin\"\n\t[appearance]=\"appearance()\"\n\t[ngClass]=\"classes()\"\n\tmatAutocompleteOrigin\n\tsubscriptSizing=\"dynamic\">\n\t<mat-label>{{ label() }}</mat-label>\n\n\t<input\n\t\t#inputEl\n\t\t#trigger=\"matAutocompleteTrigger\"\n\t\t(click)=\"trigger.openPanel()\"\n\t\t(input)=\"onInput($event)\"\n\t\t[formControl]=\"control\"\n\t\t[matAutocompleteConnectedTo]=\"origin\"\n\t\t[matAutocomplete]=\"auto\"\n\t\t[placeholder]=\"placeholder()\"\n\t\tmatInput\n\t\ttype=\"text\" />\n\n\t<div class=\"autocomplete-suffix\" matSuffix>\n\t\t@if (control.value && !control.disabled) {\n\t\t\t<button type=\"button\" (click)=\"clearInput($event)\" aria-label=\"Clear value\" class=\"suffix-action-btn\" mat-icon-button>\n\t\t\t\t<mat-icon>close</mat-icon>\n\t\t\t</button>\n\t\t} @else if (!control.disabled) {\n\t\t\t<span aria-hidden=\"true\" class=\"suffix-placeholder\"></span>\n\t\t}\n\t\t@if (!control.disabled) {\n\t\t\t<button\n\t\t\t\t(click)=\"trigger.panelOpen ? trigger.closePanel() : trigger.openPanel(); $event.stopPropagation()\"\n\t\t\t\t[attr.aria-label]=\"trigger.panelOpen ? 'Close options' : 'Open options'\"\n\t\t\t\tclass=\"suffix-action-btn\"\n\t\t\t\tmat-icon-button\n\t\t\t\ttype=\"button\">\n\t\t\t\t@if (isExpanded()) {\n\t\t\t\t\t<mat-icon>arrow_drop_up</mat-icon>\n\t\t\t\t} @else {\n\t\t\t\t\t<mat-icon>arrow_drop_down</mat-icon>\n\t\t\t\t}\n\t\t\t</button>\n\t\t}\n\t</div>\n\n\t<mat-autocomplete\n\t\t#auto=\"matAutocomplete\"\n\t\t(closed)=\"isExpanded.set(false)\"\n\t\t(opened)=\"onPanelOpened()\"\n\t\t(optionSelected)=\"onOptionSelected($event.option.value)\"\n\t\t[displayWith]=\"displayFn\">\n\t\t@if (loading()) {\n\t\t\t<mat-option disabled>\n\t\t\t\t<div style=\"display: flex; align-items: center; gap: 8px\">\n\t\t\t\t\t<mat-spinner diameter=\"20\"></mat-spinner>\n\t\t\t\t\t<span>{{ loadingText() }}</span>\n\t\t\t\t</div>\n\t\t\t</mat-option>\n\t\t} @else {\n\t\t\t@for (option of filteredOptions(); track option) {\n\t\t\t\t<mat-option [value]=\"option\">{{ displayWith()(option) }}</mat-option>\n\t\t\t} @empty {\n\t\t\t\t<mat-option disabled>{{ noOptionsText() }}</mat-option>\n\t\t\t}\n\t\t}\n\t</mat-autocomplete>\n</mat-form-field>\n", styles: [".autocomplete-suffix{display:flex;align-items:center}.suffix-action-btn{width:40px;height:40px;padding:0}.suffix-placeholder{display:inline-block;width:40px}\n"] }]
}], propDecorators: { autocompleteTrigger: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatAutocompleteTrigger), { isSignal: true }] }], matAutocomplete: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatAutocomplete), { isSignal: true }] }], inputElement: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], noOptionsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noOptionsText", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], onInputChange: [{ type: i0.Output, args: ["onInputChange"] }] } });
class AutocompleteClearButtonComponent {
constructor() {
this.clicked = output();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteClearButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: AutocompleteClearButtonComponent, isStandalone: true, selector: "autocomplete-clear-button", outputs: { clicked: "clicked" }, ngImport: i0, template: `
<button
mat-icon-button
type="button"
aria-label="Clear value"
style="padding: 0 !important; width: 32px; height: 32px;"
(click)="clicked.emit($event)">
<mat-icon>close</mat-icon>
</button>
`, isInline: true, dependencies: [{ kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteClearButtonComponent, decorators: [{
type: Component,
args: [{
selector: 'autocomplete-clear-button',
standalone: true,
imports: [MatIconButton, MatIcon],
changeDetection: ChangeDetectionStrategy.Eager,
template: `
<button
mat-icon-button
type="button"
aria-label="Clear value"
style="padding: 0 !important; width: 32px; height: 32px;"
(click)="clicked.emit($event)">
<mat-icon>close</mat-icon>
</button>
`,
}]
}], propDecorators: { clicked: [{ type: i0.Output, args: ["clicked"] }] } });
class AutocompleteDropdownButtonComponent {
constructor() {
this.expanded = signal(false, /* @ts-ignore */
...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
this.clicked = output();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteDropdownButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: AutocompleteDropdownButtonComponent, isStandalone: true, selector: "autocomplete-dropdown-button", outputs: { clicked: "clicked" }, ngImport: i0, template: `
<button
mat-icon-button
type="button"
style="padding: 0 !important; width: 32px; height: 32px;"
[attr.aria-label]="expanded() ? 'Close options' : 'Open options'"
(click)="clicked.emit($event)">
<mat-icon>{{ expanded() ? 'arrow_drop_up' : 'arrow_drop_down' }}</mat-icon>
</button>
`, isInline: true, dependencies: [{ kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteDropdownButtonComponent, decorators: [{
type: Component,
args: [{
selector: 'autocomplete-dropdown-button',
standalone: true,
imports: [MatIconButton, MatIcon],
changeDetection: ChangeDetectionStrategy.Eager,
template: `
<button
mat-icon-button
type="button"
style="padding: 0 !important; width: 32px; height: 32px;"
[attr.aria-label]="expanded() ? 'Close options' : 'Open options'"
(click)="clicked.emit($event)">
<mat-icon>{{ expanded() ? 'arrow_drop_up' : 'arrow_drop_down' }}</mat-icon>
</button>
`,
}]
}], propDecorators: { clicked: [{ type: i0.Output, args: ["clicked"] }] } });
/**
* Single directive that adds clear and dropdown-toggle icon buttons to a
* Material autocomplete input. Unlike {@link LibAutocompleteActionsDirective},
* this directive is applied directly to the `input` element and does not require
* an anchor directive or a separate suffix component.
*
* Usage:
* ```html
* <mat-form-field appearance="outline">
* <mat-label>City</mat-label>
* <input matInput [matAutocomplete]="auto" formControlName="city" autocompleteSuffix />
* <mat-autocomplete #auto="matAutocomplete"> … </mat-autocomplete>
* </mat-form-field>
* ```
*
* @author Pavan Kumar Jadda
* @since 21.8.0
*/
class AutocompleteSuffixDirective {
constructor() {
this.trigger = inject(MatAutocompleteTrigger);
this.el = inject((ElementRef));
this.renderer = inject(Renderer2);
this.destroyRef = inject(DestroyRef);
this.ngControl = inject(NgControl, { optional: true, self: true });
this.appRef = inject(ApplicationRef);
this.envInjector = inject(EnvironmentInjector);
this.clearRef = null;
this.dropdownRef = null;
this.isExpanded = false;
this.unlisten = [];
}
ngAfterViewInit() {
this.createSuffixElements();
this.setupListeners();
this.updateClearButtonVisibility();
}
createSuffixElements() {
const formField = this.el.nativeElement.closest('mat-form-field');
if (!formField) {
return;
}
const flexContainer = formField.querySelector('.mat-mdc-form-field-flex');
if (!flexContainer) {
return;
}
let suffixWrapper = flexContainer.querySelector('.mat-mdc-form-field-icon-suffix');
if (!suffixWrapper) {
suffixWrapper = this.renderer.createElement('div');
this.renderer.addClass(suffixWrapper, 'mat-mdc-form-field-icon-suffix');
this.renderer.setAttribute(suffixWrapper, 'data-mat-icon-type', 'font');
this.renderer.appendChild(flexContainer, suffixWrapper);
}
const container = this.renderer.createElement('div');
this.renderer.setStyle(container, 'display', 'flex');
this.renderer.setStyle(container, 'align-items', 'center');
this.clearRef = createComponent(AutocompleteClearButtonComponent, { environmentInjector: this.envInjector });
this.appRef.attachView(this.clearRef.hostView);
this.clearRef.instance.clicked.subscribe((e) => this.clearInput(e));
this.renderer.setStyle(this.clearRef.location.nativeElement, 'visibility', 'hidden');
this.dropdownRef = createComponent(AutocompleteDropdownButtonComponent, { environmentInjector: this.envInjector });
this.appRef.attachView(this.dropdownRef.hostView);
this.dropdownRef.instance.clicked.subscribe((e) => this.togglePanel(e));
this.renderer.appendChild(container, this.clearRef.location.nativeElement);
this.renderer.appendChild(container, this.dropdownRef.location.nativeElement);
this.renderer.appendChild(suffixWrapper, container);
this.destroyRef.onDestroy(() => {
this.clearRef?.destroy();
this.dropdownRef?.destroy();
});
}
setupListeners() {
this.unlisten.push(this.renderer.listen(this.el.nativeElement, 'input', () => this.updateClearButtonVisibility()));
const autocomplete = this.trigger.autocomplete;
const openedSub = autocomplete.opened.subscribe(() => {
this.isExpanded = true;
this.updateDropdownIcon();
this.scrollSelectedOptionIntoView();
});
const closedSub = autocomplete.closed.subscribe(() => {
this.isExpanded = false;
this.updateDropdownIcon();
this.updateClearButtonVisibility();
});
const selectedSub = autocomplete.optionSelected.subscribe(() => this.updateClearButtonVisibility());
let valueChangesSub = null;
if (this.ngControl?.control) {
valueChangesSub = this.ngControl.control.valueChanges.subscribe(() => this.updateClearButtonVisibility());
}
this.destroyRef.onDestroy(() => {
this.unlisten.forEach((fn) => fn());
openedSub.unsubscribe();
closedSub.unsubscribe();
selectedSub.unsubscribe();
valueChangesSub?.unsubscribe();
});
}
clearInput(event) {
event.preventDefault();
event.stopPropagation();
this.trigger.closePanel();
this.el.nativeElement.value = '';
if (this.ngControl?.control) {
this.ngControl.control.setValue(null, { emitEvent: true });
this.ngControl.control.markAsTouched();
}
this.updateClearButtonVisibility();
queueMicrotask(() => this.el.nativeElement.focus());
}
togglePanel(event) {
event.stopPropagation();
if (this.trigger.panelOpen) {
this.trigger.closePanel();
}
else {
this.trigger.openPanel();
}
}
updateClearButtonVisibility() {
const hasValue = !!(this.el.nativeElement.value || this.ngControl?.control?.value);
if (this.clearRef) {
this.renderer.setStyle(this.clearRef.location.nativeElement, 'visibility', hasValue ? 'visible' : 'hidden');
}
}
scrollSelectedOptionIntoView() {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
const panelEl = this.trigger.autocomplete.panel?.nativeElement;
if (!panelEl) {
return;
}
const selected = panelEl.querySelector('.mat-mdc-option.mdc-list-item--selected');
selected?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
});
});
}
updateDropdownIcon() {
if (this.dropdownRef) {
this.dropdownRef.instance.expanded.set(this.isExpanded);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteSuffixDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.5", type: AutocompleteSuffixDirective, isStandalone: true, selector: "input[matAutocomplete][autocompleteSuffix]", ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: AutocompleteSuffixDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[matAutocomplete][autocompleteSuffix]',
standalone: true,
}]
}] });
class PrintOptions {
constructor(options) {
this.printSectionId = '';
this.printTitle = '';
this.useExistingCss = false;
this.bodyClass = '';
this.openNewTab = false;
this.previewOnly = false;
this.closeWindow = true;
this.printDelay = 0;
if (options) {
Object.assign(this, options);
}
}
}
/**
* Reusable Angular directory that prints given contents of HTML element
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
class NgxPrintDirective {
constructor() {
this.document = inject(DOCUMENT);
/**
* If `true`, uses CSS of HTMl element, otherwise no CSS applied
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.useExistingCss = false;
/**
* A delay in milliseconds to force the print dialog to wait before opened. Default: 0
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.printDelay = 0;
/**
* ID of the Mat Paginator
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.paginatorId = '';
/**
* HTML tag ID of the Mat-Table Input Filter
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.inputFilterId = '';
/**
* If `true`, referenced table is Mat-Table
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.isMatTable = false;
/**
* If `true` Mat-Table paginator will be hidden
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.hideMatTablePaginator = false;
this.printStyleArray = [];
this.printOptions = new PrintOptions();
/**
* List of Style sheet files
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
this.styleSheetFileArray = '';
}
/**
* Prevents the print dialog from opening on the window
*
* @memberof NgxPrintDirective
*/
set previewOnly(value) {
this.printOptions = { ...this.printOptions, previewOnly: value };
}
/**
* List of CSS properties that needs to be applied while printing the document
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
set printStyle({ values }) {
for (const key in values) {
if (Object.prototype.hasOwnProperty.call(values, key)) {
this.printStyleArray.push((key + JSON.stringify(values[key])).replace(/['"]+/g, ''));
}
}
this.returnStyleValues();
}
/**
* Sets given style sheet files to print document
*
* @param cssList Comma separated value of CSS file names
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
set styleSheetFile(cssList) {
if (cssList.indexOf(',') !== -1) {
const cssFileArray = cssList.split(',');
for (const cssFileName of cssFileArray) {
this.styleSheetFileArray = this.styleSheetFileArray + NgxPrintDirective.linkTagFn(cssFileName);
}
}
else {
this.styleSheetFileArray = NgxPrintDirective.linkTagFn(cssList);
}
}
/**
* Build link HTMl tag based on given file name
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
static linkTagFn(cssFileName) {
return `<link rel="stylesheet" type="text/css" href="${cssFileName}">`;
}
/**
* Gets HTML element by tag name
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
static getElementTag(tag) {
const html = [];
const elements = document.getElementsByTagName(tag);
// @ts-ignore
for (const element of elements) {
html.push(element.outerHTML);
}
return html.join('\r\n');
}
/**
* Print the element upon clicking the button
*
* @since 12.0.0
* @author Pavan Kumar Jadda
*/
print() {
//Hide paginator for Material table
if (this.isMatTable && this.hideMatTablePaginator && this.matTableDataSource) {
this.matTableDataSource.paginator = null;
}
setTimeout(() => {
if (this.isMatTable) {
this.hideMatPaginatorBeforePrinting();
}
// Do something after
let printContents;
let popupWin;
let styles = '';
let links = '';
if (this.useExistingCss) {
styles = NgxPrintDirective.getElementTag('style');
links = NgxPrintDirective.getElementTag('link');
}
if (this.printSectionId) {
printContents = this.document.getElementById(this.printSectionId)?.innerHTML;
popupWin = window.open('', '_blank', 'top=0,left=0,height=auto,width=auto');
popupWin?.document.open();
popupWin?.document.write(`
<html lang="en-us">
<head>
<title>${this.printTitle ? this.printTitle : ''}</title>
${this.returnStyleValues()}
${this.styleSheetFileArray}
${styles}
${links}
</head>
<body>
${printContents}
<script defer>
function triggerPrint() {
window.removeEventListener('load', triggerPrint, false);
setTimeout(() => {
window.print();
setTimeout(function() { window.close(); }, 0);
}, ${this.printDelay});
}
window.addEventListener('load', triggerPrint, false);
</script>
</body>
</html>`);
popupWin?.document.close();
//Revert back the mat-paginator after printing
if (this.isMatTable) {
this.showMatPaginatorAfterPrinting();
}
}
}, 1000