UNPKG

carbon-components-angular

Version:
265 lines 28.3 kB
import { ChangeDetectionStrategy, Component, ContentChildren, HostBinding, Input, 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 "@angular/common"; import * as i2 from "carbon-components-angular/button"; import * as i3 from "carbon-components-angular/icon"; import * as i4 from "carbon-components-angular/context-menu"; export class MenuButtonComponent { constructor(ngZone, renderer, hostElement, viewContainerRef, changeDetectorRef) { this.ngZone = ngZone; this.renderer = renderer; this.hostElement = hostElement; this.viewContainerRef = viewContainerRef; this.changeDetectorRef = changeDetectorRef; this.menuId = `menu-button-${MenuButtonComponent.menuButtonCounter++}`; this.containerClass = true; this.kind = "primary"; this.size = "lg"; this.menuAlignment = "bottom"; this.buttonTabIndex = "0"; this.disabled = false; this.open = false; 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))); }); } /** * 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(); } /** * 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.referenceElement.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.referenceElement.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.referenceElement) { // 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.referenceElement.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(); }); } } } MenuButtonComponent.menuButtonCounter = 0; MenuButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MenuButtonComponent, deps: [{ token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); MenuButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MenuButtonComponent, selector: "cds-menu-button", inputs: { menuId: "menuId", kind: "kind", size: "size", menuAlignment: "menuAlignment", buttonTabIndex: "buttonTabIndex", disabled: "disabled", open: "open", label: "label" }, host: { properties: { "class.cds--menu-button__container": "this.containerClass" } }, queries: [{ propertyName: "projectedMenuItems", predicate: ContextMenuItemComponent }], viewQueries: [{ propertyName: "referenceElement", first: true, predicate: ["reference"], descendants: true, static: true }, { propertyName: "menuTemplate", first: true, predicate: ["menuTemplate"], descendants: true }], usesOnChanges: true, ngImport: i0, template: ` <button #reference class="cds--menu-button__trigger" [ngClass]="{'cds--menu-button__trigger--open': open}" [cdsButton]="kind" [size]="size" [attr.tabindex]="buttonTabIndex" [disabled]="disabled" type="button" [attr.aria-haspopup]="true" [attr.aria-expanded]="open" [attr.aria-controls]="open ? menuId : undefined" (click)="toggleMenu()"> {{label}} <svg cdsIcon="chevron--down" size="16" class="cds--btn__icon"> </svg> </button> <ng-template #menuTemplate> <cds-menu mode="basic" [size]="size" [open]="open" [attr.id]="menuId" [ngClass]="{ 'cds--menu-button__bottom': this.menuAlignment === 'bottom', 'cds--menu-button__bottom-start': this.menuAlignment === 'bottom-start', 'cds--menu-button__bottom-end': this.menuAlignment === 'bottom-end', 'cds--menu-top': this.menuAlignment === 'top', 'cds--menu-top-start': this.menuAlignment === 'top-start', 'cds--menu-top-end': this.menuAlignment === 'top-end' }"> <ng-content select="cds-menu-item, cds-menu-divider"></ng-content> </cds-menu> </ng-template> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: i4.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: MenuButtonComponent, decorators: [{ type: Component, args: [{ selector: "cds-menu-button", template: ` <button #reference class="cds--menu-button__trigger" [ngClass]="{'cds--menu-button__trigger--open': open}" [cdsButton]="kind" [size]="size" [attr.tabindex]="buttonTabIndex" [disabled]="disabled" type="button" [attr.aria-haspopup]="true" [attr.aria-expanded]="open" [attr.aria-controls]="open ? menuId : undefined" (click)="toggleMenu()"> {{label}} <svg cdsIcon="chevron--down" size="16" class="cds--btn__icon"> </svg> </button> <ng-template #menuTemplate> <cds-menu mode="basic" [size]="size" [open]="open" [attr.id]="menuId" [ngClass]="{ 'cds--menu-button__bottom': this.menuAlignment === 'bottom', 'cds--menu-button__bottom-start': this.menuAlignment === 'bottom-start', 'cds--menu-button__bottom-end': this.menuAlignment === 'bottom-end', 'cds--menu-top': this.menuAlignment === 'top', 'cds--menu-top-start': this.menuAlignment === 'top-start', 'cds--menu-top-end': this.menuAlignment === 'top-end' }"> <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: { menuId: [{ type: Input }], projectedMenuItems: [{ type: ContentChildren, args: [ContextMenuItemComponent] }], containerClass: [{ type: HostBinding, args: ["class.cds--menu-button__container"] }], kind: [{ type: Input }], size: [{ type: Input }], menuAlignment: [{ type: Input }], buttonTabIndex: [{ type: Input }], disabled: [{ type: Input }], open: [{ type: Input }], label: [{ type: Input }], referenceElement: [{ type: ViewChild, args: ["reference", { static: true }] }], menuTemplate: [{ type: ViewChild, args: ["menuTemplate"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS1idXR0b24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21lbnUtYnV0dG9uL21lbnUtYnV0dG9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRU4sdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxlQUFlLEVBR2YsV0FBVyxFQUNYLEtBQUssRUFRTCxTQUFTLEVBRVQsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUNOLFVBQVUsRUFDVixlQUFlLEVBQ2YsSUFBSSxFQUNKLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLHdCQUF3QixFQUFrQixNQUFNLHdDQUF3QyxDQUFDOzs7Ozs7QUFnRGxHLE1BQU0sT0FBTyxtQkFBbUI7SUFvQy9CLFlBQ1csTUFBYyxFQUNkLFFBQW1CLEVBQ25CLFdBQXVCLEVBQ3ZCLGdCQUFrQyxFQUNsQyxpQkFBb0M7UUFKcEMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsZ0JBQVcsR0FBWCxXQUFXLENBQVk7UUFDdkIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBdkN0QyxXQUFNLEdBQUcsZUFBZSxtQkFBbUIsQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7UUFjekIsbUJBQWMsR0FBRyxJQUFJLENBQUM7UUFFL0QsU0FBSSxHQUFxQyxTQUFTLENBQUM7UUFDbkQsU0FBSSxHQUF1QixJQUFJLENBQUM7UUFDaEMsa0JBQWEsR0FBd0IsUUFBUSxDQUFDO1FBQzlDLG1CQUFjLEdBQThCLEdBQUcsQ0FBQztRQUNoRCxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLFNBQUksR0FBRyxLQUFLLENBQUM7UUFNWixrQkFBYSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBR2pELGtCQUFhLEdBQW1CLEVBQUUsQ0FBQztRQUNuQyxlQUFVLEdBQXdCLFFBQVEsQ0FBQztJQVMvQyxDQUFDO0lBdENMLG9EQUFvRDtJQUNwRCxJQUErQyxrQkFBa0IsQ0FBQyxRQUE2QztRQUM5RyxtREFBbUQ7UUFDbkQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUN6QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUM5RSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBK0JEOzs7T0FHRztJQUNILFdBQVcsQ0FBQyxPQUFzQjtRQUNqQyxJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7WUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztTQUNyRDtJQUNGLENBQUM7SUFJRDs7T0FFRztJQUNILGVBQWU7UUFDZCxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDZCxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUN2QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDbEI7SUFDRixDQUFDO0lBSUQ7O01BRUU7SUFDRixXQUFXO1FBQ1YsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFHRDs7T0FFRztJQUNILG1CQUFtQixDQUFDLEtBQXFCO1FBQ3hDLHlEQUF5RDtRQUN6RCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRTtZQUNoQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7U0FDbEI7SUFDRixDQUFDO0lBSUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLEtBQUs7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDM0QsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1NBQ2xCO0lBQ0YsQ0FBQztJQUlEOztPQUVHO0lBQ0gsT0FBTztRQUNOLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzFELElBQUksSUFBSSxDQUFDLHNCQUFzQixFQUFFO1lBQ2hDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1NBQzlCO1FBQ0QsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFNBQVMsQ0FBQztRQUN4Qyx3RUFBd0U7UUFDeEUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3ZDLENBQUM7SUFJRDs7T0FFRztJQUNILFVBQVU7UUFDVCxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztRQUN2QixJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDZCx1Q0FBdUM7WUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN6RSxJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFnQixDQUFDLENBQUM7WUFDM0UsMkRBQTJEO1lBQzNELE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7Z0JBQ2pDLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsV0FBVyxJQUFJO2dCQUM3RCxHQUFHLEVBQUUsR0FBRztnQkFDUixJQUFJLEVBQUUsR0FBRzthQUNULENBQUMsQ0FBQztZQUVILG9DQUFvQztZQUNwQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7WUFFckMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFFdkQsMkRBQTJEO1lBQzNELElBQUksQ0FBQyxzQkFBc0IsR0FBRyxVQUFVLENBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLEVBQ25DLElBQUksQ0FBQyxPQUFPLEVBQ1osSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDakMsQ0FBQztTQUNGO2FBQU07WUFDTixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7U0FDZjtJQUNGLENBQUM7SUFJRCxVQUFVLENBQUMsS0FBSztRQUNmLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDdEMsQ0FBQztJQUlEOztPQUVHO0lBQ0gsaUJBQWlCO1FBQ2hCLElBQUksSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDL0MsNEZBQTRGO1lBQzVGLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxHQUFHLE1BQU0sZUFBZSxDQUNoRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUNuQyxJQUFJLENBQUMsT0FBTyxFQUNaO29CQUNDLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYTtvQkFDN0IsUUFBUSxFQUFFLE9BQU87b0JBQ2pCLFVBQVUsRUFBRTt3QkFDWCxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7cUJBQzFCO2lCQUNELENBQUMsQ0FBQztnQkFFSixJQUFJLENBQUMsYUFBYSxHQUFHLFNBQWdDLENBQUM7Z0JBRXRELDRFQUE0RTtnQkFDNUUsa0RBQWtEO2dCQUNsRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFO29CQUNqQyxRQUFRLEVBQUUsT0FBTztvQkFDakIsc0VBQXNFO29CQUN0RSxTQUFTLEVBQUUsYUFBYSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUs7aUJBQ3ZFLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdkMsQ0FBQyxDQUFDLENBQUM7U0FDSDtJQUNGLENBQUM7O0FBN0xNLHFDQUFpQixHQUFHLENBQUMsQ0FBQztnSEFEakIsbUJBQW1CO29HQUFuQixtQkFBbUIsZ1dBS2Qsd0JBQXdCLDhRQTlDL0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBc0NUOzJGQUdXLG1CQUFtQjtrQkEzQy9CLFNBQVM7bUJBQUM7b0JBQ1YsUUFBUSxFQUFFLGlCQUFpQjtvQkFDM0IsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQXNDVDtvQkFDRCxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtpQkFDL0M7Nk1BR1MsTUFBTTtzQkFBZCxLQUFLO2dCQUd5QyxrQkFBa0I7c0JBQWhFLGVBQWU7dUJBQUMsd0JBQXdCO2dCQVdTLGNBQWM7c0JBQS9ELFdBQVc7dUJBQUMsbUNBQW1DO2dCQUV2QyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRW9DLGdCQUFnQjtzQkFBekQsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNiLFlBQVk7c0JBQXRDLFNBQVM7dUJBQUMsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdEFmdGVyVmlld0luaXQsXG5cdENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuXHRDaGFuZ2VEZXRlY3RvclJlZixcblx0Q29tcG9uZW50LFxuXHRDb250ZW50Q2hpbGRyZW4sXG5cdEVsZW1lbnRSZWYsXG5cdGZvcndhcmRSZWYsXG5cdEhvc3RCaW5kaW5nLFxuXHRJbnB1dCxcblx0Tmdab25lLFxuXHRPbkNoYW5nZXMsXG5cdE9uRGVzdHJveSxcblx0UXVlcnlMaXN0LFxuXHRSZW5kZXJlcjIsXG5cdFNpbXBsZUNoYW5nZXMsXG5cdFRlbXBsYXRlUmVmLFxuXHRWaWV3Q2hpbGQsXG5cdFZpZXdDb250YWluZXJSZWZcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuaW1wb3J0IHtcblx0YXV0b1VwZGF0ZSxcblx0Y29tcHV0ZVBvc2l0aW9uLFxuXHRmbGlwXG59IGZyb20gXCJAZmxvYXRpbmctdWkvZG9tXCI7XG5pbXBvcnQgeyBDb250ZXh0TWVudUl0ZW1Db21wb25lbnQsIEl0ZW1DbGlja0V2ZW50IH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvY29udGV4dC1tZW51XCI7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tIFwicnhqc1wiO1xuXG50eXBlIE1lbnVCdXR0b25QbGFjZW1lbnQgPSBcInRvcFwiIHwgXCJ0b3Atc3RhcnRcIiB8IFwidG9wLWVuZFwiIHwgXCJib3R0b21cIiB8IFwiYm90dG9tLXN0YXJ0XCIgfCBcImJvdHRvbS1lbmRcIjtcblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiBcImNkcy1tZW51LWJ1dHRvblwiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxidXR0b25cblx0XHRcdCNyZWZlcmVuY2Vcblx0XHRcdGNsYXNzPVwiY2RzLS1tZW51LWJ1dHRvbl9fdHJpZ2dlclwiXG5cdFx0XHRbbmdDbGFzc109XCJ7J2Nkcy0tbWVudS1idXR0b25fX3RyaWdnZXItLW9wZW4nOiBvcGVufVwiXG5cdFx0XHRbY2RzQnV0dG9uXT1cImtpbmRcIlxuXHRcdFx0W3NpemVdPVwic2l6ZVwiXG5cdFx0XHRbYXR0ci50YWJpbmRleF09XCJidXR0b25UYWJJbmRleFwiXG5cdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0dHlwZT1cImJ1dHRvblwiXG5cdFx0XHRbYXR0ci5hcmlhLWhhc3BvcHVwXT1cInRydWVcIlxuXHRcdFx0W2F0dHIuYXJpYS1leHBhbmRlZF09XCJvcGVuXCJcblx0XHRcdFthdHRyLmFyaWEtY29udHJvbHNdPVwib3BlbiA/IG1lbnVJZCA6IHVuZGVmaW5lZFwiXG5cdFx0XHQoY2xpY2spPVwidG9nZ2xlTWVudSgpXCI+XG5cdFx0XHR7e2xhYmVsfX1cblx0XHRcdDxzdmdcblx0XHRcdFx0Y2RzSWNvbj1cImNoZXZyb24tLWRvd25cIlxuXHRcdFx0XHRzaXplPVwiMTZcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tYnRuX19pY29uXCI+XG5cdFx0XHQ8L3N2Zz5cblx0XHQ8L2J1dHRvbj5cblx0XHQ8bmctdGVtcGxhdGUgI21lbnVUZW1wbGF0ZT5cblx0XHRcdDxjZHMtbWVudVxuXHRcdFx0XHRtb2RlPVwiYmFzaWNcIlxuXHRcdFx0XHRbc2l6ZV09XCJzaXplXCJcblx0XHRcdFx0W29wZW5dPVwib3BlblwiXG5cdFx0XHRcdFthdHRyLmlkXT1cIm1lbnVJZFwiXG5cdFx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0XHQnY2RzLS1tZW51LWJ1dHRvbl9fYm90dG9tJzogdGhpcy5tZW51QWxpZ25tZW50ID09PSAnYm90dG9tJyxcblx0XHRcdFx0XHQnY2RzLS1tZW51LWJ1dHRvbl9fYm90dG9tLXN0YXJ0JzogdGhpcy5tZW51QWxpZ25tZW50ID09PSAnYm90dG9tLXN0YXJ0Jyxcblx0XHRcdFx0XHQnY2RzLS1tZW51LWJ1dHRvbl9fYm90dG9tLWVuZCc6IHRoaXMubWVudUFsaWdubWVudCA9PT0gJ2JvdHRvbS1lbmQnLFxuXHRcdFx0XHRcdCdjZHMtLW1lbnUtdG9wJzogdGhpcy5tZW51QWxpZ25tZW50ID09PSAndG9wJyxcblx0XHRcdFx0XHQnY2RzLS1tZW51LXRvcC1zdGFydCc6IHRoaXMubWVudUFsaWdubWVudCA9PT0gJ3RvcC1zdGFydCcsXG5cdFx0XHRcdFx0J2Nkcy0tbWVudS10b3AtZW5kJzogdGhpcy5tZW51QWxpZ25tZW50ID09PSAndG9wLWVuZCdcblx0XHRcdFx0fVwiPlxuXHRcdFx0XHQ8bmctY29udGVudCBzZWxlY3Q9XCJjZHMtbWVudS1pdGVtLCBjZHMtbWVudS1kaXZpZGVyXCI+PC9uZy1jb250ZW50PlxuXHRcdFx0PC9jZHMtbWVudT5cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRgLFxuXHRjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBNZW51QnV0dG9uQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXHRzdGF0aWMgbWVudUJ1dHRvbkNvdW50ZXIgPSAwO1xuXHRASW5wdXQoKSBtZW51SWQgPSBgbWVudS1idXR0b24tJHtNZW51QnV0dG9uQ29tcG9uZW50Lm1lbnVCdXR0b25Db3VudGVyKyt9YDtcblxuXHQvLyBMaXN0ZW4gZm9yIGNsaWNrICYgZGV0ZXJtaW5lIGlmIG1lbnUgc2hvdWxkIGNsb3NlXG5cdEBDb250ZW50Q2hpbGRyZW4oQ29udGV4dE1lbnVJdGVtQ29tcG9uZW50KSBzZXQgcHJvamVjdGVkTWVudUl0ZW1zKGl0ZW1MaXN0OiBRdWVyeUxpc3Q8Q29udGV4dE1lbnVJdGVtQ29tcG9uZW50Pikge1xuXHRcdC8vIFJlc2V0IGluIGNhc2UgdXNlciBkeW5hbWljYWxseSB1cGRhdGVzIG1lbnUgaXRlbVxuXHRcdHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzdWIpID0+IHN1Yj8udW5zdWJzY3JpYmUoKSk7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zID0gW107XG5cdFx0aXRlbUxpc3QuZm9yRWFjaCgoaXRlbSkgPT4ge1xuXHRcdFx0dGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG5cdFx0XHRcdGl0ZW0uaXRlbUNsaWNrLnN1YnNjcmliZSgoY2xpY2tFdmVudCkgPT4gdGhpcy5oYW5kbGVNZW51SXRlbUNsaWNrKGNsaWNrRXZlbnQpKVxuXHRcdFx0KTtcblx0XHR9KTtcblx0fVxuXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tbWVudS1idXR0b25fX2NvbnRhaW5lclwiKSBjb250YWluZXJDbGFzcyA9IHRydWU7XG5cblx0QElucHV0KCkga2luZDogXCJwcmltYXJ5XCIgfCBcInRlcnRpYXJ5XCIgfCBcImdob3N0XCIgPSBcInByaW1hcnlcIjtcblx0QElucHV0KCkgc2l6ZTogXCJzbVwiIHwgXCJtZFwiIHwgXCJsZ1wiID0gXCJsZ1wiO1xuXHRASW5wdXQoKSBtZW51QWxpZ25tZW50OiBNZW51QnV0dG9uUGxhY2VtZW50ID0gXCJib3R0b21cIjtcblx0QElucHV0KCkgYnV0dG9uVGFiSW5kZXg6IFwiMFwiIHwgXCIxXCIgfCBcIi0xXCIgfCBzdHJpbmcgPSBcIjBcIjtcblx0QElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblx0QElucHV0KCkgb3BlbiA9IGZhbHNlO1xuXHRASW5wdXQoKSBsYWJlbDogc3RyaW5nO1xuXG5cdEBWaWV3Q2hpbGQoXCJyZWZlcmVuY2VcIiwgeyBzdGF0aWM6IHRydWUgfSkgcmVmZXJlbmNlRWxlbWVudDogRWxlbWVudFJlZjxIVE1MQnV0dG9uRWxlbWVudD47XG5cdEBWaWV3Q2hpbGQoXCJtZW51VGVtcGxhdGVcIikgbWVudVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG5cdHByb3RlY3RlZCBkb2N1bWVudENsaWNrID0gdGhpcy5oYW5kbGVGb2N1c091dC5iaW5kKHRoaXMpO1xuXHRwcm90ZWN0ZWQgdW5tb3VudEZsb2F0aW5nRWxlbWVudDogRnVuY3Rpb247XG5cblx0cHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXHRwcml2YXRlIF9hbGlnbm1lbnQ6IE1lbnVCdXR0b25QbGFjZW1lbnQgPSBcImJvdHRvbVwiO1xuXHRwcml2YXRlIG1lbnVSZWY6IEhUTUxFbGVtZW50O1xuXG5cdGNvbnN0cnVjdG9yKFxuXHRcdHByb3RlY3RlZCBuZ1pvbmU6IE5nWm9uZSxcblx0XHRwcm90ZWN0ZWQgcmVuZGVyZXI6IFJlbmRlcmVyMixcblx0XHRwcm90ZWN0ZWQgaG9zdEVsZW1lbnQ6IEVsZW1lbnRSZWYsXG5cdFx0cHJvdGVjdGVkIHZpZXdDb250YWluZXJSZWY6IFZpZXdDb250YWluZXJSZWYsXG5cdFx0cHJvdGVjdGVkIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxuXHQpIHsgfVxuXG5cblx0LyoqXG5cdCAqIEluIGNhc2UgdXNlciB1cGRhdGVzIGFsaWdubWVudCwgc3RvcmUgaW5pdGlhbCB2YWx1ZS5cblx0ICogVGhpcyBhbGxvd3MgdXMgdG8gdGVzdCB1c2VyIHBhc3NlZCBhbGlnbm1lbnQgb24gZWFjaCBvcGVuXG5cdCAqL1xuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG5cdFx0aWYgKGNoYW5nZXMubWVudUFsaWdubWVudCkge1xuXHRcdFx0dGhpcy5fYWxpZ25tZW50ID0gY2hhbmdlcy5tZW51QWxpZ25tZW50LmN1cnJlbnRWYWx1ZTtcblx0XHR9XG5cdH1cblxuXG5cblx0LyoqXG5cdCAqIElmIHVzZXIgaGFzIHBhc3NlZCBpbiB0cnVlIGZvciBvcGVuLCB3ZSBkeW5hbWljYWxseSBvcGVuIHRoZSBtZW51XG5cdCAqL1xuXHRuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMub3Blbikge1xuXHRcdFx0dGhpcy5vcGVuID0gIXRoaXMub3Blbjtcblx0XHRcdHRoaXMudG9nZ2xlTWVudSgpO1xuXHRcdH1cblx0fVxuXG5cblxuXHQvKipcblx0KiBDbGVhbiB1cCBGbG9hdGluZy11aSAmIHN1YnNjcmlwdGlvbnNcblx0Ki9cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5jbGVhblVwKCk7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHN1YikgPT4gc3ViLnVuc3Vic2NyaWJlKCkpO1xuXHR9XG5cblxuXHQvKipcblx0ICogQXMgb2Ygbm93LCBtZW51IGJ1dHRvbiBkb2VzIG5vdCBzdXBwb3J0IG5leHRlZCBtZW51LCBvbiBidXR0b24gY2xpY2sgaXQgc2hvdWxkIGNsb3NlXG5cdCAqL1xuXHRoYW5kbGVNZW51SXRlbUNsaWNrKGV2ZW50OiBJdGVtQ2xpY2tFdmVudCkge1xuXHRcdC8vIElmIGV2ZW50IGlzIG5vdCB0eXBlIHJhZGlvL2NoZWNrYm94LCB3ZSBjbG9zZSB0aGUgbWVudVxuXHRcdGlmICghZXZlbnQudHlwZSkge1xuXHRcdFx0dGhpcy50b2dnbGVNZW51KCk7XG5cdFx0fVxuXHR9XG5cblxuXG5cdC8qKlxuXHQgKiBPbiBib2R5IGNsaWNrLCBjbG9zZSB0aGUgbWVudVxuXHQgKiBAcGFyYW0gZXZlbnRcblx0ICovXG5cdGhhbmRsZUZvY3VzT3V0KGV2ZW50KSB7XG5cdFx0aWYgKCF0aGlzLmhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KSkge1xuXHRcdFx0dGhpcy50b2dnbGVNZW51KCk7XG5cdFx0fVxuXHR9XG5cblxuXG5cdC8qKlxuXHQgKiBDbGVhbiB1cCBgYXV0b1VwZGF0ZWAgaWYgYXV0byBhbGlnbm1lbnQgaXMgZW5hYmxlZFxuXHQgKi9cblx0Y2xlYW5VcCgpIHtcblx0XHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5kb2N1bWVudENsaWNrKTtcblx0XHRpZiAodGhpcy51bm1vdW50RmxvYXRpbmdFbGVtZW50KSB7XG5cdFx0XHR0aGlzLm1lbnVSZWYucmVtb3ZlKCk7XG5cdFx0XHR0aGlzLnZpZXdDb250YWluZXJSZWYuY2xlYXIoKTtcblx0XHRcdHRoaXMudW5tb3VudEZsb2F0aW5nRWxlbWVudCgpO1xuXHRcdH1cblx0XHR0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQgPSB1bmRlZmluZWQ7XG5cdFx0Ly8gT24gYWxsIGluc3RhbmNlcyBvZiBtZW51IGNsb3NpbmcsIG1ha2Ugc3VyZSBpY29uIGRpcmVjdGlvbiBpcyBjb3JyZWN0XG5cdFx0dGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0fVxuXG5cblxuXHQvKipcblx0ICogSGFuZGxlcyBlbWl0dGluZyBvcGVuL2Nsb3NlIGV2ZW50XG5cdCAqL1xuXHR0b2dnbGVNZW51KCkge1xuXHRcdHRoaXMub3BlbiA9ICF0aGlzLm9wZW47XG5cdFx0aWYgKHRoaXMub3Blbikge1xuXHRcdFx0Ly8gUmVuZGVyIHRoZSB0ZW1wbGF0ZSAmIGFwcGVuZCB0byB2aWV3XG5cdFx0XHRjb25zdCB2aWV3ID0gdGhpcy52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUVtYmVkZGVkVmlldyh0aGlzLm1lbnVUZW1wbGF0ZSk7XG5cdFx0XHR0aGlzLm1lbnVSZWYgPSBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHZpZXcucm9vdE5vZGVzWzBdIGFzIEhUTUxFbGVtZW50KTtcblx0XHRcdC8vIEFzc2lnbiBidXR0b24gd2lkdGggdG8gdGhlIG1lbnUgcmVmIHRvIGFsaWduIHdpdGggYnV0dG9uXG5cdFx0XHRPYmplY3QuYXNzaWduKHRoaXMubWVudVJlZi5zdHlsZSwge1xuXHRcdFx0XHR3aWR0aDogYCR7dGhpcy5yZWZlcmVuY2VFbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY2xpZW50V2lkdGh9cHhgLFxuXHRcdFx0XHR0b3A6IFwiMFwiLFxuXHRcdFx0XHRsZWZ0OiBcIjBcIlxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIFJlc2V0ICYgdGVzdCBhbGlnbm1lbnQgZXZlcnkgb3BlblxuXHRcdFx0dGhpcy5tZW51QWxpZ25tZW50ID0gdGhpcy5fYWxpZ25tZW50O1xuXG5cdFx0XHRkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgdGhpcy5kb2N1bWVudENsaWNrKTtcblxuXHRcdFx0Ly8gTGlzdGVuIGZvciBldmVudHMgc3VjaCBhcyBzY3JvbGxpbmcgdG8ga2VlcCBtZW51IGFsaWduZWRcblx0XHRcdHRoaXMudW5tb3VudEZsb2F0aW5nRWxlbWVudCA9IGF1dG9VcGRhdGUoXG5cdFx0XHRcdHRoaXMucmVmZXJlbmNlRWxlbWVudC5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XHR0aGlzLm1lbnVSZWYsXG5cdFx0XHRcdHRoaXMucmVjb21wdXRlUG9zaXRpb24uYmluZCh0aGlzKVxuXHRcdFx0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5jbGVhblVwKCk7XG5cdFx0fVxuXHR9XG5cblxuXG5cdHJvdW5kQnlEUFIodmFsdWUpIHtcblx0XHRjb25zdCBkcHIgPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxO1xuXHRcdHJldHVybiBNYXRoLnJvdW5kKHZhbHVlICogZHByKSAvIGRwcjtcblx0fVxuXG5cblxuXHQvKipcblx0ICogQ29tcHV0ZSBwb3NpdGlvbiBvZiBtZW51XG5cdCAqL1xuXHRyZWNvbXB1dGVQb3NpdGlvbigpIHtcblx0XHRpZiAodGhpcy5tZW51VGVtcGxhdGUgJiYgdGhpcy5yZWZlcmVuY2VFbGVtZW50KSB7XG5cdFx0XHQvLyBSdW4gb3V0c2lkZSBvZiBhbmd1bGFyIHpvbmUgdG8gYXZvaWQgdW5uZWNlc3NhcnkgY2hhbmdlIGRldGVjdGlvbiBhbmQgcmVseSBvbiBmbG9hdGluZy11aVxuXHRcdFx0dGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRjb25zdCB7IHgsIHksIHBsYWNlbWVudCB9ID0gYXdhaXQgY29tcHV0ZVBvc2l0aW9uKFxuXHRcdFx0XHRcdHRoaXMucmVmZXJlbmNlRWxlbWVudC5uYXRpdmVFbGVtZW50LFxuXHRcdFx0XHRcdHRoaXMubWVudVJlZixcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwbGFjZW1lbnQ6IHRoaXMubWVudUFsaWdubWVudCxcblx0XHRcdFx0XHRcdHN0cmF0ZWd5OiBcImZpeGVkXCIsXG5cdFx0XHRcdFx0XHRtaWRkbGV3YXJlOiBbXG5cdFx0XHRcdFx0XHRcdGZsaXAoeyBjcm9zc0F4aXM6IGZhbHNlIH0pXG5cdFx0XHRcdFx0XHRdXG5cdFx0XHRcdFx0fSk7XG5cblx0XHRcdFx0dGhpcy5tZW51QWxpZ25tZW50ID0gcGxhY2VtZW50IGFzIE1lbnVCdXR0b25QbGFjZW1lbnQ7XG5cblx0XHRcdFx0Ly8gVXNpbmcgQ1NTT00gdG8gbWFuaXB1bGF0ZSBDU1MgdG8gYXZvaWQgY29udGVudCBzZWN1cml0eSBwb2xpY3kgaW5saW5lLXNyY1xuXHRcdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vdzNjL3dlYmFwcHNlYy1jc3AvaXNzdWVzLzIxMlxuXHRcdFx0XHRPYmplY3QuYXNzaWduKHRoaXMubWVudVJlZi5zdHlsZSwge1xuXHRcdFx0XHRcdHBvc2l0aW9uOiBcImZpeGVkXCIsXG5cdFx0XHRcdFx0Ly8gVXNpbmcgdHJhbnNmb3JtIGluc3RlYWQgb2YgdG9wL2xlZnQgcG9zaXRpb24gdG8gaW1wcm92ZSBwZXJmb3JtYW5jZVxuXHRcdFx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke3RoaXMucm91bmRCeURQUih4KX1weCwke3RoaXMucm91bmRCeURQUih5KX1weClgXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG59XG4iXX0=