UNPKG

saturn-datepicker-ext

Version:

Material datepicker with range support ## What is this?

529 lines 71.2 kB
/** * @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 { Directionality } from '@angular/cdk/bidi'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ESCAPE, UP_ARROW } from '@angular/cdk/keycodes'; import { Overlay, OverlayConfig, } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; import { DOCUMENT } from '@angular/common'; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Inject, InjectionToken, Input, NgZone, Optional, Output, ViewChild, ViewContainerRef, ViewEncapsulation, } from '@angular/core'; import { mixinColor, } from '@angular/material/core'; import { MatDialog } 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. */ let datepickerUid = 0; /** Injection token that determines the scroll handling while the calendar is open. */ export const MAT_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('sat-datepicker-scroll-strategy'); /** @docs-private */ export function MAT_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay) { return () => overlay.scrollStrategies.reposition(); } /** @docs-private */ export const 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 */ class SatDatepickerContentBase { constructor(_elementRef) { this._elementRef = _elementRef; } } const _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 */ export class SatDatepickerContent extends _SatDatepickerContentMixinBase { constructor(elementRef) { super(elementRef); /** Will emit whenever the begin date is selected */ this.beginDateSelected = new EventEmitter(); } ngAfterViewInit() { this._calendar.focusActiveCell(); } setBeginDateSelected(beginDate) { this.datepicker.setBeginDateSelected(beginDate); this.beginDateSelected.emit(beginDate); } close() { if (this.datepicker.closeAfterSelection) { this.datepicker.close(); } } } SatDatepickerContent.decorators = [ { type: Component, args: [{ 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)=\"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{height:354px;width:296px}.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;margin:-24px;max-height:80vh;overflow:auto}.mat-datepicker-content-touch .mat-calendar{max-height:788px;max-width:750px;min-height:312px;min-width:250px}@media (orientation:landscape){.mat-datepicker-content-touch .mat-calendar{height:80vh;width:64vh}}@media (orientation:portrait){.mat-datepicker-content-touch .mat-calendar{height:100vw;width:80vw}}"] },] } ]; SatDatepickerContent.ctorParameters = () => [ { type: ElementRef } ]; SatDatepickerContent.propDecorators = { beginDateSelected: [{ type: Output }], _calendar: [{ type: ViewChild, args: [SatCalendar, { static: false },] }] }; // 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. */ export class SatDatepicker { constructor(_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(); /** Emits when the begin date has been selected. */ this.beginDateSelected = 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(); /** Default color to fall back to if no value is set. */ this.defaultColor = 'primary'; if (!this._dateAdapter) { throw createMissingDateImplError('DateAdapter'); } this._scrollStrategy = scrollStrategy; } /** Whenever datepicker is for selecting range of dates. */ get rangeMode() { return this._rangeMode; } set rangeMode(mode) { this._rangeMode = mode; if (this.rangeMode) { this._validSelected = null; } else { this._beginDate = this._endDate = null; } } /** Start of dates interval. */ get beginDate() { return this._beginDate; } set beginDate(value) { this._validSelected = null; this._beginDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** End of dates interval. */ get endDate() { return this._endDate; } set endDate(value) { this._validSelected = null; this._endDate = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** The date to open the calendar to initially. */ get startAt() { // 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 startAt(value) { this._startAt = this._getValidDateOrNull(this._dateAdapter.deserialize(value)); } /** Color palette to use on the datepicker's calendar. */ get color() { return this._color || (this._datepickerInput ? this._datepickerInput._getThemePalette() : undefined); } set color(value) { this._color = value; } /** * 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 touchUi() { return this._touchUi; } set touchUi(value) { this._touchUi = coerceBooleanProperty(value); } /** Whether the datepicker pop-up should be disabled. */ get disabled() { return this._disabled === undefined && this._datepickerInput ? this._datepickerInput.disabled : !!this._disabled; } set disabled(value) { const newValue = coerceBooleanProperty(value); if (newValue !== this._disabled) { this._disabled = newValue; this._disabledChange.next(newValue); } } /** Whether the calendar is open. */ get opened() { return this._opened; } set opened(value) { value ? this.open() : this.close(); } /** The currently selected date. */ get _selected() { return this._validSelected; } set _selected(value) { this._validSelected = value; } /** The minimum selectable date. */ get _minDate() { return this._datepickerInput && this._datepickerInput.min; } /** The maximum selectable date. */ get _maxDate() { return this._datepickerInput && this._datepickerInput.max; } get _dateFilter() { return this._datepickerInput && this._datepickerInput._dateFilter; } ngOnDestroy() { this.close(); this._inputSubscription.unsubscribe(); this._disabledChange.complete(); if (this._popupRef) { this._popupRef.dispose(); this._popupComponentRef = null; } } /** Selects the given date */ select(date) { let oldValue = this._selected; this._selected = date; if (!this._dateAdapter.sameDate(oldValue, this._selected)) { this._selectedChanged.next(date); } } /** Selects the given date range */ _selectRange(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 */ _selectYear(normalizedYear) { this.yearSelected.emit(normalizedYear); } /** Emits selected month in year view */ _selectMonth(normalizedMonth) { this.monthSelected.emit(normalizedMonth); } /** * Register an input with this datepicker. * @param input The datepicker input to register with this datepicker. */ _registerInput(input) { if (this._datepickerInput) { throw Error('A SatDatepicker can only be associated with a single input.'); } this._datepickerInput = input; this._inputSubscription = this._datepickerInput._valueChange .subscribe((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. */ open() { 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. */ close() { 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 }); } const completeClose = () => { // 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(); } } setBeginDateSelected(date) { this._beginDateSelected = date; } /** Open the calendar as a dialog. */ _openAsDialog() { // 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.componentInstance.beginDateSelected.subscribe(beginDate => { this.beginDateSelected.emit(beginDate); }); this._dialogRef.afterClosed().subscribe(() => this.close()); this._dialogRef.componentInstance.datepicker = this; this._setColor(); } /** Open the calendar as a popup. */ _openAsPopup() { 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._popupComponentRef.instance.beginDateSelected.subscribe(beginDate => { this.beginDateSelected.emit(beginDate); }); this._setColor(); // Update the position once the calendar has rendered. this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(() => { this._popupRef.updatePosition(); }); } } /** Create the popup. */ _createPopup() { const 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(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(event => { if (event) { event.preventDefault(); } this.close(); }); } /** Create the popup PositionStrategy. */ _createPopupPositionStrategy() { 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. */ _getValidDateOrNull(obj) { return (this._dateAdapter.isDateInstance(obj) && this._dateAdapter.isValid(obj)) ? obj : null; } /** Passes the current theme color along to the calendar overlay. */ _setColor() { const color = this.color; if (this._popupComponentRef) { this._popupComponentRef.instance.color = color; } if (this._dialogRef) { this._dialogRef.componentInstance.color = color; } } } SatDatepicker.decorators = [ { type: Component, args: [{ selector: 'sat-datepicker', template: '', exportAs: 'matDatepicker', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None },] } ]; SatDatepicker.ctorParameters = () => [ { 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,] }] } ]; SatDatepicker.propDecorators = { rangeMode: [{ type: Input }], beginDate: [{ type: Input }], endDate: [{ type: Input }], calendarHeaderComponent: [{ type: Input }], calendarFooterComponent: [{ type: Input }], startAt: [{ type: Input }], startView: [{ type: Input }], color: [{ type: Input }], touchUi: [{ type: Input }], disabled: [{ type: Input }], yearSelected: [{ type: Output }], monthSelected: [{ type: Output }], panelClass: [{ type: Input }], dateClass: [{ type: Input }], openedStream: [{ type: Output, args: ['opened',] }], closedStream: [{ type: Output, args: ['closed',] }], beginDateSelected: [{ type: Output }], closeAfterSelection: [{ type: Input }], rangeHoverEffect: [{ type: Input }], selectFirstDateOnClose: [{ type: Input }], orderPeriodLabel: [{ type: Input }], opened: [{ type: Input }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NhdHVybi1kYXRlcGlja2VyLWV4dC9zcmMvZGF0ZXBpY2tlci9kYXRlcGlja2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMscUJBQXFCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsTUFBTSxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZELE9BQU8sRUFDTCxPQUFPLEVBQ1AsYUFBYSxHQUlkLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFDLGVBQWUsRUFBZ0IsTUFBTSxxQkFBcUIsQ0FBQztBQUNuRSxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDekMsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixTQUFTLEVBRVQsVUFBVSxFQUNWLFlBQVksRUFDWixNQUFNLEVBQ04sY0FBYyxFQUNkLEtBQUssRUFDTCxNQUFNLEVBRU4sUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsZ0JBQWdCLEVBQ2hCLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBR0wsVUFBVSxHQUVYLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFDLFNBQVMsRUFBZSxNQUFNLDBCQUEwQixDQUFDO0FBQ2pFLE9BQU8sRUFBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUNsRCxPQUFPLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzVDLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDdkMsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0seUJBQXlCLENBQUM7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QUFDO1NBQ2pEO0lBQ0gsQ0FBQzs7O1lBbGZGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsZ0JBQWdCO2dCQUMxQixRQUFRLEVBQUUsRUFBRTtnQkFDWixRQUFRLEVBQUUsZUFBZTtnQkFDekIsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07Z0JBQy9DLGFBQWEsRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO2FBQ3RDOzs7WUE3R08sU0FBUztZQWhDZixPQUFPO1lBa0JQLE1BQU07WUFLTixnQkFBZ0I7NENBcVVILE1BQU0sU0FBQyw4QkFBOEI7WUFwVDVDLFdBQVcsdUJBcVRKLFFBQVE7WUFqV2YsY0FBYyx1QkFrV1AsUUFBUTs0Q0FDUixRQUFRLFlBQUksTUFBTSxTQUFDLFFBQVE7Ozt3QkE5TXZDLEtBQUs7d0JBZUwsS0FBSztzQkFTTCxLQUFLO3NDQVdMLEtBQUs7c0NBR0wsS0FBSztzQkFHTCxLQUFLO3dCQWdCTCxLQUFLO29CQUdMLEtBQUs7c0JBY0wsS0FBSzt1QkFRTCxLQUFLOzJCQW1CTCxNQUFNOzRCQU1OLE1BQU07eUJBR04sS0FBSzt3QkFHTCxLQUFLOzJCQUdMLE1BQU0sU0FBQyxRQUFROzJCQUdmLE1BQU0sU0FBQyxRQUFRO2dDQUdmLE1BQU07a0NBR04sS0FBSzsrQkFHTCxLQUFLO3FDQUtMLEtBQUs7K0JBR0wsS0FBSztxQkFHTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7RGlyZWN0aW9uYWxpdHl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9iaWRpJztcbmltcG9ydCB7Y29lcmNlQm9vbGVhblByb3BlcnR5fSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtFU0NBUEUsIFVQX0FSUk9XfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHtcbiAgT3ZlcmxheSxcbiAgT3ZlcmxheUNvbmZpZyxcbiAgT3ZlcmxheVJlZixcbiAgUG9zaXRpb25TdHJhdGVneSxcbiAgU2Nyb2xsU3RyYXRlZ3ksXG59IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7Q29tcG9uZW50UG9ydGFsLCBDb21wb25lbnRUeXBlfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcbmltcG9ydCB7RE9DVU1FTlR9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRSZWYsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5qZWN0LFxuICBJbmplY3Rpb25Ub2tlbixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG4gIFZpZXdDb250YWluZXJSZWYsXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIENhbkNvbG9yLFxuICBDYW5Db2xvckN0b3IsXG4gIG1peGluQ29sb3IsXG4gIFRoZW1lUGFsZXR0ZSxcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvY29yZSc7XG5pbXBvcnQge01hdERpYWxvZywgTWF0RGlhbG9nUmVmfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHttZXJnZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7ZmlsdGVyLCB0YWtlfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1NhdENhbGVuZGFyfSBmcm9tICcuL2NhbGVuZGFyJztcbmltcG9ydCB7bWF0RGF0ZXBpY2tlckFuaW1hdGlvbnN9IGZyb20gJy4vZGF0ZXBpY2tlci1hbmltYXRpb25zJztcbmltcG9ydCB7Y3JlYXRlTWlzc2luZ0RhdGVJbXBsRXJyb3J9IGZyb20gJy4vZGF0ZXBpY2tlci1lcnJvcnMnO1xuaW1wb3J0IHtTYXRDYWxlbmRhckNlbGxDc3NDbGFzc2VzfSBmcm9tICcuL2NhbGVuZGFyLWJvZHknO1xuaW1wb3J0IHtTYXREYXRlcGlja2VySW5wdXQsIFNhdERhdGVwaWNrZXJSYW5nZVZhbHVlfSBmcm9tICcuL2RhdGVwaWNrZXItaW5wdXQnO1xuaW1wb3J0IHtEYXRlQWRhcHRlcn0gZnJvbSAnLi4vZGF0ZXRpbWUvZGF0ZS1hZGFwdGVyJztcblxuLyoqIFVzZWQgdG8gZ2VuZXJhdGUgYSB1bmlxdWUgSUQgZm9yIGVhY2ggZGF0ZXBpY2tlciBpbnN0YW5jZS4gKi9cbmxldCBkYXRlcGlja2VyVWlkID0gMDtcblxuLyoqIEluamVjdGlvbiB0b2tlbiB0aGF0IGRldGVybWluZXMgdGhlIHNjcm9sbCBoYW5kbGluZyB3aGlsZSB0aGUgY2FsZW5kYXIgaXMgb3Blbi4gKi9cbmV4cG9ydCBjb25zdCBNQVRfREFURVBJQ0tFUl9TQ1JPTExfU1RSQVRFR1kgPVxuICAgIG5ldyBJbmplY3Rpb25Ub2tlbjwoKSA9PiBTY3JvbGxTdHJhdGVneT4oJ3NhdC1kYXRlcGlja2VyLXNjcm9sbC1zdHJhdGVneScpO1xuXG4vKiogQGRvY3MtcHJpdmF0ZSAqL1xuZXhwb3J0IGZ1bmN0aW9uIE1BVF9EQVRFUElDS0VSX1NDUk9MTF9TVFJBVEVHWV9GQUNUT1JZKG92ZXJsYXk6IE92ZXJsYXkpOiAoKSA9PiBTY3JvbGxTdHJhdGVneSB7XG4gIHJldHVybiAoKSA9PiBvdmVybGF5LnNjcm9sbFN0cmF0ZWdpZXMucmVwb3NpdGlvbigpO1xufVxuXG4vKiogQGRvY3MtcHJpdmF0ZSAqL1xuZXhwb3J0IGNvbnN0IE1BVF9EQVRFUElDS0VSX1NDUk9MTF9TVFJBVEVHWV9GQUNUT1JZX1BST1ZJREVSID0ge1xuICBwcm92aWRlOiBNQVRfREFURVBJQ0tFUl9TQ1JPTExfU1RSQVRFR1ksXG4gIGRlcHM6IFtPdmVybGF5XSxcbiAgdXNlRmFjdG9yeTogTUFUX0RBVEVQSUNLRVJfU0NST0xMX1NUUkFURUdZX0ZBQ1RPUlksXG59O1xuXG4vLyBCb2lsZXJwbGF0ZSBmb3IgYXBwbHlpbmcgbWl4aW5zIHRvIFNhdERhdGVwaWNrZXJDb250ZW50LlxuLyoqIEBkb2NzLXByaXZhdGUgKi9cbmNsYXNzIFNhdERhdGVwaWNrZXJDb250ZW50QmFzZSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBfZWxlbWVudFJlZjogRWxlbWVudFJlZikgeyB9XG59XG5jb25zdCBfU2F0RGF0ZXBpY2tlckNvbnRlbnRNaXhpbkJhc2U6IENhbkNvbG9yQ3RvciAmIHR5cGVvZiBTYXREYXRlcGlja2VyQ29udGVudEJhc2UgPVxuICAgIG1peGluQ29sb3IoU2F0RGF0ZXBpY2tlckNvbnRlbnRCYXNlKTtcblxuLyoqXG4gKiBDb21wb25lbnQgdXNlZCBhcyB0aGUgY29udGVudCBmb3IgdGhlIGRhdGVwaWNrZXIgZGlhbG9nIGFuZCBwb3B1cC4gV2UgdXNlIHRoaXMgaW5zdGVhZCBvZiB1c2luZ1xuICogU2F0Q2FsZW5kYXIgZGlyZWN0bHkgYXMgdGhlIGNvbnRlbnQgc28gd2UgY2FuIGNvbnRyb2wgdGhlIGluaXRpYWwgZm9jdXMuIFRoaXMgYWxzbyBnaXZlcyB1cyBhXG4gKiBwbGFjZSB0byBwdXQgYWRkaXRpb25hbCBmZWF0dXJlcyBvZiB0aGUgcG9wdXAgdGhhdCBhcmUgbm90IHBhcnQgb2YgdGhlIGNhbGVuZGFyIGl0c2VsZiBpbiB0aGVcbiAqIGZ1dHVyZS4gKGUuZy4gY29uZmlybWF0aW9uIGJ1dHRvbnMpLlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzYXQtZGF0ZXBpY2tlci1jb250ZW50JyxcbiAgdGVtcGxhdGVVcmw6ICdkYXRlcGlja2VyLWNvbnRlbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWydkYXRlcGlja2VyLWNvbnRlbnQuY3NzJ10sXG4gIGhvc3Q6IHtcbiAgICAnY2xhc3MnOiAnbWF0LWRhdGVwaWNrZXItY29udGVudCcsXG4gICAgJ1tAdHJhbnNmb3JtUGFuZWxdJzogJ1wiZW50ZXJcIicsXG4gICAgJ1tjbGFzcy5tYXQtZGF0ZXBpY2tlci1jb250ZW50LXRvdWNoXSc6ICdkYXRlcGlja2VyLnRvdWNoVWknLFxuICB9LFxuICBhbmltYXRpb25zOiBbXG4gICAgbWF0RGF0ZXBpY2tlckFuaW1hdGlvbnMudHJhbnNmb3JtUGFuZWwsXG4gICAgbWF0RGF0ZXBpY2tlckFuaW1hdGlvbnMuZmFkZUluQ2FsZW5kYXIsXG4gIF0sXG4gIGV4cG9ydEFzOiAnbWF0RGF0ZXBpY2tlckNvbnRlbnQnLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW5wdXRzOiBbJ2NvbG9yJ10sXG59KVxuZXhwb3J0IGNsYXNzIFNhdERhdGVwaWNrZXJDb250ZW50PEQ+IGV4dGVuZHMgX1NhdERhdGVwaWNrZXJDb250ZW50TWl4aW5CYXNlXG4gIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgQ2FuQ29sb3Ige1xuXG4gIC8qKiBXaWxsIGVtaXQgd2hlbmV2ZXIgdGhlIGJlZ2luIGRhdGUgaXMgc2VsZWN0ZWQgKi9cbiAgQE91dHB1dCgpIGJlZ2luRGF0ZVNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxEPigpO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIGludGVybmFsIGNhbGVuZGFyIGNvbXBvbmVudC4gKi9cbiAgQFZpZXdDaGlsZChTYXRDYWxlbmRhciwge3N0YXRpYzogZmFsc2V9KSBfY2FsZW5kYXI6IFNhdENhbGVuZGFyPEQ+O1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIGRhdGVwaWNrZXIgdGhhdCBjcmVhdGVkIHRoZSBvdmVybGF5LiAqL1xuICBkYXRlcGlja2VyOiBTYXREYXRlcGlja2VyPEQ+O1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBkYXRlcGlja2VyIGlzIGFib3ZlIG9yIGJlbG93IHRoZSBpbnB1dC4gKi9cbiAgX2lzQWJvdmU6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIHN1cGVyKGVsZW1lbnRSZWYpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuX2NhbGVuZGFyLmZvY3VzQWN0aXZlQ2VsbCgpO1xuICB9XG5cbiAgc2V0QmVnaW5EYXRlU2VsZWN0ZWQoYmVnaW5EYXRlOiBEKSB7XG4gICAgdGhpcy5kYXRlcGlja2VyLnNldEJlZ2luRGF0ZVNlbGVjdGVkKGJlZ2luRGF0ZSk7XG5cbiAgICB0aGlzLmJlZ2luRGF0ZVNlbGVjdGVkLmVtaXQoYmVnaW5EYXRlKTtcbiAgfVxuXG4gIGNsb3NlKCkge1xuICAgIGlmICh0aGlzLmRhdGVwaWNrZXIuY2xvc2VBZnRlclNlbGVjdGlvbikge1xuICAgICAgdGhpcy5kYXRlcGlja2VyLmNsb3NlKCk7XG4gICAgfVxuICB9XG59XG5cblxuLy8gVE9ETyhtbWFsZXJiYSk6IFdlIHVzZSBhIGNvbXBvbmVudCBpbnN0ZWFkIG9mIGEgZGlyZWN0aXZlIGhlcmUgc28gdGhlIHVzZXIgY2FuIHVzZSBpbXBsaWNpdFxuLy8gdGVtcGxhdGUgcmVmZXJlbmNlIHZhcmlhYmxlcyAoZS5nLiAjZCB2cyAjZD1cIm1hdERhdGVwaWNrZXJcIikuIFdlIGNhbiBjaGFuZ2UgdGhpcyB0byBhIGRpcmVjdGl2ZVxuLy8gaWYgYW5ndWxhciBhZGRzIHN1cHBvcnQgZm9yIGBleHBvcnRBczogJyRpbXBsaWNpdCdgIG9uIGRpcmVjdGl2ZXMuXG4vKiogQ29tcG9uZW50IHJlc3BvbnNpYmxlIGZvciBtYW5hZ2luZyB0aGUgZGF0ZXBpY2tlciBwb3B1cC9kaWFsb2cuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzYXQtZGF0ZXBpY2tlcicsXG4gIHRlbXBsYXRlOiAnJyxcbiAgZXhwb3J0QXM6ICdtYXREYXRlcGlja2VyJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIFNhdERhdGVwaWNrZXI8RD4gaW1wbGVtZW50cyBPbkRlc3Ryb3ksIENhbkNvbG9yIHtcblxuICAvKiogV2hlbmV2ZXIgZGF0ZXBpY2tlciBpcyBmb3Igc2VsZWN0aW5nIHJhbmdlIG9mIGRhdGVzLiAqL1xuICBASW5wdXQoKVxuICBnZXQgcmFuZ2VNb2RlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9yYW5nZU1vZGU7XG4gIH1cbiAgc2V0IHJhbmdlTW9kZShtb2RlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fcmFuZ2VNb2RlID0gbW9kZTtcbiAgICBpZiAodGhpcy5yYW5nZU1vZGUpIHtcbiAgICAgIHRoaXMuX3ZhbGlkU2VsZWN0ZWQgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9iZWdpbkRhdGUgPSB0aGlzLl9lbmREYXRlID0gbnVsbDtcbiAgICB9XG4gIH1cbiAgcHJpdmF0ZSBfcmFuZ2VNb2RlO1xuXG4gIC8qKiBTdGFydCBvZiBkYXRlcyBpbnRlcnZhbC4gKi9cbiAgQElucHV0KClcbiAgZ2V0IGJlZ2luRGF0ZSgpOiBEIHwgbnVsbCB7IHJldHVybiB0aGlzLl9iZWdpbkRhdGU7IH1cbiAgc2V0IGJlZ2luRGF0ZSh2YWx1ZTogRCB8IG51bGwpIHtcbiAgICB0aGlzLl92YWxpZFNlbGVjdGVkID0gbnVsbDtcbiAgICB0aGlzLl9iZWdpbkRhdGUgPSB0aGlzLl9nZXRWYWxpZERhdGVPck51bGwodGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgfVxuICBfYmVnaW5EYXRlOiBEIHwgbnVsbDtcblxuICAvKiogRW5kIG9mIGRhdGVzIGludGVydmFsLiAqL1xuICBASW5wdXQoKVxuICBnZXQgZW5kRGF0ZSgpOiBEIHwgbnVsbCB7IHJldHVybiB0aGlzLl9lbmREYXRlOyB9XG4gIHNldCBlbmREYXRlKHZhbHVlOiBEIHwgbnVsbCkge1xuICAgIHRoaXMuX3ZhbGlkU2VsZWN0ZWQgPSBudWxsO1xuICAgIHRoaXMuX2VuZERhdGUgPSB0aGlzLl9nZXRWYWxpZERhdGVPck51bGwodGhpcy5fZGF0ZUFkYXB0ZXIuZGVzZXJpYWxpemUodmFsdWUpKTtcbiAgfVxuICBfZW5kRGF0ZTogRC