carbon-components-angular
Version:
Next generation components
306 lines (304 loc) • 31.7 kB
JavaScript
import { ChangeDetectionStrategy, Component, ContentChildren, EventEmitter, HostBinding, Input, Output, ViewChild } from "@angular/core";
import { autoUpdate, computePosition, flip } from "@floating-ui/dom";
import { ContextMenuItemComponent } from "carbon-components-angular/context-menu";
import * as i0 from "@angular/core";
import * as i1 from "carbon-components-angular/button";
import * as i2 from "carbon-components-angular/icon";
import * as i3 from "carbon-components-angular/context-menu";
export class ComboButtonComponent {
constructor(ngZone, renderer, hostElement, viewContainerRef, changeDetectorRef) {
this.ngZone = ngZone;
this.renderer = renderer;
this.hostElement = hostElement;
this.viewContainerRef = viewContainerRef;
this.changeDetectorRef = changeDetectorRef;
this.comboId = `combo-button-${ComboButtonComponent.comboButtonCounter++}`;
this.size = "lg";
this.disabled = false;
this.menuAlignment = "bottom";
this.tooltipAutoAlign = false;
this.tooltipPlacement = "bottom";
this.open = false;
this.actionClick = new EventEmitter();
this.comboButtonContainer = true;
this.documentClick = this.handleFocusOut.bind(this);
this.subscriptions = [];
this._alignment = "bottom";
}
// Listen for click & determine if menu should close
set projectedMenuItems(itemList) {
// Reset in case user dynamically updates menu item
this.subscriptions.forEach((sub) => sub?.unsubscribe());
this.subscriptions = [];
itemList.forEach((item) => {
this.subscriptions.push(item.itemClick.subscribe((clickEvent) => this.handleMenuItemClick(clickEvent)));
});
}
get sizeLg() { return this.size === "lg"; }
get sizeMd() { return this.size === "md"; }
get sizeSm() { return this.size === "sm"; }
get sizeXs() { return this.size === "xs"; }
get ariaOwns() {
return this.open ? this.comboId : undefined;
}
/**
* In case user updates alignment, store initial value.
* This allows us to test user passed alignment on each open
*/
ngOnChanges(changes) {
if (changes.menuAlignment) {
this._alignment = changes.menuAlignment.currentValue;
}
}
/**
* If user has passed in true for open, we dynamically open the menu
*/
ngAfterViewInit() {
if (this.open) {
this.open = !this.open;
this.toggleMenu();
}
}
/**
* Clean up Floating-ui & subscriptions
*/
ngOnDestroy() {
this.cleanUp();
this.subscriptions.forEach((sub) => sub.unsubscribe());
}
/**
* As of now, menu button does not support nexted menu, on button click it should close
*/
handleMenuItemClick(event) {
// If event is not type radio/checkbox, we close the menu
if (!event.type) {
this.toggleMenu();
}
}
/**
* On body click, close the menu
* @param event
*/
handleFocusOut(event) {
if (!this.hostElement.nativeElement.contains(event.target)) {
this.toggleMenu();
}
}
/**
* Clean up `autoUpdate` if auto alignment is enabled
*/
cleanUp() {
document.removeEventListener("click", this.documentClick);
if (this.unmountFloatingElement) {
this.menuRef.remove();
this.viewContainerRef.clear();
this.unmountFloatingElement();
}
this.unmountFloatingElement = undefined;
// On all instances of menu closing, make sure icon direction is correct
this.changeDetectorRef.markForCheck();
}
/**
* On action click, notify user
* If the menu is open, close the menu
* @param event
*/
onActionClick(event) {
if (this.open) {
this.toggleMenu();
}
this.actionClick.emit(event);
}
/**
* Handles emitting open/close event
*/
toggleMenu() {
this.open = !this.open;
if (this.open) {
// Render the template & append to view
const view = this.viewContainerRef.createEmbeddedView(this.menuTemplate);
this.menuRef = document.body.appendChild(view.rootNodes[0]);
// Assign button width to the menu ref to align with button
Object.assign(this.menuRef.style, {
width: `${this.hostElement.nativeElement.clientWidth}px`,
top: "0",
left: "0"
});
// Reset & test alignment every open
this.menuAlignment = this._alignment;
document.addEventListener("click", this.documentClick);
// Listen for events such as scrolling to keep menu aligned
this.unmountFloatingElement = autoUpdate(this.hostElement.nativeElement, this.menuRef, this.recomputePosition.bind(this));
}
else {
this.cleanUp();
}
}
roundByDPR(value) {
const dpr = window.devicePixelRatio || 1;
return Math.round(value * dpr) / dpr;
}
/**
* Compute position of menu
*/
recomputePosition() {
if (this.menuTemplate && this.hostElement) {
// Run outside of angular zone to avoid unnecessary change detection and rely on floating-ui
this.ngZone.runOutsideAngular(async () => {
const { x, y, placement } = await computePosition(this.hostElement.nativeElement, this.menuRef, {
placement: this.menuAlignment,
strategy: "fixed",
middleware: [
flip({ crossAxis: false })
]
});
this.menuAlignment = placement;
// Using CSSOM to manipulate CSS to avoid content security policy inline-src
// https://github.com/w3c/webappsec-csp/issues/212
Object.assign(this.menuRef.style, {
position: "fixed",
// Using transform instead of top/left position to improve performance
transform: `translate(${this.roundByDPR(x)}px,${this.roundByDPR(y)}px)`
});
this.changeDetectorRef.markForCheck();
});
}
}
}
ComboButtonComponent.comboButtonCounter = 0;
ComboButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ComboButtonComponent, deps: [{ token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
ComboButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: ComboButtonComponent, selector: "cds-combo-button", inputs: { comboId: "comboId", size: "size", label: "label", disabled: "disabled", menuAlignment: "menuAlignment", description: "description", tooltipAutoAlign: "tooltipAutoAlign", tooltipPlacement: "tooltipPlacement", open: "open" }, outputs: { actionClick: "actionClick" }, host: { properties: { "class.cds--combo-button__container--open": "this.open", "class.cds--combo-button__container": "this.comboButtonContainer", "class.cds--combo-button__container--lg": "this.sizeLg", "class.cds--combo-button__container--md": "this.sizeMd", "class.cds--combo-button__container--sm": "this.sizeSm", "class.cds--combo-button__container--xs": "this.sizeXs", "attr.aria-owns": "this.ariaOwns" } }, queries: [{ propertyName: "projectedMenuItems", predicate: ContextMenuItemComponent }], viewQueries: [{ propertyName: "menuTemplate", first: true, predicate: ["menuTemplate"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<div class="cds--combo-button__primary-action" [attr.aria-owns]="open ? comboId : undefined">
<button
cdsButton="primary"
[size]="size"
[attr.title]="label"
[disabled]="disabled"
type="button"
(click)="onActionClick($event)">
{{label}}
</button>
</div>
<cds-icon-button
[buttonNgClass]="{ 'cds--combo-button__trigger': true }"
[buttonAttributes]="{
'aria-haspopup': true,
'aria-expanded': open,
'aria-controls': open ? comboId : undefined
}"
[size]="size"
[description]="description"
[disabled]="disabled"
[autoAlign]="tooltipAutoAlign"
[align]="tooltipPlacement"
(click)="toggleMenu()">
<svg
cdsIcon="chevron--down"
size="16">
</svg>
</cds-icon-button>
<ng-template #menuTemplate>
<cds-menu
mode="basic"
[size]="size"
[open]="open"
[attr.id]="comboId">
<ng-content select="cds-menu-item, cds-menu-divider"></ng-content>
</cds-menu>
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: i1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "component", type: i1.IconButton, selector: "cds-icon-button, ibm-icon-button", inputs: ["buttonNgClass", "buttonAttributes", "buttonId", "kind", "size", "type", "isExpressive", "disabled", "description", "showTooltipWhenDisabled"], outputs: ["click", "focus", "blur", "tooltipClick"] }, { kind: "directive", type: i2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i3.ContextMenuComponent, selector: "cds-menu, cds-context-menu, ibm-context-menu", inputs: ["open", "position", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ComboButtonComponent, decorators: [{
type: Component,
args: [{
selector: "cds-combo-button",
template: `
<div class="cds--combo-button__primary-action" [attr.aria-owns]="open ? comboId : undefined">
<button
cdsButton="primary"
[size]="size"
[attr.title]="label"
[disabled]="disabled"
type="button"
(click)="onActionClick($event)">
{{label}}
</button>
</div>
<cds-icon-button
[buttonNgClass]="{ 'cds--combo-button__trigger': true }"
[buttonAttributes]="{
'aria-haspopup': true,
'aria-expanded': open,
'aria-controls': open ? comboId : undefined
}"
[size]="size"
[description]="description"
[disabled]="disabled"
[autoAlign]="tooltipAutoAlign"
[align]="tooltipPlacement"
(click)="toggleMenu()">
<svg
cdsIcon="chevron--down"
size="16">
</svg>
</cds-icon-button>
<ng-template #menuTemplate>
<cds-menu
mode="basic"
[size]="size"
[open]="open"
[attr.id]="comboId">
<ng-content select="cds-menu-item, cds-menu-divider"></ng-content>
</cds-menu>
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { comboId: [{
type: Input
}], projectedMenuItems: [{
type: ContentChildren,
args: [ContextMenuItemComponent]
}], size: [{
type: Input
}], label: [{
type: Input
}], disabled: [{
type: Input
}], menuAlignment: [{
type: Input
}], description: [{
type: Input
}], tooltipAutoAlign: [{
type: Input
}], tooltipPlacement: [{
type: Input
}], open: [{
type: Input
}, {
type: HostBinding,
args: ["class.cds--combo-button__container--open"]
}], actionClick: [{
type: Output
}], comboButtonContainer: [{
type: HostBinding,
args: ["class.cds--combo-button__container"]
}], sizeLg: [{
type: HostBinding,
args: ["class.cds--combo-button__container--lg"]
}], sizeMd: [{
type: HostBinding,
args: ["class.cds--combo-button__container--md"]
}], sizeSm: [{
type: HostBinding,
args: ["class.cds--combo-button__container--sm"]
}], sizeXs: [{
type: HostBinding,
args: ["class.cds--combo-button__container--xs"]
}], ariaOwns: [{
type: HostBinding,
args: ["attr.aria-owns"]
}], menuTemplate: [{
type: ViewChild,
args: ["menuTemplate"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tYm8tYnV0dG9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21iby1idXR0b24vY29tYm8tYnV0dG9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxlQUFlLEVBRWYsWUFBWSxFQUNaLFdBQVcsRUFDWCxLQUFLLEVBSUwsTUFBTSxFQUtOLFNBQVMsRUFFVCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQ04sVUFBVSxFQUNWLGVBQWUsRUFDZixJQUFJLEVBQ0osTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQUUsd0JBQXdCLEVBQWtCLE1BQU0sd0NBQXdDLENBQUM7Ozs7O0FBaURsRyxNQUFNLE9BQU8sb0JBQW9CO0lBMkNoQyxZQUNXLE1BQWMsRUFDZCxRQUFtQixFQUNuQixXQUF1QixFQUN2QixnQkFBa0MsRUFDbEMsaUJBQW9DO1FBSnBDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLGdCQUFXLEdBQVgsV0FBVyxDQUFZO1FBQ3ZCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQTlDdEMsWUFBTyxHQUFHLGdCQUFnQixvQkFBb0IsQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLENBQUM7UUFjdEUsU0FBSSxHQUE4QixJQUFJLENBQUM7UUFFdkMsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQixrQkFBYSxHQUF5QixRQUFRLENBQUM7UUFFL0MscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBQ3pCLHFCQUFnQixHQUFHLFFBQVEsQ0FBQztRQUM2QixTQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ3JFLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVMsQ0FBQztRQUNDLHlCQUFvQixHQUFHLElBQUksQ0FBQztRQVdy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O3NCQUFoRSxXQUFXO3VCQUFDLHdDQUF3QztnQkFDTSxNQUFNO3NCQUFoRSxXQUFXO3VCQUFDLHdDQUF3QztnQkFDTSxNQUFNO3NCQUFoRSxXQUFXO3VCQUFDLHdDQUF3QztnQkFDbEIsUUFBUTtzQkFBMUMsV0FBVzt1QkFBQyxnQkFBZ0I7Z0JBSUYsWUFBWTtzQkFBdEMsU0FBUzt1QkFBQyxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0QWZ0ZXJWaWV3SW5pdCxcblx0Q2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG5cdENoYW5nZURldGVjdG9yUmVmLFxuXHRDb21wb25lbnQsXG5cdENvbnRlbnRDaGlsZHJlbixcblx0RWxlbWVudFJlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRIb3N0QmluZGluZyxcblx0SW5wdXQsXG5cdE5nWm9uZSxcblx0T25DaGFuZ2VzLFxuXHRPbkRlc3Ryb3ksXG5cdE91dHB1dCxcblx0UXVlcnlMaXN0LFxuXHRSZW5kZXJlcjIsXG5cdFNpbXBsZUNoYW5nZXMsXG5cdFRlbXBsYXRlUmVmLFxuXHRWaWV3Q2hpbGQsXG5cdFZpZXdDb250YWluZXJSZWZcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQge1xuXHRhdXRvVXBkYXRlLFxuXHRjb21wdXRlUG9zaXRpb24sXG5cdGZsaXBcbn0gZnJvbSBcIkBmbG9hdGluZy11aS9kb21cIjtcbmltcG9ydCB7IENvbnRleHRNZW51SXRlbUNvbXBvbmVudCwgSXRlbUNsaWNrRXZlbnQgfSBmcm9tIFwiY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhci9jb250ZXh0LW1lbnVcIjtcblxudHlwZSBDb21ib0J1dHRvblBsYWNlbWVudCA9IFwidG9wXCIgfCBcInRvcC1zdGFydFwiIHwgXCJ0b3AtZW5kXCIgfCBcImJvdHRvbVwiIHwgXCJib3R0b20tc3RhcnRcIiB8IFwiYm90dG9tLWVuZFwiO1xuXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLWNvbWJvLWJ1dHRvblwiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxkaXYgY2xhc3M9XCJjZHMtLWNvbWJvLWJ1dHRvbl9fcHJpbWFyeS1hY3Rpb25cIiBbYXR0ci5hcmlhLW93bnNdPVwib3BlbiA/IGNvbWJvSWQgOiB1bmRlZmluZWRcIj5cblx0XHRcdDxidXR0b25cblx0XHRcdFx0Y2RzQnV0dG9uPVwicHJpbWFyeVwiXG5cdFx0XHRcdFtzaXplXT1cInNpemVcIlxuXHRcdFx0XHRbYXR0ci50aXRsZV09XCJsYWJlbFwiXG5cdFx0XHRcdFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG5cdFx0XHRcdHR5cGU9XCJidXR0b25cIlxuXHRcdFx0XHQoY2xpY2spPVwib25BY3Rpb25DbGljaygkZXZlbnQpXCI+XG5cdFx0XHRcdHt7bGFiZWx9fVxuXHRcdFx0PC9idXR0b24+XG5cdFx0PC9kaXY+XG5cdFx0PGNkcy1pY29uLWJ1dHRvblxuXHRcdFx0W2J1dHRvbk5nQ2xhc3NdPVwieyAnY2RzLS1jb21iby1idXR0b25fX3RyaWdnZXInOiB0cnVlIH1cIlxuXHRcdFx0W2J1dHRvbkF0dHJpYnV0ZXNdPVwie1xuXHRcdFx0XHQnYXJpYS1oYXNwb3B1cCc6IHRydWUsXG5cdFx0XHRcdCdhcmlhLWV4cGFuZGVkJzogb3Blbixcblx0XHRcdFx0J2FyaWEtY29udHJvbHMnOiBvcGVuID8gY29tYm9JZCA6IHVuZGVmaW5lZFxuXHRcdFx0fVwiXG5cdFx0XHRbc2l6ZV09XCJzaXplXCJcblx0XHRcdFtkZXNjcmlwdGlvbl09XCJkZXNjcmlwdGlvblwiXG5cdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0W2F1dG9BbGlnbl09XCJ0b29sdGlwQXV0b0FsaWduXCJcblx0XHRcdFthbGlnbl09XCJ0b29sdGlwUGxhY2VtZW50XCJcblx0XHRcdChjbGljayk9XCJ0b2dnbGVNZW51KClcIj5cblx0XHRcdDxzdmdcblx0XHRcdFx0Y2RzSWNvbj1cImNoZXZyb24tLWRvd25cIlxuXHRcdFx0XHRzaXplPVwiMTZcIj5cblx0XHRcdDwvc3ZnPlxuXHRcdDwvY2RzLWljb24tYnV0dG9uPlxuXG5cdFx0PG5nLXRlbXBsYXRlICNtZW51VGVtcGxhdGU+XG5cdFx0XHQ8Y2RzLW1lbnVcblx0XHRcdFx0bW9kZT1cImJhc2ljXCJcblx0XHRcdFx0W3NpemVdPVwic2l6ZVwiXG5cdFx0XHRcdFtvcGVuXT1cIm9wZW5cIlxuXHRcdFx0XHRbYXR0ci5pZF09XCJjb21ib0lkXCI+XG5cdFx0XHRcdDxuZy1jb250ZW50IHNlbGVjdD1cImNkcy1tZW51LWl0ZW0sIGNkcy1tZW51LWRpdmlkZXJcIj48L25nLWNvbnRlbnQ+XG5cdFx0XHQ8L2Nkcy1tZW51PlxuXHRcdDwvbmctdGVtcGxhdGU+XG5cdGAsXG5cdGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIENvbWJvQnV0dG9uQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXHRzdGF0aWMgY29tYm9CdXR0b25Db3VudGVyID0gMDtcblx0QElucHV0KCkgY29tYm9JZCA9IGBjb21iby1idXR0b24tJHtDb21ib0J1dHRvbkNvbXBvbmVudC5jb21ib0J1dHRvbkNvdW50ZXIrK31gO1xuXG5cdC8vIExpc3RlbiBmb3IgY2xpY2sgJiBkZXRlcm1pbmUgaWYgbWVudSBzaG91bGQgY2xvc2Vcblx0QENvbnRlbnRDaGlsZHJlbihDb250ZXh0TWVudUl0ZW1Db21wb25lbnQpIHNldCBwcm9qZWN0ZWRNZW51SXRlbXMoaXRlbUxpc3Q6IFF1ZXJ5TGlzdDxDb250ZXh0TWVudUl0ZW1Db21wb25lbnQ+KSB7XG5cdFx0Ly8gUmVzZXQgaW4gY2FzZSB1c2VyIGR5bmFtaWNhbGx5IHVwZGF0ZXMgbWVudSBpdGVtXG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHN1YikgPT4gc3ViPy51bnN1YnNjcmliZSgpKTtcblx0XHR0aGlzLnN1YnNjcmlwdGlvbnMgPSBbXTtcblx0XHRpdGVtTGlzdC5mb3JFYWNoKChpdGVtKSA9PiB7XG5cdFx0XHR0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcblx0XHRcdFx0aXRlbS5pdGVtQ2xpY2suc3Vic2NyaWJlKChjbGlja0V2ZW50KSA9PiB0aGlzLmhhbmRsZU1lbnVJdGVtQ2xpY2soY2xpY2tFdmVudCkpXG5cdFx0XHQpO1xuXHRcdH0pO1xuXHR9XG5cblx0QElucHV0KCkgc2l6ZTogXCJ4c1wiIHwgXCJzbVwiIHwgXCJtZFwiIHwgXCJsZ1wiID0gXCJsZ1wiO1xuXHRASW5wdXQoKSBsYWJlbDogc3RyaW5nO1xuXHRASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXHRASW5wdXQoKSBtZW51QWxpZ25tZW50OiBDb21ib0J1dHRvblBsYWNlbWVudCA9IFwiYm90dG9tXCI7XG5cdEBJbnB1dCgpIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG5cdEBJbnB1dCgpIHRvb2x0aXBBdXRvQWxpZ24gPSBmYWxzZTtcblx0QElucHV0KCkgdG9vbHRpcFBsYWNlbWVudCA9IFwiYm90dG9tXCI7XG5cdEBJbnB1dCgpIEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tY29tYm8tYnV0dG9uX19jb250YWluZXItLW9wZW5cIikgb3BlbiA9IGZhbHNlO1xuXHRAT3V0cHV0KCkgYWN0aW9uQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPEV2ZW50PigpO1xuXHRASG9zdEJpbmRpbmcoXCJjbGFzcy5jZHMtLWNvbWJvLWJ1dHRvbl9fY29udGFpbmVyXCIpIGNvbWJvQnV0dG9uQ29udGFpbmVyID0gdHJ1ZTtcblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1jb21iby1idXR0b25fX2NvbnRhaW5lci0tbGdcIikgZ2V0IHNpemVMZygpIHsgcmV0dXJuIHRoaXMuc2l6ZSA9PT0gXCJsZ1wiOyB9XG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tY29tYm8tYnV0dG9uX19jb250YWluZXItLW1kXCIpIGdldCBzaXplTWQoKSB7IHJldHVybiB0aGlzLnNpemUgPT09IFwibWRcIjsgfVxuXHRASG9zdEJpbmRpbmcoXCJjbGFzcy5jZHMtLWNvbWJvLWJ1dHRvbl9fY29udGFpbmVyLS1zbVwiKSBnZXQgc2l6ZVNtKCkgeyByZXR1cm4gdGhpcy5zaXplID09PSBcInNtXCI7IH1cblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1jb21iby1idXR0b25fX2NvbnRhaW5lci0teHNcIikgZ2V0IHNpemVYcygpIHsgcmV0dXJuIHRoaXMuc2l6ZSA9PT0gXCJ4c1wiOyB9XG5cdEBIb3N0QmluZGluZyhcImF0dHIuYXJpYS1vd25zXCIpIGdldCBhcmlhT3ducygpIHtcblx0XHRyZXR1cm4gdGhpcy5vcGVuID8gdGhpcy5jb21ib0lkIDogdW5kZWZpbmVkO1xuXHR9XG5cblx0QFZpZXdDaGlsZChcIm1lbnVUZW1wbGF0ZVwiKSBtZW51VGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cblx0cHJvdGVjdGVkIGRvY3VtZW50Q2xpY2sgPSB0aGlzLmhhbmRsZUZvY3VzT3V0LmJpbmQodGhpcyk7XG5cdHByb3RlY3RlZCB1bm1vdW50RmxvYXRpbmdFbGVtZW50OiBGdW5jdGlvbjtcblxuXHRwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG5cdHByaXZhdGUgX2FsaWdubWVudDogQ29tYm9CdXR0b25QbGFjZW1lbnQgPSBcImJvdHRvbVwiO1xuXHRwcml2YXRlIG1lbnVSZWY6IEhUTUxFbGVtZW50O1xuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHByb3RlY3RlZCBuZ1pvbmU6IE5nWm9uZSxcblx0XHRwcm90ZWN0ZWQgcmVuZGVyZXI6IFJlbmRlcmVyMixcblx0XHRwcm90ZWN0ZWQgaG9zdEVsZW1lbnQ6IEVsZW1lbnRSZWYsXG5cdFx0cHJvdGVjdGVkIHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG5cdFx0cHJvdGVjdGVkIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxuXHQpIHsgfVxuXG5cblx0LyoqXG5cdCAqIEluIGNhc2UgdXNlciB1cGRhdGVzIGFsaWdubWVudCwgc3RvcmUgaW5pdGlhbCB2YWx1ZS5cblx0ICogVGhpcyBhbGxvd3MgdXMgdG8gdGVzdCB1c2VyIHBhc3NlZCBhbGlnbm1lbnQgb24gZWFjaCBvcGVuXG5cdCAqL1xuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG5cdFx0aWYgKGNoYW5nZXMubWVudUFsaWdubWVudCkge1xuXHRcdFx0dGhpcy5fYWxpZ25tZW50ID0gY2hhbmdlcy5tZW51QWxpZ25tZW50LmN1cnJlbnRWYWx1ZTtcblx0XHR9XG5cdH1cblxuXG5cblx0LyoqXG5cdCAqIElmIHVzZXIgaGFzIHBhc3NlZCBpbiB0cnVlIGZvciBvcGVuLCB3ZSBkeW5hbWljYWxseSBvcGVuIHRoZSBtZW51XG5cdCAqL1xuXHRuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMub3Blbikge1xuXHRcdFx0dGhpcy5vcGVuID0gIXRoaXMub3Blbjtcblx0XHRcdHRoaXMudG9nZ2xlTWVudSgpO1xuXHRcdH1cblx0fVxuXG5cblxuXHQvKipcblx0KiBDbGVhbiB1cCBGbG9hdGluZy11aSAmIHN1YnNjcmlwdGlvbnNcblx0Ki9cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5jbGVhblVwKCk7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHN1YikgPT4gc3ViLnVuc3Vic2NyaWJlKCkpO1xuXHR9XG5cblxuXHQvKipcblx0ICogQXMgb2Ygbm93LCBtZW51IGJ1dHRvbiBkb2VzIG5vdCBzdXBwb3J0IG5leHRlZCBtZW51LCBvbiBidXR0b24gY2xpY2sgaXQgc2hvdWxkIGNsb3NlXG5cdCAqL1xuXHRoYW5kbGVNZW51SXRlbUNsaWNrKGV2ZW50OiBJdGVtQ2xpY2tFdmVudCkge1xuXHRcdC8vIElmIGV2ZW50IGlzIG5vdCB0eXBlIHJhZGlvL2NoZWNrYm94LCB3ZSBjbG9zZSB0aGUgbWVudVxuXHRcdGlmICghZXZlbnQudHlwZSkge1xuXHRcdFx0dGhpcy50b2dnbGVNZW51KCk7XG5cdFx0fVxuXHR9XG5cblxuXG5cdC8qKlxuXHQgKiBPbiBib2R5IGNsaWNrLCBjbG9zZSB0aGUgbWVudVxuXHQgKiBAcGFyYW0gZXZlbnRcblx0ICovXG5cdGhhbmRsZUZvY3VzT3V0KGV2ZW50KSB7XG5cdFx0aWYgKCF0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KSkge1xuXHRcdFx0dGhpcy50b2dnbGVNZW51KCk7XG5cdFx0fVxuXHR9XG5cblxuXG5cdC8qKlxuXHQgKiBDbGVhbiB1cCBgYXV0b1VwZGF0ZWAgaWYgYXV0byBhbGlnbm1lbnQgaXMgZW5hYmxlZFxuXHQgKi9cblx0Y2xlYW5VcCgpIHtcblx0XHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5kb2N1bWVudENsaWNrKTtcblx0XHRpZiAodGhpcy51bm1vdW50RmxvYXRpbmdFbGVtZW50KSB7XG5cdFx0XHR0aGlzLm1lbnVSZWYucmVtb3ZlKCk7XG5cdFx0XHR0aGlzLnZpZXdDb250YWluZXJSZWYuY2xlYXIoKTtcblx0XHRcdHRoaXMudW5tb3VudEZsb2F0aW5nRWxlbWVudCgpO1xuXHRcdH1cblx0XHR0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQgPSB1bmRlZmluZWQ7XG5cdFx0Ly8gT24gYWxsIGluc3RhbmNlcyBvZiBtZW51IGNsb3NpbmcsIG1ha2Ugc3VyZSBpY29uIGRpcmVjdGlvbiBpcyBjb3JyZWN0XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0fVxuXG5cblx0LyoqXG5cdCAqIE9uIGFjdGlvbiBjbGljaywgbm90aWZ5IHVzZXJcblx0ICogSWYgdGhlIG1lbnUgaXMgb3BlbiwgY2xvc2UgdGhlIG1lbnVcblx0ICogQHBhcmFtIGV2ZW50XG5cdCAqL1xuXHRvbkFjdGlvbkNsaWNrKGV2ZW50OiBQb2ludGVyRXZlbnQpIHtcblx0XHRpZiAodGhpcy5vcGVuKSB7XG5cdFx0XHR0aGlzLnRvZ2dsZU1lbnUoKTtcblx0XHR9XG5cdFx0dGhpcy5hY3Rpb25DbGljay5lbWl0KGV2ZW50KTtcblx0fVxuXG5cblxuXHQvKipcblx0ICogSGFuZGxlcyBlbWl0dGluZyBvcGVuL2Nsb3NlIGV2ZW50XG5cdCAqL1xuXHR0b2dnbGVNZW51KCkge1xuXHRcdHRoaXMub3BlbiA9ICF0aGlzLm9wZW47XG5cdFx0aWYgKHRoaXMub3Blbikge1xuXHRcdFx0Ly8gUmVuZGVyIHRoZSB0ZW1wbGF0ZSAmIGFwcGVuZCB0byB2aWV3XG5cdFx0XHRjb25zdCB2aWV3ID0gdGhpcy52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUVtYmVkZGVkVmlldyh0aGlzLm1lbnVUZW1wbGF0ZSk7XG5cdFx0XHR0aGlzLm1lbnVSZWYgPSBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHZpZXcucm9vdE5vZGVzWzBdIGFzIEhUTUxFbGVtZW50KTtcblx0XHRcdC8vIEFzc2lnbiBidXR0b24gd2lkdGggdG8gdGhlIG1lbnUgcmVmIHRvIGFsaWduIHdpdGggYnV0dG9uXG5cdFx0XHRPYmplY3QuYXNzaWduKHRoaXMubWVudVJlZi5zdHlsZSwge1xuXHRcdFx0XHR3aWR0aDogYCR7dGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRofXB4YCxcblx0XHRcdFx0dG9wOiBcIjBcIixcblx0XHRcdFx0bGVmdDogXCIwXCJcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBSZXNldCAmIHRlc3QgYWxpZ25tZW50IGV2ZXJ5IG9wZW5cblx0XHRcdHRoaXMubWVudUFsaWdubWVudCA9IHRoaXMuX2FsaWdubWVudDtcblxuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHRoaXMuZG9jdW1lbnRDbGljayk7XG5cblx0XHRcdC8vIExpc3RlbiBmb3IgZXZlbnRzIHN1Y2ggYXMgc2Nyb2xsaW5nIHRvIGtlZXAgbWVudSBhbGlnbmVkXG5cdFx0XHR0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQgPSBhdXRvVXBkYXRlKFxuXHRcdFx0XHR0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHRcdHRoaXMubWVudVJlZixcblx0XHRcdFx0dGhpcy5yZWNvbXB1dGVQb3NpdGlvbi5iaW5kKHRoaXMpXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNsZWFuVXAoKTtcblx0XHR9XG5cdH1cblxuXG5cblx0cm91bmRCeURQUih2YWx1ZSkge1xuXHRcdGNvbnN0IGRwciA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIHx8IDE7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQodmFsdWUgKiBkcHIpIC8gZHByO1xuXHR9XG5cblxuXG5cdC8qKlxuXHQgKiBDb21wdXRlIHBvc2l0aW9uIG9mIG1lbnVcblx0ICovXG5cdHJlY29tcHV0ZVBvc2l0aW9uKCkge1xuXHRcdGlmICh0aGlzLm1lbnVUZW1wbGF0ZSAmJiB0aGlzLmhvc3RFbGVtZW50KSB7XG5cdFx0XHQvLyBSdW4gb3V0c2lkZSBvZiBhbmd1bGFyIHpvbmUgdG8gYXZvaWQgdW5uZWNlc3NhcnkgY2hhbmdlIGRldGVjdGlvbiBhbmQgcmVseSBvbiBmbG9hdGluZy11aVxuXHRcdFx0dGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRjb25zdCB7IHgsIHksIHBsYWNlbWVudCB9ID0gYXdhaXQgY29tcHV0ZVBvc2l0aW9uKFxuXHRcdFx0XHRcdHRoaXMuaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudCxcblx0XHRcdFx0XHR0aGlzLm1lbnVSZWYsXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0cGxhY2VtZW50OiB0aGlzLm1lbnVBbGlnbm1lbnQsXG5cdFx0XHRcdFx0XHRzdHJhdGVneTogXCJmaXhlZFwiLFxuXHRcdFx0XHRcdFx0bWlkZGxld2FyZTogW1xuXHRcdFx0XHRcdFx0XHRmbGlwKHsgY3Jvc3NBeGlzOiBmYWxzZSB9KVxuXHRcdFx0XHRcdFx0XVxuXHRcdFx0XHRcdH0pO1xuXG5cdFx0XHRcdHRoaXMubWVudUFsaWdubWVudCA9IHBsYWNlbWVudCBhcyBDb21ib0J1dHRvblBsYWNlbWVudDtcblxuXHRcdFx0XHQvLyBVc2luZyBDU1NPTSB0byBtYW5pcHVsYXRlIENTUyB0byBhdm9pZCBjb250ZW50IHNlY3VyaXR5IHBvbGljeSBpbmxpbmUtc3JjXG5cdFx0XHRcdC8vIGh0dHBzOi8vZ2l0aHViLmNvbS93M2Mvd2ViYXBwc2VjLWNzcC9pc3N1ZXMvMjEyXG5cdFx0XHRcdE9iamVjdC5hc3NpZ24odGhpcy5tZW51UmVmLnN0eWxlLCB7XG5cdFx0XHRcdFx0cG9zaXRpb246IFwiZml4ZWRcIixcblx0XHRcdFx0XHQvLyBVc2luZyB0cmFuc2Zvcm0gaW5zdGVhZCBvZiB0b3AvbGVmdCBwb3NpdGlvbiB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG5cdFx0XHRcdFx0dHJhbnNmb3JtOiBgdHJhbnNsYXRlKCR7dGhpcy5yb3VuZEJ5RFBSKHgpfXB4LCR7dGhpcy5yb3VuZEJ5RFBSKHkpfXB4KWBcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cbiJdfQ==