UNPKG

angular-nepali-datepicker

Version:

Simple Nepali datepicker component for angular applications

380 lines 36.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Component, forwardRef, Input, ViewEncapsulation } from "@angular/core"; import * as NepaliDateConverter from "nepali-date"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import { daysMapping, monthsMapping } from "./mapping"; var DatepickerComponent = /** @class */ (function () { function DatepickerComponent() { var _this = this; this.nepaliDateToday = { day: 0, month: 0, year: 0 }; this.currentNepaliDate = { day: 0, month: 0, year: 0 }; this.formattedDate = ""; this.currentDate = new Date(); this.years = []; this.daysMapping = daysMapping; this.monthsMapping = monthsMapping; this.isOpen = false; this.hideInput = false; this.alwaysVisible = false; this.language = "ne"; this.monthDisplayType = "default"; this.dayDisplayType = "default"; this.dateFormatter = function (selectedDate) { /** @type {?} */ var dd = selectedDate.day < 10 ? "0" + selectedDate.day : selectedDate.day; /** @type {?} */ var mm = selectedDate.month < 10 ? "0" + selectedDate.month : selectedDate.month; return dd + "/" + mm + "/" + _this.selectedDate.year; }; this.propagateChange = function (_) { }; this.propagateTouch = function (_) { }; } /** * @return {?} */ DatepickerComponent.prototype.ngOnInit = /** * @return {?} */ function () { /** @type {?} */ var nepaliDateToday = new NepaliDateConverter(new Date()); this.nepaliDateToday = { year: nepaliDateToday.getYear(), month: nepaliDateToday.getMonth(), day: nepaliDateToday.getDate() }; this.setCurrentDate(); this.populateYears(); this.setCurrentMonthData(); }; /** * @return {?} */ DatepickerComponent.prototype.setCurrentDate = /** * @return {?} */ function () { /** @type {?} */ var currentNepaliDate; if (!this.selectedDate) { currentNepaliDate = new NepaliDateConverter(this.currentDate); } else { var _a = this.selectedDate, year = _a.year, month = _a.month, day = _a.day; currentNepaliDate = new NepaliDateConverter(year, month, day); this.currentDate = currentNepaliDate.getEnglishDate(); } this.currentNepaliDate = { year: currentNepaliDate.getYear(), month: currentNepaliDate.getMonth(), day: currentNepaliDate.getDate() }; }; /** * @return {?} */ DatepickerComponent.prototype.populateYears = /** * @return {?} */ function () { for (var i = 2001; i <= 2088; i++) { this.years.push(i); } }; /** * @return {?} */ DatepickerComponent.prototype.resetCurrentMonthData = /** * @return {?} */ function () { this.currentMonthData = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [] }; }; /** * @return {?} */ DatepickerComponent.prototype.formatValue = /** * @return {?} */ function () { if (this.selectedDate) { this.formattedDate = this.dateFormatter(this.selectedDate); } }; /** * @param {?} value * @return {?} */ DatepickerComponent.prototype.writeValue = /** * @param {?} value * @return {?} */ function (value) { if (value) { this.selectedDate = value; this.currentNepaliDate = value; this.formatValue(); } }; /** * @return {?} */ DatepickerComponent.prototype.registerOnTouched = /** * @return {?} */ function () { }; /** * @param {?} fn * @return {?} */ DatepickerComponent.prototype.registerOnChange = /** * @param {?} fn * @return {?} */ function (fn) { this.propagateChange = fn; }; /** * @return {?} */ DatepickerComponent.prototype.setCurrentMonthData = /** * @return {?} */ function () { this.resetCurrentMonthData(); // fill the currentMonthData with current date /** @type {?} */ var day = this.currentDate.getDay(); this.currentMonthData[day] = [this.currentNepaliDate.day]; // fill the currentMonthData with day before the current date this.setMonthDataBefore(day - 1, this.currentNepaliDate.day - 1); // fill the currentMonthData with day after the current date this.setMonthDataAfter(day + 1, this.currentNepaliDate.day + 1); // we need some empty spaces in place so that the dates are shown in correct order // eg if the 1st day starts on monday then we need 1 empty space for non existingn date on Sunday this.createEmptySpaces(); }; /** * @param {?} day * @param {?} date * @return {?} */ DatepickerComponent.prototype.setMonthDataBefore = /** * @param {?} day * @param {?} date * @return {?} */ function (day, date) { if (date >= 1) { if (day < 0) { day = 6; } this.currentMonthData[day] = tslib_1.__spread([date], this.currentMonthData[day]); this.setMonthDataBefore(--day, --date); } }; /** * @param {?} day * @param {?} date * @return {?} */ DatepickerComponent.prototype.setMonthDataAfter = /** * @param {?} day * @param {?} date * @return {?} */ function (day, date) { /** @type {?} */ var nepaliDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, date); // only add the data if the current month matches if (nepaliDate.getMonth() === this.currentNepaliDate.month) { if (day > 6) { day = 0; } this.currentMonthData[day] = tslib_1.__spread(this.currentMonthData[day], [date]); this.setMonthDataAfter(++day, ++date); } }; /** * @return {?} */ DatepickerComponent.prototype.createEmptySpaces = /** * @return {?} */ function () { // first find out which day has the 1st // if its a Sunday, then don't do anything else add 1 space on each previous day /** @type {?} */ var dayIndex = 0; Object.values(this.currentMonthData).find(function (value, index) { if (value.includes(1)) { dayIndex = index; } return value.includes(1); }); if (dayIndex) { for (dayIndex; dayIndex > 0; dayIndex--) { /** @type {?} */ var monthData = this.currentMonthData[dayIndex - 1]; this.currentMonthData[dayIndex - 1] = tslib_1.__spread([null], monthData); } } }; /** * @param {?} day * @return {?} */ DatepickerComponent.prototype.selectDate = /** * @param {?} day * @return {?} */ function (day) { this.selectedDate = tslib_1.__assign({}, this.currentNepaliDate, { day: day }); this.formatValue(); this.close(); this.propagateChange(this.selectedDate); }; /** * @param {?} year * @return {?} */ DatepickerComponent.prototype.selectYear = /** * @param {?} year * @return {?} */ function (year) { this.currentNepaliDate.year = +year; /** @type {?} */ var newDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, this.currentNepaliDate.day); this.currentDate = newDate.getEnglishDate(); this.setCurrentMonthData(); }; /** * @param {?} month * @return {?} */ DatepickerComponent.prototype.selectMonth = /** * @param {?} month * @return {?} */ function (month) { this.currentNepaliDate.month = this.monthsMapping[this.language][this.monthDisplayType].indexOf(month); /** @type {?} */ var newDate = new NepaliDateConverter(this.currentNepaliDate.year, this.currentNepaliDate.month, this.currentNepaliDate.day); this.currentDate = newDate.getEnglishDate(); this.setCurrentMonthData(); }; /** * @return {?} */ DatepickerComponent.prototype.toggleOpen = /** * @return {?} */ function () { if (!this.alwaysVisible) { this.isOpen = !this.isOpen; } }; /** * @return {?} */ DatepickerComponent.prototype.open = /** * @return {?} */ function () { this.isOpen = true; }; /** * @return {?} */ DatepickerComponent.prototype.close = /** * @return {?} */ function () { this.isOpen = false; this.setCurrentDate(); }; DatepickerComponent.decorators = [ { type: Component, args: [{ selector: "np-datepicker", template: "<input\r\n class=\"datepicker__input\"\r\n type=\"text\"\r\n [value]=\"formattedDate | toNp: language\"\r\n [ngClass]=\"inputClass\"\r\n #origin=\"cdkOverlayOrigin\"\r\n cdk-overlay-origin\r\n (focus)=\"open()\"\r\n (keydown)=\"$event.preventDefault()\"\r\n aria-hidden=\"true\"\r\n [hidden]=\"hideInput\">\r\n<ng-template\r\n cdk-connected-overlay\r\n cdkConnectedOverlayLockPosition\r\n cdkConnectedOverlayHasBackdrop\r\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\r\n [cdkConnectedOverlayOrigin]=\"origin\"\r\n [cdkConnectedOverlayOpen]=\"isOpen\"\r\n (backdropClick)=\"close()\"\r\n (detach)=\"close()\">\r\n <ng-container [ngTemplateOutlet]=\"dp\"></ng-container>\r\n</ng-template>\r\n\r\n<ng-container [ngTemplateOutlet]=\"dp\" *ngIf=\"alwaysVisible\"></ng-container>\r\n\r\n<ng-template #dp>\r\n <div class=\"datepicker__container\">\r\n <div class=\"datepicker__options-container\">\r\n <span class=\"datepicker__options-year-container\">\r\n <span>\r\n {{'Year' | toNp : language : 'word'}}:\r\n </span>\r\n <select (change)=\"selectYear($event.target.value)\">\r\n <option\r\n *ngFor=\"let year of years\"\r\n [value]=\"year\"\r\n [selected]=\"year === currentNepaliDate?.year\">\r\n {{year | toNp: language }}\r\n </option>\r\n </select>\r\n </span>\r\n <span class=\"datepicker__options-month-container\">\r\n <span>{{'Month' | toNp : language : 'word'}}: </span>\r\n <select (change)=\"selectMonth($event.target.value)\">\r\n <option\r\n *ngFor=\"let month of monthsMapping[language][monthDisplayType]; index as i\"\r\n [value]=\"month\"\r\n [selected]=\"i === currentNepaliDate?.month\">\r\n {{month}}\r\n </option>\r\n </select>\r\n </span>\r\n </div>\r\n <div class=\"datepicker__days-container\">\r\n <div class=\"datepicker__days\" *ngFor=\"let day of daysMapping[language][dayDisplayType]; index as i\">\r\n <div class=\"datepicker__weekday\">{{day}}</div>\r\n <div class=\"datepicker__date-container\" *ngFor=\"let date of currentMonthData[i]\">\r\n <div\r\n class=\"datepicker__date\"\r\n [class.datepicker__date--active]=\"\r\n date === selectedDate?.day &&\r\n currentNepaliDate.month === selectedDate?.month &&\r\n currentNepaliDate.year === selectedDate?.year\r\n \"\r\n [class.datepicker__date--current-day]=\"\r\n date === nepaliDateToday.day &&\r\n currentNepaliDate.month === nepaliDateToday.month &&\r\n currentNepaliDate.year === nepaliDateToday.year\r\n \"\r\n [class.datepicker__date--disabled]=\"!date\"\r\n (click)=\"selectDate(date)\">\r\n <span *ngIf=\"!date\">&nbsp;</span>\r\n {{date | toNp: language }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>", providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(function () { return DatepickerComponent; }), multi: true } ], encapsulation: ViewEncapsulation.None, styles: [".cdk-global-overlay-wrapper,.cdk-overlay-container{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;top:0;bottom:0;left:0;right:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:transparent;transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}@media screen and (-ms-high-contrast:active){.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}}.cdk-overlay-dark-backdrop{background:rgba(0,0,0,.32)}.cdk-overlay-transparent-backdrop,.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}.datepicker__input{display:block}.datepicker__container{--font-family:arial,sans-serif;--font-size:14px;--container-padding:8px 5px;--container-border-color:lightgray;--container-border:1px solid;--container-background-color:white;--select-height:24px;--option-margin:0 0 7px;--option-year-container-margin:0 10px 0;--days-size:40px;--weekday-margin:0 0 5px;--active-day-color:white;--active-day-background:#27a4f7;--hover-color:#27a4f7;--selected-color:#27a4f7;display:inline-block;font-family:\"arial, sans-serif\";font-family:var(--font-family);font-size:14px;font-size:var(--font-size);padding:8px 5px;padding:var(--container-padding);border:1px solid #d3d3d3;border:var(--container-border);border-color:var(--container-border-color);background-color:#fff;background-color:var(--container-background-color)}.datepicker__options-container{margin:0 0 7px;margin:var(--option-margin)}.datepicker__options-container select{height:24px;height:var(--select-height)}.datepicker__options-year-container{display:inline-block;margin:0 10px;margin:var(--option-year-container-margin)}.datepicker__days{display:inline-block;vertical-align:top;text-align:center;width:40px;width:var(--days-size)}.datepicker__weekday{margin:0 0 5px;margin:var(--weekday-margin);font-weight:700;text-align:center}.datepicker__date{width:40px;width:var(--days-size);height:40px;height:var(--days-size);line-height:40px;line-height:var(--days-size);cursor:pointer}.datepicker__date--active{color:#fff;color:var(--active-day-color);background:#27a4f7;background:var(--active-day-background)}.datepicker__date--current-day:not(.datepicker__date--active){color:#27a4f7;color:var(--selected-color);font-weight:700}.datepicker__date--disabled{pointer-events:none}.datepicker__date:hover:not(.datepicker__date--active){color:#27a4f7;color:var(--hover-color);transition:color .3s}"] }] } ]; /** @nocollapse */ DatepickerComponent.ctorParameters = function () { return []; }; DatepickerComponent.propDecorators = { hideInput: [{ type: Input }], alwaysVisible: [{ type: Input }], inputClass: [{ type: Input }], language: [{ type: Input }], monthDisplayType: [{ type: Input }], dayDisplayType: [{ type: Input }], dateFormatter: [{ type: Input }] }; return DatepickerComponent; }()); export { DatepickerComponent }; if (false) { /** @type {?} */ DatepickerComponent.prototype.nepaliDateToday; /** @type {?} */ DatepickerComponent.prototype.currentNepaliDate; /** @type {?} */ DatepickerComponent.prototype.selectedDate; /** @type {?} */ DatepickerComponent.prototype.formattedDate; /** @type {?} */ DatepickerComponent.prototype.currentDate; /** @type {?} */ DatepickerComponent.prototype.displayDate; /** @type {?} */ DatepickerComponent.prototype.years; /** @type {?} */ DatepickerComponent.prototype.currentMonthData; /** @type {?} */ DatepickerComponent.prototype.daysMapping; /** @type {?} */ DatepickerComponent.prototype.monthsMapping; /** @type {?} */ DatepickerComponent.prototype.isOpen; /** @type {?} */ DatepickerComponent.prototype.hideInput; /** @type {?} */ DatepickerComponent.prototype.alwaysVisible; /** @type {?} */ DatepickerComponent.prototype.inputClass; /** @type {?} */ DatepickerComponent.prototype.language; /** @type {?} */ DatepickerComponent.prototype.monthDisplayType; /** @type {?} */ DatepickerComponent.prototype.dayDisplayType; /** @type {?} */ DatepickerComponent.prototype.dateFormatter; /** @type {?} */ DatepickerComponent.prototype.propagateChange; /** @type {?} */ DatepickerComponent.prototype.propagateTouch; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLW5lcGFsaS1kYXRlcGlja2VyLyIsInNvdXJjZXMiOlsibGliL2RhdGVwaWNrZXIvZGF0ZXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFVBQVUsRUFDVixLQUFLLEVBQ0wsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sS0FBSyxtQkFBbUIsTUFBTSxhQUFhLENBQUM7QUFDbkQsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBUXpFLE9BQU8sRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXZEO0lBMkRFO1FBQUEsaUJBQWdCO1FBN0NoQixvQkFBZSxHQUFlLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUM1RCxzQkFBaUIsR0FBZSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFFOUQsa0JBQWEsR0FBRyxFQUFFLENBQUM7UUFDbkIsZ0JBQVcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBSXpCLFVBQUssR0FBYSxFQUFFLENBQUM7UUFJckIsZ0JBQVcsR0FBZ0IsV0FBVyxDQUFDO1FBRXZDLGtCQUFhLEdBQWlCLGFBQWEsQ0FBQztRQUU1QyxXQUFNLEdBQUcsS0FBSyxDQUFDO1FBR2YsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUdsQixrQkFBYSxHQUFHLEtBQUssQ0FBQztRQU10QixhQUFRLEdBQWdCLElBQUksQ0FBQztRQUc3QixxQkFBZ0IsR0FBbUMsU0FBUyxDQUFDO1FBRzdELG1CQUFjLEdBQXdCLFNBQVMsQ0FBQztRQUdoRCxrQkFB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QzVELGdEQUE4RDs7SUFDOUQsMkNBQXlCOztJQUN6Qiw0Q0FBbUI7O0lBQ25CLDBDQUF5Qjs7SUFFekIsMENBQW9COztJQUVwQixvQ0FBcUI7O0lBRXJCLCtDQUE0Qjs7SUFFNUIsMENBQXVDOztJQUV2Qyw0Q0FBNEM7O0lBRTVDLHFDQUFlOztJQUVmLHdDQUNrQjs7SUFFbEIsNENBQ3NCOztJQUV0Qix5Q0FDbUI7O0lBRW5CLHVDQUM2Qjs7SUFFN0IsK0NBQzZEOztJQUU3RCw2Q0FDZ0Q7O0lBRWhELDRDQU9FOztJQXlERiw4Q0FBaUM7O0lBRWpDLDZDQUFnQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uSW5pdCxcclxuICBmb3J3YXJkUmVmLFxyXG4gIElucHV0LFxyXG4gIFZpZXdFbmNhcHN1bGF0aW9uXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0ICogYXMgTmVwYWxpRGF0ZUNvbnZlcnRlciBmcm9tIFwibmVwYWxpLWRhdGVcIjtcclxuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XHJcbmltcG9ydCB7XHJcbiAgTmVwYWxpRGF0ZSxcclxuICBNb250aERhdGEsXHJcbiAgRGF5c01hcHBpbmcsXHJcbiAgTW9udGhNYXBwaW5nLFxyXG4gIERhdGVGb3JtYXR0ZXJcclxufSBmcm9tIFwiLi90eXBlc1wiO1xyXG5pbXBvcnQgeyBkYXlzTWFwcGluZywgbW9udGhzTWFwcGluZyB9IGZyb20gXCIuL21hcHBpbmdcIjtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiBcIm5wLWRhdGVwaWNrZXJcIixcclxuICB0ZW1wbGF0ZVVybDogXCIuL2RhdGVwaWNrZXIuY29tcG9uZW50Lmh0bWxcIixcclxuICBzdHlsZVVybHM6IFtcIi4vZGF0ZXBpY2tlci5jb21wb25lbnQuc2Nzc1wiXSxcclxuICBwcm92aWRlcnM6IFtcclxuICAgIHtcclxuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVwaWNrZXJDb21wb25lbnQpLFxyXG4gICAgICBtdWx0aTogdHJ1ZVxyXG4gICAgfVxyXG4gIF0sXHJcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRGF0ZXBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xyXG4gIG5lcGFsaURhdGVUb2RheTogTmVwYWxpRGF0ZSA9IHsgZGF5OiAwLCBtb250aDogMCwgeWVhcjogMCB9O1xyXG4gIGN1cnJlbnROZXBhbGlEYXRlOiBOZXBhbGlEYXRlID0geyBkYXk6IDAsIG1vbnRoOiAwLCB5ZWFyOiAwIH07XHJcbiAgc2VsZWN0ZWREYXRlOiBOZXBhbGlEYXRlO1xyXG4gIGZvcm1hdHRlZERhdGUgPSBcIlwiO1xyXG4gIGN1cnJlbnREYXRlID0gbmV3IERhdGUoKTtcclxuXHJcbiAgZGlzcGxheURhdGU6IHN0cmluZztcclxuXHJcbiAgeWVhcnM6IG51bWJlcltdID0gW107XHJcblxyXG4gIGN1cnJlbnRNb250aERhdGE6IE1vbnRoRGF0YTtcclxuXHJcbiAgZGF5c01hcHBpbmc6IERheXNNYXBwaW5nID0gZGF5c01hcHBpbmc7XHJcblxyXG4gIG1vbnRoc01hcHBpbmc6IE1vbnRoTWFwcGluZyA9IG1vbnRoc01hcHBpbmc7XHJcblxyXG4gIGlzT3BlbiA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGhpZGVJbnB1dCA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKVxyXG4gIGFsd2F5c1Zpc2libGUgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KClcclxuICBpbnB1dENsYXNzOiBzdHJpbmc7XHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgbGFuZ3VhZ2U6IFwiZW5cIiB8IFwibmVcIiA9IFwibmVcIjtcclxuXHJcbiAgQElucHV0KClcclxuICBtb250aERpc3BsYXlUeXBlOiBcImRlZmF1bHRcIiB8IFwibW9kZXJuXCIgfCBcInNob3J0XCIgPSBcImRlZmF1bHRcIjtcclxuXHJcbiAgQElucHV0KClcclxuICBkYXlEaXNwbGF5VHlwZTogXCJkZWZhdWx0XCIgfCBcInNob3J0XCIgPSBcImRlZmF1bHRcIjtcclxuXHJcbiAgQElucHV0KClcclxuICBkYXRlRm9ybWF0dGVyOiBEYXRlRm9ybWF0dGVyID0gKHNlbGVjdGVkRGF0ZTogTmVwYWxpRGF0ZSkgPT4ge1xyXG4gICAgY29uc3QgZGQgPVxyXG4gICAgICBzZWxlY3RlZERhdGUuZGF5IDwgMTAgPyBcIjBcIiArIHNlbGVjdGVkRGF0ZS5kYXkgOiBzZWxlY3RlZERhdGUuZGF5O1xyXG4gICAgY29uc3QgbW0gPVxyXG4gICAgICBzZWxlY3RlZERhdGUubW9udGggPCAxMCA/IFwiMFwiICsgc2VsZWN0ZWREYXRlLm1vbnRoIDogc2VsZWN0ZWREYXRlLm1vbnRoO1xyXG4gICAgcmV0dXJuIGAke2RkfS8ke21tfS8ke3RoaXMuc2VsZWN0ZWREYXRlLnllYXJ9YDtcclxuICB9O1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgY29uc3QgbmVwYWxpRGF0ZVRvZGF5ID0gbmV3IE5lcGFsaURhdGVDb252ZXJ0ZXIobmV3IERhdGUoKSk7XHJcbiAgICB0aGlzLm5lcGFsaURhdGVUb2RheSA9IHtcclxuICAgICAgeWVhcjogbmVwYWxpRGF0ZVRvZGF5LmdldFllYXIoKSxcclxuICAgICAgbW9udGg6IG5lcGFsaURhdGVUb2RheS5nZXRNb250aCgpLFxyXG4gICAgICBkYXk6IG5lcGFsaURhdGVUb2RheS5nZXREYXRlKClcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5zZXRDdXJyZW50RGF0ZSgpO1xyXG4gICAgdGhpcy5wb3B1bGF0ZVllYXJzKCk7XHJcbiAgICB0aGlzLnNldEN1cnJlbnRNb250aERhdGEoKTtcclxuICB9XHJcblxyXG4gIHNldEN1cnJlbnREYXRlKCkge1xyXG4gICAgbGV0IGN1cnJlbnROZXBhbGlEYXRlO1xyXG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkRGF0ZSkge1xyXG4gICAgICBjdXJyZW50TmVwYWxpRGF0ZSA9IG5ldyBOZXBhbGlEYXRlQ29udmVydGVyKHRoaXMuY3VycmVudERhdGUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgeyB5ZWFyLCBtb250aCwgZGF5IH0gPSB0aGlzLnNlbGVjdGVkRGF0ZTtcclxuICAgICAgY3VycmVudE5lcGFsaURhdGUgPSBuZXcgTmVwYWxpRGF0ZUNvbnZlcnRlcih5ZWFyLCBtb250aCwgZGF5KTtcclxuICAgICAgdGhpcy5jdXJyZW50RGF0ZSA9IGN1cnJlbnROZXBhbGlEYXRlLmdldEVuZ2xpc2hEYXRlKCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlID0ge1xyXG4gICAgICB5ZWFyOiBjdXJyZW50TmVwYWxpRGF0ZS5nZXRZZWFyKCksXHJcbiAgICAgIG1vbnRoOiBjdXJyZW50TmVwYWxpRGF0ZS5nZXRNb250aCgpLFxyXG4gICAgICBkYXk6IGN1cnJlbnROZXBhbGlEYXRlLmdldERhdGUoKVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHBvcHVsYXRlWWVhcnMoKSB7XHJcbiAgICBmb3IgKGxldCBpID0gMjAwMTsgaSA8PSAyMDg4OyBpKyspIHtcclxuICAgICAgdGhpcy55ZWFycy5wdXNoKGkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmVzZXRDdXJyZW50TW9udGhEYXRhKCkge1xyXG4gICAgdGhpcy5jdXJyZW50TW9udGhEYXRhID0ge1xyXG4gICAgICAwOiBbXSxcclxuICAgICAgMTogW10sXHJcbiAgICAgIDI6IFtdLFxyXG4gICAgICAzOiBbXSxcclxuICAgICAgNDogW10sXHJcbiAgICAgIDU6IFtdLFxyXG4gICAgICA2OiBbXVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGZvcm1hdFZhbHVlKCkge1xyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWREYXRlKSB7XHJcbiAgICAgIHRoaXMuZm9ybWF0dGVkRGF0ZSA9IHRoaXMuZGF0ZUZvcm1hdHRlcih0aGlzLnNlbGVjdGVkRGF0ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7fTtcclxuXHJcbiAgcHJvcGFnYXRlVG91Y2ggPSAoXzogYW55KSA9PiB7fTtcclxuXHJcbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KSB7XHJcbiAgICBpZiAodmFsdWUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZERhdGUgPSB2YWx1ZTtcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZSA9IHZhbHVlO1xyXG4gICAgICB0aGlzLmZvcm1hdFZhbHVlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uVG91Y2hlZCgpIHt9XHJcblxyXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm4pIHtcclxuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICBzZXRDdXJyZW50TW9udGhEYXRhKCkge1xyXG4gICAgdGhpcy5yZXNldEN1cnJlbnRNb250aERhdGEoKTtcclxuICAgIC8vIGZpbGwgdGhlIGN1cnJlbnRNb250aERhdGEgd2l0aCBjdXJyZW50IGRhdGVcclxuICAgIGNvbnN0IGRheSA9IHRoaXMuY3VycmVudERhdGUuZ2V0RGF5KCk7XHJcbiAgICB0aGlzLmN1cnJlbnRNb250aERhdGFbZGF5XSA9IFt0aGlzLmN1cnJlbnROZXBhbGlEYXRlLmRheV07XHJcblxyXG4gICAgLy8gZmlsbCB0aGUgY3VycmVudE1vbnRoRGF0YSB3aXRoIGRheSBiZWZvcmUgdGhlIGN1cnJlbnQgZGF0ZVxyXG4gICAgdGhpcy5zZXRNb250aERhdGFCZWZvcmUoZGF5IC0gMSwgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5kYXkgLSAxKTtcclxuXHJcbiAgICAvLyBmaWxsIHRoZSBjdXJyZW50TW9udGhEYXRhIHdpdGggZGF5IGFmdGVyIHRoZSBjdXJyZW50IGRhdGVcclxuICAgIHRoaXMuc2V0TW9udGhEYXRhQWZ0ZXIoZGF5ICsgMSwgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5kYXkgKyAxKTtcclxuXHJcbiAgICAvLyB3ZSBuZWVkIHNvbWUgZW1wdHkgc3BhY2VzIGluIHBsYWNlIHNvIHRoYXQgdGhlIGRhdGVzIGFyZSBzaG93biBpbiBjb3JyZWN0IG9yZGVyXHJcbiAgICAvLyBlZyBpZiB0aGUgMXN0IGRheSBzdGFydHMgb24gbW9uZGF5IHRoZW4gd2UgbmVlZCAxIGVtcHR5IHNwYWNlIGZvciBub24gZXhpc3RpbmduIGRhdGUgb24gU3VuZGF5XHJcbiAgICB0aGlzLmNyZWF0ZUVtcHR5U3BhY2VzKCk7XHJcbiAgfVxyXG5cclxuICBzZXRNb250aERhdGFCZWZvcmUoZGF5LCBkYXRlKSB7XHJcbiAgICBpZiAoZGF0ZSA+PSAxKSB7XHJcbiAgICAgIGlmIChkYXkgPCAwKSB7XHJcbiAgICAgICAgZGF5ID0gNjtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmN1cnJlbnRNb250aERhdGFbZGF5XSA9IFtkYXRlLCAuLi50aGlzLmN1cnJlbnRNb250aERhdGFbZGF5XV07XHJcbiAgICAgIHRoaXMuc2V0TW9udGhEYXRhQmVmb3JlKC0tZGF5LCAtLWRhdGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2V0TW9udGhEYXRhQWZ0ZXIoZGF5LCBkYXRlKSB7XHJcbiAgICBjb25zdCBuZXBhbGlEYXRlID0gbmV3IE5lcGFsaURhdGVDb252ZXJ0ZXIoXHJcbiAgICAgIHRoaXMuY3VycmVudE5lcGFsaURhdGUueWVhcixcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5tb250aCxcclxuICAgICAgZGF0ZVxyXG4gICAgKTtcclxuICAgIC8vICBvbmx5IGFkZCB0aGUgZGF0YSBpZiB0aGUgY3VycmVudCBtb250aCBtYXRjaGVzXHJcbiAgICBpZiAobmVwYWxpRGF0ZS5nZXRNb250aCgpID09PSB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLm1vbnRoKSB7XHJcbiAgICAgIGlmIChkYXkgPiA2KSB7XHJcbiAgICAgICAgZGF5ID0gMDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmN1cnJlbnRNb250aERhdGFbZGF5XSA9IFsuLi50aGlzLmN1cnJlbnRNb250aERhdGFbZGF5XSwgZGF0ZV07XHJcbiAgICAgIHRoaXMuc2V0TW9udGhEYXRhQWZ0ZXIoKytkYXksICsrZGF0ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjcmVhdGVFbXB0eVNwYWNlcygpIHtcclxuICAgIC8vIGZpcnN0IGZpbmQgb3V0IHdoaWNoIGRheSBoYXMgdGhlIDFzdFxyXG4gICAgLy8gIGlmIGl0cyBhIFN1bmRheSwgdGhlbiBkb24ndCBkbyBhbnl0aGluZyBlbHNlIGFkZCAxIHNwYWNlIG9uIGVhY2ggcHJldmlvdXMgZGF5XHJcbiAgICBsZXQgZGF5SW5kZXggPSAwO1xyXG4gICAgT2JqZWN0LnZhbHVlcyh0aGlzLmN1cnJlbnRNb250aERhdGEpLmZpbmQoKHZhbHVlLCBpbmRleCkgPT4ge1xyXG4gICAgICBpZiAodmFsdWUuaW5jbHVkZXMoMSkpIHtcclxuICAgICAgICBkYXlJbmRleCA9IGluZGV4O1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB2YWx1ZS5pbmNsdWRlcygxKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChkYXlJbmRleCkge1xyXG4gICAgICBmb3IgKGRheUluZGV4OyBkYXlJbmRleCA+IDA7IGRheUluZGV4LS0pIHtcclxuICAgICAgICBjb25zdCBtb250aERhdGEgPSB0aGlzLmN1cnJlbnRNb250aERhdGFbZGF5SW5kZXggLSAxXTtcclxuICAgICAgICB0aGlzLmN1cnJlbnRNb250aERhdGFbZGF5SW5kZXggLSAxXSA9IFtudWxsLCAuLi5tb250aERhdGFdO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzZWxlY3REYXRlKGRheTogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnNlbGVjdGVkRGF0ZSA9IHsgLi4udGhpcy5jdXJyZW50TmVwYWxpRGF0ZSwgZGF5IH07XHJcbiAgICB0aGlzLmZvcm1hdFZhbHVlKCk7XHJcbiAgICB0aGlzLmNsb3NlKCk7XHJcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSh0aGlzLnNlbGVjdGVkRGF0ZSk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RZZWFyKHllYXI6IHN0cmluZykge1xyXG4gICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS55ZWFyID0gK3llYXI7XHJcbiAgICBjb25zdCBuZXdEYXRlID0gbmV3IE5lcGFsaURhdGVDb252ZXJ0ZXIoXHJcbiAgICAgIHRoaXMuY3VycmVudE5lcGFsaURhdGUueWVhcixcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5tb250aCxcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5kYXlcclxuICAgICk7XHJcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbmV3RGF0ZS5nZXRFbmdsaXNoRGF0ZSgpO1xyXG4gICAgdGhpcy5zZXRDdXJyZW50TW9udGhEYXRhKCk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RNb250aChtb250aDogc3RyaW5nKSB7XHJcbiAgICB0aGlzLmN1cnJlbnROZXBhbGlEYXRlLm1vbnRoID0gdGhpcy5tb250aHNNYXBwaW5nW3RoaXMubGFuZ3VhZ2VdW1xyXG4gICAgICB0aGlzLm1vbnRoRGlzcGxheVR5cGVcclxuICAgIF0uaW5kZXhPZihtb250aCk7XHJcbiAgICBjb25zdCBuZXdEYXRlID0gbmV3IE5lcGFsaURhdGVDb252ZXJ0ZXIoXHJcbiAgICAgIHRoaXMuY3VycmVudE5lcGFsaURhdGUueWVhcixcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5tb250aCxcclxuICAgICAgdGhpcy5jdXJyZW50TmVwYWxpRGF0ZS5kYXlcclxuICAgICk7XHJcbiAgICB0aGlzLmN1cnJlbnREYXRlID0gbmV3RGF0ZS5nZXRFbmdsaXNoRGF0ZSgpO1xyXG4gICAgdGhpcy5zZXRDdXJyZW50TW9udGhEYXRhKCk7XHJcbiAgfVxyXG5cclxuICB0b2dnbGVPcGVuKCkge1xyXG4gICAgaWYgKCF0aGlzLmFsd2F5c1Zpc2libGUpIHtcclxuICAgICAgdGhpcy5pc09wZW4gPSAhdGhpcy5pc09wZW47XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvcGVuKCkge1xyXG4gICAgdGhpcy5pc09wZW4gPSB0cnVlO1xyXG4gIH1cclxuXHJcbiAgY2xvc2UoKSB7XHJcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xyXG4gICAgdGhpcy5zZXRDdXJyZW50RGF0ZSgpO1xyXG4gIH1cclxufVxyXG4iXX0=