saturn-datepicker
Version:
Material datepicker with range support ## What is this?
617 lines • 74.7 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as tslib_1 from "tslib";
import { Directionality } from '@angular/cdk/bidi';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { ESCAPE, UP_ARROW } from '@angular/cdk/keycodes';
import { Overlay, OverlayConfig, OverlayRef, PositionStrategy, ScrollStrategy, } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { DOCUMENT } from '@angular/common';
import { AfterViewInit, ChangeDetectionStrategy, Component, ComponentRef, ElementRef, EventEmitter, Inject, InjectionToken, Input, NgZone, OnDestroy, Optional, Output, ViewChild, ViewContainerRef, ViewEncapsulation, } from '@angular/core';
import { mixinColor, } from '@angular/material/core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { merge, Subject, Subscription } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { SatCalendar } from './calendar';
import { matDatepickerAnimations } from './datepicker-animations';
import { createMissingDateImplError } from './datepicker-errors';
import { DateAdapter } from '../datetime/date-adapter';
/** Used to generate a unique ID for each datepicker instance. */
var datepickerUid = 0;
/** Injection token that determines the scroll handling while the calendar is open. */
export var MAT_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('sat-datepicker-scroll-strategy');
/** @docs-private */
export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay) {
return function () { return overlay.scrollStrategies.reposition(); };
}
/** @docs-private */
export var MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER = {
provide: MAT_DATEPICKER_SCROLL_STRATEGY,
deps: [Overlay],
useFactory: MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY,
};
// Boilerplate for applying mixins to SatDatepickerContent.
/** @docs-private */
var SatDatepickerContentBase = /** @class */ (function () {
function SatDatepickerContentBase(_elementRef) {
this._elementRef = _elementRef;
}
return SatDatepickerContentBase;
}());
var _SatDatepickerContentMixinBase = mixinColor(SatDatepickerContentBase);
/**
* Component used as the content for the datepicker dialog and popup. We use this instead of using
* SatCalendar directly as the content so we can control the initial focus. This also gives us a
* place to put additional features of the popup that are not part of the calendar itself in the
* future. (e.g. confirmation buttons).
* @docs-private
*/
var SatDatepickerContent = /** @class */ (function (_super) {
tslib_1.__extends(SatDatepickerContent, _super);
function SatDatepickerContent(elementRef) {
return _super.call(this, elementRef) || this;
}
SatDatepickerContent.prototype.ngAfterViewInit = function () {
this._calendar.focusActiveCell();
};
SatDatepickerContent.prototype.close = function () {
if (this.datepicker.closeAfterSelection) {
this.datepicker.close();
}
};
SatDatepickerContent.ctorParameters = function () { return [
{ type: ElementRef }
]; };
tslib_1.__decorate([
ViewChild(SatCalendar, { static: false })
], SatDatepickerContent.prototype, "_calendar", void 0);
SatDatepickerContent = tslib_1.__decorate([
Component({
moduleId: module.id,
selector: 'sat-datepicker-content',
template: "<sat-calendar cdkTrapFocus\n [id]=\"datepicker.id\"\n [ngClass]=\"datepicker.panelClass\"\n [startAt]=\"datepicker.startAt\"\n [startView]=\"datepicker.startView\"\n [minDate]=\"datepicker._minDate\"\n [maxDate]=\"datepicker._maxDate\"\n [dateFilter]=\"datepicker._dateFilter\"\n [rangeHoverEffect]=\"datepicker.rangeHoverEffect\"\n [headerComponent]=\"datepicker.calendarHeaderComponent\"\n [footerComponent]=\"datepicker.calendarFooterComponent\"\n [selected]=\"datepicker._selected\"\n [dateClass]=\"datepicker.dateClass\"\n [@fadeInCalendar]=\"'enter'\"\n (selectedChange)=\"datepicker.select($event)\"\n (yearSelected)=\"datepicker._selectYear($event)\"\n (monthSelected)=\"datepicker._selectMonth($event)\"\n [beginDate]=\"datepicker._beginDate\"\n [endDate]=\"datepicker._endDate\"\n [rangeMode]=\"datepicker.rangeMode\"\n [closeAfterSelection]=\"datepicker.closeAfterSelection\"\n [orderPeriodLabel]=\"datepicker.orderPeriodLabel\"\n (dateRangesChange)=\"datepicker._selectRange($event)\"\n (beginDateSelectedChange)=\"datepicker.setBeginDateSelected($event)\"\n (_userSelection)=\"close()\">\n</sat-calendar>\n",
host: {
'class': 'mat-datepicker-content',
'[@transformPanel]': '"enter"',
'[class.mat-datepicker-content-touch]': 'datepicker.touchUi',
},
animations: [
matDatepickerAnimations.transformPanel,
matDatepickerAnimations.fadeInCalendar,
],
exportAs: 'matDatepickerContent',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
inputs: ['color'],
styles: [".mat-datepicker-content{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12);display:block}.mat-datepicker-content .mat-calendar{width:296px;height:354px}.mat-datepicker-content-touch{box-shadow:0 0 0 0 rgba(0,0,0,.2),0 0 0 0 rgba(0,0,0,.14),0 0 0 0 rgba(0,0,0,.12);display:block;max-height:80vh;overflow:auto;margin:-24px}.mat-datepicker-content-touch .mat-calendar{min-width:250px;min-height:312px;max-width:750px;max-height:788px}@media all and (orientation:landscape){.mat-datepicker-content-touch .mat-calendar{width:64vh;height:80vh}}@media all and (orientation:portrait){.mat-datepicker-content-touch .mat-calendar{width:80vw;height:100vw}}"]
})
], SatDatepickerContent);
return SatDatepickerContent;
}(_SatDatepickerContentMixinBase));
export { SatDatepickerContent };
// TODO(mmalerba): We use a component instead of a directive here so the user can use implicit
// template reference variables (e.g. #d vs #d="matDatepicker"). We can change this to a directive
// if angular adds support for `exportAs: '$implicit'` on directives.
/** Component responsible for managing the datepicker popup/dialog. */
var SatDatepicker = /** @class */ (function () {
function SatDatepicker(_dialog, _overlay, _ngZone, _viewContainerRef, scrollStrategy, _dateAdapter, _dir, _document) {
this._dialog = _dialog;
this._overlay = _overlay;
this._ngZone = _ngZone;
this._viewContainerRef = _viewContainerRef;
this._dateAdapter = _dateAdapter;
this._dir = _dir;
this._document = _document;
/** The view that the calendar should start in. */
this.startView = 'month';
this._touchUi = false;
/**
* Emits selected year in multiyear view.
* This doesn't imply a change on the selected date.
*/
this.yearSelected = new EventEmitter();
/**
* Emits selected month in year view.
* This doesn't imply a change on the selected date.
*/
this.monthSelected = new EventEmitter();
/** Emits when the datepicker has been opened. */
this.openedStream = new EventEmitter();
/** Emits when the datepicker has been closed. */
this.closedStream = new EventEmitter();
/** Enables datepicker closing after selection */
this.closeAfterSelection = true;
/** Enables datepicker MouseOver effect on range mode */
this.rangeHoverEffect = true;
/** In range mod, enable datepicker to select the first date selected as a one-day-range,
* if the user closes the picker before selecting another date
*/
this.selectFirstDateOnClose = false;
/** Order the views when clicking on period label button */
this.orderPeriodLabel = 'multi-year';
this._opened = false;
/** The id for the datepicker calendar. */
this.id = "sat-datepicker-" + datepickerUid++;
this._validSelected = null;
/** The element that was focused before the datepicker was opened. */
this._focusedElementBeforeOpen = null;
/** Subscription to value changes in the associated input element. */
this._inputSubscription = Subscription.EMPTY;
/** Emits when the datepicker is disabled. */
this._disabledChange = new Subject();
/** Emits new selected date when selected date changes. */
this._selectedChanged = new Subject();
if (!this._dateAdapter) {
throw createMissingDateImplError('DateAdapter');
}
this._scrollStrategy = scrollStrategy;
}
Object.defineProperty(SatDatepicker.prototype, "rangeMode", {
/** Whenever datepicker is for selecting range of dates. */
get: function () {
return this._rangeMode;
},
set: function (mode) {
this._rangeMode = mode;
if (this.rangeMode) {
this._validSelected = null;
}
else {
this._beginDate = this._endDate = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "beginDate", {
/** Start of dates interval. */
get: function () { return this._beginDate; },
set: function (value) {
this._validSelected = null;
this._beginDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "endDate", {
/** End of dates interval. */
get: function () { return this._endDate; },
set: function (value) {
this._validSelected = null;
this._endDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "startAt", {
/** The date to open the calendar to initially. */
get: function () {
// If an explicit startAt is set we start there, otherwise we start at whatever the currently
// selected value is.
if (this.rangeMode) {
return this._startAt || (this._datepickerInput && this._datepickerInput.value ?
this._datepickerInput.value.begin : null);
}
return this._startAt || (this._datepickerInput ? this._datepickerInput.value : null);
},
set: function (value) {
this._startAt = this._getValidDateOrNull(this._dateAdapter.deserialize(value));
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "color", {
/** Color palette to use on the datepicker's calendar. */
get: function () {
return this._color ||
(this._datepickerInput ? this._datepickerInput._getThemePalette() : undefined);
},
set: function (value) {
this._color = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "touchUi", {
/**
* Whether the calendar UI is in touch mode. In touch mode the calendar opens in a dialog rather
* than a popup and elements have more padding to allow for bigger touch targets.
*/
get: function () { return this._touchUi; },
set: function (value) {
this._touchUi = coerceBooleanProperty(value);
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "disabled", {
/** Whether the datepicker pop-up should be disabled. */
get: function () {
return this._disabled === undefined && this._datepickerInput ?
this._datepickerInput.disabled : !!this._disabled;
},
set: function (value) {
var newValue = coerceBooleanProperty(value);
if (newValue !== this._disabled) {
this._disabled = newValue;
this._disabledChange.next(newValue);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "opened", {
/** Whether the calendar is open. */
get: function () { return this._opened; },
set: function (value) { value ? this.open() : this.close(); },
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "_selected", {
/** The currently selected date. */
get: function () { return this._validSelected; },
set: function (value) { this._validSelected = value; },
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "_minDate", {
/** The minimum selectable date. */
get: function () {
return this._datepickerInput && this._datepickerInput.min;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "_maxDate", {
/** The maximum selectable date. */
get: function () {
return this._datepickerInput && this._datepickerInput.max;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SatDatepicker.prototype, "_dateFilter", {
get: function () {
return this._datepickerInput && this._datepickerInput._dateFilter;
},
enumerable: true,
configurable: true
});
SatDatepicker.prototype.ngOnDestroy = function () {
this.close();
this._inputSubscription.unsubscribe();
this._disabledChange.complete();
if (this._popupRef) {
this._popupRef.dispose();
this._popupComponentRef = null;
}
};
/** Selects the given date */
SatDatepicker.prototype.select = function (date) {
var oldValue = this._selected;
this._selected = date;
if (!this._dateAdapter.sameDate(oldValue, this._selected)) {
this._selectedChanged.next(date);
}
};
/** Selects the given date range */
SatDatepicker.prototype._selectRange = function (dates) {
this._beginDateSelected = null;
if (!this._dateAdapter.sameDate(dates.begin, this.beginDate) ||
!this._dateAdapter.sameDate(dates.end, this.endDate)) {
this._selectedChanged.next(dates);
}
this._beginDate = dates.begin;
this._endDate = dates.end;
};
/** Emits the selected year in multiyear view */
SatDatepicker.prototype._selectYear = function (normalizedYear) {
this.yearSelected.emit(normalizedYear);
};
/** Emits selected month in year view */
SatDatepicker.prototype._selectMonth = function (normalizedMonth) {
this.monthSelected.emit(normalizedMonth);
};
/**
* Register an input with this datepicker.
* @param input The datepicker input to register with this datepicker.
*/
SatDatepicker.prototype._registerInput = function (input) {
var _this = this;
if (this._datepickerInput) {
throw Error('A SatDatepicker can only be associated with a single input.');
}
this._datepickerInput = input;
this._inputSubscription =
this._datepickerInput._valueChange
.subscribe(function (value) {
if (value === null) {
_this.beginDate = _this.endDate = _this._selected = null;
return;
}
if (value && value.hasOwnProperty('begin') && value.hasOwnProperty('end')) {
value = value;
if (value.begin && value.end &&
_this._dateAdapter.compareDate(value.begin, value.end) <= 0) {
_this.beginDate = value.begin;
_this.endDate = value.end;
}
else {
_this.beginDate = _this.endDate = null;
}
}
else {
_this._selected = value;
}
});
};
/** Open the calendar. */
SatDatepicker.prototype.open = function () {
if (this._opened || this.disabled) {
return;
}
if (!this._datepickerInput) {
throw Error('Attempted to open an SatDatepicker with no associated input.');
}
if (this._document) {
this._focusedElementBeforeOpen = this._document.activeElement;
}
this.touchUi ? this._openAsDialog() : this._openAsPopup();
this._opened = true;
this.openedStream.emit();
};
/** Close the calendar. */
SatDatepicker.prototype.close = function () {
var _this = this;
if (!this._opened) {
return;
}
if (this._popupRef && this._popupRef.hasAttached()) {
this._popupRef.detach();
}
if (this._dialogRef) {
this._dialogRef.close();
this._dialogRef = null;
}
if (this._calendarPortal && this._calendarPortal.isAttached) {
this._calendarPortal.detach();
}
if (this._beginDateSelected && this.selectFirstDateOnClose) {
this._selectRange({ begin: this._beginDateSelected, end: this._beginDateSelected });
}
var completeClose = function () {
// The `_opened` could've been reset already if
// we got two events in quick succession.
if (_this._opened) {
_this._opened = false;
_this.closedStream.emit();
_this._focusedElementBeforeOpen = null;
}
};
if (this._focusedElementBeforeOpen &&
typeof this._focusedElementBeforeOpen.focus === 'function') {
// Because IE moves focus asynchronously, we can't count on it being restored before we've
// marked the datepicker as closed. If the event fires out of sequence and the element that
// we're refocusing opens the datepicker on focus, the user could be stuck with not being
// able to close the calendar at all. We work around it by making the logic, that marks
// the datepicker as closed, async as well.
this._focusedElementBeforeOpen.focus();
setTimeout(completeClose);
}
else {
completeClose();
}
};
SatDatepicker.prototype.setBeginDateSelected = function (date) {
this._beginDateSelected = date;
};
/** Open the calendar as a dialog. */
SatDatepicker.prototype._openAsDialog = function () {
var _this = this;
// Usually this would be handled by `open` which ensures that we can only have one overlay
// open at a time, however since we reset the variables in async handlers some overlays
// may slip through if the user opens and closes multiple times in quick succession (e.g.
// by holding down the enter key).
if (this._dialogRef) {
this._dialogRef.close();
}
this._dialogRef = this._dialog.open(SatDatepickerContent, {
direction: this._dir ? this._dir.value : 'ltr',
viewContainerRef: this._viewContainerRef,
panelClass: 'mat-datepicker-dialog',
});
this._dialogRef.afterClosed().subscribe(function () { return _this.close(); });
this._dialogRef.componentInstance.datepicker = this;
this._setColor();
};
/** Open the calendar as a popup. */
SatDatepicker.prototype._openAsPopup = function () {
var _this = this;
if (!this._calendarPortal) {
this._calendarPortal = new ComponentPortal(SatDatepickerContent, this._viewContainerRef);
}
if (!this._popupRef) {
this._createPopup();
}
if (!this._popupRef.hasAttached()) {
this._popupComponentRef = this._popupRef.attach(this._calendarPortal);
this._popupComponentRef.instance.datepicker = this;
this._setColor();
// Update the position once the calendar has rendered.
this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(function () {
_this._popupRef.updatePosition();
});
}
};
/** Create the popup. */
SatDatepicker.prototype._createPopup = function () {
var _this = this;
var overlayConfig = new OverlayConfig({
positionStrategy: this._createPopupPositionStrategy(),
hasBackdrop: true,
backdropClass: 'mat-overlay-transparent-backdrop',
direction: this._dir,
scrollStrategy: this._scrollStrategy(),
panelClass: 'mat-datepicker-popup',
});
this._popupRef = this._overlay.create(overlayConfig);
this._popupRef.overlayElement.setAttribute('role', 'dialog');
merge(this._popupRef.backdropClick(), this._popupRef.detachments(), this._popupRef.keydownEvents().pipe(filter(function (event) {
// Closing on alt + up is only valid when there's an input associated with the datepicker.
return event.keyCode === ESCAPE ||
(_this._datepickerInput && event.altKey && event.keyCode === UP_ARROW);
}))).subscribe(function (event) {
if (event) {
event.preventDefault();
}
_this.close();
});
};
/** Create the popup PositionStrategy. */
SatDatepicker.prototype._createPopupPositionStrategy = function () {
return this._overlay.position()
.flexibleConnectedTo(this._datepickerInput.getConnectedOverlayOrigin())
.withTransformOriginOn('.mat-datepicker-content')
.withFlexibleDimensions(false)
.withViewportMargin(8)
.withLockedPosition()
.withPositions([
{
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top'
},
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom'
},
{
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top'
},
{
originX: 'end',
originY: 'top',
overlayX: 'end',
overlayY: 'bottom'
}
]);
};
/**
* @param obj The object to check.
* @returns The given object if it is both a date instance and valid, otherwise null.
*/
SatDatepicker.prototype._getValidDateOrNull = function (obj) {
return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null;
};
/** Passes the current theme color along to the calendar overlay. */
SatDatepicker.prototype._setColor = function () {
var color = this.color;
if (this._popupComponentRef) {
this._popupComponentRef.instance.color = color;
}
if (this._dialogRef) {
this._dialogRef.componentInstance.color = color;
}
};
SatDatepicker.ctorParameters = function () { return [
{ type: MatDialog },
{ type: Overlay },
{ type: NgZone },
{ type: ViewContainerRef },
{ type: undefined, decorators: [{ type: Inject, args: [MAT_DATEPICKER_SCROLL_STRATEGY,] }] },
{ type: DateAdapter, decorators: [{ type: Optional }] },
{ type: Directionality, decorators: [{ type: Optional }] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DOCUMENT,] }] }
]; };
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "rangeMode", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "beginDate", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "endDate", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "calendarHeaderComponent", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "calendarFooterComponent", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "startAt", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "startView", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "color", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "touchUi", null);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "disabled", null);
tslib_1.__decorate([
Output()
], SatDatepicker.prototype, "yearSelected", void 0);
tslib_1.__decorate([
Output()
], SatDatepicker.prototype, "monthSelected", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "panelClass", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "dateClass", void 0);
tslib_1.__decorate([
Output('opened')
], SatDatepicker.prototype, "openedStream", void 0);
tslib_1.__decorate([
Output('closed')
], SatDatepicker.prototype, "closedStream", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "closeAfterSelection", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "rangeHoverEffect", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "selectFirstDateOnClose", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "orderPeriodLabel", void 0);
tslib_1.__decorate([
Input()
], SatDatepicker.prototype, "opened", null);
SatDatepicker = tslib_1.__decorate([
Component({
moduleId: module.id,
selector: 'sat-datepicker',
template: '',
exportAs: 'matDatepicker',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
}),
tslib_1.__param(4, Inject(MAT_DATEPICKER_SCROLL_STRATEGY)),
tslib_1.__param(5, Optional()),
tslib_1.__param(6, Optional()),
tslib_1.__param(7, Optional()), tslib_1.__param(7, Inject(DOCUMENT))
], SatDatepicker);
return SatDatepicker;
}());
export { SatDatepicker };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5qcyIsInNvdXJjZVJvb3QiOiJuZzovL3NhdHVybi1kYXRlcGlja2VyLyIsInNvdXJjZXMiOlsiZGF0ZXBpY2tlci9kYXRlcGlja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRzs7QUFFSCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDakQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxFQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsT0FBTyxFQUNQLGFBQWEsRUFDYixVQUFVLEVBQ1YsZ0JBQWdCLEVBQ2hCLGNBQWMsR0FDZixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBQyxlQUFlLEVBQWdCLE1BQU0scUJBQXFCLENBQUM7QUFDbkUsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFDTCxhQUFhLEVBQ2IsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFlBQVksRUFDWixNQUFNLEVBQ04sY0FBYyxFQUNkLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULFFBQVEsRUFDUixNQUFNLEVBQ04sU0FBUyxFQUNULGdCQUFnQixFQUNoQixpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdMLFVBQVUsR0FFWCxNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBQyxTQUFTLEVBQUUsWUFBWSxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDakUsT0FBTyxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ2xELE9BQU8sRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFDLFdBQVcsRUFB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QUUsbUJBQUEsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFBO09BM005QixhQUFhLENBNGR6QjtJQUFELG9CQUFDO0NBQUEsQUE1ZEQsSUE0ZEM7U0E1ZFksYUFBYSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0RpcmVjdGlvbmFsaXR5fSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQge2NvZXJjZUJvb2xlYW5Qcm9wZXJ0eX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvZXJjaW9uJztcbmltcG9ydCB7RVNDQVBFLCBVUF9BUlJPV30gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcbmltcG9ydCB7XG4gIE92ZXJsYXksXG4gIE92ZXJsYXlDb25maWcsXG4gIE92ZXJsYXlSZWYsXG4gIFBvc2l0aW9uU3RyYXRlZ3ksXG4gIFNjcm9sbFN0cmF0ZWd5LFxufSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQge0NvbXBvbmVudFBvcnRhbCwgQ29tcG9uZW50VHlwZX0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BvcnRhbCc7XG5pbXBvcnQge0RPQ1VNRU5UfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgQ29tcG9uZW50UmVmLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEluamVjdCxcbiAgSW5qZWN0aW9uVG9rZW4sXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uRGVzdHJveSxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBDYW5Db2xvcixcbiAgQ2FuQ29sb3JDdG9yLFxuICBtaXhpbkNvbG9yLFxuICBUaGVtZVBhbGV0dGUsXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NvcmUnO1xuaW1wb3J0IHtNYXREaWFsb2csIE1hdERpYWxvZ1JlZn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7bWVyZ2UsIFN1YmplY3QsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2ZpbHRlciwgdGFrZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtTYXRDYWxlbmRhcn0gZnJvbSAnLi9jYWxlbmRhcic7XG5pbXBvcnQge21hdERhdGVwaWNrZXJBbmltYXRpb25zfSBmcm9tICcuL2RhdGVwaWNrZXItYW5pbWF0aW9ucyc7XG5pbXBvcnQge2NyZWF0ZU1pc3NpbmdEYXRlSW1wbEVycm9yfSBmcm9tICcuL2RhdGVwaWNrZXItZXJyb3JzJztcbmltcG9ydCB7U2F0Q2FsZW5kYXJDZWxsQ3NzQ2xhc3Nlc30gZnJvbSAnLi9jYWxlbmRhci1ib2R5JztcbmltcG9ydCB7U2F0RGF0ZXBpY2tlcklucHV0LCBTYXREYXRlcGlja2VyUmFuZ2VWYWx1ZX0gZnJvbSAnLi9kYXRlcGlja2VyLWlucHV0JztcbmltcG9ydCB7RGF0ZUFkYXB0ZXJ9IGZyb20gJy4uL2RhdGV0aW1lL2RhdGUtYWRhcHRlcic7XG5cbi8qKiBVc2VkIHRvIGdlbmVyYXRlIGEgdW5pcXVlIElEIGZvciBlYWNoIGRhdGVwaWNrZXIgaW5zdGFuY2UuICovXG5sZXQgZGF0ZXBpY2tlclVpZCA9IDA7XG5cbi8qKiBJbmplY3Rpb24gdG9rZW4gdGhhdCBkZXRlcm1pbmVzIHRoZSBzY3JvbGwgaGFuZGxpbmcgd2hpbGUgdGhlIGNhbGVuZGFyIGlzIG9wZW4uICovXG5leHBvcnQgY29uc3QgTUFUX0RBVEVQSUNLRVJfU0NST0xMX1NUUkFURUdZID1cbiAgICBuZXcgSW5qZWN0aW9uVG9rZW48KCkgPT4gU2Nyb2xsU3RyYXRlZ3k+KCdzYXQtZGF0ZXBpY2tlci1zY3JvbGwtc3RyYXRlZ3knKTtcblxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmV4cG9ydCBmdW5jdGlvbiBNQVRfREFURVBJQ0tFUl9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWShvdmVybGF5OiBPdmVybGF5KTogKCkgPT4gU2Nyb2xsU3RyYXRlZ3kge1xuICByZXR1cm4gKCkgPT4gb3ZlcmxheS5zY3JvbGxTdHJhdGVnaWVzLnJlcG9zaXRpb24oKTtcbn1cblxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmV4cG9ydCBjb25zdCBNQVRfREFURVBJQ0tFUl9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWV9QUk9WSURFUiA9IHtcbiAgcHJvdmlkZTogTUFUX0RBVEVQSUNLRVJfU0NST0xMX1NUUkFURUdZLFxuICBkZXBzOiBbT3ZlcmxheV0sXG4gIHVzZUZhY3Rvcnk6IE1BVF9EQVRFUElDS0VSX1NDUk9MTF9TVFJBVEVHWV9GQUNUT1JZLFxufTtcblxuLy8gQm9pbGVycGxhdGUgZm9yIGFwcGx5aW5nIG1peGlucyB0byBTYXREYXRlcGlja2VyQ29udGVudC5cbi8qKiBAZG9jcy1wcml2YXRlICovXG5jbGFzcyBTYXREYXRlcGlja2VyQ29udGVudEJhc2Uge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWYpIHsgfVxufVxuY29uc3QgX1NhdERhdGVwaWNrZXJDb250ZW50TWl4aW5CYXNlOiBDYW5Db2xvckN0b3IgJiB0eXBlb2YgU2F0RGF0ZXBpY2tlckNvbnRlbnRCYXNlID1cbiAgICBtaXhpbkNvbG9yKFNhdERhdGVwaWNrZXJDb250ZW50QmFzZSk7XG5cbi8qKlxuICogQ29tcG9uZW50IHVzZWQgYXMgdGhlIGNvbnRlbnQg