ng-material-date-range-picker
Version:
This library provides the date range selection with two views.
356 lines • 67.6 kB
JavaScript
/**
* @(#)ng-date-picker.component.ts Sept 05, 2023
*
* @author Aakash Kumar
*/
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core';
import { DatePipe } from '@angular/common';
import { DateRange } from '@angular/material/datepicker';
import { DEFAULT_DATE_OPTION_ENUM } from './constant/date-filter-enum';
import { DEFAULT_DATE_OPTIONS } from './data/default-date-options';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/material/input";
import * as i3 from "@angular/material/form-field";
import * as i4 from "@angular/cdk/overlay";
import * as i5 from "@angular/material/icon";
import * as i6 from "@angular/material/button";
import * as i7 from "@angular/material/list";
import * as i8 from "@angular/material/tooltip";
import * as i9 from "./calendar/calendar.component";
export class NgDatePickerComponent {
constructor(cdref, el) {
this.cdref = cdref;
this.el = el;
this.isDateOptionList = false;
this.isCustomRange = false;
this.inputLabel = 'Date Range';
this.staticOptionId = 'static-options';
this.dynamicOptionId = 'dynamic-options';
this.calendarId = 'custom-calendar';
this.enableDefaultOptions = true;
this.dateFormat = 'dd/MM/yyyy';
this.isShowStaticDefaultOptions = false;
this.hideDefaultOptions = false;
this.cdkConnectedOverlayOffsetX = 0;
this.cdkConnectedOverlayOffsetY = 0;
this.listCdkConnectedOverlayOffsetY = 0;
this.listCdkConnectedOverlayOffsetX = 0;
this.selectedOptionIndex = 3;
this.displaySelectedLabel = false;
this.cdkConnectedOverlayPush = true;
this.cdkConnectedOverlayPositions = [];
// default min date is current date - 10 years.
this.minDate = new Date(new Date().setFullYear(new Date().getFullYear() - 10));
// default max date is current date - 10 years.
this.maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 10));
this._dateDropDownOptions = [];
this.onDateSelectionChanged = new EventEmitter();
this.dateListOptions = new EventEmitter();
}
set dateDropDownOptions(defaultDateList) {
if (this.enableDefaultOptions) {
this._dateDropDownOptions =
this.getClone(DEFAULT_DATE_OPTIONS).concat(defaultDateList);
}
else {
this._dateDropDownOptions = defaultDateList;
}
}
get dateDropDownOptions() {
return this._dateDropDownOptions ?? [];
}
ngOnInit() {
if (!this._dateDropDownOptions.length && this.enableDefaultOptions) {
this._dateDropDownOptions =
this.getClone(DEFAULT_DATE_OPTIONS);
this._dateDropDownOptions[this.selectedOptionIndex].isSelected = true;
}
this.dateListOptions.emit(this.dateDropDownOptions);
}
ngAfterViewInit() {
this.updateDefaultDatesValues();
}
/**
* This method toggles the visibility of default date option's List.
*/
toggleDateOptionSelectionList(event) {
if (event) {
event.preventDefault();
event.stopImmediatePropagation();
}
const selectedOption = this.dateDropDownOptions.filter((option) => option.isSelected);
if (selectedOption.length &&
selectedOption[0].optionKey === DEFAULT_DATE_OPTION_ENUM.CUSTOM) {
this.toggleCustomDateRangeView();
}
else {
this.isDateOptionList = !this.isDateOptionList;
}
}
/**
* This method updates the date range on button click.
*
* @param input HTMLInputElement
* @param selectedDates DateRange<Date>
*/
updateCustomRange(input, selectedDates) {
this.updateSelectedDates(input, selectedDates?.start ?? new Date(), selectedDates?.end ?? new Date(), null);
if (this.isCustomRange) {
this.resetOptionSelection();
this.selectCustomOption();
this.isCustomRange = false;
}
}
/**
* This method update the date on specified option.
*
* @param option ISelectDateOption
* @param input HTMLInputElement
*/
updateSelection(option, input) {
this.isDateOptionList = false;
if (option.optionKey !== DEFAULT_DATE_OPTION_ENUM.CUSTOM) {
this.isCustomRange = false;
this.resetOptionSelection(option);
this.updateDateOnOptionSelect(option, input);
}
else {
this.isCustomRange = true;
}
this.cdref.markForCheck();
}
// This method sets custom option as selected.
selectCustomOption() {
const customOption = this.dateDropDownOptions.filter((option) => option.optionKey === DEFAULT_DATE_OPTION_ENUM.CUSTOM);
customOption[0].isSelected = true;
}
/**
* This method toggles the custom date range selection view.
*/
toggleCustomDateRangeView() {
this.isCustomRange = !this.isCustomRange;
}
/**
* Clears the selected dates and resets date-related properties.
*
* @param event - The mouse event that triggered the clear action.
*/
clearSelection(event) {
event.stopImmediatePropagation();
const currentDate = new Date();
const year = currentDate.getFullYear();
this.minDate = new Date(currentDate.setFullYear(year - 10));
this.maxDate = new Date(currentDate.setFullYear(year + 10));
this.selectedDates = null;
this.resetOptionSelection();
const dateInputField = this.el.nativeElement.querySelector('#date-input-field');
if (dateInputField) {
dateInputField.value = '';
}
this.cdref.markForCheck();
const selectedDateEventData = {
range: null,
selectedOption: null,
};
this.onDateSelectionChanged.emit(selectedDateEventData);
}
/**
* This method sets clicked element as selected.
* @param option ISelectDateOption
*/
resetOptionSelection(option) {
this.dateDropDownOptions.forEach((option) => (option.isSelected = false));
if (option) {
option.isSelected = true;
}
this.cdref.markForCheck();
}
/**
* Updates the selected dates based on the given option and input element.
*
* @param option - The date option selected by the user.
* @param input - The HTML input element to update.
*/
updateDateOnOptionSelect(option, input) {
const currDate = new Date();
let startDate = new Date();
let lastDate = new Date();
// If there is a callback function, use it to get the date range
if (option.callBackFunction) {
const dateRange = option.callBackFunction();
if (dateRange?.start && dateRange?.end) {
this.updateSelectedDates(input, dateRange.start, dateRange.end, option);
return;
}
}
// Determine the date range based on the option key
switch (option.optionKey) {
case DEFAULT_DATE_OPTION_ENUM.DATE_DIFF:
startDate.setDate(startDate.getDate() + option.dateDiff);
break;
case DEFAULT_DATE_OPTION_ENUM.LAST_MONTH:
currDate.setMonth(currDate.getMonth() - 1);
startDate = new Date(currDate.getFullYear(), currDate.getMonth(), 1);
lastDate = new Date(currDate.getFullYear(), currDate.getMonth(), this.getDaysInMonth(currDate));
break;
case DEFAULT_DATE_OPTION_ENUM.THIS_MONTH:
startDate = new Date(currDate.getFullYear(), currDate.getMonth(), 1);
lastDate = new Date(currDate.getFullYear(), currDate.getMonth(), this.getDaysInMonth(currDate));
break;
case DEFAULT_DATE_OPTION_ENUM.YEAR_TO_DATE:
startDate = new Date(currDate.getFullYear(), 0, 1);
break;
case DEFAULT_DATE_OPTION_ENUM.MONTH_TO_DATE:
startDate = new Date(currDate.getFullYear(), currDate.getMonth(), 1);
break;
default:
break;
}
// Update the selected dates
this.updateSelectedDates(input, startDate, lastDate, option);
}
/**
* This method updates dates on selection.
*
* @param input HTMLInputElement
* @param startDate Date
* @param endDate Date
*/
updateSelectedDates(input, startDate, endDate, option) {
this.selectedDates = new DateRange(startDate, endDate);
input.value =
this.displaySelectedLabel && option
? option.optionLabel
: this.getDateString(startDate) + ' - ' + this.getDateString(endDate);
const selectedOption = this.dateDropDownOptions.filter((option) => option.isSelected)[0];
const selectedDateEventData = {
range: new DateRange(new Date(startDate), new Date(endDate)),
selectedOption: selectedOption,
};
this.onDateSelectionChanged.emit(selectedDateEventData);
this.cdref.markForCheck();
}
/**
* This method converts the given date into specified string format.
*
* @param date Date
* @returns formatted date.
*/
getDateString(date) {
const datePipe = new DatePipe('en');
return datePipe.transform(date, this.dateFormat) ?? '';
}
/**
* This method return the number of days in moth on specified date.
*
* @param date Date
* @returns number
*/
getDaysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
}
/**
* This method clone the data.
*
* @param data T
* @returns T
*/
getClone(data) {
return JSON.parse(JSON.stringify(data));
}
/**
* This method update the default date values on init.
*/
updateDefaultDatesValues() {
const input = this.el.nativeElement.querySelector('#date-input-field');
if (this.selectedDates &&
this.selectedDates.start &&
this.selectedDates.end) {
const customOption = this._dateDropDownOptions.filter((option) => option.optionKey === DEFAULT_DATE_OPTION_ENUM.CUSTOM);
customOption[0].isSelected = true;
input.value =
this.getDateString(this.selectedDates.start) +
' - ' +
this.getDateString(this.selectedDates.end);
}
else {
const selectedOptions = this._dateDropDownOptions.filter((option) => option.isSelected);
if (selectedOptions.length &&
selectedOptions[0].optionKey !== DEFAULT_DATE_OPTION_ENUM.CUSTOM) {
this.updatedFromListValueSelection(selectedOptions[0], input);
}
}
this.cdref.detectChanges();
}
/**
* This method updates the date values based on default option selection.
*
* @param selectedOption ISelectDateOption
* @param input HTMLInputElement
*/
updatedFromListValueSelection(selectedOption, input) {
// This will update value if option is selected from provided custom list.
if (selectedOption['callBackFunction']) {
const dateRange = selectedOption.callBackFunction();
if (dateRange?.start && dateRange?.end) {
this.updateSelectedDates(input, dateRange.start, dateRange.end, selectedOption);
}
}
else {
// This will update value if option is selected from default list.
this.updateDateOnOptionSelect(selectedOption, input);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: NgDatePickerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.6", type: NgDatePickerComponent, selector: "ng-date-range-picker", inputs: { inputLabel: "inputLabel", staticOptionId: "staticOptionId", dynamicOptionId: "dynamicOptionId", calendarId: "calendarId", enableDefaultOptions: "enableDefaultOptions", selectedDates: "selectedDates", dateFormat: "dateFormat", isShowStaticDefaultOptions: "isShowStaticDefaultOptions", hideDefaultOptions: "hideDefaultOptions", cdkConnectedOverlayOffsetX: "cdkConnectedOverlayOffsetX", cdkConnectedOverlayOffsetY: "cdkConnectedOverlayOffsetY", listCdkConnectedOverlayOffsetY: "listCdkConnectedOverlayOffsetY", listCdkConnectedOverlayOffsetX: "listCdkConnectedOverlayOffsetX", selectedOptionIndex: "selectedOptionIndex", displaySelectedLabel: "displaySelectedLabel", cdkConnectedOverlayPush: "cdkConnectedOverlayPush", cdkConnectedOverlayPositions: "cdkConnectedOverlayPositions", minDate: "minDate", maxDate: "maxDate", dateDropDownOptions: "dateDropDownOptions" }, outputs: { onDateSelectionChanged: "onDateSelectionChanged", dateListOptions: "dateListOptions" }, ngImport: i0, template: "<!--**\r\n * @(#)ng-date-picker.component.html Sept 05, 2023\r\n\r\n * @author Aakash Kumar\r\n *-->\r\n<div class=\"date-picker-main\" cdkOverlayOrigin #trigger>\r\n <mat-form-field class=\"w-full\" [class]=\"{'display-hidden':isShowStaticDefaultOptions}\" (click)=\"toggleDateOptionSelectionList($event)\">\r\n <mat-label (click)=\"toggleDateOptionSelectionList($event)\">{{inputLabel}}</mat-label>\r\n <input matInput readonly=\"readonly\" #dateInput class=\"cursor-pointer\" id=\"date-input-field\">\r\n <button mat-icon-button matSuffix class=\"cursor-pointer pe-0 ps-0\" matTooltip=\"Clear\" *ngIf=\"!!dateInput.value\"\r\n (click)=\"clearSelection($event)\"><mat-icon>clear</mat-icon></button>\r\n <button mat-icon-button matSuffix class=\"cursor-pointer\"> <mat-icon>date_range</mat-icon></button>\r\n </mat-form-field>\r\n\r\n @if(dateDropDownOptions && dateDropDownOptions.length && isShowStaticDefaultOptions) {\r\n <mat-action-list class=\"w-full custom-ckd-container range-input\" [id]=\"staticOptionId\">\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if (option.isVisible) {\r\n <mat-list-item [activated]=\"option.isSelected\" (click)=\"updateSelection(option, dateInput)\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n }\r\n\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayHasBackdrop]=\"false\" [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"isDateOptionList\" [cdkConnectedOverlayPush]=\"cdkConnectedOverlayPush\"\r\n [cdkConnectedOverlayOffsetX]=\"listCdkConnectedOverlayOffsetX\" [cdkConnectedOverlayOffsetY]=\"listCdkConnectedOverlayOffsetY\"\r\n (overlayOutsideClick)=\"!isShowStaticDefaultOptions && toggleDateOptionSelectionList()\">\r\n\r\n @if(dateDropDownOptions && dateDropDownOptions.length && !isShowStaticDefaultOptions) {\r\n <mat-action-list [id]=\"dynamicOptionId\" class=\"w-full custom-ckd-container range-input\">\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if (option.isVisible) {\r\n <mat-list-item [activated]=\"option.isSelected\" (click)=\"updateSelection(option, dateInput)\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n }\r\n </ng-template>\r\n\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayHasBackdrop]=\"false\" [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"isCustomRange\" [cdkConnectedOverlayPush]=\"cdkConnectedOverlayPush\"\r\n [cdkConnectedOverlayPositions]=\"cdkConnectedOverlayPositions\" [cdkConnectedOverlayOffsetX]=\"cdkConnectedOverlayOffsetX\"\r\n [cdkConnectedOverlayOffsetY]=\"cdkConnectedOverlayOffsetY\" (overlayOutsideClick)=\"toggleCustomDateRangeView()\">\r\n <div class=\"custom-ckd-container custom-calendar-container\" [class]=\"{'without-default-opt':hideDefaultOptions}\">\r\n <div class=\"row-1\">\r\n <div class=\"pt-custom br-right column-1\" *ngIf=\"!hideDefaultOptions\">\r\n <mat-action-list>\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if(option.isVisible) {\r\n <mat-list-item (click)=\"updateSelection(option, dateInput)\"\r\n [activated]=\"option.isSelected\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n </div>\r\n <div class=\"mt-2 column-2\"><lib-calendar [selectedDates]=\"selectedDates\" #calendar [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"></lib-calendar></div>\r\n </div>\r\n <div class=\"row-2 br-top\">\r\n <div class=\"text-end my-2 w-full\">\r\n <div class=\"footer-content\">\r\n <span id=\"range-label-text\">\r\n {{calendar?.selectedDates?.start | date: dateFormat}}\r\n @if (calendar?.selectedDates?.end) {\r\n <span> - {{calendar.selectedDates?.end | date:\r\n dateFormat}} </span>\r\n }\r\n </span>\r\n <div class=\"d-inline buttons\">\r\n <button mat-button mat-raised-button class=\"p-3 mx-2\" (click)=\"isCustomRange=false;\">Cancel</button>\r\n <button mat-button mat-raised-button color=\"primary\" class=\"ms-2 p-3\"\r\n [class.disabled]=\"!(calendar?.selectedDates?.start && calendar?.selectedDates?.end)\"\r\n (click)=\"updateCustomRange(dateInput,calendar.selectedDates);\"> Apply </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n</div>\r\n", styles: ["::ng-deep .cdk-overlay-dark-backdrop{background:none}mat-list-item{height:35px}::ng-deep .cdk-overlay-pane:has(.custom-ckd-container){width:100%;background-color:var(--bg-color, white);max-height:100vh;overflow-y:auto;overflow-x:hidden;max-width:700px;margin-top:-22px;border:1px solid var(--border-color, #ddd)}::ng-deep .cdk-overlay-pane:has(.range-input){max-width:250px}.br-top{border-top:1px solid var(--border-color, #ddd)}.br-right{border-right:1px solid var(--border-color, #ddd)}.disabled{pointer-events:none;opacity:.5}.mat-button,.mdc-button{font-family:var(--mdc-list-list-item-label-text-font);line-height:var(--mdc-list-list-item-label-text-line-height);font-size:var(--mdc-list-list-item-label-text-size);font-weight:var(--mdc-list-list-item-label-text-weight);letter-spacing:var(--mdc-list-list-item-label-text-tracking)}.w-full{width:100%}.display-hidden{display:none}.custom-calendar-container,.row-1,.row-2{width:100%;display:block;float:left}.row-2{padding:.7rem}.footer-content{width:100%;align-items:center;display:flex;text-align:right;justify-content:end;gap:10px;margin-right:2rem;text-overflow:ellipsis}.buttons{margin-right:1.5rem;display:flex;gap:10px}.column-1{width:25%;display:block;float:left}.column-2{width:73%;display:block;float:left}@media (max-width: 400px){.footer-content{display:block}#range-label-text{margin-right:1.5rem}.buttons{float:right;margin-top:20px}}@media (max-width: 650px){.column-1,.column-2{width:100%}}@media (min-width: 650px){.column-1{width:25%}.column-2{width:74%}}.without-default-opt .column-1{display:none}.without-default-opt .column-2{width:100%;display:block;float:left}.pe-0{padding-right:0}.ps-0{padding-left:0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], 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: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatActionList, selector: "mat-action-list", exportAs: ["matActionList"] }, { kind: "component", type: i7.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i9.CalendarComponent, selector: "lib-calendar", inputs: ["selectedDates", "minDate", "maxDate"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: NgDatePickerComponent, decorators: [{
type: Component,
args: [{ selector: 'ng-date-range-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--**\r\n * @(#)ng-date-picker.component.html Sept 05, 2023\r\n\r\n * @author Aakash Kumar\r\n *-->\r\n<div class=\"date-picker-main\" cdkOverlayOrigin #trigger>\r\n <mat-form-field class=\"w-full\" [class]=\"{'display-hidden':isShowStaticDefaultOptions}\" (click)=\"toggleDateOptionSelectionList($event)\">\r\n <mat-label (click)=\"toggleDateOptionSelectionList($event)\">{{inputLabel}}</mat-label>\r\n <input matInput readonly=\"readonly\" #dateInput class=\"cursor-pointer\" id=\"date-input-field\">\r\n <button mat-icon-button matSuffix class=\"cursor-pointer pe-0 ps-0\" matTooltip=\"Clear\" *ngIf=\"!!dateInput.value\"\r\n (click)=\"clearSelection($event)\"><mat-icon>clear</mat-icon></button>\r\n <button mat-icon-button matSuffix class=\"cursor-pointer\"> <mat-icon>date_range</mat-icon></button>\r\n </mat-form-field>\r\n\r\n @if(dateDropDownOptions && dateDropDownOptions.length && isShowStaticDefaultOptions) {\r\n <mat-action-list class=\"w-full custom-ckd-container range-input\" [id]=\"staticOptionId\">\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if (option.isVisible) {\r\n <mat-list-item [activated]=\"option.isSelected\" (click)=\"updateSelection(option, dateInput)\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n }\r\n\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayHasBackdrop]=\"false\" [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"isDateOptionList\" [cdkConnectedOverlayPush]=\"cdkConnectedOverlayPush\"\r\n [cdkConnectedOverlayOffsetX]=\"listCdkConnectedOverlayOffsetX\" [cdkConnectedOverlayOffsetY]=\"listCdkConnectedOverlayOffsetY\"\r\n (overlayOutsideClick)=\"!isShowStaticDefaultOptions && toggleDateOptionSelectionList()\">\r\n\r\n @if(dateDropDownOptions && dateDropDownOptions.length && !isShowStaticDefaultOptions) {\r\n <mat-action-list [id]=\"dynamicOptionId\" class=\"w-full custom-ckd-container range-input\">\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if (option.isVisible) {\r\n <mat-list-item [activated]=\"option.isSelected\" (click)=\"updateSelection(option, dateInput)\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n }\r\n </ng-template>\r\n\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayHasBackdrop]=\"false\" [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"isCustomRange\" [cdkConnectedOverlayPush]=\"cdkConnectedOverlayPush\"\r\n [cdkConnectedOverlayPositions]=\"cdkConnectedOverlayPositions\" [cdkConnectedOverlayOffsetX]=\"cdkConnectedOverlayOffsetX\"\r\n [cdkConnectedOverlayOffsetY]=\"cdkConnectedOverlayOffsetY\" (overlayOutsideClick)=\"toggleCustomDateRangeView()\">\r\n <div class=\"custom-ckd-container custom-calendar-container\" [class]=\"{'without-default-opt':hideDefaultOptions}\">\r\n <div class=\"row-1\">\r\n <div class=\"pt-custom br-right column-1\" *ngIf=\"!hideDefaultOptions\">\r\n <mat-action-list>\r\n @for (option of dateDropDownOptions; track option.optionKey) {\r\n @if(option.isVisible) {\r\n <mat-list-item (click)=\"updateSelection(option, dateInput)\"\r\n [activated]=\"option.isSelected\">{{option.optionLabel}}</mat-list-item>\r\n }\r\n }\r\n </mat-action-list>\r\n </div>\r\n <div class=\"mt-2 column-2\"><lib-calendar [selectedDates]=\"selectedDates\" #calendar [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"></lib-calendar></div>\r\n </div>\r\n <div class=\"row-2 br-top\">\r\n <div class=\"text-end my-2 w-full\">\r\n <div class=\"footer-content\">\r\n <span id=\"range-label-text\">\r\n {{calendar?.selectedDates?.start | date: dateFormat}}\r\n @if (calendar?.selectedDates?.end) {\r\n <span> - {{calendar.selectedDates?.end | date:\r\n dateFormat}} </span>\r\n }\r\n </span>\r\n <div class=\"d-inline buttons\">\r\n <button mat-button mat-raised-button class=\"p-3 mx-2\" (click)=\"isCustomRange=false;\">Cancel</button>\r\n <button mat-button mat-raised-button color=\"primary\" class=\"ms-2 p-3\"\r\n [class.disabled]=\"!(calendar?.selectedDates?.start && calendar?.selectedDates?.end)\"\r\n (click)=\"updateCustomRange(dateInput,calendar.selectedDates);\"> Apply </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n</div>\r\n", styles: ["::ng-deep .cdk-overlay-dark-backdrop{background:none}mat-list-item{height:35px}::ng-deep .cdk-overlay-pane:has(.custom-ckd-container){width:100%;background-color:var(--bg-color, white);max-height:100vh;overflow-y:auto;overflow-x:hidden;max-width:700px;margin-top:-22px;border:1px solid var(--border-color, #ddd)}::ng-deep .cdk-overlay-pane:has(.range-input){max-width:250px}.br-top{border-top:1px solid var(--border-color, #ddd)}.br-right{border-right:1px solid var(--border-color, #ddd)}.disabled{pointer-events:none;opacity:.5}.mat-button,.mdc-button{font-family:var(--mdc-list-list-item-label-text-font);line-height:var(--mdc-list-list-item-label-text-line-height);font-size:var(--mdc-list-list-item-label-text-size);font-weight:var(--mdc-list-list-item-label-text-weight);letter-spacing:var(--mdc-list-list-item-label-text-tracking)}.w-full{width:100%}.display-hidden{display:none}.custom-calendar-container,.row-1,.row-2{width:100%;display:block;float:left}.row-2{padding:.7rem}.footer-content{width:100%;align-items:center;display:flex;text-align:right;justify-content:end;gap:10px;margin-right:2rem;text-overflow:ellipsis}.buttons{margin-right:1.5rem;display:flex;gap:10px}.column-1{width:25%;display:block;float:left}.column-2{width:73%;display:block;float:left}@media (max-width: 400px){.footer-content{display:block}#range-label-text{margin-right:1.5rem}.buttons{float:right;margin-top:20px}}@media (max-width: 650px){.column-1,.column-2{width:100%}}@media (min-width: 650px){.column-1{width:25%}.column-2{width:74%}}.without-default-opt .column-1{display:none}.without-default-opt .column-2{width:100%;display:block;float:left}.pe-0{padding-right:0}.ps-0{padding-left:0}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { inputLabel: [{
type: Input
}], staticOptionId: [{
type: Input
}], dynamicOptionId: [{
type: Input
}], calendarId: [{
type: Input
}], enableDefaultOptions: [{
type: Input
}], selectedDates: [{
type: Input
}], dateFormat: [{
type: Input
}], isShowStaticDefaultOptions: [{
type: Input
}], hideDefaultOptions: [{
type: Input
}], cdkConnectedOverlayOffsetX: [{
type: Input
}], cdkConnectedOverlayOffsetY: [{
type: Input
}], listCdkConnectedOverlayOffsetY: [{
type: Input
}], listCdkConnectedOverlayOffsetX: [{
type: Input
}], selectedOptionIndex: [{
type: Input
}], displaySelectedLabel: [{
type: Input
}], cdkConnectedOverlayPush: [{
type: Input
}], cdkConnectedOverlayPositions: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], onDateSelectionChanged: [{
type: Output
}], dateListOptions: [{
type: Output
}], dateDropDownOptions: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctZGF0ZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZGF0ZS1waWNrZXIvc3JjL2xpYi9uZy1kYXRlLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1kYXRlLXBpY2tlci9zcmMvbGliL25nLWRhdGUtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBRUwsdUJBQXVCLEVBRXZCLFNBQVMsRUFFVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3pELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDOzs7Ozs7Ozs7OztBQVVuRSxNQUFNLE9BQU8scUJBQXFCO0lBb0NoQyxZQUFvQixLQUF3QixFQUFVLEVBQWM7UUFBaEQsVUFBSyxHQUFMLEtBQUssQ0FBbUI7UUFBVSxPQUFFLEdBQUYsRUFBRSxDQUFZO1FBbkNwRSxxQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFDbEMsa0JBQWEsR0FBWSxLQUFLLENBQUM7UUFDdEIsZUFBVSxHQUFXLFlBQVksQ0FBQztRQUNsQyxtQkFBYyxHQUFHLGdCQUFnQixDQUFDO1FBQ2xDLG9CQUFlLEdBQUcsaUJBQWlCLENBQUM7UUFDcEMsZUFBVSxHQUFXLGlCQUFpQixDQUFDO1FBQ3ZDLHlCQUFvQixHQUFZLElBQUksQ0FBQztRQUVyQyxlQUFVLEdBQVcsWUFBWSxDQUFDO1FBQ2xDLCtCQUEwQixHQUFZLEtBQUssQ0FBQztRQUM1Qyx1QkFBa0Is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b0I7c0JBQTVCLEtBQUs7Z0JBQ0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUNHLDRCQUE0QjtzQkFBcEMsS0FBSztnQkFHRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csT0FBTztzQkFBZixLQUFLO2dCQUlJLHNCQUFzQjtzQkFBL0IsTUFBTTtnQkFDRyxlQUFlO3NCQUF4QixNQUFNO2dCQVVILG1CQUFtQjtzQkFEdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxyXG4gKiBAKCMpbmctZGF0ZS1waWNrZXIuY29tcG9uZW50LnRzIFNlcHQgMDUsIDIwMjNcclxuICpcclxuICogQGF1dGhvciBBYWthc2ggS3VtYXJcclxuICovXHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgRWxlbWVudFJlZixcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25Jbml0LFxyXG4gIE91dHB1dCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRGF0ZVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBEYXRlUmFuZ2UgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kYXRlcGlja2VyJztcclxuaW1wb3J0IHsgREVGQVVMVF9EQVRFX09QVElPTl9FTlVNIH0gZnJvbSAnLi9jb25zdGFudC9kYXRlLWZpbHRlci1lbnVtJztcclxuaW1wb3J0IHsgREVGQVVMVF9EQVRFX09QVElPTlMgfSBmcm9tICcuL2RhdGEvZGVmYXVsdC1kYXRlLW9wdGlvbnMnO1xyXG5pbXBvcnQgeyBJU2VsZWN0RGF0ZU9wdGlvbiB9IGZyb20gJy4vbW9kZWwvc2VsZWN0LWRhdGUtb3B0aW9uJztcclxuaW1wb3J0IHsgU2VsZWN0ZWREYXRlRXZlbnQgfSBmcm9tICcuLi9wdWJsaWMtYXBpJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmctZGF0ZS1yYW5nZS1waWNrZXInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9uZy1kYXRlLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vbmctZGF0ZS1waWNrZXIuY29tcG9uZW50LnNjc3MnXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5nRGF0ZVBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XHJcbiAgaXNEYXRlT3B0aW9uTGlzdDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGlzQ3VzdG9tUmFuZ2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBpbnB1dExhYmVsOiBzdHJpbmcgPSAnRGF0ZSBSYW5nZSc7XHJcbiAgQElucHV0KCkgc3RhdGljT3B0aW9uSWQgPSAnc3RhdGljLW9wdGlvbnMnO1xyXG4gIEBJbnB1dCgpIGR5bmFtaWNPcHRpb25JZCA9ICdkeW5hbWljLW9wdGlvbnMnO1xyXG4gIEBJbnB1dCgpIGNhbGVuZGFySWQ6IHN0cmluZyA9ICdjdXN0b20tY2FsZW5kYXInO1xyXG4gIEBJbnB1dCgpIGVuYWJsZURlZmF1bHRPcHRpb25zOiBib29sZWFuID0gdHJ1ZTtcclxuICBASW5wdXQoKSBzZWxlY3RlZERhdGVzITogRGF0ZVJhbmdlPERhdGU+IHwgbnVsbDtcclxuICBASW5wdXQoKSBkYXRlRm9ybWF0OiBzdHJpbmcgPSAnZGQvTU0veXl5eSc7XHJcbiAgQElucHV0KCkgaXNTaG93U3RhdGljRGVmYXVsdE9wdGlvbnM6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBoaWRlRGVmYXVsdE9wdGlvbnM6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBjZGtDb25uZWN0ZWRPdmVybGF5T2Zmc2V0WCA9IDA7XHJcbiAgQElucHV0KCkgY2RrQ29ubmVjdGVkT3ZlcmxheU9mZnNldFkgPSAwO1xyXG4gIEBJbnB1dCgpIGxpc3RDZGtDb25uZWN0ZWRPdmVybGF5T2Zmc2V0WSA9IDA7XHJcbiAgQElucHV0KCkgbGlzdENka0Nvbm5lY3RlZE92ZXJsYXlPZmZzZXRYID0gMDtcclxuICBASW5wdXQoKSBzZWxlY3RlZE9wdGlvbkluZGV4ID0gMztcclxuICBASW5wdXQoKSBkaXNwbGF5U2VsZWN0ZWRMYWJlbCA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGNka0Nvbm5lY3RlZE92ZXJsYXlQdXNoID0gdHJ1ZTtcclxuICBASW5wdXQoKSBjZGtDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25zID0gW107XHJcblxyXG4gIC8vIGRlZmF1bHQgbWluIGRhdGUgaXMgY3VycmVudCBkYXRlIC0gMTAgeWVhcnMuXHJcbiAgQElucHV0KCkgbWluRGF0ZSA9IG5ldyBEYXRlKFxyXG4gICAgbmV3IERhdGUoKS5zZXRGdWxsWWVhcihuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCkgLSAxMClcclxuICApO1xyXG5cclxuICAvLyBkZWZhdWx0IG1heCBkYXRlIGlzIGN1cnJlbnQgZGF0ZSAtIDEwIHllYXJzLlxyXG4gIEBJbnB1dCgpIG1heERhdGUgPSBuZXcgRGF0ZShcclxuICAgIG5ldyBEYXRlKCkuc2V0RnVsbFllYXIobmV3IERhdGUoKS5nZXRGdWxsWWVhcigpICsgMTApXHJcbiAgKTtcclxuXHJcbiAgQE91dHB1dCgpIG9uRGF0ZVNlbGVjdGlvbkNoYW5nZWQ6IEV2ZW50RW1pdHRlcjxTZWxlY3RlZERhdGVFdmVudD47XHJcbiAgQE91dHB1dCgpIGRhdGVMaXN0T3B0aW9uczogRXZlbnRFbWl0dGVyPElTZWxlY3REYXRlT3B0aW9uW10+O1xyXG5cclxuICBwcml2YXRlIF9kYXRlRHJvcERvd25PcHRpb25zOiBJU2VsZWN0RGF0ZU9wdGlvbltdID0gW107XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2RyZWY6IENoYW5nZURldGVjdG9yUmVmLCBwcml2YXRlIGVsOiBFbGVtZW50UmVmKSB7XHJcbiAgICB0aGlzLm9uRGF0ZVNlbGVjdGlvbkNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFNlbGVjdGVkRGF0ZUV2ZW50PigpO1xyXG4gICAgdGhpcy5kYXRlTGlzdE9wdGlvbnMgPSBuZXcgRXZlbnRFbWl0dGVyPElTZWxlY3REYXRlT3B0aW9uW10+KCk7XHJcbiAgfVxyXG5cclxuICBASW5wdXQoKVxyXG4gIHNldCBkYXRlRHJvcERvd25PcHRpb25zKGRlZmF1bHREYXRlTGlzdDogSVNlbGVjdERhdGVPcHRpb25bXSkge1xyXG4gICAgaWYgKHRoaXMuZW5hYmxlRGVmYXVsdE9wdGlvbnMpIHtcclxuICAgICAgdGhpcy5fZGF0ZURyb3BEb3duT3B0aW9ucyA9XHJcbiAgICAgICAgdGhpcy5nZXRDbG9uZTxJU2VsZWN0RGF0ZU9wdGlvbltdPihERUZBVUxUX0RBVEVfT1BUSU9OUykuY29uY2F0KFxyXG4gICAgICAgICAgZGVmYXVsdERhdGVMaXN0XHJcbiAgICAgICAgKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuX2RhdGVEcm9wRG93bk9wdGlvbnMgPSBkZWZhdWx0RGF0ZUxpc3Q7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXQgZGF0ZURyb3BEb3duT3B0aW9ucygpOiBJU2VsZWN0RGF0ZU9wdGlvbltdIHtcclxuICAgIHJldHVybiB0aGlzLl9kYXRlRHJvcERvd25PcHRpb25zID8/IFtdO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuX2RhdGVEcm9wRG93bk9wdGlvbnMubGVuZ3RoICYmIHRoaXMuZW5hYmxlRGVmYXVsdE9wdGlvbnMpIHtcclxuICAgICAgdGhpcy5fZGF0ZURyb3BEb3duT3B0aW9ucyA9XHJcbiAgICAgICAgdGhpcy5nZXRDbG9uZTxJU2VsZWN0RGF0ZU9wdGlvbltdPihERUZBVUxUX0RBVEVfT1BUSU9OUyk7XHJcbiAgICAgIHRoaXMuX2RhdGVEcm9wRG93bk9wdGlvbnNbdGhpcy5zZWxlY3RlZE9wdGlvbkluZGV4XS5pc1NlbGVjdGVkID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHRoaXMuZGF0ZUxpc3RPcHRpb25zLmVtaXQodGhpcy5kYXRlRHJvcERvd25PcHRpb25zKTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMudXBkYXRlRGVmYXVsdERhdGVzVmFsdWVzKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIG1ldGhvZCB0b2dnbGVzIHRoZSB2aXNpYmlsaXR5IG9mIGRlZmF1bHQgZGF0ZSBvcHRpb24ncyBMaXN0LlxyXG4gICAqL1xyXG4gIHRvZ2dsZURhdGVPcHRpb25TZWxlY3Rpb25MaXN0KGV2ZW50PzogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgaWYgKGV2ZW50KSB7XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xyXG4gICAgfVxyXG4gICAgY29uc3Qgc2VsZWN0ZWRPcHRpb24gPSB0aGlzLmRhdGVEcm9wRG93bk9wdGlvbnMuZmlsdGVyKFxyXG4gICAgICAob3B0aW9uKSA9PiBvcHRpb24uaXNTZWxlY3RlZFxyXG4gICAgKTtcclxuICAgIGlmIChcclxuICAgICAgc2VsZWN0ZWRPcHRpb24ubGVuZ3RoICYmXHJcbiAgICAgIHNlbGVjdGVkT3B0aW9uWzBdLm9wdGlvbktleSA9PT0gREVGQVVMVF9EQVRFX09QVElPTl9FTlVNLkNVU1RPTVxyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMudG9nZ2xlQ3VzdG9tRGF0ZVJhbmdlVmlldygpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5pc0RhdGVPcHRpb25MaXN0ID0gIXRoaXMuaXNEYXRlT3B0aW9uTGlzdDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgdGhlIGRhdGUgcmFuZ2Ugb24gYnV0dG9uIGNsaWNrLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGlucHV0IEhUTUxJbnB1dEVsZW1lbnRcclxuICAgKiBAcGFyYW0gc2VsZWN0ZWREYXRlcyBEYXRlUmFuZ2U8RGF0ZT5cclxuICAgKi9cclxuICB1cGRhdGVDdXN0b21SYW5nZShcclxuICAgIGlucHV0OiBIVE1MSW5wdXRFbGVtZW50LFxyXG4gICAgc2VsZWN0ZWREYXRlczogRGF0ZVJhbmdlPERhdGU+IHwgbnVsbFxyXG4gICk6IHZvaWQge1xyXG4gICAgdGhpcy51cGRhdGVTZWxlY3RlZERhdGVzKFxyXG4gICAgICBpbnB1dCxcclxuICAgICAgc2VsZWN0ZWREYXRlcz8uc3RhcnQgPz8gbmV3IERhdGUoKSxcclxuICAgICAgc2VsZWN0ZWREYXRlcz8uZW5kID8/IG5ldyBEYXRlKCksXHJcbiAgICAgIG51bGxcclxuICAgICk7XHJcbiAgICBpZiAodGhpcy5pc0N1c3RvbVJhbmdlKSB7XHJcbiAgICAgIHRoaXMucmVzZXRPcHRpb25TZWxlY3Rpb24oKTtcclxuICAgICAgdGhpcy5zZWxlY3RDdXN0b21PcHRpb24oKTtcclxuICAgICAgdGhpcy5pc0N1c3RvbVJhbmdlID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGlzIG1ldGhvZCB1cGRh