ngx-animating-datepicker
Version:
An Animating Datepicker for Angular 2+, for some smooth date picking :).
715 lines • 68.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, EventEmitter, HostBinding, Input, Output, ViewChild } from '@angular/core';
import { DatepickerService } from '../../services/datepicker.service';
import { UtilitiesService } from '../../services/utilities.service';
import { DefaultOptions } from './datepicker.options';
export class DatepickerComponent {
/**
* @param {?} utils
* @param {?} element
*/
constructor(utils, element) {
this.utils = utils;
this.element = element;
/* ==============================================
* Internal Properties
* ============================================== */
this.date = new Date();
this.year = null;
this.month = null;
this.today = this.date;
this.months = null;
this.weekdays = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
this.selectedRange = 'startDate';
this.startDate = null;
this.endDate = null;
this.initialised = false;
this.weekStartArray = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
/* ==============================================
* Initial Options
* ============================================== */
this._options = DefaultOptions;
/* ==============================================
* External Properties
* ============================================== */
/**
* Set the the language manualy. A string with a BCP 47 language tag
* @example nl-NL
*/
this._language = navigator.language;
/**
* Minimal Date: If set the dates before it will be disabled
*/
this._minDate = null;
/**
* Maximal Date: If set the dates after it will be disabled
*/
this._maxDate = null;
/**
* Selected Dates: handles the selected dates array. Can be set both internally and externally
*/
this._selectedDates = [];
this.selectedDatesChange = new EventEmitter();
this.theme = '';
this.isOpen = true;
this.asDirective = false;
this.animate = false;
this.topPosition = null;
this.leftPosition = null;
this.bottomPosition = null;
this.rightPosition = null;
}
/**
* @param {?} options
* @return {?}
*/
set options(options) {
if (options === undefined || !options) {
return;
}
this._options = Object.assign({}, this._options, options);
if (options.currentDate !== undefined) {
this.date = this.options.currentDate;
}
if (this.initialised) {
this.goToDate();
}
}
/**
* @return {?}
*/
get options() {
return this._options;
}
/**
* @param {?} value
* @return {?}
*/
set language(value) {
if (!value || value === undefined || !DatepickerService.isValidIsoCode(value)) {
return;
}
this._language = value;
this.renderWeekdays();
}
/**
* @return {?}
*/
get language() {
return this._language;
}
/**
* @param {?} value
* @return {?}
*/
set minDate(value) {
if (value === undefined || value === this._minDate) {
return;
}
this._minDate = new Date(value);
this.goToDate();
}
/**
* @return {?}
*/
get minDate() {
return this._minDate;
}
/**
* @param {?} value
* @return {?}
*/
set maxDate(value) {
if (value === undefined || value === this._minDate) {
return;
}
this._maxDate = new Date(value);
this.goToDate();
}
/**
* @return {?}
*/
get maxDate() {
return this._maxDate;
}
/**
* @param {?} value
* @return {?}
*/
set selectedDates(value) {
/** @type {?} */
const _value = Array.isArray(value) ? value : [value];
if (!DatepickerService.isValidDate(_value)) {
return;
}
this._selectedDates = _value;
if (this.options.range) {
this.resetRange();
}
this.goToDate();
this.selectedDatesChange.emit(this._selectedDates);
}
/**
* @return {?}
*/
get selectedDates() {
return this._selectedDates;
}
/**
* @return {?}
*/
ngOnInit() {
this.initialised = true;
if (!this.month && !this.year) {
this.goToDate(this.options.currentDate);
}
}
/**
* Creates a day array
*
* @param {?} year
* @param {?} month
* @param {?=} isRestDays
* @return {?}
*/
createDayArray(year, month, isRestDays) {
/** @type {?} */
const days = [];
/** @type {?} */
const daysInMonth = DatepickerService.getDaysInMonth(year, month);
for (let index = 0; index < daysInMonth; index++) {
/** @type {?} */
const dayNumber = index + 1;
/** @type {?} */
const date = new Date(year, month, dayNumber);
/** @type {?} */
const day = {
date,
dayNumber,
isFirst: dayNumber === 1,
isLast: dayNumber === daysInMonth,
isToday: this.isToday(date),
isSelected: this.isSelected(date),
isRest: isRestDays,
isHidden: isRestDays && this.options.hideRestDays,
isDisabled: ((this.minDate || this.maxDate) && this.isDisabled(date)) ||
(isRestDays && this.options.disableRestDays),
isInRange: this.isInRange(date) ||
((this.isStartDate(date) || this.isEndDate(date)) && this.startDate && this.endDate),
isStartDate: this.isStartDate(date),
isEndDate: this.isEndDate(date)
};
days.push(day);
}
return days;
}
/**
* Get the days from the next month
*
* @param {?} year
* @param {?} month
* @return {?}
*/
getNextRestDays(year, month) {
/** @type {?} */
const monthLength = DatepickerService.getDaysInMonth(year, month);
/** @type {?} */
const weekStartIndex = this.weekStartArray.indexOf(this.options.weekStart);
// Get the end of the month number minus the week start index
/** @type {?} */
const endOfTheMonth = new Date(year, month, monthLength).getDay() - weekStartIndex;
// Flip minus to plus when the end month number is minus.
// this occurs when there are less rest days then the week start index
/** @type {?} */
const _endOfTheMonth = endOfTheMonth < 0 ? 7 - Math.abs(endOfTheMonth) : endOfTheMonth;
/** @type {?} */
const nextDays = this.createDayArray(DatepickerService.getYearOfNextMonth(year, month), DatepickerService.getNextMonth(month), true).slice(0, 7 - _endOfTheMonth);
return nextDays.length > 6 ? [] : nextDays;
}
/**
* Get the days of the previous month
*
* @param {?} year
* @param {?} month
* @return {?}
*/
getPreviousRestDays(year, month) {
/** @type {?} */
const startOfTheMonth = new Date(year, month, 0).getDay();
/** @type {?} */
const previousDays = this.createDayArray(DatepickerService.getYearOfPreviousMonth(year, month), DatepickerService.getPreviousMonth(month), true);
/** @type {?} */
const weekStartIndex = this.weekStartArray.indexOf(this.options.weekStart);
/** @type {?} */
const _weekStartIndex = weekStartIndex === 0 ? 0 : (7 - weekStartIndex);
/** @type {?} */
let sliceIndex = previousDays.length - startOfTheMonth - _weekStartIndex;
sliceIndex = previousDays.length - sliceIndex >= 7 ? sliceIndex + 7 : sliceIndex;
return previousDays.slice(sliceIndex, previousDays.length);
}
/**
* Merge all the day arrays together
*
* @param {?} year
* @param {?} month
* @return {?}
*/
getMergedDayArrays(year, month) {
return [
...this.getPreviousRestDays(year, month),
...this.createDayArray(year, month),
...this.getNextRestDays(year, month)
];
}
/**
* Create the calendar array from the week arrays
*
* @param {?} year
* @param {?} month
* @return {?}
*/
createCalendarArray(year, month) {
/** @type {?} */
const dayArray = this.getMergedDayArrays(year, month);
/** @type {?} */
const weeks = DatepickerService.createWeekArray(dayArray);
return [{ weeks: weeks }];
}
/**
* Update value is being triggered
*
* @param {?} date
* @return {?}
*/
updateValue(date) {
if (this.options.range) {
this.selectRange(date);
}
else if (!this.isSelected(date)) {
if (this.options.selectMultiple) {
this.selectDate(date);
}
else {
this.toggleDate(date);
}
if (this.options.closeOnSelect) {
this.close(true);
}
}
else {
this.deselectDate(date);
if (this.options.closeOnSelect) {
this.close(true);
}
}
this.months = this.createCalendarArray(this.year, this.month);
}
/**
* Select range method - contains the logic to select the start- and endrange
*
* @param {?} date
* @return {?}
*/
selectRange(date) {
if (this.isSelected(date)) {
this.deselectDate(date);
}
else if (DatepickerService.isEarlier(date, this.startDate)) {
if (this.startDate) {
this.toggleDate(date, this.startDate, true);
}
else {
this.selectDate(date);
}
this.startDate = date;
this.selectEndDate();
}
else if (this.endDate && DatepickerService.isLater(date, this.endDate)) {
this.toggleDate(date, this.endDate);
this.endDate = date;
this.selectStartDate();
}
else if (this.selectedRange === 'startDate') {
if (this.startDate) {
this.toggleDate(date, this.startDate, true);
}
else {
this.selectDate(date);
}
this.startDate = date;
this.selectEndDate();
}
else if (this.selectedRange === 'endDate') {
if (this.endDate) {
this.toggleDate(date, this.endDate);
}
else {
this.selectDate(date);
}
this.endDate = date;
this.selectStartDate();
if (this.options.closeOnSelect) {
this.close(true);
}
}
}
/**
* Reset the range if the selected dates change externally
* @return {?}
*/
resetRange() {
if (this._selectedDates.length === 1) {
this.startDate = this._selectedDates[0];
this.endDate = null;
}
else if (this._selectedDates.length === 0) {
this.startDate = null;
this.endDate = null;
}
}
/**
* Toggle a date. One in, on out.
*
* @param {?} date - Date to be toggled on
* @param {?=} toggleDate - Optional set specific date to toggle off
* @param {?=} unshift - Optional set to unshift in the selectedDates array. is passed to selectDate method
* @return {?}
*/
toggleDate(date, toggleDate, unshift) {
if (!toggleDate) {
this.selectedDates = [date];
}
else if (unshift) {
this._selectedDates.unshift(date);
this.selectedDates = this._selectedDates.filter(selectedDate => {
return selectedDate.toDateString() !== toggleDate.toDateString();
});
}
else {
this._selectedDates.push(date);
this.selectedDates = this._selectedDates.filter(selectedDate => {
return selectedDate.toDateString() !== toggleDate.toDateString();
});
}
}
/**
* Select a date
*
* @param {?} date
* @param {?=} unshift - Optional set to unshift instead of push the date in the selectedDates array
* @return {?}
*/
selectDate(date, unshift) {
/** @type {?} */
const selectedDates = [...this.selectedDates];
if (unshift) {
selectedDates.unshift(date);
}
else {
selectedDates.push(date);
}
this.selectedDates = selectedDates;
}
/**
* Deselect a date
*
* @param {?} date
* @return {?}
*/
deselectDate(date) {
this.selectedDates = this._selectedDates.filter(selectedDate => {
return selectedDate.toDateString() !== date.toDateString();
});
}
/**
* Go to the next month
* @return {?}
*/
goToNextMonth() {
this.year = DatepickerService.getYearOfNextMonth(this.year, this.month);
this.month = DatepickerService.getNextMonth(this.month);
this.totalYearMonth = [{ month: this.month, year: this.year }];
this.months = this.createCalendarArray(this.year, this.month);
}
/**
* Go to the previous month
* @return {?}
*/
goToPreviousMonth() {
this.year = DatepickerService.getYearOfPreviousMonth(this.year, this.month);
this.month = DatepickerService.getPreviousMonth(this.month);
this.totalYearMonth = [{ month: this.month, year: this.year }];
this.months = this.createCalendarArray(this.year, this.month);
}
/**
* Go to a specific month. Is also used to rerender the datepicker
*
* @param {?=} date - default is the current date.
* @return {?}
*/
goToDate(date = this.date) {
this.month = date.getMonth();
this.year = date.getFullYear();
this.totalYearMonth = [{ month: this.month, year: this.year }];
this.months = this.createCalendarArray(this.year, this.month);
}
/**
* Render weekdays when options or language changes
* @return {?}
*/
renderWeekdays() {
this.weekdays = DatepickerService.getWeekDays(this._language, this.options.weekdayFormat, this.options.weekStart);
}
/**
* Set the open state to true
* @return {?}
*/
open() {
if (this.isOpen) {
return;
}
this.isOpen = true;
}
/**
* Close the datepicker
*
* @param {?=} useTimeout - optional timeout
* @return {?}
*/
close(useTimeout) {
if (!this.isOpen) {
return;
}
/** @type {?} */
const timeout = useTimeout ? this.options.timeoutBeforeClosing : 0;
setTimeout(() => {
this.isOpen = false;
}, timeout);
}
/**
* Select the start date - used for range functionality
* @return {?}
*/
selectStartDate() {
this.selectedRange = 'startDate';
}
/**
* Select the end date - used for range functionality
* @return {?}
*/
selectEndDate() {
this.selectedRange = 'endDate';
}
// TODO: maybe output the startDate and Endate or just of internal use
/**
* Check if date is the start date
* @param {?} date
* @return {?}
*/
isStartDate(date) {
return this.startDate && date.toDateString() === this.startDate.toDateString();
}
/**
* Check if date is the end date
* @param {?} date
* @return {?}
*/
isEndDate(date) {
return this.endDate && date.toDateString() === this.endDate.toDateString();
}
/**
* Check if date is today
* @param {?} date
* @return {?}
*/
isToday(date) {
return date.toDateString() === this.today.toDateString();
}
/**
* Check if date is selected
* @param {?} dateToCheck
* @return {?}
*/
isSelected(dateToCheck) {
return this._selectedDates.map(date => date.toDateString()).indexOf(dateToCheck.toDateString()) !== -1;
}
/**
* Check if date is disabled
* @param {?} date
* @return {?}
*/
isDisabled(date) {
if (!this.minDate) {
return !(date < this.maxDate);
}
if (!this.maxDate) {
return !(date > this.minDate);
}
return !(date < this.maxDate && date > this.minDate);
}
/**
* Check if date is in range
* @param {?} date
* @return {?}
*/
isInRange(date) {
return this.startDate && this.endDate && this.startDate < date && date < this.endDate;
}
}
DatepickerComponent.decorators = [
{ type: Component, args: [{
selector: 'aa-datepicker',
template: `<div class="datepicker__wrapper">
<div>
<aa-navigation
[hideNavigation]="options.hideNavigation"
(previousClick)="goToPreviousMonth()"
(nextClick)="goToNextMonth()"
[language]="language"
[totalYearMonth]="totalYearMonth"></aa-navigation>
<div class="datepicker__weekdays-wrapper">
<div class="datepicker__weekdays-container">
<table class="datepicker__weekdays">
<thead>
<td class="datepicker__weekday" *ngFor="let weekday of weekdays; index as i">{{weekday}}</td>
</thead>
</table>
</div>
</div>
</div>
<div class="datepicker__calendar-wrapper">
<div *ngFor="let month of months;" class="datepicker__calendar-container">
<table class="datepicker__calendar">
<tbody>
<tr *ngFor="let week of month.weeks; index as i">
<td class="datepicker__day" *ngFor="let day of week.days; index as i" [ngClass]="{
'is-first': day.isFirst,
'is-last': day.isLast,
'is-hidden': day.isHidden,
'is-disabled': day.isDisabled,
'is-today': day.isToday,
'is-selected': day.isSelected,
'is-in-range': day.isInRange,
'is-start-date': day.isStartDate,
'is-end-date': day.isEndDate,
'is-rest': day.isRest
}">
<button class="datepicker__button" [disabled]="day.isDisabled || day.isHidden"
(click)="updateValue(day.date)">{{day.dayNumber}}
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<ng-content></ng-content>
</div>`,
styles: [`:host{font-family:Arial,Helvetica,sans-serif;border:1px solid #d9d9d8;width:300px;position:relative;display:inline-block;z-index:2;border-radius:4px;box-shadow:0 1px 5px rgba(0,0,0,.15);overflow:hidden;background-color:#fff;box-sizing:border-box;visibility:hidden}:host *{box-sizing:border-box}:host .datepicker__calendar-container{padding:0 10px 10px}:host .datepicker__footer{position:relative;z-index:1}:host table{width:100%;table-layout:fixed;border-spacing:0;border-collapse:collapse}:host td{padding:0}:host .datepicker__weekdays-wrapper::after,:host .datepicker__weekdays-wrapper::before{content:' ';display:table}:host .datepicker__weekdays-wrapper::after{clear:both}:host .datepicker__weekdays-container{padding:10px 10px 0;float:left}:host .datepicker__weekdays{table-layout:fixed;width:100%}:host .datepicker__weekday{color:grey;font-size:12px;height:20px;text-align:center}:host .datepicker__day{position:relative;text-align:center;height:40px;width:auto;border:1px solid #d9d9d8}:host .datepicker__day.is-rest{border:none}:host .datepicker__button{padding:0;background-color:transparent;border:none;outline:0;font-style:inherit;cursor:pointer;color:#8e8d8a;width:100%;height:100%}:host .datepicker__button:hover{border:1px solid transparent;background-color:#f2f2f2;color:#8e8d8a}:host .is-hidden{opacity:0;display:table-cell}:host .is-rest{border:none}:host .is-rest .datepicker__button{color:#c0c0be}:host .is-today .datepicker__button{background-color:#eae7dc}:host .is-in-range .datepicker__button{background-color:#e98074;color:#fff}:host .is-in-range .datepicker__button:hover{background-color:#e66c5e}:host .is-selected .datepicker__button{background-color:#e85a4f;color:#fff;font-weight:700}:host .is-selected .datepicker__button:hover{background-color:#e23022}:host .is-start-date .datepicker__button{background-color:#e85a4f;color:#fff}:host .is-end-date .datepicker__button{background-color:#e85a4f;color:#fff}:host .is-disabled .datepicker__button{color:#d9d9d8;cursor:default}:host .is-disabled .datepicker__button:hover{background-color:transparent}:host.is-directive{visibility:hidden;position:absolute}:host.is-open{visibility:visible}:host.is-animate{transition:height .2s ease-in;width:300px}:host.is-animate .datepicker__main{transition:height .2s ease-in}:host.is-animate .datepicker__calendar-wrapper{position:absolute;width:200%;left:0}:host.is-animate .datepicker__calendar{float:left;width:100%}:host.is-animate .datepicker__calendar-container{float:left}`]
},] },
];
DatepickerComponent.ctorParameters = () => [
{ type: UtilitiesService },
{ type: ElementRef }
];
DatepickerComponent.propDecorators = {
options: [{ type: Input, args: ['options',] }],
language: [{ type: Input }],
minDate: [{ type: Input }],
maxDate: [{ type: Input }],
selectedDatesChange: [{ type: Output }],
selectedDates: [{ type: Input }],
calendarContainer: [{ type: ViewChild, args: ['calendarContainer',] }],
calendarTopContainer: [{ type: ViewChild, args: ['calendarTopContainer',] }],
theme: [{ type: HostBinding, args: ['class',] }, { type: Input }],
isOpen: [{ type: HostBinding, args: ['class.is-open',] }, { type: Input }],
asDirective: [{ type: HostBinding, args: ['class.is-directive',] }],
animate: [{ type: HostBinding, args: ['class.is-animate',] }],
topPosition: [{ type: HostBinding, args: ['style.top.px',] }],
leftPosition: [{ type: HostBinding, args: ['style.left.px',] }],
bottomPosition: [{ type: HostBinding, args: ['style.bottom.px',] }],
rightPosition: [{ type: HostBinding, args: ['style.right.px',] }]
};
if (false) {
/** @type {?} */
DatepickerComponent.prototype.date;
/** @type {?} */
DatepickerComponent.prototype.year;
/** @type {?} */
DatepickerComponent.prototype.month;
/** @type {?} */
DatepickerComponent.prototype.today;
/** @type {?} */
DatepickerComponent.prototype.months;
/** @type {?} */
DatepickerComponent.prototype.weekdays;
/** @type {?} */
DatepickerComponent.prototype.totalYearMonth;
/** @type {?} */
DatepickerComponent.prototype.selectedRange;
/** @type {?} */
DatepickerComponent.prototype.startDate;
/** @type {?} */
DatepickerComponent.prototype.endDate;
/** @type {?} */
DatepickerComponent.prototype.initialised;
/**
* @type {?}
* @private
*/
DatepickerComponent.prototype.weekStartArray;
/** @type {?} */
DatepickerComponent.prototype._options;
/**
* Set the the language manualy. A string with a BCP 47 language tag
* \@example nl-NL
* @type {?}
*/
DatepickerComponent.prototype._language;
/**
* Minimal Date: If set the dates before it will be disabled
* @type {?}
*/
DatepickerComponent.prototype._minDate;
/**
* Maximal Date: If set the dates after it will be disabled
* @type {?}
*/
DatepickerComponent.prototype._maxDate;
/**
* Selected Dates: handles the selected dates array. Can be set both internally and externally
* @type {?}
* @private
*/
DatepickerComponent.prototype._selectedDates;
/** @type {?} */
DatepickerComponent.prototype.selectedDatesChange;
/** @type {?} */
DatepickerComponent.prototype.calendarContainer;
/** @type {?} */
DatepickerComponent.prototype.calendarTopContainer;
/** @type {?} */
DatepickerComponent.prototype.theme;
/** @type {?} */
DatepickerComponent.prototype.isOpen;
/** @type {?} */
DatepickerComponent.prototype.asDirective;
/** @type {?} */
DatepickerComponent.prototype.animate;
/** @type {?} */
DatepickerComponent.prototype.topPosition;
/** @type {?} */
DatepickerComponent.prototype.leftPosition;
/** @type {?} */
DatepickerComponent.prototype.bottomPosition;
/** @type {?} */
DatepickerComponent.prototype.rightPosition;
/** @type {?} */
DatepickerComponent.prototype.utils;
/** @type {?} */
DatepickerComponent.prototype.element;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtYW5pbWF0aW5nLWRhdGVwaWNrZXIvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9kYXRlcGlja2VyL2RhdGVwaWNrZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR25ILE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQW9EdEQsTUFBTTs7Ozs7SUFnSkwsWUFBbUIsS0FBdUIsRUFBUyxPQUFtQjtRQUFuRCxVQUFLLEdBQUwsS0FBSyxDQUFrQjtRQUFTLFlBQU8sR0FBUCxPQUFPLENBQVk7UUEvSXRFOzs0REFFb0Q7UUFDN0MsU0FBSSxHQUFTLElBQUksSUFBSSxFQUFFLENBQUM7UUFDeEIsU0FBSSxHQUFXLElBQUksQ0FBQztRQUNwQixVQUFLLEdBQVcsSUFBSSxDQUFDO1FBQ3JCLFVBQUssR0FBUyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3hCLFdBQU0sR0FBWSxJQUFJLENBQUM7UUFDdkIsYUFBUSxHQUFhLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFekQsa0JBQWEsR0FBRyxXQUFXLENBQUM7UUFDNUIsY0FBUyxHQUFTLElBQUksQ0FBQztRQUN2QixZQUFPLEdBQVMsSUFBSSxDQUFDO1FBQ3JCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ25CLG1CQUFjLEdBQUcsQ0FB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LFdBQVcsU0FBQyxlQUFlOzZCQUMzQixXQUFXLFNBQUMsaUJBQWlCOzRCQUM3QixXQUFXLFNBQUMsZ0JBQWdCOzs7O0lBMUk3QixtQ0FBK0I7O0lBQy9CLG1DQUEyQjs7SUFDM0Isb0NBQTRCOztJQUM1QixvQ0FBK0I7O0lBQy9CLHFDQUE4Qjs7SUFDOUIsdUNBQWdFOztJQUNoRSw2Q0FBbUM7O0lBQ25DLDRDQUFtQzs7SUFDbkMsd0NBQThCOztJQUM5QixzQ0FBNEI7O0lBQzVCLDBDQUEyQjs7Ozs7SUFDM0IsNkNBQXdHOztJQUt4Ryx1Q0FBMEM7Ozs7OztJQTZCMUMsd0NBQStCOzs7OztJQW1CL0IsdUNBQXVCOzs7OztJQWlCdkIsdUNBQXVCOzs7Ozs7SUFpQnZCLDZDQUFvQzs7SUFDcEMsa0RBQW1EOztJQTBCbkQsZ0RBQXFFOztJQUNyRSxtREFBMkU7O0lBQzNFLG9DQUVXOztJQUNYLHFDQUVjOztJQUNkLDBDQUF1RDs7SUFDdkQsc0NBQWlEOztJQUNqRCwwQ0FBd0Q7O0lBQ3hELDJDQUEwRDs7SUFDMUQsNkNBQThEOztJQUM5RCw0Q0FBNEQ7O0lBRWhELG9DQUE4Qjs7SUFBRSxzQ0FBMEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIElucHV0LCBPbkluaXQsIE91dHB1dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPcHRpb25zIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2RhdGVwaWNrZXItb3B0aW9ucy5tb2RlbCc7XG5pbXBvcnQge1llYXJNb250aCwgRGF5LCBNb250aCwgV2Vla30gZnJvbSAnLi4vLi4vbW9kZWxzL2RhdGVwaWNrZXIubW9kZWwnO1xuaW1wb3J0IHsgRGF0ZXBpY2tlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9kYXRlcGlja2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgVXRpbGl0aWVzU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3V0aWxpdGllcy5zZXJ2aWNlJztcbmltcG9ydCB7IERlZmF1bHRPcHRpb25zIH0gZnJvbSAnLi9kYXRlcGlja2VyLm9wdGlvbnMnO1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6ICdhYS1kYXRlcGlja2VyJyxcblx0dGVtcGxhdGU6IGA8ZGl2IGNsYXNzPVwiZGF0ZXBpY2tlcl9fd3JhcHBlclwiPlxuXHQ8ZGl2PlxuXHRcdDxhYS1uYXZpZ2F0aW9uXG5cdFx0XHRcdFtoaWRlTmF2aWdhdGlvbl09XCJvcHRpb25zLmhpZGVOYXZpZ2F0aW9uXCJcbiAgICAgICAgICAgICAgICAocHJldmlvdXNDbGljayk9XCJnb1RvUHJldmlvdXNNb250aCgpXCJcblx0XHRcdFx0KG5leHRDbGljayk9XCJnb1RvTmV4dE1vbnRoKClcIlxuXHRcdFx0XHRbbGFuZ3VhZ2VdPVwibGFuZ3VhZ2VcIlxuXHRcdFx0XHRbdG90YWxZZWFyTW9udGhdPVwidG90YWxZZWFyTW9udGhcIj48L2FhLW5hdmlnYXRpb24+XG5cdFx0PGRpdiBjbGFzcz1cImRhdGVwaWNrZXJfX3dlZWtkYXlzLXdyYXBwZXJcIj5cblx0XHRcdDxkaXYgY2xhc3M9XCJkYXRlcGlja2VyX193ZWVrZGF5cy1jb250YWluZXJcIj5cblx0XHRcdFx0PHRhYmxlIGNsYXNzPVwiZGF0ZXBpY2tlcl9fd2Vla2RheXNcIj5cblx0XHRcdFx0XHQ8dGhlYWQ+XG5cdFx0XHRcdFx0PHRkIGNsYXNzPVwiZGF0ZXBpY2tlcl9fd2Vla2RheVwiICpuZ0Zvcj1cImxldCB3ZWVrZGF5IG9mIHdlZWtkYXlzOyBpbmRleCBhcyBpXCI+e3t3ZWVrZGF5fX08L3RkPlxuXHRcdFx0XHRcdDwvdGhlYWQ+XG5cdFx0XHRcdDwvdGFibGU+XG5cdFx0XHQ8L2Rpdj5cblx0XHQ8L2Rpdj5cblx0PC9kaXY+XG5cdDxkaXYgY2xhc3M9XCJkYXRlcGlja2VyX19jYWxlbmRhci13cmFwcGVyXCI+XG5cdFx0PGRpdiAqbmdGb3I9XCJsZXQgbW9udGggb2YgbW9udGhzO1wiIGNsYXNzPVwiZGF0ZXBpY2tlcl9fY2FsZW5kYXItY29udGFpbmVyXCI+XG5cdFx0XHQ8dGFibGUgY2xhc3M9XCJkYXRlcGlja2VyX19jYWxlbmRhclwiPlxuXHRcdFx0XHQ8dGJvZHk+XG5cdFx0XHRcdDx0ciAqbmdGb3I9XCJsZXQgd2VlayBvZiBtb250aC53ZWVrczsgaW5kZXggYXMgaVwiPlxuXHRcdFx0XHRcdDx0ZCBjbGFzcz1cImRhdGVwaWNrZXJfX2RheVwiICpuZ0Zvcj1cImxldCBkYXkgb2Ygd2Vlay5kYXlzOyBpbmRleCBhcyBpXCIgW25nQ2xhc3NdPVwie1xuXHRcdFx0J2lzLWZpcnN0JzogZGF5LmlzRmlyc3QsXG5cdFx0XHQnaXMtbGFzdCc6IGRheS5pc0xhc3QsXG5cdFx0XHQnaXMtaGlkZGVuJzogZGF5LmlzSGlkZGVuLFxuXHRcdFx0J2lzLWRpc2FibGVkJzogZGF5LmlzRGlzYWJsZWQsXG5cdFx0XHQnaXMtdG9kYXknOiBkYXkuaXNUb2RheSxcblx0XHRcdCdpcy1zZWxlY3RlZCc6IGRheS5pc1NlbGVjdGVkLFxuXHRcdFx0J2lzLWluLXJhbmdlJzogZGF5LmlzSW5SYW5nZSxcblx0XHRcdCdpcy1zdGFydC1kYXRlJzogZGF5LmlzU3RhcnREYXRlLFxuXHRcdFx0J2lzLWVuZC1kYXRlJzogZGF5LmlzRW5kRGF0ZSxcblx0XHRcdCdpcy1yZXN0JzogZGF5LmlzUmVzdFxuXHRcdFx0fVwiPlxuXHRcdFx0XHRcdFx0PGJ1dHRvbiBjbGFzcz1cImRhdGVwaWNrZXJfX2J1dHRvblwiIFtkaXNhYmxlZF09XCJkYXkuaXNEaXNhYmxlZCB8fCBkYXkuaXNIaWRkZW5cIlxuXHRcdFx0XHRcdFx0XHRcdChjbGljayk9XCJ1cGRhdGVWYWx1ZShkYXkuZGF0ZSlcIj57e2RheS5kYXlOdW1iZXJ9fVxuXHRcdFx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHRcdFx0PC90ZD5cblx0XHRcdFx0PC90cj5cblx0XHRcdFx0PC90Ym9keT5cblx0XHRcdDwvdGFibGU+XG5cdFx0PC9kaXY+XG5cdDwvZGl2PlxuXHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG48L2Rpdj5gLFxuXHRzdHlsZXM6IFtgOmhvc3R7Zm9udC1mYW1pbHk6QXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWY7Ym9yZGVyOjFweCBzb2xpZCAjZDlkOWQ4O3dpZHRoOjMwMHB4O3Bvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6aW5saW5lLWJsb2NrO3otaW5kZXg6Mjtib3JkZXItcmFkaXVzOjRweDtib3gtc2hhZG93OjAgMXB4IDVweCByZ2JhKDAsMCwwLC4xNSk7b3ZlcmZsb3c6aGlkZGVuO2JhY2tncm91bmQtY29sb3I6I2ZmZjtib3gtc2l6aW5nOmJvcmRlci1ib3g7dmlzaWJpbGl0eTpoaWRkZW59Omhvc3QgKntib3gtc2l6aW5nOmJvcmRlci1ib3h9Omhvc3QgLmRhdGVwaWNrZXJfX2NhbGVuZGFyLWNvbnRhaW5lcntwYWRkaW5nOjAgMTBweCAxMHB4fTpob3N0IC5kYXRlcGlja2VyX19mb290ZXJ7cG9zaXRpb246cmVsYXRpdmU7ei1pbmRleDoxfTpob3N0IHRhYmxle3dpZHRoOjEwMCU7dGFibGUtbGF5b3V0OmZpeGVkO2JvcmRlci1zcGFjaW5nOjA7Ym9yZGVyLWNvbGxhcHNlOmNvbGxhcHNlfTpob3N0IHRke3BhZGRpbmc6MH06aG9zdCAuZGF0ZXBpY2tlcl9fd2Vla2RheXMtd3JhcHBlcjo6YWZ0ZXIsOmhvc3QgLmRhdGVwaWNrZXJfX3dlZWtkYXlzLXdyYXBwZXI6OmJlZm9yZXtjb250ZW50OicgJztkaXNwbGF5OnRhYmxlfTpob3N0IC5kYXRlcGlja2VyX193ZWVrZGF5cy13cmFwcGVyOjphZnRlcntjbGVhcjpib3RofTpob3N0IC5kYXRlcGlja2VyX193ZWVrZGF5cy1jb250YWluZXJ7cGFkZGluZzoxMHB4IDEwcHggMDtmbG9hdDpsZWZ0fTpob3N0IC5kYXRlcGlja2VyX193ZWVrZGF5c3t0YWJsZS1sYXlvdXQ6Zml4ZWQ7d2lkdGg6MTAwJX06aG9zdCAuZGF0ZXBpY2tlcl9fd2Vla2RheXtjb2xvcjpncmV5O2ZvbnQtc2l6ZToxMnB4O2hlaWdodDoyMHB4O3RleHQtYWxpZ246Y2VudGVyfTpob3N0IC5kYXRlcGlja2VyX19kYXl7cG9zaXRpb246cmVsYXRpdmU7dGV4dC1hbGlnbjpjZW50ZXI7aGVpZ2h0OjQwcHg7d2lkdGg6YXV0bztib3JkZXI6MXB4IHNvbGlkICNkOWQ5ZDh9Omhvc3QgLmRhdGVwaWNrZXJfX2RheS5pcy1yZXN0e2JvcmRlcjpub25lfTpob3N0IC5kYXRlcGlja2VyX19idXR0b257cGFkZGluZzowO2JhY2tncm91bmQtY29sb3I6dHJhbnNwYXJlbnQ7Ym9yZGVyOm5vbmU7b3V0bGluZTowO2ZvbnQtc3R5bGU6aW5oZXJpdDtjdXJzb3I6cG9pbnRlcjtjb2xvcjojOGU4ZDhhO3dpZHRoOjEwMCU7aGVpZ2h0OjEwMCV9Omhvc3QgLmRhdGVwaWNrZXJfX2J1dHRvbjpob3Zlcntib3JkZXI6MXB4IHNvbGlkIHRyYW5zcGFyZW50O2JhY2tncm91bmQtY29sb3I6I2YyZjJmMjtjb2xvcjojOGU4ZDhhfTpob3N0IC5pcy1oaWRkZW57b3BhY2l0eTowO2Rpc3BsYXk6dGFibGUtY2VsbH06aG9zdCAuaXMtcmVzdHtib3JkZXI6bm9uZX06aG9zdCAuaXMtcmVzdCAuZGF0ZXBpY2tlcl9fYnV0dG9ue2NvbG9yOiNjMGMwYmV9Omhvc3QgLmlzLXRvZGF5IC5kYXRlcGlja2VyX19idXR0b257YmFja2dyb3VuZC1jb2xvcjojZWFlN2RjfTpob3N0IC5pcy1pbi1yYW5nZSAuZGF0ZXBpY2tlcl9fYnV0dG9ue2JhY2tncm91bmQtY29sb3I6I2U5ODA3NDtjb2xvcjojZmZmfTpob3N0IC5pcy1pbi1yYW5nZSAuZGF0ZXBpY2tlcl9fYnV0dG9uOmhvdmVye2JhY2tncm91bmQtY29sb3I6I2U2NmM1ZX06aG9zdCAuaXMtc2VsZWN0ZWQgLmRhdGVwaWNrZXJfX2J1dHRvbntiYWNrZ3JvdW5kLWNvbG9yOiNlODVhNGY7Y29sb3I6I2ZmZjtmb250LXdlaWdodDo3MDB9Omhvc3QgLmlzLXNlbGVjdGVkIC5kYXRlcGlja2VyX19idXR0b246aG92ZXJ7YmFja2dyb3VuZC1jb2xvcjojZTIzMDIyfTpob3N0IC5pcy1zdGFydC1kYXRlIC5kYXRlcGlja2VyX19idXR0b257YmFja2dyb3VuZC1jb2xvcjojZTg1YTRmO2NvbG9yOiNmZmZ9Omhvc3QgLmlzLWVuZC1kYXRlIC5kYXRlcGlja2VyX19idXR0b257YmFja2dyb3VuZC1jb2xvcjojZTg1YTRmO2NvbG9yOiNmZmZ9Omhvc3QgLmlzLWRpc2FibGVkIC5kYXRlcGlja2VyX19idXR0b257Y29sb3I6I2Q5ZDlkODtjdXJzb3I6ZGVmYXVsdH06aG9zdCAuaXMtZGlzYWJsZWQgLmRhdGVwaWNrZXJfX2J1dHRvbjpob3ZlcntiYWNrZ3JvdW5kLWNvbG9yOnRyYW5zcGFyZW50fTpob3N0LmlzLWRpcmVjdGl2ZXt2aXNpYmlsaXR5OmhpZGRlbjtwb3NpdGlvbjphYnNvbHV0ZX06aG9zdC5pcy1vcGVue3Zpc2liaWxpdHk6dmlzaWJsZX06aG9zdC5pcy1hbmltYXRle3RyYW5zaXRpb246aGVpZ2h0IC4ycyBlYXNlLWluO3dpZHRoOjMwMHB4fTpob3N0LmlzLWFuaW1hdGUgLmRhdGVwaWNrZXJfX21haW57dHJhbnNpdGlvbjpoZWlnaHQgLjJzIGVhc2UtaW59Omhvc3QuaXMtYW5pbWF0ZSAuZGF0ZXBpY2tlcl9fY2FsZW5kYXItd3JhcHBlcntwb3NpdGlvbjphYnNvbHV0ZTt3aWR0aDoyMDAlO2xlZnQ6MH06aG9zdC5pcy1hbmltYXRlIC5kYXRlcGlja2VyX19jYWxlbmRhcntmbG9hdDpsZWZ0O3dpZHRoOjEwMCV9Omhvc3QuaXMtYW5pbWF0ZSAuZGF0ZXBpY2tlcl9fY2FsZW5kYXItY29udGFpbmVye2Zsb2F0OmxlZnR9YF1cbn0pXG5leHBvcnQgY2xhc3MgRGF0ZXBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cdC8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblx0ICogSW50ZXJuYWwgUHJvcGVydGllc1xuXHQgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cdHB1YmxpYyBkYXRlOiBEYXRlID0gbmV3IERhdGUoKTtcblx0cHVibGljIHllYXI6IG51bWJlciA9IG51bGw7XG5cdHB1YmxpYyBtb250aDogbnVtYmVyID0gbnVsbDtcblx0cHVibGljIHRvZGF5OiBEYXRlID0gdGhpcy5kYXRlO1xuXHRwdWJsaWMgbW9udGhzOiBNb250aFtdID0gbnVsbDtcblx0cHVibGljIHdlZWtkYXlzOiBzdHJpbmdbXSA9IFsnTScsICdUJywgJ1cnLCAnVCcsICdGJywgJ1MnLCAnUyddO1xuXHRwdWJsaWMgdG90YWxZZWFyTW9udGg6IFllYXJNb250aFtdO1xuXHRwdWJsaWMgc2VsZWN0ZWRSYW5nZSA9ICdzdGFydERhdGUnO1xuXHRwdWJsaWMgc3RhcnREYXRlOiBEYXRlID0gbnVsbDtcblx0cHVibGljIGVuZERhdGU6IERhdGUgPSBudWxsO1xuXHRwdWJsaWMgaW5pdGlhbGlzZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSB3ZWVrU3RhcnRBcnJheSA9IFsnbW9uZGF5JywgJ3R1ZXNkYXknLCAnd2VkbmVzZGF5JywgJ3RodXJzZGF5JywgJ2ZyaWRheScsICdzYXR1cmRheScsICdzdW5kYXknXTtcblxuXHQvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cdCAqIEluaXRpYWwgT3B0aW9uc1xuXHQgKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovXG5cdHB1YmxpYyBfb3B0aW9uczogT3B0aW9ucyA9IERlZmF1bHRPcHRpb25zO1xuXHRASW5wdXQoJ29wdGlvbnMnKVxuXHRzZXQgb3B0aW9ucyhvcHRpb25zOiBPcHRpb25zKSB7XG5