UNPKG

@clr/angular

Version:

Angular components for Clarity

175 lines 27.1 kB
/* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { Component, HostListener } from '@angular/core'; import { Keys } from '../../utils/enums/keys.enum'; import { normalizeKey } from '../../utils/focus/key-focus/util'; import { CalendarViewModel } from './model/calendar-view.model'; import { NO_OF_DAYS_IN_A_WEEK } from './utils/constants'; import * as i0 from "@angular/core"; import * as i1 from "./providers/locale-helper.service"; import * as i2 from "./providers/date-navigation.service"; import * as i3 from "./providers/datepicker-focus.service"; import * as i4 from "./providers/date-io.service"; import * as i5 from "./providers/date-form-control.service"; import * as i6 from "../../utils/popover/providers/popover-toggle.service"; import * as i7 from "@angular/common"; import * as i8 from "./day"; export class ClrCalendar { constructor(_localeHelperService, _dateNavigationService, _datepickerFocusService, _dateIOService, _elRef, _dateFormControlService, _toggleService) { this._localeHelperService = _localeHelperService; this._dateNavigationService = _dateNavigationService; this._datepickerFocusService = _datepickerFocusService; this._dateIOService = _dateIOService; this._elRef = _elRef; this._dateFormControlService = _dateFormControlService; this._toggleService = _toggleService; this._subs = []; this.generateCalendarView(); this.initializeSubscriptions(); } /** * Gets the locale days according to the TranslationWidth.Narrow format. */ get localeDays() { return this._localeHelperService.localeDays; } get calendar() { return this._dateNavigationService.displayedCalendar; } get selectedDay() { return this._dateNavigationService.selectedDay; } get selectedEndDay() { return this._dateNavigationService.selectedEndDay; } get focusedDay() { return this._dateNavigationService.focusedDay; } get today() { return this._dateNavigationService.today; } /** * Focuses on the focusable day when the Calendar View is initialized. */ ngAfterViewInit() { this._datepickerFocusService.focusCell(this._elRef); } /** * Unsubscribe from subscriptions. */ ngOnDestroy() { this._subs.forEach((sub) => sub.unsubscribe()); } /** * Delegates Keyboard arrow navigation to the DateNavigationService. */ onKeyDown(event) { if (event && this.focusedDay) { switch (normalizeKey(event.key)) { case Keys.ArrowUp: event.preventDefault(); this._dateNavigationService.incrementFocusDay(-1 * NO_OF_DAYS_IN_A_WEEK); break; case Keys.ArrowDown: event.preventDefault(); this._dateNavigationService.incrementFocusDay(NO_OF_DAYS_IN_A_WEEK); break; case Keys.ArrowLeft: event.preventDefault(); this._dateNavigationService.incrementFocusDay(-1); break; case Keys.ArrowRight: event.preventDefault(); this._dateNavigationService.incrementFocusDay(1); break; default: break; // No default case. ESLint x-( } } } setSelectedDay(day) { const hasActionButtons = this._dateNavigationService.hasActionButtons; const selectedDates = this.updateCalendarViewModal(day); this._dateNavigationService.notifySelectedDayChanged(selectedDates, { emitEvent: !hasActionButtons }); if (!hasActionButtons) { this._dateFormControlService.markAsDirty(); this.validateAndCloseDatePicker(); } } /** * Initialize subscriptions to: * 1. update the calendar view model. * 2. update the focusable day in the calendar view model. * 3. focus on the focusable day in the calendar. */ initializeSubscriptions() { this._subs.push(this._dateNavigationService.displayedCalendarChange.subscribe(() => { this.generateCalendarView(); })); this._subs.push(this._dateNavigationService.focusedDayChange.subscribe((focusedDay) => { this.calendarViewModel.updateFocusableDay(focusedDay); })); this._subs.push(this._dateNavigationService.focusOnCalendarChange.subscribe(() => { this._datepickerFocusService.focusCell(this._elRef); })); this._subs.push(this._dateNavigationService.refreshCalendarView.subscribe(() => { this.refreshCalendarViewModal(); })); } validateAndCloseDatePicker() { if ((this._dateNavigationService.isRangePicker && this._dateNavigationService.selectedDay && this._dateNavigationService.selectedEndDay) || (!this._dateNavigationService.isRangePicker && this._dateNavigationService.selectedDay)) { this._toggleService.open = false; } } updateCalendarViewModal(day) { const startDate = this.calendarViewModel.selectedDay || null, isRangePicker = this._dateNavigationService.isRangePicker; let endDate = this.calendarViewModel.selectedEndDay || null; if (isRangePicker) { if (!startDate || (!!startDate && !!endDate) || (!!startDate && day?.isBefore(startDate))) { this.calendarViewModel.updateSelectedDay(day); if (endDate) { endDate = undefined; this.calendarViewModel.updateSelectedEndDay(endDate); } } else { this.calendarViewModel.updateSelectedEndDay(day); } } else { this.calendarViewModel.updateSelectedDay(day); } return isRangePicker ? { startDate: this.calendarViewModel.selectedDay, endDate: this.calendarViewModel.selectedEndDay } : this.calendarViewModel.selectedDay; } refreshCalendarViewModal() { this.calendarViewModel.updateSelectedDay(this._dateNavigationService.selectedDay); if (this._dateNavigationService.isRangePicker) { this.calendarViewModel.updateSelectedEndDay(this._dateNavigationService.selectedEndDay); } } /** * Generates the Calendar View based on the calendar retrieved from the DateNavigationService. */ generateCalendarView() { this.calendarViewModel = new CalendarViewModel(this.calendar, this.selectedDay, this.selectedEndDay, this.focusedDay, this.today, this._localeHelperService.firstDayOfWeek, this._dateIOService.disabledDates); } } ClrCalendar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrCalendar, deps: [{ token: i1.LocaleHelperService }, { token: i2.DateNavigationService }, { token: i3.DatepickerFocusService }, { token: i4.DateIOService }, { token: i0.ElementRef }, { token: i5.DateFormControlService }, { token: i6.ClrPopoverToggleService }], target: i0.ɵɵFactoryTarget.Component }); ClrCalendar.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrCalendar, selector: "clr-calendar", host: { listeners: { "keydown": "onKeyDown($event)" } }, ngImport: i0, template: "<table class=\"calendar-table\" role=\"presentation\">\n <tr class=\"calendar-row weekdays\">\n <th *ngFor=\"let day of localeDays\" class=\"calendar-cell weekday\">\n <span [attr.aria-label]=\"day.day\">{{day.narrow}}</span>\n </th>\n </tr>\n <tr class=\"calendar-row\" *ngFor=\"let row of calendarViewModel.calendarView\">\n <td *ngFor=\"let dayView of row\" class=\"calendar-cell\">\n <clr-day [clrDayView]=\"dayView\" (selectDay)=\"setSelectedDay($event)\"></clr-day>\n </td>\n </tr>\n</table>\n", dependencies: [{ kind: "directive", type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i8.ClrDay, selector: "clr-day", inputs: ["clrDayView"], outputs: ["selectDay"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrCalendar, decorators: [{ type: Component, args: [{ selector: 'clr-calendar', template: "<table class=\"calendar-table\" role=\"presentation\">\n <tr class=\"calendar-row weekdays\">\n <th *ngFor=\"let day of localeDays\" class=\"calendar-cell weekday\">\n <span [attr.aria-label]=\"day.day\">{{day.narrow}}</span>\n </th>\n </tr>\n <tr class=\"calendar-row\" *ngFor=\"let row of calendarViewModel.calendarView\">\n <td *ngFor=\"let dayView of row\" class=\"calendar-cell\">\n <clr-day [clrDayView]=\"dayView\" (selectDay)=\"setSelectedDay($event)\"></clr-day>\n </td>\n </tr>\n</table>\n" }] }], ctorParameters: function () { return [{ type: i1.LocaleHelperService }, { type: i2.DateNavigationService }, { type: i3.DatepickerFocusService }, { type: i4.DateIOService }, { type: i0.ElementRef }, { type: i5.DateFormControlService }, { type: i6.ClrPopoverToggleService }]; }, propDecorators: { onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyL3NyYy9mb3Jtcy9kYXRlcGlja2VyL2NhbGVuZGFyLnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci9zcmMvZm9ybXMvZGF0ZXBpY2tlci9jYWxlbmRhci5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBYyxZQUFZLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFHL0UsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUloRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQVFoRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7Ozs7OztBQU16RCxNQUFNLE9BQU8sV0FBVztJQVF0QixZQUNVLG9CQUF5QyxFQUN6QyxzQkFBNkMsRUFDN0MsdUJBQStDLEVBQy9DLGNBQTZCLEVBQzdCLE1BQStCLEVBQy9CLHVCQUErQyxFQUMvQyxjQUF1QztRQU52Qyx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXFCO1FBQ3pDLDJCQUFzQixHQUF0QixzQkFBc0IsQ0FBdUI7UUFDN0MsNEJBQXVCLEdBQXZCLHVCQUF1QixDQUF3QjtRQUMvQyxtQkFBYyxHQUFkLGNBQWMsQ0FBZTtRQUM3QixXQUFNLEdBQU4sTUFBTSxDQUF5QjtRQUMvQiw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXdCO1FBQy9DLG1CQUFjLEdBQWQsY0FBYyxDQUF5QjtRQVR6QyxVQUFLLEdBQW1CLEVBQUUsQ0FBQztRQVdqQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lB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QUFzQixDQUFDLGFBQWEsRUFBRTtZQUM3QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1NBQ3pGO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssb0JBQW9CO1FBQzFCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLGlCQUFpQixDQUM1QyxJQUFJLENBQUMsUUFBUSxFQUNiLElBQUksQ0FBQyxXQUFXLEVBQ2hCLElBQUksQ0FBQyxjQUFjLEVBQ25CLElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLEtBQUssRUFDVixJQUFJLENBQUMsb0JBQW9CLENBQUMsY0FBYyxFQUN4QyxJQUFJLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FDbEMsQ0FBQztJQUNKLENBQUM7O3dHQTVMVSxXQUFXOzRGQUFYLFdBQVcsNkdDN0J4QiwrZ0JBWUE7MkZEaUJhLFdBQVc7a0JBSnZCLFNBQVM7K0JBQ0UsY0FBYzttVEFxRXhCLFNBQVM7c0JBRFIsWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE2LTIwMjUgQnJvYWRjb20uIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBUaGUgdGVybSBcIkJyb2FkY29tXCIgcmVmZXJzIHRvIEJyb2FkY29tIEluYy4gYW5kL29yIGl0cyBzdWJzaWRpYXJpZXMuXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlLlxuICogVGhlIGZ1bGwgbGljZW5zZSBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQgaW4gTElDRU5TRSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBwcm9qZWN0LlxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBLZXlzIH0gZnJvbSAnLi4vLi4vdXRpbHMvZW51bXMva2V5cy5lbnVtJztcbmltcG9ydCB7IG5vcm1hbGl6ZUtleSB9IGZyb20gJy4uLy4uL3V0aWxzL2ZvY3VzL2tleS1mb2N1cy91dGlsJztcbmltcG9ydCB7IENsclBvcG92ZXJUb2dnbGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvcG9wb3Zlci9wcm92aWRlcnMvcG9wb3Zlci10b2dnbGUuc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlUmFuZ2VJbnB1dCB9IGZyb20gJy4vaW50ZXJmYWNlcy9kYXRlLXJhbmdlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBDbHJEYXlPZldlZWsgfSBmcm9tICcuL2ludGVyZmFjZXMvZGF5LW9mLXdlZWsuaW50ZXJmYWNlJztcbmltcG9ydCB7IENhbGVuZGFyVmlld01vZGVsIH0gZnJvbSAnLi9tb2RlbC9jYWxlbmRhci12aWV3Lm1vZGVsJztcbmltcG9ydCB7IENhbGVuZGFyTW9kZWwgfSBmcm9tICcuL21vZGVsL2NhbGVuZGFyLm1vZGVsJztcbmltcG9ydCB7IERheU1vZGVsIH0gZnJvbSAnLi9tb2RlbC9kYXkubW9kZWwnO1xuaW1wb3J0IHsgRGF0ZUZvcm1Db250cm9sU2VydmljZSB9IGZyb20gJy4vcHJvdmlkZXJzL2RhdGUtZm9ybS1jb250cm9sLnNlcnZpY2UnO1xuaW1wb3J0IHsgRGF0ZUlPU2VydmljZSB9IGZyb20gJy4vcHJvdmlkZXJzL2RhdGUtaW8uc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlTmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuL3Byb3ZpZGVycy9kYXRlLW5hdmlnYXRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBEYXRlcGlja2VyRm9jdXNTZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvZGF0ZXBpY2tlci1mb2N1cy5zZXJ2aWNlJztcbmltcG9ydCB7IExvY2FsZUhlbHBlclNlcnZpY2UgfSBmcm9tICcuL3Byb3ZpZGVycy9sb2NhbGUtaGVscGVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgTk9fT0ZfREFZU19JTl9BX1dFRUsgfSBmcm9tICcuL3V0aWxzL2NvbnN0YW50cyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Nsci1jYWxlbmRhcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9jYWxlbmRhci5odG1sJyxcbn0pXG5leHBvcnQgY2xhc3MgQ2xyQ2FsZW5kYXIgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAvKipcbiAgICogQ2FsZW5kYXIgVmlldyBNb2RlbCB0byBnZW5lcmF0ZSB0aGUgQ2FsZW5kYXIuXG4gICAqL1xuICBjYWxlbmRhclZpZXdNb2RlbDogQ2FsZW5kYXJWaWV3TW9kZWw7XG5cbiAgcHJpdmF0ZSBfc3ViczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9sb2NhbGVIZWxwZXJTZXJ2aWNlOiBMb2NhbGVIZWxwZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgX2RhdGVOYXZpZ2F0aW9uU2VydmljZTogRGF0ZU5hdmlnYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgX2RhdGVwaWNrZXJGb2N1c1NlcnZpY2U6IERhdGVwaWNrZXJGb2N1c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBfZGF0ZUlPU2VydmljZTogRGF0ZUlPU2VydmljZSxcbiAgICBwcml2YXRlIF9lbFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgcHJpdmF0ZSBfZGF0ZUZvcm1Db250cm9sU2VydmljZTogRGF0ZUZvcm1Db250cm9sU2VydmljZSxcbiAgICBwcml2YXRlIF90b2dnbGVTZXJ2aWNlOiBDbHJQb3BvdmVyVG9nZ2xlU2VydmljZVxuICApIHtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXJWaWV3KCk7XG4gICAgdGhpcy5pbml0aWFsaXplU3Vic2NyaXB0aW9ucygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGxvY2FsZSBkYXlzIGFjY29yZGluZyB0byB0aGUgVHJhbnNsYXRpb25XaWR0aC5OYXJyb3cgZm9ybWF0LlxuICAgKi9cbiAgZ2V0IGxvY2FsZURheXMoKTogUmVhZG9ubHlBcnJheTxDbHJEYXlPZldlZWs+IHtcbiAgICByZXR1cm4gdGhpcy5fbG9jYWxlSGVscGVyU2VydmljZS5sb2NhbGVEYXlzO1xuICB9XG5cbiAgZ2V0IGNhbGVuZGFyKCk6IENhbGVuZGFyTW9kZWwge1xuICAgIHJldHVybiB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuZGlzcGxheWVkQ2FsZW5kYXI7XG4gIH1cblxuICBnZXQgc2VsZWN0ZWREYXkoKTogRGF5TW9kZWwge1xuICAgIHJldHVybiB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2Uuc2VsZWN0ZWREYXk7XG4gIH1cblxuICBnZXQgc2VsZWN0ZWRFbmREYXkoKTogRGF5TW9kZWwge1xuICAgIHJldHVybiB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2Uuc2VsZWN0ZWRFbmREYXk7XG4gIH1cblxuICBnZXQgZm9jdXNlZERheSgpOiBEYXlNb2RlbCB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5mb2N1c2VkRGF5O1xuICB9XG5cbiAgZ2V0IHRvZGF5KCk6IERheU1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnRvZGF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEZvY3VzZXMgb24gdGhlIGZvY3VzYWJsZSBkYXkgd2hlbiB0aGUgQ2FsZW5kYXIgVmlldyBpcyBpbml0aWFsaXplZC5cbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLl9kYXRlcGlja2VyRm9jdXNTZXJ2aWNlLmZvY3VzQ2VsbCh0aGlzLl9lbFJlZik7XG4gIH1cblxuICAvKipcbiAgICogVW5zdWJzY3JpYmUgZnJvbSBzdWJzY3JpcHRpb25zLlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fc3Vicy5mb3JFYWNoKChzdWI6IFN1YnNjcmlwdGlvbikgPT4gc3ViLnVuc3Vic2NyaWJlKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGVnYXRlcyBLZXlib2FyZCBhcnJvdyBuYXZpZ2F0aW9uIHRvIHRoZSBEYXRlTmF2aWdhdGlvblNlcnZpY2UuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdrZXlkb3duJywgWyckZXZlbnQnXSlcbiAgb25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgaWYgKGV2ZW50ICYmIHRoaXMuZm9jdXNlZERheSkge1xuICAgICAgc3dpdGNoIChub3JtYWxpemVLZXkoZXZlbnQua2V5KSkge1xuICAgICAgICBjYXNlIEtleXMuQXJyb3dVcDpcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5pbmNyZW1lbnRGb2N1c0RheSgtMSAqIE5PX09GX0RBWVNfSU5fQV9XRUVLKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBLZXlzLkFycm93RG93bjpcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5pbmNyZW1lbnRGb2N1c0RheShOT19PRl9EQVlTX0lOX0FfV0VFSyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgS2V5cy5BcnJvd0xlZnQ6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuaW5jcmVtZW50Rm9jdXNEYXkoLTEpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEtleXMuQXJyb3dSaWdodDpcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5pbmNyZW1lbnRGb2N1c0RheSgxKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBicmVhazsgLy8gTm8gZGVmYXVsdCBjYXNlLiBFU0xpbnQgeC0oXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc2V0U2VsZWN0ZWREYXkoZGF5OiBEYXlNb2RlbCkge1xuICAgIGNvbnN0IGhhc0FjdGlvbkJ1dHRvbnMgPSB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuaGFzQWN0aW9uQnV0dG9ucztcbiAgICBjb25zdCBzZWxlY3RlZERhdGVzOiBEYXlNb2RlbCB8IERhdGVSYW5nZUlucHV0ID0gdGhpcy51cGRhdGVDYWxlbmRhclZpZXdNb2RhbChkYXkpO1xuICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5ub3RpZnlTZWxlY3RlZERheUNoYW5nZWQoc2VsZWN0ZWREYXRlcywgeyBlbWl0RXZlbnQ6ICFoYXNBY3Rpb25CdXR0b25zIH0pO1xuICAgIGlmICghaGFzQWN0aW9uQnV0dG9ucykge1xuICAgICAgdGhpcy5fZGF0ZUZvcm1Db250cm9sU2VydmljZS5tYXJrQXNEaXJ0eSgpO1xuICAgICAgdGhpcy52YWxpZGF0ZUFuZENsb3NlRGF0ZVBpY2tlcigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIHN1YnNjcmlwdGlvbnMgdG86XG4gICAqIDEuIHVwZGF0ZSB0aGUgY2FsZW5kYXIgdmlldyBtb2RlbC5cbiAgICogMi4gdXBkYXRlIHRoZSBmb2N1c2FibGUgZGF5IGluIHRoZSBjYWxlbmRhciB2aWV3IG1vZGVsLlxuICAgKiAzLiBmb2N1cyBvbiB0aGUgZm9jdXNhYmxlIGRheSBpbiB0aGUgY2FsZW5kYXIuXG4gICAqL1xuICBwcml2YXRlIGluaXRpYWxpemVTdWJzY3JpcHRpb25zKCk6IHZvaWQge1xuICAgIHRoaXMuX3N1YnMucHVzaChcbiAgICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5kaXNwbGF5ZWRDYWxlbmRhckNoYW5nZS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXJWaWV3KCk7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLl9zdWJzLnB1c2goXG4gICAgICB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuZm9jdXNlZERheUNoYW5nZS5zdWJzY3JpYmUoKGZvY3VzZWREYXk6IERheU1vZGVsKSA9PiB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlRm9jdXNhYmxlRGF5KGZvY3VzZWREYXkpO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmZvY3VzT25DYWxlbmRhckNoYW5nZS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9kYXRlcGlja2VyRm9jdXNTZXJ2aWNlLmZvY3VzQ2VsbCh0aGlzLl9lbFJlZik7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLl9zdWJzLnB1c2goXG4gICAgICB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UucmVmcmVzaENhbGVuZGFyVmlldy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnJlZnJlc2hDYWxlbmRhclZpZXdNb2RhbCgpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZUFuZENsb3NlRGF0ZVBpY2tlcigpIHtcbiAgICBpZiAoXG4gICAgICAodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmlzUmFuZ2VQaWNrZXIgJiZcbiAgICAgICAgdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5ICYmXG4gICAgICAgIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5zZWxlY3RlZEVuZERheSkgfHxcbiAgICAgICghdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmlzUmFuZ2VQaWNrZXIgJiYgdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5KVxuICAgICkge1xuICAgICAgdGhpcy5fdG9nZ2xlU2VydmljZS5vcGVuID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVDYWxlbmRhclZpZXdNb2RhbChkYXk6IERheU1vZGVsKTogRGF5TW9kZWwgfCBEYXRlUmFuZ2VJbnB1dCB7XG4gICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5jYWxlbmRhclZpZXdNb2RlbC5zZWxlY3RlZERheSB8fCBudWxsLFxuICAgICAgaXNSYW5nZVBpY2tlciA9IHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5pc1JhbmdlUGlja2VyO1xuICAgIGxldCBlbmREYXRlID0gdGhpcy5jYWxlbmRhclZpZXdNb2RlbC5zZWxlY3RlZEVuZERheSB8fCBudWxsO1xuXG4gICAgaWYgKGlzUmFuZ2VQaWNrZXIpIHtcbiAgICAgIGlmICghc3RhcnREYXRlIHx8ICghIXN0YXJ0RGF0ZSAmJiAhIWVuZERhdGUpIHx8ICghIXN0YXJ0RGF0ZSAmJiBkYXk/LmlzQmVmb3JlKHN0YXJ0RGF0ZSkpKSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlU2VsZWN0ZWREYXkoZGF5KTtcbiAgICAgICAgaWYgKGVuZERhdGUpIHtcbiAgICAgICAgICBlbmREYXRlID0gdW5kZWZpbmVkO1xuICAgICAgICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlU2VsZWN0ZWRFbmREYXkoZW5kRGF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlU2VsZWN0ZWRFbmREYXkoZGF5KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jYWxlbmRhclZpZXdNb2RlbC51cGRhdGVTZWxlY3RlZERheShkYXkpO1xuICAgIH1cblxuICAgIHJldHVybiBpc1JhbmdlUGlja2VyXG4gICAgICA/IHsgc3RhcnREYXRlOiB0aGlzLmNhbGVuZGFyVmlld01vZGVsLnNlbGVjdGVkRGF5LCBlbmREYXRlOiB0aGlzLmNhbGVuZGFyVmlld01vZGVsLnNlbGVjdGVkRW5kRGF5IH1cbiAgICAgIDogdGhpcy5jYWxlbmRhclZpZXdNb2RlbC5zZWxlY3RlZERheTtcbiAgfVxuXG4gIHByaXZhdGUgcmVmcmVzaENhbGVuZGFyVmlld01vZGFsKCkge1xuICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlU2VsZWN0ZWREYXkodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5KTtcbiAgICBpZiAodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmlzUmFuZ2VQaWNrZXIpIHtcbiAgICAgIHRoaXMuY2FsZW5kYXJWaWV3TW9kZWwudXBkYXRlU2VsZWN0ZWRFbmREYXkodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRW5kRGF5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIHRoZSBDYWxlbmRhciBWaWV3IGJhc2VkIG9uIHRoZSBjYWxlbmRhciByZXRyaWV2ZWQgZnJvbSB0aGUgRGF0ZU5hdmlnYXRpb25TZXJ2aWNlLlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNhbGVuZGFyVmlldygpOiB2b2lkIHtcbiAgICB0aGlzLmNhbGVuZGFyVmlld01vZGVsID0gbmV3IENhbGVuZGFyVmlld01vZGVsKFxuICAgICAgdGhpcy5jYWxlbmRhcixcbiAgICAgIHRoaXMuc2VsZWN0ZWREYXksXG4gICAgICB0aGlzLnNlbGVjdGVkRW5kRGF5LFxuICAgICAgdGhpcy5mb2N1c2VkRGF5LFxuICAgICAgdGhpcy50b2RheSxcbiAgICAgIHRoaXMuX2xvY2FsZUhlbHBlclNlcnZpY2UuZmlyc3REYXlPZldlZWssXG4gICAgICB0aGlzLl9kYXRlSU9TZXJ2aWNlLmRpc2FibGVkRGF0ZXNcbiAgICApO1xuICB9XG59XG4iLCI8dGFibGUgY2xhc3M9XCJjYWxlbmRhci10YWJsZVwiIHJvbGU9XCJwcmVzZW50YXRpb25cIj5cbiAgPHRyIGNsYXNzPVwiY2FsZW5kYXItcm93IHdlZWtkYXlzXCI+XG4gICAgPHRoICpuZ0Zvcj1cImxldCBkYXkgb2YgbG9jYWxlRGF5c1wiIGNsYXNzPVwiY2FsZW5kYXItY2VsbCB3ZWVrZGF5XCI+XG4gICAgICA8c3BhbiBbYXR0ci5hcmlhLWxhYmVsXT1cImRheS5kYXlcIj57e2RheS5uYXJyb3d9fTwvc3Bhbj5cbiAgICA8L3RoPlxuICA8L3RyPlxuICA8dHIgY2xhc3M9XCJjYWxlbmRhci1yb3dcIiAqbmdGb3I9XCJsZXQgcm93IG9mIGNhbGVuZGFyVmlld01vZGVsLmNhbGVuZGFyVmlld1wiPlxuICAgIDx0ZCAqbmdGb3I9XCJsZXQgZGF5VmlldyBvZiByb3dcIiBjbGFzcz1cImNhbGVuZGFyLWNlbGxcIj5cbiAgICAgIDxjbHItZGF5IFtjbHJEYXlWaWV3XT1cImRheVZpZXdcIiAoc2VsZWN0RGF5KT1cInNldFNlbGVjdGVkRGF5KCRldmVudClcIj48L2Nsci1kYXk+XG4gICAgPC90ZD5cbiAgPC90cj5cbjwvdGFibGU+XG4iXX0=