UNPKG

carbon-components-angular

Version:
328 lines 37.7 kB
import { Component, Input, HostListener, HostBinding, ViewChild, ContentChildren, ViewChildren } from "@angular/core"; import { BaseTabHeader } from "./base-tab-header.component"; import { Tab } from "./tab.component"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/utils"; import * as i2 from "carbon-components-angular/i18n"; import * as i3 from "@angular/common"; const VERTICAL_TAB_HEIGHT = 64; /** * The `TabHeadersVertical` component renders tab headers in a vertical * orientation. It contains the `Tab` items and supports keyboard navigation * via ArrowUp/ArrowDown/Home/End. */ export class TabHeadersVertical extends BaseTabHeader { constructor(elementRef, changeDetectorRef, eventService, renderer, i18n) { super(elementRef, changeDetectorRef, eventService, renderer); this.elementRef = elementRef; this.changeDetectorRef = changeDetectorRef; this.eventService = eventService; this.renderer = renderer; this.i18n = i18n; /** * i18n strings for the tab list `aria-label` fallback. */ this.translations = this.i18n.get().TABS; this.verticalClass = true; /** * Focused tab index when `followFocus` is false (manual activation) */ this.activeIndex = null; /** * Whether the tab list is overflowing at the top (some tabs are clipped). */ this.isOverflowingTop = false; /** * Whether the tab list is overflowing at the bottom (some tabs are clipped). */ this.isOverflowingBottom = false; this.listScrollHandler = () => this.updateOverflowState(); this.type = "contained"; } keyboardInput(event) { if (!this.tabs) { return; } const tabsArray = this.tabs.toArray(); const enabledTabs = tabsArray.filter(tab => !tab.disabled); if (enabledTabs.length === 0) { return; } const referenceIndex = this.followFocus ? this.currentSelectedTab : (this.activeIndex !== null ? this.activeIndex : this.currentSelectedTab); const currentEnabledIndex = Math.max(0, enabledTabs.indexOf(tabsArray[referenceIndex])); let nextEnabledIndex = currentEnabledIndex; let handled = false; if (event.key === "ArrowDown") { nextEnabledIndex = (currentEnabledIndex + 1) % enabledTabs.length; handled = true; } else if (event.key === "ArrowUp") { nextEnabledIndex = (enabledTabs.length + currentEnabledIndex - 1) % enabledTabs.length; handled = true; } else if (event.key === "Home") { nextEnabledIndex = 0; handled = true; } else if (event.key === "End") { nextEnabledIndex = enabledTabs.length - 1; handled = true; } if (handled) { event.preventDefault(); const nextTab = enabledTabs[nextEnabledIndex]; const nextIndex = tabsArray.indexOf(nextTab); if (this.followFocus) { this.selectTab(nextTab, nextIndex); } else { this.activeIndex = nextIndex; } this.allTabHeaders.toArray()[nextIndex].nativeElement.focus(); return; } if ((event.key === " " || event.key === "Spacebar") && !this.followFocus) { const focusIndex = this.activeIndex !== null ? this.activeIndex : this.currentSelectedTab; this.selectTab(tabsArray[focusIndex], focusIndex); } } handleBlur(event) { const relatedTarget = event.relatedTarget; const container = this.headerContainer?.nativeElement; if (container && relatedTarget && container.contains(relatedTarget)) { return; } if (!this.followFocus) { this.activeIndex = this.currentSelectedTab; } } ngOnInit() { this.resizeObserver = new ResizeObserver(() => { this.updateOverflowState(); this.changeDetectorRef.detectChanges(); }); this.resizeObserver.observe(this.headerContainer.nativeElement); this.headerContainer.nativeElement.addEventListener("scroll", this.listScrollHandler); } ngOnDestroy() { this.resizeObserver?.unobserve(this.headerContainer.nativeElement); this.headerContainer.nativeElement.removeEventListener("scroll", this.listScrollHandler); } ngAfterContentInit() { if (!this.tabInput) { this.tabs = this.tabQuery; } else { this.tabs = this.tabInput; } this.tabs.forEach(tab => tab.cacheActive = this.cacheActive); this.tabs.changes.subscribe(() => { this.setFirstTab(); this.changeDetectorRef.markForCheck(); }); this.setFirstTab(); } ngOnChanges(changes) { if (this.tabs && changes.cacheActive) { this.tabs.forEach(tab => tab.cacheActive = this.cacheActive); } } onTabFocus(index) { if (this.followFocus) { this.currentSelectedTab = index; } else { this.activeIndex = index; } this.scrollSelectedTabIntoView(); } selectTab(tab, tabIndex) { if (tab.disabled) { return; } this.currentSelectedTab = tabIndex; this.activeIndex = tabIndex; this.tabs.forEach(_tab => _tab.active = false); tab.active = true; tab.doSelect(); this.scrollSelectedTabIntoView(); } getSelectedTab() { const selected = this.tabs.find(tab => tab.active); if (selected) { return selected; } return { headingIsTemplate: false, heading: "" }; } updateOverflowState() { const element = this.headerContainer?.nativeElement; if (!element) { return; } const halfTabHeight = VERTICAL_TAB_HEIGHT / 2; this.isOverflowingBottom = element.scrollTop + element.clientHeight + halfTabHeight <= element.scrollHeight; this.isOverflowingTop = element.scrollTop > halfTabHeight; this.changeDetectorRef.markForCheck(); } scrollSelectedTabIntoView() { const container = this.headerContainer?.nativeElement; if (!container) { return; } const selectedHeader = this.allTabHeaders?.toArray()[this.currentSelectedTab]?.nativeElement; if (!selectedHeader) { return; } const containerRect = container.getBoundingClientRect(); const selectedRect = selectedHeader.getBoundingClientRect(); const halfTabHeight = VERTICAL_TAB_HEIGHT / 2; if (selectedRect.top - halfTabHeight < containerRect.top || selectedRect.top - containerRect.top + VERTICAL_TAB_HEIGHT + halfTabHeight > containerRect.height) { container.scrollTo({ top: Math.max(0, (this.currentSelectedTab - 1) * VERTICAL_TAB_HEIGHT), behavior: "smooth" }); } } setFirstTab() { setTimeout(() => { let firstTab = this.tabs.find(tab => tab.active); if (!firstTab && this.tabs.first) { firstTab = this.tabs.first; firstTab.active = true; } if (firstTab) { this.currentSelectedTab = this.tabs.toArray().indexOf(firstTab); this.activeIndex = this.currentSelectedTab; firstTab.doSelect(); this.updateOverflowState(); } }); } } TabHeadersVertical.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TabHeadersVertical, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1.EventService }, { token: i0.Renderer2 }, { token: i2.I18n }], target: i0.ɵɵFactoryTarget.Component }); TabHeadersVertical.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TabHeadersVertical, selector: "cds-tab-headers-vertical, ibm-tab-headers-vertical", inputs: { tabInput: ["tabs", "tabInput"], translations: "translations" }, host: { listeners: { "keydown": "keyboardInput($event)", "blur": "handleBlur($event)" }, properties: { "class.cds--tabs--vertical": "this.verticalClass" } }, queries: [{ propertyName: "tabQuery", predicate: Tab }], viewQueries: [{ propertyName: "headerContainer", first: true, predicate: ["tabList"], descendants: true, static: true }, { propertyName: "allTabHeaders", predicate: ["tabItem"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: ` <div *ngIf="isOverflowingTop" class="cds--tab--list-gradient_top"></div> <div #tabList class="cds--tab--list" role="tablist" [attr.aria-label]="ariaLabel || translations.HEADER_ARIA_LABEL" [attr.aria-labelledby]="ariaLabelledby || null"> <ng-container [ngTemplateOutlet]="contentBefore"></ng-container> <button *ngFor="let tab of tabs; let i = index;" #tabItem role="tab" [attr.aria-selected]="tab.active" [attr.tabindex]="(tab.active?0:-1)" [attr.aria-controls]="tab.id" [attr.aria-disabled]="tab.disabled" [disabled]="tab.disabled" [ngClass]="{ 'cds--tabs__nav-item--selected': tab.active, 'cds--tabs__nav-item--disabled': tab.disabled }" class="cds--tabs__nav-item cds--tabs__nav-link" type="button" draggable="false" id="{{tab.id}}-header" [attr.title]="tab.title || (!tab.headingIsTemplate ? tab.heading : null)" (focus)="onTabFocus(i)" (click)="selectTab(tab, i)"> <div class="cds--tabs__nav-item-label-wrapper"> <span class="cds--tabs__nav-item-label"> <ng-container *ngIf="!tab.headingIsTemplate"> {{ tab.heading }} </ng-container> <ng-template *ngIf="tab.headingIsTemplate" [ngTemplateOutlet]="tab.heading" [ngTemplateOutletContext]="{$implicit: tab.context}"> </ng-template> </span> </div> </button> <ng-container [ngTemplateOutlet]="contentAfter"></ng-container> </div> <div *ngIf="isOverflowingBottom" class="cds--tab--list-gradient_bottom"></div> `, isInline: true, dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TabHeadersVertical, decorators: [{ type: Component, args: [{ selector: "cds-tab-headers-vertical, ibm-tab-headers-vertical", template: ` <div *ngIf="isOverflowingTop" class="cds--tab--list-gradient_top"></div> <div #tabList class="cds--tab--list" role="tablist" [attr.aria-label]="ariaLabel || translations.HEADER_ARIA_LABEL" [attr.aria-labelledby]="ariaLabelledby || null"> <ng-container [ngTemplateOutlet]="contentBefore"></ng-container> <button *ngFor="let tab of tabs; let i = index;" #tabItem role="tab" [attr.aria-selected]="tab.active" [attr.tabindex]="(tab.active?0:-1)" [attr.aria-controls]="tab.id" [attr.aria-disabled]="tab.disabled" [disabled]="tab.disabled" [ngClass]="{ 'cds--tabs__nav-item--selected': tab.active, 'cds--tabs__nav-item--disabled': tab.disabled }" class="cds--tabs__nav-item cds--tabs__nav-link" type="button" draggable="false" id="{{tab.id}}-header" [attr.title]="tab.title || (!tab.headingIsTemplate ? tab.heading : null)" (focus)="onTabFocus(i)" (click)="selectTab(tab, i)"> <div class="cds--tabs__nav-item-label-wrapper"> <span class="cds--tabs__nav-item-label"> <ng-container *ngIf="!tab.headingIsTemplate"> {{ tab.heading }} </ng-container> <ng-template *ngIf="tab.headingIsTemplate" [ngTemplateOutlet]="tab.heading" [ngTemplateOutletContext]="{$implicit: tab.context}"> </ng-template> </span> </div> </button> <ng-container [ngTemplateOutlet]="contentAfter"></ng-container> </div> <div *ngIf="isOverflowingBottom" class="cds--tab--list-gradient_bottom"></div> ` }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1.EventService }, { type: i0.Renderer2 }, { type: i2.I18n }]; }, propDecorators: { tabInput: [{ type: Input, args: ["tabs"] }], translations: [{ type: Input }], verticalClass: [{ type: HostBinding, args: ["class.cds--tabs--vertical"] }], headerContainer: [{ type: ViewChild, args: ["tabList", { static: true }] }], tabQuery: [{ type: ContentChildren, args: [Tab] }], allTabHeaders: [{ type: ViewChildren, args: ["tabItem"] }], keyboardInput: [{ type: HostListener, args: ["keydown", ["$event"]] }], handleBlur: [{ type: HostListener, args: ["blur", ["$event"]] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiLWhlYWRlcnMtdmVydGljYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhYnMvdGFiLWhlYWRlcnMtdmVydGljYWwuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTixTQUFTLEVBRVQsS0FBSyxFQUNMLFlBQVksRUFDWixXQUFXLEVBQ1gsU0FBUyxFQUNULGVBQWUsRUFFZixZQUFZLEVBUVosTUFBTSxlQUFlLENBQUM7QUFJdkIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzVELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7QUFFdEMsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7QUFFL0I7Ozs7R0FJRztBQWtESCxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsYUFBYTtJQXlDcEQsWUFDVyxVQUFzQixFQUN0QixpQkFBb0MsRUFDcEMsWUFBMEIsRUFDMUIsUUFBbUIsRUFDbkIsSUFBVTtRQUVwQixLQUFLLENBQUMsVUFBVSxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztRQU5uRCxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBQ3RCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixTQUFJLEdBQUosSUFBSSxDQUFNO1FBdENyQjs7V0FFRztRQUNNLGlCQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUFFSCxrQkFBYSxHQUFHLElBQUksQ0FBQztRQVkvRDs7V0FFRztRQUNILGdCQUFXLEdBQWtCLElBQUksQ0FBQztRQUVsQzs7V0FFRztRQUNILHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUN6Qjs7V0FFRztRQUNILHdCQUFtQixH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QUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcblx0Q29tcG9uZW50LFxyXG5cdFF1ZXJ5TGlzdCxcclxuXHRJbnB1dCxcclxuXHRIb3N0TGlzdGVuZXIsXHJcblx0SG9zdEJpbmRpbmcsXHJcblx0Vmlld0NoaWxkLFxyXG5cdENvbnRlbnRDaGlsZHJlbixcclxuXHRBZnRlckNvbnRlbnRJbml0LFxyXG5cdFZpZXdDaGlsZHJlbixcclxuXHRFbGVtZW50UmVmLFxyXG5cdE9uQ2hhbmdlcyxcclxuXHRTaW1wbGVDaGFuZ2VzLFxyXG5cdE9uRGVzdHJveSxcclxuXHRPbkluaXQsXHJcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXHJcblx0UmVuZGVyZXIyXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgRXZlbnRTZXJ2aWNlIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvdXRpbHNcIjtcclxuaW1wb3J0IHsgSTE4biB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL2kxOG5cIjtcclxuXHJcbmltcG9ydCB7IEJhc2VUYWJIZWFkZXIgfSBmcm9tIFwiLi9iYXNlLXRhYi1oZWFkZXIuY29tcG9uZW50XCI7XHJcbmltcG9ydCB7IFRhYiB9IGZyb20gXCIuL3RhYi5jb21wb25lbnRcIjtcclxuXHJcbmNvbnN0IFZFUlRJQ0FMX1RBQl9IRUlHSFQgPSA2NDtcclxuXHJcbi8qKlxyXG4gKiBUaGUgYFRhYkhlYWRlcnNWZXJ0aWNhbGAgY29tcG9uZW50IHJlbmRlcnMgdGFiIGhlYWRlcnMgaW4gYSB2ZXJ0aWNhbFxyXG4gKiBvcmllbnRhdGlvbi4gSXQgY29udGFpbnMgdGhlIGBUYWJgIGl0ZW1zIGFuZCBzdXBwb3J0cyBrZXlib2FyZCBuYXZpZ2F0aW9uXHJcbiAqIHZpYSBBcnJvd1VwL0Fycm93RG93bi9Ib21lL0VuZC5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG5cdHNlbGVjdG9yOiBcImNkcy10YWItaGVhZGVycy12ZXJ0aWNhbCwgaWJtLXRhYi1oZWFkZXJzLXZlcnRpY2FsXCIsXHJcblx0dGVtcGxhdGU6IGBcclxuXHRcdDxkaXYgKm5nSWY9XCJpc092ZXJmbG93aW5nVG9wXCIgY2xhc3M9XCJjZHMtLXRhYi0tbGlzdC1ncmFkaWVudF90b3BcIj48L2Rpdj5cclxuXHRcdDxkaXZcclxuXHRcdFx0I3RhYkxpc3RcclxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRhYi0tbGlzdFwiXHJcblx0XHRcdHJvbGU9XCJ0YWJsaXN0XCJcclxuXHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgdHJhbnNsYXRpb25zLkhFQURFUl9BUklBX0xBQkVMXCJcclxuXHRcdFx0W2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cImFyaWFMYWJlbGxlZGJ5IHx8IG51bGxcIj5cclxuXHRcdFx0PG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjb250ZW50QmVmb3JlXCI+PC9uZy1jb250YWluZXI+XHJcblx0XHRcdDxidXR0b25cclxuXHRcdFx0XHQqbmdGb3I9XCJsZXQgdGFiIG9mIHRhYnM7IGxldCBpID0gaW5kZXg7XCJcclxuXHRcdFx0XHQjdGFiSXRlbVxyXG5cdFx0XHRcdHJvbGU9XCJ0YWJcIlxyXG5cdFx0XHRcdFthdHRyLmFyaWEtc2VsZWN0ZWRdPVwidGFiLmFjdGl2ZVwiXHJcblx0XHRcdFx0W2F0dHIudGFiaW5kZXhdPVwiKHRhYi5hY3RpdmU/MDotMSlcIlxyXG5cdFx0XHRcdFthdHRyLmFyaWEtY29udHJvbHNdPVwidGFiLmlkXCJcclxuXHRcdFx0XHRbYXR0ci5hcmlhLWRpc2FibGVkXT1cInRhYi5kaXNhYmxlZFwiXHJcblx0XHRcdFx0W2Rpc2FibGVkXT1cInRhYi5kaXNhYmxlZFwiXHJcblx0XHRcdFx0W25nQ2xhc3NdPVwie1xyXG5cdFx0XHRcdFx0J2Nkcy0tdGFic19fbmF2LWl0ZW0tLXNlbGVjdGVkJzogdGFiLmFjdGl2ZSxcclxuXHRcdFx0XHRcdCdjZHMtLXRhYnNfX25hdi1pdGVtLS1kaXNhYmxlZCc6IHRhYi5kaXNhYmxlZFxyXG5cdFx0XHRcdH1cIlxyXG5cdFx0XHRcdGNsYXNzPVwiY2RzLS10YWJzX19uYXYtaXRlbSBjZHMtLXRhYnNfX25hdi1saW5rXCJcclxuXHRcdFx0XHR0eXBlPVwiYnV0dG9uXCJcclxuXHRcdFx0XHRkcmFnZ2FibGU9XCJmYWxzZVwiXHJcblx0XHRcdFx0aWQ9XCJ7e3RhYi5pZH19LWhlYWRlclwiXHJcblx0XHRcdFx0W2F0dHIudGl0bGVdPVwidGFiLnRpdGxlIHx8ICghdGFiLmhlYWRpbmdJc1RlbXBsYXRlID8gdGFiLmhlYWRpbmcgOiBudWxsKVwiXHJcblx0XHRcdFx0KGZvY3VzKT1cIm9uVGFiRm9jdXMoaSlcIlxyXG5cdFx0XHRcdChjbGljayk9XCJzZWxlY3RUYWIodGFiLCBpKVwiPlxyXG5cdFx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLXRhYnNfX25hdi1pdGVtLWxhYmVsLXdyYXBwZXJcIj5cclxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwiY2RzLS10YWJzX19uYXYtaXRlbS1sYWJlbFwiPlxyXG5cdFx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIXRhYi5oZWFkaW5nSXNUZW1wbGF0ZVwiPlxyXG5cdFx0XHRcdFx0XHRcdHt7IHRhYi5oZWFkaW5nIH19XHJcblx0XHRcdFx0XHRcdDwvbmctY29udGFpbmVyPlxyXG5cdFx0XHRcdFx0XHQ8bmctdGVtcGxhdGVcclxuXHRcdFx0XHRcdFx0XHQqbmdJZj1cInRhYi5oZWFkaW5nSXNUZW1wbGF0ZVwiXHJcblx0XHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRdPVwidGFiLmhlYWRpbmdcIlxyXG5cdFx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7JGltcGxpY2l0OiB0YWIuY29udGV4dH1cIj5cclxuXHRcdFx0XHRcdFx0PC9uZy10ZW1wbGF0ZT5cclxuXHRcdFx0XHRcdDwvc3Bhbj5cclxuXHRcdFx0XHQ8L2Rpdj5cclxuXHRcdFx0PC9idXR0b24+XHJcblx0XHRcdDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29udGVudEFmdGVyXCI+PC9uZy1jb250YWluZXI+XHJcblx0XHQ8L2Rpdj5cclxuXHRcdDxkaXYgKm5nSWY9XCJpc092ZXJmbG93aW5nQm90dG9tXCIgY2xhc3M9XCJjZHMtLXRhYi0tbGlzdC1ncmFkaWVudF9ib3R0b21cIj48L2Rpdj5cclxuXHRgXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUYWJIZWFkZXJzVmVydGljYWwgZXh0ZW5kcyBCYXNlVGFiSGVhZGVyIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCB7XHJcblx0LyoqXHJcblx0ICogTGlzdCBvZiBgVGFiYCBjb21wb25lbnRzLlxyXG5cdCAqL1xyXG5cdC8vIGRpc2FibGUgdGhlIG5leHQgbGluZSBiZWNhdXNlIHdlIG5lZWQgdG8gcmVuYW1lIHRoZSBpbnB1dFxyXG5cdC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZVxyXG5cdEBJbnB1dChcInRhYnNcIikgdGFiSW5wdXQ6IFF1ZXJ5TGlzdDxUYWI+O1xyXG5cclxuXHQvKipcclxuXHQgKiBpMThuIHN0cmluZ3MgZm9yIHRoZSB0YWIgbGlzdCBgYXJpYS1sYWJlbGAgZmFsbGJhY2suXHJcblx0ICovXHJcblx0QElucHV0KCkgdHJhbnNsYXRpb25zID0gdGhpcy5pMThuLmdldCgpLlRBQlM7XHJcblxyXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tdGFicy0tdmVydGljYWxcIikgdmVydGljYWxDbGFzcyA9IHRydWU7XHJcblxyXG5cdEBWaWV3Q2hpbGQoXCJ0YWJMaXN0XCIsIHsgc3RhdGljOiB0cnVlIH0pIGhlYWRlckNvbnRhaW5lcjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnRlbnRDaGlsZCBvZiBhbGwgdGhlIHRhYnNcclxuXHQgKi9cclxuXHRAQ29udGVudENoaWxkcmVuKFRhYikgdGFiUXVlcnk6IFF1ZXJ5TGlzdDxUYWI+O1xyXG5cdHRhYnM6IFF1ZXJ5TGlzdDxUYWI+O1xyXG5cclxuXHRAVmlld0NoaWxkcmVuKFwidGFiSXRlbVwiKSBhbGxUYWJIZWFkZXJzOiBRdWVyeUxpc3Q8RWxlbWVudFJlZj47XHJcblxyXG5cdC8qKlxyXG5cdCAqIEZvY3VzZWQgdGFiIGluZGV4IHdoZW4gYGZvbGxvd0ZvY3VzYCBpcyBmYWxzZSAobWFudWFsIGFjdGl2YXRpb24pXHJcblx0ICovXHJcblx0YWN0aXZlSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xyXG5cclxuXHQvKipcclxuXHQgKiBXaGV0aGVyIHRoZSB0YWIgbGlzdCBpcyBvdmVyZmxvd2luZyBhdCB0aGUgdG9wIChzb21lIHRhYnMgYXJlIGNsaXBwZWQpLlxyXG5cdCAqL1xyXG5cdGlzT3ZlcmZsb3dpbmdUb3AgPSBmYWxzZTtcclxuXHQvKipcclxuXHQgKiBXaGV0aGVyIHRoZSB0YWIgbGlzdCBpcyBvdmVyZmxvd2luZyBhdCB0aGUgYm90dG9tIChzb21lIHRhYnMgYXJlIGNsaXBwZWQpLlxyXG5cdCAqL1xyXG5cdGlzT3ZlcmZsb3dpbmdCb3R0b20gPSBmYWxzZTtcclxuXHJcblx0cHJpdmF0ZSByZXNpemVPYnNlcnZlcjogUmVzaXplT2JzZXJ2ZXI7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0cHJvdGVjdGVkIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXHJcblx0XHRwcm90ZWN0ZWQgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxyXG5cdFx0cHJvdGVjdGVkIGV2ZW50U2VydmljZTogRXZlbnRTZXJ2aWNlLFxyXG5cdFx0cHJvdGVjdGVkIHJlbmRlcmVyOiBSZW5kZXJlcjIsXHJcblx0XHRwcm90ZWN0ZWQgaTE4bjogSTE4blxyXG5cdCkge1xyXG5cdFx0c3VwZXIoZWxlbWVudFJlZiwgY2hhbmdlRGV0ZWN0b3JSZWYsIGV2ZW50U2VydmljZSwgcmVuZGVyZXIpO1xyXG5cdFx0dGhpcy50eXBlID0gXCJjb250YWluZWRcIjtcclxuXHR9XHJcblxyXG5cdEBIb3N0TGlzdGVuZXIoXCJrZXlkb3duXCIsIFtcIiRldmVudFwiXSlcclxuXHRrZXlib2FyZElucHV0KGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XHJcblx0XHRpZiAoIXRoaXMudGFicykge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblx0XHRjb25zdCB0YWJzQXJyYXkgPSB0aGlzLnRhYnMudG9BcnJheSgpO1xyXG5cdFx0Y29uc3QgZW5hYmxlZFRhYnMgPSB0YWJzQXJyYXkuZmlsdGVyKHRhYiA9PiAhdGFiLmRpc2FibGVkKTtcclxuXHRcdGlmIChlbmFibGVkVGFicy5sZW5ndGggPT09IDApIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IHJlZmVyZW5jZUluZGV4ID0gdGhpcy5mb2xsb3dGb2N1cyA/XHJcblx0XHRcdHRoaXMuY3VycmVudFNlbGVjdGVkVGFiIDpcclxuXHRcdFx0KHRoaXMuYWN0aXZlSW5kZXggIT09IG51bGwgPyB0aGlzLmFjdGl2ZUluZGV4IDogdGhpcy5jdXJyZW50U2VsZWN0ZWRUYWIpO1xyXG5cdFx0Y29uc3QgY3VycmVudEVuYWJsZWRJbmRleCA9IE1hdGgubWF4KDAsIGVuYWJsZWRUYWJzLmluZGV4T2YodGFic0FycmF5W3JlZmVyZW5jZUluZGV4XSkpO1xyXG5cclxuXHRcdGxldCBuZXh0RW5hYmxlZEluZGV4ID0gY3VycmVudEVuYWJsZWRJbmRleDtcclxuXHRcdGxldCBoYW5kbGVkID0gZmFsc2U7XHJcblxyXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd0Rvd25cIikge1xyXG5cdFx0XHRuZXh0RW5hYmxlZEluZGV4ID0gKGN1cnJlbnRFbmFibGVkSW5kZXggKyAxKSAlIGVuYWJsZWRUYWJzLmxlbmd0aDtcclxuXHRcdFx0aGFuZGxlZCA9IHRydWU7XHJcblx0XHR9IGVsc2UgaWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd1VwXCIpIHtcclxuXHRcdFx0bmV4dEVuYWJsZWRJbmRleCA9IChlbmFibGVkVGFicy5sZW5ndGggKyBjdXJyZW50RW5hYmxlZEluZGV4IC0gMSkgJSBlbmFibGVkVGFicy5sZW5ndGg7XHJcblx0XHRcdGhhbmRsZWQgPSB0cnVlO1xyXG5cdFx0fSBlbHNlIGlmIChldmVudC5rZXkgPT09IFwiSG9tZVwiKSB7XHJcblx0XHRcdG5leHRFbmFibGVkSW5kZXggPSAwO1xyXG5cdFx0XHRoYW5kbGVkID0gdHJ1ZTtcclxuXHRcdH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSBcIkVuZFwiKSB7XHJcblx0XHRcdG5leHRFbmFibGVkSW5kZXggPSBlbmFibGVkVGFicy5sZW5ndGggLSAxO1xyXG5cdFx0XHRoYW5kbGVkID0gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoaGFuZGxlZCkge1xyXG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRjb25zdCBuZXh0VGFiID0gZW5hYmxlZFRhYnNbbmV4dEVuYWJsZWRJbmRleF07XHJcblx0XHRcdGNvbnN0IG5leHRJbmRleCA9IHRhYnNBcnJheS5pbmRleE9mKG5leHRUYWIpO1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuZm9sbG93Rm9jdXMpIHtcclxuXHRcdFx0XHR0aGlzLnNlbGVjdFRhYihuZXh0VGFiLCBuZXh0SW5kZXgpO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRoaXMuYWN0aXZlSW5kZXggPSBuZXh0SW5kZXg7XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5hbGxUYWJIZWFkZXJzLnRvQXJyYXkoKVtuZXh0SW5kZXhdLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICgoZXZlbnQua2V5ID09PSBcIiBcIiB8fCBldmVudC5rZXkgPT09IFwiU3BhY2ViYXJcIikgJiYgIXRoaXMuZm9sbG93Rm9jdXMpIHtcclxuXHRcdFx0Y29uc3QgZm9jdXNJbmRleCA9IHRoaXMuYWN0aXZlSW5kZXggIT09IG51bGwgPyB0aGlzLmFjdGl2ZUluZGV4IDogdGhpcy5jdXJyZW50U2VsZWN0ZWRUYWI7XHJcblx0XHRcdHRoaXMuc2VsZWN0VGFiKHRhYnNBcnJheVtmb2N1c0luZGV4XSwgZm9jdXNJbmRleCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRASG9zdExpc3RlbmVyKFwiYmx1clwiLCBbXCIkZXZlbnRcIl0pXHJcblx0aGFuZGxlQmx1cihldmVudDogRm9jdXNFdmVudCkge1xyXG5cdFx0Y29uc3QgcmVsYXRlZFRhcmdldCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQgYXMgTm9kZSB8IG51bGw7XHJcblx0XHRjb25zdCBjb250YWluZXIgPSB0aGlzLmhlYWRlckNvbnRhaW5lcj8ubmF0aXZlRWxlbWVudDtcclxuXHRcdGlmIChjb250YWluZXIgJiYgcmVsYXRlZFRhcmdldCAmJiBjb250YWluZXIuY29udGFpbnMocmVsYXRlZFRhcmdldCkpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cdFx0aWYgKCF0aGlzLmZvbGxvd0ZvY3VzKSB7XHJcblx0XHRcdHRoaXMuYWN0aXZlSW5kZXggPSB0aGlzLmN1cnJlbnRTZWxlY3RlZFRhYjtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdG5nT25Jbml0KCk6IHZvaWQge1xyXG5cdFx0dGhpcy5yZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlT3ZlcmZsb3dTdGF0ZSgpO1xyXG5cdFx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcclxuXHRcdH0pO1xyXG5cdFx0dGhpcy5yZXNpemVPYnNlcnZlci5vYnNlcnZlKHRoaXMuaGVhZGVyQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQpO1xyXG5cdFx0dGhpcy5oZWFkZXJDb250YWluZXIubmF0aXZlRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFwic2Nyb2xsXCIsIHRoaXMubGlzdFNjcm9sbEhhbmRsZXIpO1xyXG5cdH1cclxuXHJcblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcblx0XHR0aGlzLnJlc2l6ZU9ic2VydmVyPy51bm9ic2VydmUodGhpcy5oZWFkZXJDb250YWluZXIubmF0aXZlRWxlbWVudCk7XHJcblx0XHR0aGlzLmhlYWRlckNvbnRhaW5lci5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJzY3JvbGxcIiwgdGhpcy5saXN0U2Nyb2xsSGFuZGxlcik7XHJcblx0fVxyXG5cclxuXHRuZ0FmdGVyQ29udGVudEluaXQoKSB7XHJcblx0XHRpZiAoIXRoaXMudGFiSW5wdXQpIHtcclxuXHRcdFx0dGhpcy50YWJzID0gdGhpcy50YWJRdWVyeTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMudGFicyA9IHRoaXMudGFiSW5wdXQ7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy50YWJzLmZvckVhY2godGFiID0+IHRhYi5jYWNoZUFjdGl2ZSA9IHRoaXMuY2FjaGVBY3RpdmUpO1xyXG5cdFx0dGhpcy50YWJzLmNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHtcclxuXHRcdFx0dGhpcy5zZXRGaXJzdFRhYigpO1xyXG5cdFx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xyXG5cdFx0fSk7XHJcblx0XHR0aGlzLnNldEZpcnN0VGFiKCk7XHJcblx0fVxyXG5cclxuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcblx0XHRpZiAodGhpcy50YWJzICYmIGNoYW5nZXMuY2FjaGVBY3RpdmUpIHtcclxuXHRcdFx0dGhpcy50YWJzLmZvckVhY2godGFiID0+IHRhYi5jYWNoZUFjdGl2ZSA9IHRoaXMuY2FjaGVBY3RpdmUpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0b25UYWJGb2N1cyhpbmRleDogbnVtYmVyKSB7XHJcblx0XHRpZiAodGhpcy5mb2xsb3dGb2N1cykge1xyXG5cdFx0XHR0aGlzLmN1cnJlbnRTZWxlY3RlZFRhYiA9IGluZGV4O1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0dGhpcy5hY3RpdmVJbmRleCA9IGluZGV4O1xyXG5cdFx0fVxyXG5cdFx0dGhpcy5zY3JvbGxTZWxlY3RlZFRhYkludG9WaWV3KCk7XHJcblx0fVxyXG5cclxuXHRzZWxlY3RUYWIodGFiOiBUYWIsIHRhYkluZGV4OiBudW1iZXIpIHtcclxuXHRcdGlmICh0YWIuZGlzYWJsZWQpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cdFx0dGhpcy5jdXJyZW50U2VsZWN0ZWRUYWIgPSB0YWJJbmRleDtcclxuXHRcdHRoaXMuYWN0aXZlSW5kZXggPSB0YWJJbmRleDtcclxuXHRcdHRoaXMudGFicy5mb3JFYWNoKF90YWIgPT4gX3RhYi5hY3RpdmUgPSBmYWxzZSk7XHJcblx0XHR0YWIuYWN0aXZlID0gdHJ1ZTtcclxuXHRcdHRhYi5kb1NlbGVjdCgpO1xyXG5cdFx0dGhpcy5zY3JvbGxTZWxlY3RlZFRhYkludG9WaWV3KCk7XHJcblx0fVxyXG5cclxuXHRnZXRTZWxlY3RlZFRhYigpOiBhbnkge1xyXG5cdFx0Y29uc3Qgc2VsZWN0ZWQgPSB0aGlzLnRhYnMuZmluZCh0YWIgPT4gdGFiLmFjdGl2ZSk7XHJcblx0XHRpZiAoc2VsZWN0ZWQpIHtcclxuXHRcdFx0cmV0dXJuIHNlbGVjdGVkO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHsgaGVhZGluZ0lzVGVtcGxhdGU6IGZhbHNlLCBoZWFkaW5nOiBcIlwiIH07XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgdXBkYXRlT3ZlcmZsb3dTdGF0ZSgpIHtcclxuXHRcdGNvbnN0IGVsZW1lbnQgPSB0aGlzLmhlYWRlckNvbnRhaW5lcj8ubmF0aXZlRWxlbWVudDtcclxuXHRcdGlmICghZWxlbWVudCkge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblx0XHRjb25zdCBoYWxmVGFiSGVpZ2h0ID0gVkVSVElDQUxfVEFCX0hFSUdIVCAvIDI7XHJcblx0XHR0aGlzLmlzT3ZlcmZsb3dpbmdCb3R0b20gPVxyXG5cdFx0XHRlbGVtZW50LnNjcm9sbFRvcCArIGVsZW1lbnQuY2xpZW50SGVpZ2h0ICsgaGFsZlRhYkhlaWdodCA8PSBlbGVtZW50LnNjcm9sbEhlaWdodDtcclxuXHRcdHRoaXMuaXNPdmVyZmxvd2luZ1RvcCA9IGVsZW1lbnQuc2Nyb2xsVG9wID4gaGFsZlRhYkhlaWdodDtcclxuXHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XHJcblx0fVxyXG5cclxuXHRwcm90ZWN0ZWQgc2Nyb2xsU2VsZWN0ZWRUYWJJbnRvVmlldygpIHtcclxuXHRcdGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuaGVhZGVyQ29udGFpbmVyPy5uYXRpdmVFbGVtZW50O1xyXG5cdFx0aWYgKCFjb250YWluZXIpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cdFx0Y29uc3Qgc2VsZWN0ZWRIZWFkZXIgPSB0aGlzLmFsbFRhYkhlYWRlcnM/LnRvQXJyYXkoKVt0aGlzLmN1cnJlbnRTZWxlY3RlZFRhYl0/Lm5hdGl2ZUVsZW1lbnQ7XHJcblx0XHRpZiAoIXNlbGVjdGVkSGVhZGVyKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHRcdGNvbnN0IGNvbnRhaW5lclJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcblx0XHRjb25zdCBzZWxlY3RlZFJlY3QgPSBzZWxlY3RlZEhlYWRlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHRcdGNvbnN0IGhhbGZUYWJIZWlnaHQgPSBWRVJUSUNBTF9UQUJfSEVJR0hUIC8gMjtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdHNlbGVjdGVkUmVjdC50b3AgLSBoYWxmVGFiSGVpZ2h0IDwgY29udGFpbmVyUmVjdC50b3AgfHxcclxuXHRcdFx0c2VsZWN0ZWRSZWN0LnRvcCAtIGNvbnRhaW5lclJlY3QudG9wICsgVkVSVElDQUxfVEFCX0hFSUdIVCArIGhhbGZUYWJIZWlnaHQgPiBjb250YWluZXJSZWN0LmhlaWdodFxyXG5cdFx0KSB7XHJcblx0XHRcdGNvbnRhaW5lci5zY3JvbGxUbyh7XHJcblx0XHRcdFx0dG9wOiBNYXRoLm1heCgwLCAodGhpcy5jdXJyZW50U2VsZWN0ZWRUYWIgLSAxKSAqIFZFUlRJQ0FMX1RBQl9IRUlHSFQpLFxyXG5cdFx0XHRcdGJlaGF2aW9yOiBcInNtb290aFwiXHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJvdGVjdGVkIHNldEZpcnN0VGFiKCkge1xyXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdGxldCBmaXJzdFRhYiA9IHRoaXMudGFicy5maW5kKHRhYiA9PiB0YWIuYWN0aXZlKTtcclxuXHRcdFx0aWYgKCFmaXJzdFRhYiAmJiB0aGlzLnRhYnMuZmlyc3QpIHtcclxuXHRcdFx0XHRmaXJzdFRhYiA9IHRoaXMudGFicy5maXJzdDtcclxuXHRcdFx0XHRmaXJzdFRhYi5hY3RpdmUgPSB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChmaXJzdFRhYikge1xyXG5cdFx0XHRcdHRoaXMuY3VycmVudFNlbGVjdGVkVGFiID0gdGhpcy50YWJzLnRvQXJyYXkoKS5pbmRleE9mKGZpcnN0VGFiKTtcclxuXHRcdFx0XHR0aGlzLmFjdGl2ZUluZGV4ID0gdGhpcy5jdXJyZW50U2VsZWN0ZWRUYWI7XHJcblx0XHRcdFx0Zmlyc3RUYWIuZG9TZWxlY3QoKTtcclxuXHRcdFx0XHR0aGlzLnVwZGF0ZU92ZXJmbG93U3RhdGUoKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cdHByaXZhdGUgbGlzdFNjcm9sbEhhbmRsZXIgPSAoKSA9PiB0aGlzLnVwZGF0ZU92ZXJmbG93U3RhdGUoKTtcclxufVxyXG4iXX0=