@clr/angular
Version:
Angular components for Clarity
304 lines (302 loc) • 30.9 kB
JavaScript
/*
* 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 { YearRangeModel } from './model/year-range.model';
import * as i0 from "@angular/core";
import * as i1 from "./providers/date-navigation.service";
import * as i2 from "./providers/view-manager.service";
import * as i3 from "./providers/datepicker-focus.service";
import * as i4 from "../../utils/i18n/common-strings.service";
import * as i5 from "@angular/common";
import * as i6 from "../../icon/icon";
export class ClrYearpicker {
constructor(_dateNavigationService, _viewManagerService, _datepickerFocusService, _elRef, commonStrings) {
this._dateNavigationService = _dateNavigationService;
this._viewManagerService = _viewManagerService;
this._datepickerFocusService = _datepickerFocusService;
this._elRef = _elRef;
this.commonStrings = commonStrings;
this.yearRangeModel = new YearRangeModel(this.calendarYear);
this._focusedYear = this.calendarYear;
}
get selectedStartYear() {
return this._dateNavigationService.selectedDay?.year;
}
get selectedEndYear() {
return this._dateNavigationService.selectedEndDay?.year;
}
/**
* Gets the year which the user is currently on.
*/
get calendarYear() {
return this._dateNavigationService.displayedCalendar.year;
}
isCurrentCalendarYear(year) {
return year === new Date().getFullYear();
}
getIsRangeStartYear(year) {
return this._dateNavigationService.isRangePicker && year === this._dateNavigationService.selectedDay?.year;
}
getIsRangeEndYear(year) {
return this._dateNavigationService.isRangePicker && year === this._dateNavigationService.selectedEndDay?.year;
}
/**
* Focuses on the current calendar year when the View is initialized.
*/
ngAfterViewInit() {
this._datepickerFocusService.focusCell(this._elRef);
}
/**
* Handles the Keyboard arrow navigation for the yearpicker.
*/
onKeyDown(event) {
// NOTE: Didn't move this to the date navigation service because
// the logic is fairly simple and it didn't make sense for me
// to create extra observables just to move this logic to the service.
if (event) {
const key = normalizeKey(event.key);
if (key === Keys.ArrowUp) {
event.preventDefault();
this.incrementFocusYearBy(-2);
}
else if (key === Keys.ArrowDown) {
event.preventDefault();
this.incrementFocusYearBy(2);
}
else if (key === Keys.ArrowRight) {
event.preventDefault();
this.incrementFocusYearBy(1);
}
else if (key === Keys.ArrowLeft) {
event.preventDefault();
this.incrementFocusYearBy(-1);
}
}
}
/**
* Calls the DateNavigationService to update the year value of the calendar.
* Also changes the view to the daypicker.
*/
changeYear(year) {
this._dateNavigationService.changeYear(year);
this._viewManagerService.changeToDayView();
}
/**
* Calls the DateNavigationService to update the hovered year value of the calendar
*/
onHover(year) {
this._dateNavigationService.hoveredYear = year;
}
/**
* Updates the YearRangeModel to the previous decade.
*/
previousDecade() {
this.yearRangeModel = this.yearRangeModel.previousDecade();
// Year in the yearpicker is not focused because while navigating to a different decade,
// you want the focus to remain on the decade switcher arrows.
}
/**
* Updates the YearRangeModel to the current decade.
*/
currentDecade() {
if (!this.yearRangeModel.inRange(this._dateNavigationService.today.year)) {
this.yearRangeModel = this.yearRangeModel.currentDecade();
}
this._datepickerFocusService.focusCell(this._elRef);
}
/**
* Updates the YearRangeModel to the next decade.
*/
nextDecade() {
this.yearRangeModel = this.yearRangeModel.nextDecade();
// Year in the yearpicker is not focused because while navigating to a different decade,
// you want the focus to remain on the decade switcher arrows.
}
/**
* Compares the year passed to the focused year and returns the tab index.
*/
getTabIndex(year) {
if (!this.yearRangeModel.inRange(this._focusedYear)) {
if (this.yearRangeModel.inRange(this.calendarYear)) {
this._focusedYear = this.calendarYear;
}
else if (this.yearRangeModel.inRange(this.selectedEndYear)) {
this._focusedYear = this.selectedEndYear;
}
else {
this._focusedYear = this.yearRangeModel.middleYear;
}
}
return this._focusedYear === year ? 0 : -1;
}
/**
* Applicable only to date range picker
* Compares the year passed is in between the start and end date range
*/
isInRange(year) {
if (!this._dateNavigationService.isRangePicker) {
return false;
}
if (this._dateNavigationService.selectedDay?.year && this.selectedEndYear) {
return year > this.selectedStartYear && year < this.selectedEndYear;
}
else if (this._dateNavigationService.selectedDay?.year && !this.selectedEndYear) {
return year > this.selectedStartYear && year < this._dateNavigationService.hoveredYear;
}
else {
return false;
}
}
changeToDayView() {
this._viewManagerService.changeToDayView();
}
/**
* Increments the focus year by the value passed. Updates the YearRangeModel if the
* new value is not in the current decade.
*/
incrementFocusYearBy(value) {
this._focusedYear = this._focusedYear + value;
if (!this.yearRangeModel.inRange(this._focusedYear)) {
if (value > 0) {
this.yearRangeModel = this.yearRangeModel.nextDecade();
}
else {
this.yearRangeModel = this.yearRangeModel.previousDecade();
}
}
this._datepickerFocusService.focusCell(this._elRef);
}
}
ClrYearpicker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrYearpicker, deps: [{ token: i1.DateNavigationService }, { token: i2.ViewManagerService }, { token: i3.DatepickerFocusService }, { token: i0.ElementRef }, { token: i4.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component });
ClrYearpicker.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrYearpicker, selector: "clr-yearpicker", host: { attributes: { "role": "application" }, listeners: { "keydown": "onKeyDown($event)" }, properties: { "class.yearpicker": "true" } }, ngImport: i0, template: `
<div class="calendar-header">
<div class="calendar-pickers">
<button class="calendar-btn yearpicker-trigger year-range" type="button" (click)="changeToDayView()">
{{ yearRangeModel.yearRange[0] }} - {{ yearRangeModel.yearRange[yearRangeModel.yearRange.length - 1] }}
</button>
</div>
<div class="year-switchers">
<button
class="calendar-btn switcher"
type="button"
(click)="previousDecade()"
[attr.aria-label]="commonStrings.keys.datepickerPreviousDecade"
>
<cds-icon
shape="angle"
direction="left"
[attr.title]="commonStrings.keys.datepickerPreviousDecade"
></cds-icon>
</button>
<button
class="calendar-btn switcher"
type="button"
(click)="currentDecade()"
[attr.aria-label]="commonStrings.keys.datepickerCurrentDecade"
>
<cds-icon shape="event" [attr.title]="commonStrings.keys.datepickerCurrentDecade"></cds-icon>
</button>
<button
class="calendar-btn switcher"
type="button"
(click)="nextDecade()"
[attr.aria-label]="commonStrings.keys.datepickerNextDecade"
>
<cds-icon shape="angle" direction="right" [attr.title]="commonStrings.keys.datepickerNextDecade"></cds-icon>
</button>
</div>
</div>
<div class="years">
<button
*ngFor="let year of yearRangeModel.yearRange"
type="button"
class="calendar-btn year"
[attr.tabindex]="getTabIndex(year)"
[class.is-selected]="year === selectedStartYear || year === selectedEndYear"
[class.is-start-range]="getIsRangeStartYear(year)"
[class.is-end-range]="getIsRangeEndYear(year)"
[class.in-range]="isInRange(year)"
[class.is-today]="isCurrentCalendarYear(year)"
(click)="changeYear(year)"
(mouseenter)="onHover(year)"
>
{{ year }}
</button>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.CdsIconCustomTag, selector: "cds-icon" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrYearpicker, decorators: [{
type: Component,
args: [{
selector: 'clr-yearpicker',
template: `
<div class="calendar-header">
<div class="calendar-pickers">
<button class="calendar-btn yearpicker-trigger year-range" type="button" (click)="changeToDayView()">
{{ yearRangeModel.yearRange[0] }} - {{ yearRangeModel.yearRange[yearRangeModel.yearRange.length - 1] }}
</button>
</div>
<div class="year-switchers">
<button
class="calendar-btn switcher"
type="button"
(click)="previousDecade()"
[attr.aria-label]="commonStrings.keys.datepickerPreviousDecade"
>
<cds-icon
shape="angle"
direction="left"
[attr.title]="commonStrings.keys.datepickerPreviousDecade"
></cds-icon>
</button>
<button
class="calendar-btn switcher"
type="button"
(click)="currentDecade()"
[attr.aria-label]="commonStrings.keys.datepickerCurrentDecade"
>
<cds-icon shape="event" [attr.title]="commonStrings.keys.datepickerCurrentDecade"></cds-icon>
</button>
<button
class="calendar-btn switcher"
type="button"
(click)="nextDecade()"
[attr.aria-label]="commonStrings.keys.datepickerNextDecade"
>
<cds-icon shape="angle" direction="right" [attr.title]="commonStrings.keys.datepickerNextDecade"></cds-icon>
</button>
</div>
</div>
<div class="years">
<button
*ngFor="let year of yearRangeModel.yearRange"
type="button"
class="calendar-btn year"
[attr.tabindex]="getTabIndex(year)"
[class.is-selected]="year === selectedStartYear || year === selectedEndYear"
[class.is-start-range]="getIsRangeStartYear(year)"
[class.is-end-range]="getIsRangeEndYear(year)"
[class.in-range]="isInRange(year)"
[class.is-today]="isCurrentCalendarYear(year)"
(click)="changeYear(year)"
(mouseenter)="onHover(year)"
>
{{ year }}
</button>
</div>
`,
host: {
'[class.yearpicker]': 'true',
role: 'application',
},
}]
}], ctorParameters: function () { return [{ type: i1.DateNavigationService }, { type: i2.ViewManagerService }, { type: i3.DatepickerFocusService }, { type: i0.ElementRef }, { type: i4.ClrCommonStringsService }]; }, propDecorators: { onKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieWVhcnBpY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXIvc3JjL2Zvcm1zL2RhdGVwaWNrZXIveWVhcnBpY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBaUIsU0FBUyxFQUFjLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRWhFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7QUFxRTFELE1BQU0sT0FBTyxhQUFhO0lBV3hCLFlBQ1Usc0JBQTZDLEVBQzdDLG1CQUF1QyxFQUN2Qyx1QkFBK0MsRUFDL0MsTUFBK0IsRUFDaEMsYUFBc0M7UUFKckMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF1QjtRQUM3Qyx3QkFBbUIsR0FBbkIsbUJBQW1CLENBQW9CO1FBQ3ZDLDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBd0I7UUFDL0MsV0FBTSxHQUFOLE1BQU0sQ0FBeUI7UUFDaEMsa0JBQWEsR0FBYixhQUFhLENBQXlCO1FBRTdDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztJQUN4QyxDQUFDO0lBRUQsSUFBSSxpQkFBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQztJQUN2RCxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUM7SUFDMUQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFB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TTt3QkFDNUIsSUFBSSxFQUFFLGFBQWE7cUJBQ3BCO2lCQUNGO2lQQTZEQyxTQUFTO3NCQURSLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxNi0yMDI1IEJyb2FkY29tLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogVGhlIHRlcm0gXCJCcm9hZGNvbVwiIHJlZmVycyB0byBCcm9hZGNvbSBJbmMuIGFuZC9vciBpdHMgc3Vic2lkaWFyaWVzLlxuICogVGhpcyBzb2Z0d2FyZSBpcyByZWxlYXNlZCB1bmRlciBNSVQgbGljZW5zZS5cbiAqIFRoZSBmdWxsIGxpY2Vuc2UgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGluIExJQ0VOU0UgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgcHJvamVjdC5cbiAqL1xuXG5pbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBLZXlzIH0gZnJvbSAnLi4vLi4vdXRpbHMvZW51bXMva2V5cy5lbnVtJztcbmltcG9ydCB7IG5vcm1hbGl6ZUtleSB9IGZyb20gJy4uLy4uL3V0aWxzL2ZvY3VzL2tleS1mb2N1cy91dGlsJztcbmltcG9ydCB7IENsckNvbW1vblN0cmluZ3NTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vdXRpbHMvaTE4bi9jb21tb24tc3RyaW5ncy5zZXJ2aWNlJztcbmltcG9ydCB7IFllYXJSYW5nZU1vZGVsIH0gZnJvbSAnLi9tb2RlbC95ZWFyLXJhbmdlLm1vZGVsJztcbmltcG9ydCB7IERhdGVOYXZpZ2F0aW9uU2VydmljZSB9IGZyb20gJy4vcHJvdmlkZXJzL2RhdGUtbmF2aWdhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IERhdGVwaWNrZXJGb2N1c1NlcnZpY2UgfSBmcm9tICcuL3Byb3ZpZGVycy9kYXRlcGlja2VyLWZvY3VzLnNlcnZpY2UnO1xuaW1wb3J0IHsgVmlld01hbmFnZXJTZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvdmlldy1tYW5hZ2VyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjbHIteWVhcnBpY2tlcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImNhbGVuZGFyLWhlYWRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhbGVuZGFyLXBpY2tlcnNcIj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImNhbGVuZGFyLWJ0biB5ZWFycGlja2VyLXRyaWdnZXIgeWVhci1yYW5nZVwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiY2hhbmdlVG9EYXlWaWV3KClcIj5cbiAgICAgICAgICB7eyB5ZWFyUmFuZ2VNb2RlbC55ZWFyUmFuZ2VbMF0gfX0gLSB7eyB5ZWFyUmFuZ2VNb2RlbC55ZWFyUmFuZ2VbeWVhclJhbmdlTW9kZWwueWVhclJhbmdlLmxlbmd0aCAtIDFdIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwieWVhci1zd2l0Y2hlcnNcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiY2FsZW5kYXItYnRuIHN3aXRjaGVyXCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAoY2xpY2spPVwicHJldmlvdXNEZWNhZGUoKVwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJjb21tb25TdHJpbmdzLmtleXMuZGF0ZXBpY2tlclByZXZpb3VzRGVjYWRlXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxjZHMtaWNvblxuICAgICAgICAgICAgc2hhcGU9XCJhbmdsZVwiXG4gICAgICAgICAgICBkaXJlY3Rpb249XCJsZWZ0XCJcbiAgICAgICAgICAgIFthdHRyLnRpdGxlXT1cImNvbW1vblN0cmluZ3Mua2V5cy5kYXRlcGlja2VyUHJldmlvdXNEZWNhZGVcIlxuICAgICAgICAgID48L2Nkcy1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiY2FsZW5kYXItYnRuIHN3aXRjaGVyXCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAoY2xpY2spPVwiY3VycmVudERlY2FkZSgpXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImNvbW1vblN0cmluZ3Mua2V5cy5kYXRlcGlja2VyQ3VycmVudERlY2FkZVwiXG4gICAgICAgID5cbiAgICAgICAgICA8Y2RzLWljb24gc2hhcGU9XCJldmVudFwiIFthdHRyLnRpdGxlXT1cImNvbW1vblN0cmluZ3Mua2V5cy5kYXRlcGlja2VyQ3VycmVudERlY2FkZVwiPjwvY2RzLWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgY2xhc3M9XCJjYWxlbmRhci1idG4gc3dpdGNoZXJcIlxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIChjbGljayk9XCJuZXh0RGVjYWRlKClcIlxuICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiY29tbW9uU3RyaW5ncy5rZXlzLmRhdGVwaWNrZXJOZXh0RGVjYWRlXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxjZHMtaWNvbiBzaGFwZT1cImFuZ2xlXCIgZGlyZWN0aW9uPVwicmlnaHRcIiBbYXR0ci50aXRsZV09XCJjb21tb25TdHJpbmdzLmtleXMuZGF0ZXBpY2tlck5leHREZWNhZGVcIj48L2Nkcy1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cInllYXJzXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0Zvcj1cImxldCB5ZWFyIG9mIHllYXJSYW5nZU1vZGVsLnllYXJSYW5nZVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNhbGVuZGFyLWJ0biB5ZWFyXCJcbiAgICAgICAgW2F0dHIudGFiaW5kZXhdPVwiZ2V0VGFiSW5kZXgoeWVhcilcIlxuICAgICAgICBbY2xhc3MuaXMtc2VsZWN0ZWRdPVwieWVhciA9PT0gc2VsZWN0ZWRTdGFydFllYXIgfHwgeWVhciA9PT0gc2VsZWN0ZWRFbmRZZWFyXCJcbiAgICAgICAgW2NsYXNzLmlzLXN0YXJ0LXJhbmdlXT1cImdldElzUmFuZ2VTdGFydFllYXIoeWVhcilcIlxuICAgICAgICBbY2xhc3MuaXMtZW5kLXJhbmdlXT1cImdldElzUmFuZ2VFbmRZZWFyKHllYXIpXCJcbiAgICAgICAgW2NsYXNzLmluLXJhbmdlXT1cImlzSW5SYW5nZSh5ZWFyKVwiXG4gICAgICAgIFtjbGFzcy5pcy10b2RheV09XCJpc0N1cnJlbnRDYWxlbmRhclllYXIoeWVhcilcIlxuICAgICAgICAoY2xpY2spPVwiY2hhbmdlWWVhcih5ZWFyKVwiXG4gICAgICAgIChtb3VzZWVudGVyKT1cIm9uSG92ZXIoeWVhcilcIlxuICAgICAgPlxuICAgICAgICB7eyB5ZWFyIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgaG9zdDoge1xuICAgICdbY2xhc3MueWVhcnBpY2tlcl0nOiAndHJ1ZScsXG4gICAgcm9sZTogJ2FwcGxpY2F0aW9uJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgQ2xyWWVhcnBpY2tlciBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuICAvKipcbiAgICogWWVhclJhbmdlTW9kZWwgd2hpY2ggaXMgdXNlZCB0byBidWlsZCB0aGUgWWVhclBpY2tlciB2aWV3LlxuICAgKi9cbiAgeWVhclJhbmdlTW9kZWw6IFllYXJSYW5nZU1vZGVsO1xuXG4gIC8qKlxuICAgKiBLZWVwcyB0cmFjayBvZiB0aGUgY3VycmVudCBmb2N1c2VkIHllYXIuXG4gICAqL1xuICBwcml2YXRlIF9mb2N1c2VkWWVhcjogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2RhdGVOYXZpZ2F0aW9uU2VydmljZTogRGF0ZU5hdmlnYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgX3ZpZXdNYW5hZ2VyU2VydmljZTogVmlld01hbmFnZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgX2RhdGVwaWNrZXJGb2N1c1NlcnZpY2U6IERhdGVwaWNrZXJGb2N1c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBfZWxSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgIHB1YmxpYyBjb21tb25TdHJpbmdzOiBDbHJDb21tb25TdHJpbmdzU2VydmljZVxuICApIHtcbiAgICB0aGlzLnllYXJSYW5nZU1vZGVsID0gbmV3IFllYXJSYW5nZU1vZGVsKHRoaXMuY2FsZW5kYXJZZWFyKTtcbiAgICB0aGlzLl9mb2N1c2VkWWVhciA9IHRoaXMuY2FsZW5kYXJZZWFyO1xuICB9XG5cbiAgZ2V0IHNlbGVjdGVkU3RhcnRZZWFyKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5zZWxlY3RlZERheT8ueWVhcjtcbiAgfVxuXG4gIGdldCBzZWxlY3RlZEVuZFllYXIoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRW5kRGF5Py55ZWFyO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHllYXIgd2hpY2ggdGhlIHVzZXIgaXMgY3VycmVudGx5IG9uLlxuICAgKi9cbiAgZ2V0IGNhbGVuZGFyWWVhcigpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuZGlzcGxheWVkQ2FsZW5kYXIueWVhcjtcbiAgfVxuXG4gIGlzQ3VycmVudENhbGVuZGFyWWVhcih5ZWFyOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4geWVhciA9PT0gbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpO1xuICB9XG5cbiAgZ2V0SXNSYW5nZVN0YXJ0WWVhcih5ZWFyOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmlzUmFuZ2VQaWNrZXIgJiYgeWVhciA9PT0gdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5Py55ZWFyO1xuICB9XG5cbiAgZ2V0SXNSYW5nZUVuZFllYXIoeWVhcjogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5pc1JhbmdlUGlja2VyICYmIHllYXIgPT09IHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS5zZWxlY3RlZEVuZERheT8ueWVhcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1c2VzIG9uIHRoZSBjdXJyZW50IGNhbGVuZGFyIHllYXIgd2hlbiB0aGUgVmlldyBpcyBpbml0aWFsaXplZC5cbiAgICovXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLl9kYXRlcGlja2VyRm9jdXNTZXJ2aWNlLmZvY3VzQ2VsbCh0aGlzLl9lbFJlZik7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgS2V5Ym9hcmQgYXJyb3cgbmF2aWdhdGlvbiBmb3IgdGhlIHllYXJwaWNrZXIuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdrZXlkb3duJywgWyckZXZlbnQnXSlcbiAgb25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgLy8gTk9URTogRGlkbid0IG1vdmUgdGhpcyB0byB0aGUgZGF0ZSBuYXZpZ2F0aW9uIHNlcnZpY2UgYmVjYXVzZVxuICAgIC8vIHRoZSBsb2dpYyBpcyBmYWlybHkgc2ltcGxlIGFuZCBpdCBkaWRuJ3QgbWFrZSBzZW5zZSBmb3IgbWVcbiAgICAvLyB0byBjcmVhdGUgZXh0cmEgb2JzZXJ2YWJsZXMganVzdCB0byBtb3ZlIHRoaXMgbG9naWMgdG8gdGhlIHNlcnZpY2UuXG4gICAgaWYgKGV2ZW50KSB7XG4gICAgICBjb25zdCBrZXkgPSBub3JtYWxpemVLZXkoZXZlbnQua2V5KTtcbiAgICAgIGlmIChrZXkgPT09IEtleXMuQXJyb3dVcCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmluY3JlbWVudEZvY3VzWWVhckJ5KC0yKTtcbiAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSBLZXlzLkFycm93RG93bikge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmluY3JlbWVudEZvY3VzWWVhckJ5KDIpO1xuICAgICAgfSBlbHNlIGlmIChrZXkgPT09IEtleXMuQXJyb3dSaWdodCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmluY3JlbWVudEZvY3VzWWVhckJ5KDEpO1xuICAgICAgfSBlbHNlIGlmIChrZXkgPT09IEtleXMuQXJyb3dMZWZ0KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMuaW5jcmVtZW50Rm9jdXNZZWFyQnkoLTEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxscyB0aGUgRGF0ZU5hdmlnYXRpb25TZXJ2aWNlIHRvIHVwZGF0ZSB0aGUgeWVhciB2YWx1ZSBvZiB0aGUgY2FsZW5kYXIuXG4gICAqIEFsc28gY2hhbmdlcyB0aGUgdmlldyB0byB0aGUgZGF5cGlja2VyLlxuICAgKi9cbiAgY2hhbmdlWWVhcih5ZWFyOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuY2hhbmdlWWVhcih5ZWFyKTtcbiAgICB0aGlzLl92aWV3TWFuYWdlclNlcnZpY2UuY2hhbmdlVG9EYXlWaWV3KCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbHMgdGhlIERhdGVOYXZpZ2F0aW9uU2VydmljZSB0byB1cGRhdGUgdGhlIGhvdmVyZWQgeWVhciB2YWx1ZSBvZiB0aGUgY2FsZW5kYXJcbiAgICovXG4gIG9uSG92ZXIoeWVhcjogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLmhvdmVyZWRZZWFyID0geWVhcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBZZWFyUmFuZ2VNb2RlbCB0byB0aGUgcHJldmlvdXMgZGVjYWRlLlxuICAgKi9cbiAgcHJldmlvdXNEZWNhZGUoKTogdm9pZCB7XG4gICAgdGhpcy55ZWFyUmFuZ2VNb2RlbCA9IHRoaXMueWVhclJhbmdlTW9kZWwucHJldmlvdXNEZWNhZGUoKTtcbiAgICAvLyBZZWFyIGluIHRoZSB5ZWFycGlja2VyIGlzIG5vdCBmb2N1c2VkIGJlY2F1c2Ugd2hpbGUgbmF2aWdhdGluZyB0byBhIGRpZmZlcmVudCBkZWNhZGUsXG4gICAgLy8geW91IHdhbnQgdGhlIGZvY3VzIHRvIHJlbWFpbiBvbiB0aGUgZGVjYWRlIHN3aXRjaGVyIGFycm93cy5cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBZZWFyUmFuZ2VNb2RlbCB0byB0aGUgY3VycmVudCBkZWNhZGUuXG4gICAqL1xuICBjdXJyZW50RGVjYWRlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy55ZWFyUmFuZ2VNb2RlbC5pblJhbmdlKHRoaXMuX2RhdGVOYXZpZ2F0aW9uU2VydmljZS50b2RheS55ZWFyKSkge1xuICAgICAgdGhpcy55ZWFyUmFuZ2VNb2RlbCA9IHRoaXMueWVhclJhbmdlTW9kZWwuY3VycmVudERlY2FkZSgpO1xuICAgIH1cbiAgICB0aGlzLl9kYXRlcGlja2VyRm9jdXNTZXJ2aWNlLmZvY3VzQ2VsbCh0aGlzLl9lbFJlZik7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgWWVhclJhbmdlTW9kZWwgdG8gdGhlIG5leHQgZGVjYWRlLlxuICAgKi9cbiAgbmV4dERlY2FkZSgpOiB2b2lkIHtcbiAgICB0aGlzLnllYXJSYW5nZU1vZGVsID0gdGhpcy55ZWFyUmFuZ2VNb2RlbC5uZXh0RGVjYWRlKCk7XG4gICAgLy8gWWVhciBpbiB0aGUgeWVhcnBpY2tlciBpcyBub3QgZm9jdXNlZCBiZWNhdXNlIHdoaWxlIG5hdmlnYXRpbmcgdG8gYSBkaWZmZXJlbnQgZGVjYWRlLFxuICAgIC8vIHlvdSB3YW50IHRoZSBmb2N1cyB0byByZW1haW4gb24gdGhlIGRlY2FkZSBzd2l0Y2hlciBhcnJvd3MuXG4gIH1cblxuICAvKipcbiAgICogQ29tcGFyZXMgdGhlIHllYXIgcGFzc2VkIHRvIHRoZSBmb2N1c2VkIHllYXIgYW5kIHJldHVybnMgdGhlIHRhYiBpbmRleC5cbiAgICovXG4gIGdldFRhYkluZGV4KHllYXI6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKCF0aGlzLnllYXJSYW5nZU1vZGVsLmluUmFuZ2UodGhpcy5fZm9jdXNlZFllYXIpKSB7XG4gICAgICBpZiAodGhpcy55ZWFyUmFuZ2VNb2RlbC5pblJhbmdlKHRoaXMuY2FsZW5kYXJZZWFyKSkge1xuICAgICAgICB0aGlzLl9mb2N1c2VkWWVhciA9IHRoaXMuY2FsZW5kYXJZZWFyO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLnllYXJSYW5nZU1vZGVsLmluUmFuZ2UodGhpcy5zZWxlY3RlZEVuZFllYXIpKSB7XG4gICAgICAgIHRoaXMuX2ZvY3VzZWRZZWFyID0gdGhpcy5zZWxlY3RlZEVuZFllYXI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9mb2N1c2VkWWVhciA9IHRoaXMueWVhclJhbmdlTW9kZWwubWlkZGxlWWVhcjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2ZvY3VzZWRZZWFyID09PSB5ZWFyID8gMCA6IC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpY2FibGUgb25seSB0byBkYXRlIHJhbmdlIHBpY2tlclxuICAgKiBDb21wYXJlcyB0aGUgeWVhciBwYXNzZWQgaXMgaW4gYmV0d2VlbiB0aGUgc3RhcnQgYW5kIGVuZCBkYXRlIHJhbmdlXG4gICAqL1xuICBpc0luUmFuZ2UoeWVhcjogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuaXNSYW5nZVBpY2tlcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5Py55ZWFyICYmIHRoaXMuc2VsZWN0ZWRFbmRZZWFyKSB7XG4gICAgICByZXR1cm4geWVhciA+IHRoaXMuc2VsZWN0ZWRTdGFydFllYXIgJiYgeWVhciA8IHRoaXMuc2VsZWN0ZWRFbmRZZWFyO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fZGF0ZU5hdmlnYXRpb25TZXJ2aWNlLnNlbGVjdGVkRGF5Py55ZWFyICYmICF0aGlzLnNlbGVjdGVkRW5kWWVhcikge1xuICAgICAgcmV0dXJuIHllYXIgPiB0aGlzLnNlbGVjdGVkU3RhcnRZZWFyICYmIHllYXIgPCB0aGlzLl9kYXRlTmF2aWdhdGlvblNlcnZpY2UuaG92ZXJlZFllYXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBjaGFuZ2VUb0RheVZpZXcoKSB7XG4gICAgdGhpcy5fdmlld01hbmFnZXJTZXJ2aWNlLmNoYW5nZVRvRGF5VmlldygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEluY3JlbWVudHMgdGhlIGZvY3VzIHllYXIgYnkgdGhlIHZhbHVlIHBhc3NlZC4gVXBkYXRlcyB0aGUgWWVhclJhbmdlTW9kZWwgaWYgdGhlXG4gICAqIG5ldyB2YWx1ZSBpcyBub3QgaW4gdGhlIGN1cnJlbnQgZGVjYWRlLlxuICAgKi9cbiAgcHJpdmF0ZSBpbmNyZW1lbnRGb2N1c1llYXJCeSh2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fZm9jdXNlZFllYXIgPSB0aGlzLl9mb2N1c2VkWWVhciArIHZhbHVlO1xuICAgIGlmICghdGhpcy55ZWFyUmFuZ2VNb2RlbC5pblJhbmdlKHRoaXMuX2ZvY3VzZWRZZWFyKSkge1xuICAgICAgaWYgKHZhbHVlID4gMCkge1xuICAgICAgICB0aGlzLnllYXJSYW5nZU1vZGVsID0gdGhpcy55ZWFyUmFuZ2VNb2RlbC5uZXh0RGVjYWRlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnllYXJSYW5nZU1vZGVsID0gdGhpcy55ZWFyUmFuZ2VNb2RlbC5wcmV2aW91c0RlY2FkZSgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLl9kYXRlcGlja2VyRm9jdXNTZXJ2aWNlLmZvY3VzQ2VsbCh0aGlzLl9lbFJlZik7XG4gIH1cbn1cbiJdfQ==