UNPKG

carbon-components-angular

Version:
282 lines 34.8 kB
import { Directive, EventEmitter, HostBinding, Input, Output } from "@angular/core"; import { arrow, autoUpdate, computePosition, flip, offset } from "@floating-ui/dom"; import * as i0 from "@angular/core"; export class PopoverContainer { constructor(elementRef, ngZone, renderer, changeDetectorRef) { this.elementRef = elementRef; this.ngZone = ngZone; this.renderer = renderer; this.changeDetectorRef = changeDetectorRef; this._align = "bottom"; this.alignmentClassPrefix = "cds--popover--"; /** * Emits an event when the dialog is closed */ this.onClose = new EventEmitter(); /** * Emits an event when the dialog is opened */ this.onOpen = new EventEmitter(); /** * Emits an event when the state of `isOpen` changes. Allows `isOpen` to be double bound */ this.isOpenChange = new EventEmitter(); /** * Show caret at the alignment position */ this.caret = true; /** * Enable drop shadow around the popover container */ this.dropShadow = true; /** * Enable high contrast for popover container */ this.highContrast = false; /** * **Experimental**: Use floating-ui to position the tooltip * This is not toggleable - should be assigned once */ this.autoAlign = false; this.containerClass = true; this.isOpen = false; } /** * Set alignment of popover * As of v5, `oldPlacements` are now deprecated in favor of Placements * * When `autoAlign` is set to `true`, alignment may change for best placement */ set align(alignment) { // If alignment is not passed, the default value will be `undefined`. if (!alignment) { return; } const previousAlignment = this._align; switch (alignment) { case "top-left": this._align = "top-start"; break; case "top-right": this._align = "top-end"; break; case "bottom-left": this._align = "bottom-start"; break; case "bottom-right": this._align = "bottom-end"; break; case "left-top": this._align = "left-start"; break; case "left-bottom": this._align = "left-end"; break; case "right-top": this._align = "right-start"; break; case "right-bottom": this._align = "right-end"; break; default: this._align = alignment; break; } this.updateAlignmentClass(this._align, previousAlignment); } /** * Handles emitting open/close event * @param open - Is the popover container open * @param event - Event */ handleChange(open, event) { // We only emit the event when parameter has an event to keep existing behavior if ((this.isOpen !== open) && event) { this.isOpenChange.emit(open); } if (open) { if (event) { this.onOpen.emit(event); } // when auto alignment is enabled, use auto update to set the placement for the element if (this.autoAlign) { if (this.caretRef) { // Get caret offset/height property // Getting computed styles once every open, otherwise expensive. const computedStyle = getComputedStyle(this.caretRef); const offset = computedStyle.getPropertyValue("--cds-popover-offset"); const height = computedStyle.getPropertyValue("--cds-popover-caret-height"); this.caretOffset = (offset?.includes("px") ? Number(offset.split("px", 1)[0]) : Number(offset.split("rem", 1)[0]) * 16) || 10; this.caretHeight = (height?.includes("px") ? Number(height.split("px", 1)[0]) : Number(height.split("rem", 1)[0]) * 16) || 6; } if (this.elementRef.nativeElement && this.popoverContentRef) { this.unmountFloatingElement = autoUpdate(this.elementRef.nativeElement, this.popoverContentRef, this.recomputePosition.bind(this)); } } } else { this.cleanUp(); if (event) { this.onClose.emit(event); } } this.isOpen = open; this.changeDetectorRef.markForCheck(); } roundByDPR(value) { const dpr = window.devicePixelRatio || 1; return Math.round(value * dpr) / dpr; } /** * Compute position of tooltip when autoAlign is enabled */ recomputePosition() { // Run outside of angular zone to avoid unnecessary change detection and rely on floating-ui this.ngZone.runOutsideAngular(async () => { const { x, y, placement, middlewareData } = await computePosition(this.elementRef.nativeElement, this.popoverContentRef, { placement: this._align, strategy: "fixed", middleware: [ offset(this.caretOffset), flip({ fallbackAxisSideDirection: "start" }), arrow({ element: this.caretRef }) ] }); const previousAlignment = this._align; this._align = placement; this.updateAlignmentClass(this._align, previousAlignment); // Using CSSOM to manipulate CSS to avoid content security policy inline-src // https://github.com/w3c/webappsec-csp/issues/212 Object.assign(this.popoverContentRef.style, { position: "fixed", top: "0", left: "0", // Using transform instead of top/left position to improve performance transform: `translate(${this.roundByDPR(x)}px,${this.roundByDPR(y)}px)` }); if (middlewareData.arrow) { const { x: arrowX, y: arrowY } = middlewareData.arrow; const staticSide = { top: "bottom", right: "left", bottom: "top", left: "right" }[placement.split("-")[0]]; this.caretRef.style.left = arrowX != null ? `${arrowX}px` : ""; this.caretRef.style.top = arrowY != null ? `${arrowY}px` : ""; this.caretRef.style.right = ""; this.caretRef.style.bottom = ""; if (staticSide) { this.caretRef.style[staticSide] = `${-this.caretHeight}px`; } } }); } /** * Close the popover and reopen it with updated values without emitting an event * @param changes */ ngOnChanges(changes) { // Close and reopen the popover, handle alignment/programmatic open/close const originalState = this.isOpen; this.handleChange(false); // Ignore first change since content is not initialized if (changes.autoAlign && !changes.autoAlign.firstChange) { // Reset the inline styles this.popoverContentRef = this.elementRef.nativeElement.querySelector(".cds--popover-content"); this.popoverContentRef.setAttribute("style", ""); this.caretRef = this.elementRef.nativeElement.querySelector("span.cds--popover-caret"); } this.handleChange(originalState); } /** * Handle initialization of element */ ngAfterViewInit() { this.initializeReferences(); } initializeReferences() { this.updateAlignmentClass(this._align); // Initialize html references since they will not change and are required for popover components this.popoverContentRef = this.elementRef.nativeElement.querySelector(".cds--popover-content"); this.caretRef = this.elementRef.nativeElement.querySelector("span.cds--popover-caret"); // Handle initial isOpen this.handleChange(this.isOpen); } /** * Clean up */ ngOnDestroy() { this.cleanUp(); } /** * Clean up `autoUpdate` if auto alignment is enabled */ cleanUp() { if (this.unmountFloatingElement) { this.unmountFloatingElement(); } this.unmountFloatingElement = undefined; } /** * Replace existing previous alignment class with new * @param previousAlignment */ updateAlignmentClass(newAlignment, previousAlignment) { if (this.elementRef.nativeElement && previousAlignment !== newAlignment) { const regexp = new RegExp("right|top|left|bottom"); // Since we are constantly switching, it's safer to delete all matching class names this.elementRef.nativeElement.classList.forEach(className => { if (regexp.test(className)) { this.renderer.removeClass(this.elementRef.nativeElement, `${className}`); } }); this.renderer.addClass(this.elementRef.nativeElement, `${this.alignmentClassPrefix}${newAlignment}`); } } } PopoverContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PopoverContainer, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); PopoverContainer.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: PopoverContainer, selector: "[cdsPopover], [ibmPopover]", inputs: { align: "align", caret: "caret", dropShadow: "dropShadow", highContrast: "highContrast", autoAlign: "autoAlign", isOpen: "isOpen" }, outputs: { onClose: "onClose", onOpen: "onOpen", isOpenChange: "isOpenChange" }, host: { properties: { "class.cds--popover--caret": "this.caret", "class.cds--popover--drop-shadow": "this.dropShadow", "class.cds--popover--high-contrast": "this.highContrast", "class.cds--popover--auto-align": "this.autoAlign", "class.cds--popover-container": "this.containerClass", "class.cds--popover--open": "this.isOpen" } }, usesOnChanges: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PopoverContainer, decorators: [{ type: Directive, args: [{ selector: "[cdsPopover], [ibmPopover]" }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { align: [{ type: Input }], onClose: [{ type: Output }], onOpen: [{ type: Output }], isOpenChange: [{ type: Output }], caret: [{ type: HostBinding, args: ["class.cds--popover--caret"] }, { type: Input }], dropShadow: [{ type: HostBinding, args: ["class.cds--popover--drop-shadow"] }, { type: Input }], highContrast: [{ type: HostBinding, args: ["class.cds--popover--high-contrast"] }, { type: Input }], autoAlign: [{ type: HostBinding, args: ["class.cds--popover--auto-align"] }, { type: Input }], containerClass: [{ type: HostBinding, args: ["class.cds--popover-container"] }], isOpen: [{ type: Input }, { type: HostBinding, args: ["class.cds--popover--open"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wb3Zlci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcG9wb3Zlci9wb3BvdmVyLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR04sU0FBUyxFQUVULFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUlMLE1BQU0sRUFHTixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQ04sS0FBSyxFQUNMLFVBQVUsRUFDVixlQUFlLEVBQ2YsSUFBSSxFQUNKLE1BQU0sRUFFTixNQUFNLGtCQUFrQixDQUFDOztBQWUxQixNQUFNLE9BQU8sZ0JBQWdCO0lBdUY1QixZQUNXLFVBQXNCLEVBQ3RCLE1BQWMsRUFDZCxRQUFtQixFQUNuQixpQkFBb0M7UUFIcEMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0QixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2QsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBN0MvQyxXQUFNLEdBQWMsUUFBUSxDQUFDO1FBQ3BCLHlCQUFvQixHQUFHLGdCQUFnQixDQUFDO1FBRWpEOztXQUVHO1FBQ08sWUFBTyxHQUF3QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzVEOztXQUVHO1FBQ08sV0FBTSxHQUF3QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzNEOztXQUVHO1FBQ08saUJBQVksR0FBRyxJQUFJLFlBQVksRUFBVyxDQUFDO1FBQ3JEOztXQUVHO1FBQ2dELFVBQUssR0FBRyxJQUFJLENBQUM7UUFDaEU7O1dBRUc7UUFDc0QsZUFBVSxHQUFHLElBQUksQ0FBQztRQUMzRTs7V0FFRztRQUN3RCxpQkFBWSxHQUFHLEtBQUssQ0FBQztRQUNoRjs7O1dBR0c7UUFDcUQsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUM3QixtQkFBYyxHQUFHLElBQUksQ0FBQztRQUNqQixXQUFNLEdBQUcsS0FBSyxDQUFDO0lBYTlE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RixJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUMzRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQzNCLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLEdBQUcsU0FBUyxFQUFFLENBQUMsQ0FBQztpQkFDekU7WUFDRixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixHQUFHLFlBQVksRUFBRSxDQUFDLENBQUM7U0FDckc7SUFDRixDQUFDOzs2R0E3UVcsZ0JBQWdCO2lHQUFoQixnQkFBZ0I7MkZBQWhCLGdCQUFnQjtrQkFINUIsU0FBUzttQkFBQztvQkFDVixRQUFRLEVBQUUsNEJBQTRCO2lCQUN0Qzs4S0FRYSxLQUFLO3NCQUFqQixLQUFLO2dCQTZDSSxPQUFPO3NCQUFoQixNQUFNO2dCQUlHLE1BQU07c0JBQWYsTUFBTTtnQkFJRyxZQUFZO3NCQUFyQixNQUFNO2dCQUk0QyxLQUFLO3NCQUF2RCxXQUFXO3VCQUFDLDJCQUEyQjs7c0JBQUcsS0FBSztnQkFJUyxVQUFVO3NCQUFsRSxXQUFXO3VCQUFDLGlDQUFpQzs7c0JBQUcsS0FBSztnQkFJSyxZQUFZO3NCQUF0RSxXQUFXO3VCQUFDLG1DQUFtQzs7c0JBQUcsS0FBSztnQkFLQSxTQUFTO3NCQUFoRSxXQUFXO3VCQUFDLGdDQUFnQzs7c0JBQUcsS0FBSztnQkFDUixjQUFjO3NCQUExRCxXQUFXO3VCQUFDLDhCQUE4QjtnQkFDTyxNQUFNO3NCQUF2RCxLQUFLOztzQkFBSSxXQUFXO3VCQUFDLDBCQUEwQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdEFmdGVyVmlld0luaXQsXG5cdENoYW5nZURldGVjdG9yUmVmLFxuXHREaXJlY3RpdmUsXG5cdEVsZW1lbnRSZWYsXG5cdEV2ZW50RW1pdHRlcixcblx0SG9zdEJpbmRpbmcsXG5cdElucHV0LFxuXHROZ1pvbmUsXG5cdE9uQ2hhbmdlcyxcblx0T25EZXN0cm95LFxuXHRPdXRwdXQsXG5cdFJlbmRlcmVyMixcblx0U2ltcGxlQ2hhbmdlc1xufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHtcblx0YXJyb3csXG5cdGF1dG9VcGRhdGUsXG5cdGNvbXB1dGVQb3NpdGlvbixcblx0ZmxpcCxcblx0b2Zmc2V0LFxuXHRQbGFjZW1lbnRcbn0gZnJvbSBcIkBmbG9hdGluZy11aS9kb21cIjtcblxuLy8gRGVwcmVjYXRlZCBwb3BvdmVyIGFsaWdubWVudHNcbnR5cGUgb2xkUGxhY2VtZW50ID0gXCJ0b3AtbGVmdFwiXG5cdHwgXCJ0b3AtcmlnaHRcIlxuXHR8IFwiYm90dG9tLWxlZnRcIlxuXHR8IFwiYm90dG9tLXJpZ2h0XCJcblx0fCBcImxlZnQtYm90dG9tXCJcblx0fCBcImxlZnQtdG9wXCJcblx0fCBcInJpZ2h0LWJvdHRvbVwiXG5cdHwgXCJyaWdodC10b3BcIjtcblxuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiBcIltjZHNQb3BvdmVyXSwgW2libVBvcG92ZXJdXCJcbn0pXG5leHBvcnQgY2xhc3MgUG9wb3ZlckNvbnRhaW5lciBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblx0LyoqXG5cdCAqIFNldCBhbGlnbm1lbnQgb2YgcG9wb3ZlclxuXHQgKiBBcyBvZiB2NSwgYG9sZFBsYWNlbWVudHNgIGFyZSBub3cgZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBQbGFjZW1lbnRzXG5cdCAqXG5cdCAqIFdoZW4gYGF1dG9BbGlnbmAgaXMgc2V0IHRvIGB0cnVlYCwgYWxpZ25tZW50IG1heSBjaGFuZ2UgZm9yIGJlc3QgcGxhY2VtZW50XG5cdCAqL1xuXHRASW5wdXQoKSBzZXQgYWxpZ24oYWxpZ25tZW50OiBvbGRQbGFjZW1lbnQgfCBQbGFjZW1lbnQpIHtcblx0XHQvLyBJZiBhbGlnbm1lbnQgaXMgbm90IHBhc3NlZCwgdGhlIGRlZmF1bHQgdmFsdWUgd2lsbCBiZSBgdW5kZWZpbmVkYC5cblx0XHRpZiAoIWFsaWdubWVudCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IHByZXZpb3VzQWxpZ25tZW50ID0gdGhpcy5fYWxpZ247XG5cdFx0c3dpdGNoIChhbGlnbm1lbnQpIHtcblx0XHRcdGNhc2UgXCJ0b3AtbGVmdFwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwidG9wLXN0YXJ0XCI7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcInRvcC1yaWdodFwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwidG9wLWVuZFwiO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJib3R0b20tbGVmdFwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwiYm90dG9tLXN0YXJ0XCI7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcImJvdHRvbS1yaWdodFwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwiYm90dG9tLWVuZFwiO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJsZWZ0LXRvcFwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwibGVmdC1zdGFydFwiO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJsZWZ0LWJvdHRvbVwiOlxuXHRcdFx0XHR0aGlzLl9hbGlnbiA9IFwibGVmdC1lbmRcIjtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwicmlnaHQtdG9wXCI6XG5cdFx0XHRcdHRoaXMuX2FsaWduID0gXCJyaWdodC1zdGFydFwiO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJyaWdodC1ib3R0b21cIjpcblx0XHRcdFx0dGhpcy5fYWxpZ24gPSBcInJpZ2h0LWVuZFwiO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHRoaXMuX2FsaWduID0gYWxpZ25tZW50IGFzIFBsYWNlbWVudDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHRcdHRoaXMudXBkYXRlQWxpZ25tZW50Q2xhc3ModGhpcy5fYWxpZ24sIHByZXZpb3VzQWxpZ25tZW50KTtcblx0fVxuXG5cdF9hbGlnbjogUGxhY2VtZW50ID0gXCJib3R0b21cIjtcblx0cmVhZG9ubHkgYWxpZ25tZW50Q2xhc3NQcmVmaXggPSBcImNkcy0tcG9wb3Zlci0tXCI7XG5cblx0LyoqXG5cdCAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIGRpYWxvZyBpcyBjbG9zZWRcblx0ICovXG5cdEBPdXRwdXQoKSBvbkNsb3NlOiBFdmVudEVtaXR0ZXI8RXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXHQvKipcblx0ICogRW1pdHMgYW4gZXZlbnQgd2hlbiB0aGUgZGlhbG9nIGlzIG9wZW5lZFxuXHQgKi9cblx0QE91dHB1dCgpIG9uT3BlbjogRXZlbnRFbWl0dGVyPEV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblx0LyoqXG5cdCAqIEVtaXRzIGFuIGV2ZW50IHdoZW4gdGhlIHN0YXRlIG9mIGBpc09wZW5gIGNoYW5nZXMuIEFsbG93cyBgaXNPcGVuYCB0byBiZSBkb3VibGUgYm91bmRcblx0ICovXG5cdEBPdXRwdXQoKSBpc09wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cdC8qKlxuXHQgKiBTaG93IGNhcmV0IGF0IHRoZSBhbGlnbm1lbnQgcG9zaXRpb25cblx0ICovXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tcG9wb3Zlci0tY2FyZXRcIikgQElucHV0KCkgY2FyZXQgPSB0cnVlO1xuXHQvKipcblx0ICogRW5hYmxlIGRyb3Agc2hhZG93IGFyb3VuZCB0aGUgcG9wb3ZlciBjb250YWluZXJcblx0ICovXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tcG9wb3Zlci0tZHJvcC1zaGFkb3dcIikgQElucHV0KCkgZHJvcFNoYWRvdyA9IHRydWU7XG5cdC8qKlxuXHQgKiBFbmFibGUgaGlnaCBjb250cmFzdCBmb3IgcG9wb3ZlciBjb250YWluZXJcblx0ICovXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tcG9wb3Zlci0taGlnaC1jb250cmFzdFwiKSBASW5wdXQoKSBoaWdoQ29udHJhc3QgPSBmYWxzZTtcblx0LyoqXG5cdCAqICoqRXhwZXJpbWVudGFsKio6IFVzZSBmbG9hdGluZy11aSB0byBwb3NpdGlvbiB0aGUgdG9vbHRpcFxuXHQgKiBUaGlzIGlzIG5vdCB0b2dnbGVhYmxlIC0gc2hvdWxkIGJlIGFzc2lnbmVkIG9uY2Vcblx0ICovXG5cdEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tcG9wb3Zlci0tYXV0by1hbGlnblwiKSBASW5wdXQoKSBhdXRvQWxpZ24gPSBmYWxzZTtcblx0QEhvc3RCaW5kaW5nKFwiY2xhc3MuY2RzLS1wb3BvdmVyLWNvbnRhaW5lclwiKSBjb250YWluZXJDbGFzcyA9IHRydWU7XG5cdEBJbnB1dCgpIEBIb3N0QmluZGluZyhcImNsYXNzLmNkcy0tcG9wb3Zlci0tb3BlblwiKSBpc09wZW4gPSBmYWxzZTtcblxuXHRwcm90ZWN0ZWQgcG9wb3ZlckNvbnRlbnRSZWY6IEhUTUxFbGVtZW50O1xuXHRwcm90ZWN0ZWQgY2FyZXRSZWY6IEhUTUxFbGVtZW50O1xuXHRwcm90ZWN0ZWQgY2FyZXRPZmZzZXQ6IG51bWJlcjtcblx0cHJvdGVjdGVkIGNhcmV0SGVpZ2h0OiBudW1iZXI7XG5cdHByb3RlY3RlZCB1bm1vdW50RmxvYXRpbmdFbGVtZW50OiBGdW5jdGlvbjtcblxuXHRjb25zdHJ1Y3Rvcihcblx0XHRwcm90ZWN0ZWQgZWxlbWVudFJlZjogRWxlbWVudFJlZixcblx0XHRwcm90ZWN0ZWQgbmdab25lOiBOZ1pvbmUsXG5cdFx0cHJvdGVjdGVkIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG5cdFx0cHJvdGVjdGVkIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxuXHQpIHt9XG5cblx0LyoqXG5cdCAqIEhhbmRsZXMgZW1pdHRpbmcgb3Blbi9jbG9zZSBldmVudFxuXHQgKiBAcGFyYW0gb3BlbiAtIElzIHRoZSBwb3BvdmVyIGNvbnRhaW5lciBvcGVuXG5cdCAqIEBwYXJhbSBldmVudCAtIEV2ZW50XG5cdCAqL1xuXHRoYW5kbGVDaGFuZ2Uob3BlbjogYm9vbGVhbiwgZXZlbnQ/OiBFdmVudCkge1xuXHRcdC8vIFdlIG9ubHkgZW1pdCB0aGUgZXZlbnQgd2hlbiBwYXJhbWV0ZXIgaGFzIGFuIGV2ZW50IHRvIGtlZXAgZXhpc3RpbmcgYmVoYXZpb3Jcblx0XHRpZiAoKHRoaXMuaXNPcGVuICE9PSBvcGVuKSAmJiBldmVudCkge1xuXHRcdFx0dGhpcy5pc09wZW5DaGFuZ2UuZW1pdChvcGVuKTtcblx0XHR9XG5cblx0XHRpZiAob3Blbikge1xuXHRcdFx0aWYgKGV2ZW50KSB7XG5cdFx0XHRcdHRoaXMub25PcGVuLmVtaXQoZXZlbnQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB3aGVuIGF1dG8gYWxpZ25tZW50IGlzIGVuYWJsZWQsIHVzZSBhdXRvIHVwZGF0ZSB0byBzZXQgdGhlIHBsYWNlbWVudCBmb3IgdGhlIGVsZW1lbnRcblx0XHRcdGlmICh0aGlzLmF1dG9BbGlnbikge1xuXHRcdFx0XHRpZiAodGhpcy5jYXJldFJlZikge1xuXHRcdFx0XHRcdC8vIEdldCBjYXJldCBvZmZzZXQvaGVpZ2h0IHByb3BlcnR5XG5cdFx0XHRcdFx0Ly8gR2V0dGluZyBjb21wdXRlZCBzdHlsZXMgb25jZSBldmVyeSBvcGVuLCBvdGhlcndpc2UgZXhwZW5zaXZlLlxuXHRcdFx0XHRcdGNvbnN0IGNvbXB1dGVkU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKHRoaXMuY2FyZXRSZWYpO1xuXHRcdFx0XHRcdGNvbnN0IG9mZnNldCA9IGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY2RzLXBvcG92ZXItb2Zmc2V0XCIpO1xuXHRcdFx0XHRcdGNvbnN0IGhlaWdodCA9IGNvbXB1dGVkU3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY2RzLXBvcG92ZXItY2FyZXQtaGVpZ2h0XCIpO1xuXHRcdFx0XHRcdHRoaXMuY2FyZXRPZmZzZXQgPSAob2Zmc2V0Py5pbmNsdWRlcyhcInB4XCIpID8gTnVtYmVyKG9mZnNldC5zcGxpdChcInB4XCIsIDEpWzBdKSA6IE51bWJlcihvZmZzZXQuc3BsaXQoXCJyZW1cIiwgMSlbMF0pICogMTYpIHx8IDEwO1xuXHRcdFx0XHRcdHRoaXMuY2FyZXRIZWlnaHQgPSAoaGVpZ2h0Py5pbmNsdWRlcyhcInB4XCIpID8gTnVtYmVyKGhlaWdodC5zcGxpdChcInB4XCIsIDEpWzBdKSA6IE51bWJlcihoZWlnaHQuc3BsaXQoXCJyZW1cIiwgMSlbMF0pICogMTYpIHx8IDY7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50ICYmIHRoaXMucG9wb3ZlckNvbnRlbnRSZWYpIHtcblx0XHRcdFx0XHR0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQgPSBhdXRvVXBkYXRlKFxuXHRcdFx0XHRcdFx0dGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHRcdFx0XHR0aGlzLnBvcG92ZXJDb250ZW50UmVmLFxuXHRcdFx0XHRcdFx0dGhpcy5yZWNvbXB1dGVQb3NpdGlvbi5iaW5kKHRoaXMpXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLmNsZWFuVXAoKTtcblx0XHRcdGlmIChldmVudCkge1xuXHRcdFx0XHR0aGlzLm9uQ2xvc2UuZW1pdChldmVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHRoaXMuaXNPcGVuID0gb3Blbjtcblx0XHR0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuXHR9XG5cblx0cm91bmRCeURQUih2YWx1ZSkge1xuXHRcdGNvbnN0IGRwciA9IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIHx8IDE7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQodmFsdWUgKiBkcHIpIC8gZHByO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbXB1dGUgcG9zaXRpb24gb2YgdG9vbHRpcCB3aGVuIGF1dG9BbGlnbiBpcyBlbmFibGVkXG5cdCAqL1xuXHRyZWNvbXB1dGVQb3NpdGlvbigpIHtcblx0XHQvLyBSdW4gb3V0c2lkZSBvZiBhbmd1bGFyIHpvbmUgdG8gYXZvaWQgdW5uZWNlc3NhcnkgY2hhbmdlIGRldGVjdGlvbiBhbmQgcmVseSBvbiBmbG9hdGluZy11aVxuXHRcdHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKGFzeW5jICgpID0+IHtcblx0XHRcdGNvbnN0IHsgeCwgeSwgcGxhY2VtZW50LCBtaWRkbGV3YXJlRGF0YSB9ID0gYXdhaXQgY29tcHV0ZVBvc2l0aW9uKFxuXHRcdFx0XHR0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcblx0XHRcdFx0dGhpcy5wb3BvdmVyQ29udGVudFJlZixcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHBsYWNlbWVudDogdGhpcy5fYWxpZ24sXG5cdFx0XHRcdFx0c3RyYXRlZ3k6IFwiZml4ZWRcIixcblx0XHRcdFx0XHRtaWRkbGV3YXJlOiBbXG5cdFx0XHRcdFx0XHRvZmZzZXQodGhpcy5jYXJldE9mZnNldCksXG5cdFx0XHRcdFx0XHRmbGlwKHsgZmFsbGJhY2tBeGlzU2lkZURpcmVjdGlvbjogXCJzdGFydFwiIH0pLFxuXHRcdFx0XHRcdFx0YXJyb3coeyBlbGVtZW50OiB0aGlzLmNhcmV0UmVmIH0pXG5cdFx0XHRcdFx0XVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0Y29uc3QgcHJldmlvdXNBbGlnbm1lbnQgPSB0aGlzLl9hbGlnbjtcblx0XHRcdHRoaXMuX2FsaWduID0gcGxhY2VtZW50O1xuXHRcdFx0dGhpcy51cGRhdGVBbGlnbm1lbnRDbGFzcyh0aGlzLl9hbGlnbiwgcHJldmlvdXNBbGlnbm1lbnQpO1xuXG5cdFx0XHQvLyBVc2luZyBDU1NPTSB0byBtYW5pcHVsYXRlIENTUyB0byBhdm9pZCBjb250ZW50IHNlY3VyaXR5IHBvbGljeSBpbmxpbmUtc3JjXG5cdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vdzNjL3dlYmFwcHNlYy1jc3AvaXNzdWVzLzIxMlxuXHRcdFx0T2JqZWN0LmFzc2lnbih0aGlzLnBvcG92ZXJDb250ZW50UmVmLnN0eWxlLCB7XG5cdFx0XHRcdHBvc2l0aW9uOiBcImZpeGVkXCIsXG5cdFx0XHRcdHRvcDogXCIwXCIsXG5cdFx0XHRcdGxlZnQ6IFwiMFwiLFxuXHRcdFx0XHQvLyBVc2luZyB0cmFuc2Zvcm0gaW5zdGVhZCBvZiB0b3AvbGVmdCBwb3NpdGlvbiB0byBpbXByb3ZlIHBlcmZvcm1hbmNlXG5cdFx0XHRcdHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke3RoaXMucm91bmRCeURQUih4KX1weCwke3RoaXMucm91bmRCeURQUih5KX1weClgXG5cdFx0XHR9KTtcblxuXHRcdFx0aWYgKG1pZGRsZXdhcmVEYXRhLmFycm93KSB7XG5cdFx0XHRcdGNvbnN0IHsgeDogYXJyb3dYLCB5OiBhcnJvd1kgfSA9IG1pZGRsZXdhcmVEYXRhLmFycm93O1xuXG5cdFx0XHRcdGNvbnN0IHN0YXRpY1NpZGUgPSB7XG5cdFx0XHRcdFx0dG9wOiBcImJvdHRvbVwiLFxuXHRcdFx0XHRcdHJpZ2h0OiBcImxlZnRcIixcblx0XHRcdFx0XHRib3R0b206IFwidG9wXCIsXG5cdFx0XHRcdFx0bGVmdDogXCJyaWdodFwiXG5cdFx0XHRcdH1bcGxhY2VtZW50LnNwbGl0KFwiLVwiKVswXV07XG5cblx0XHRcdFx0dGhpcy5jYXJldFJlZi5zdHlsZS5sZWZ0ID0gYXJyb3dYICE9IG51bGwgPyBgJHthcnJvd1h9cHhgIDogXCJcIjtcblx0XHRcdFx0dGhpcy5jYXJldFJlZi5zdHlsZS50b3AgPSBhcnJvd1kgIT0gbnVsbCA/IGAke2Fycm93WX1weGAgOiBcIlwiO1xuXHRcdFx0XHR0aGlzLmNhcmV0UmVmLnN0eWxlLnJpZ2h0ID0gXCJcIjtcblx0XHRcdFx0dGhpcy5jYXJldFJlZi5zdHlsZS5ib3R0b20gPSBcIlwiO1xuXG5cdFx0XHRcdGlmIChzdGF0aWNTaWRlKSB7XG5cdFx0XHRcdFx0dGhpcy5jYXJldFJlZi5zdHlsZVtzdGF0aWNTaWRlXSA9IGAkey10aGlzLmNhcmV0SGVpZ2h0fXB4YDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsb3NlIHRoZSBwb3BvdmVyIGFuZCByZW9wZW4gaXQgd2l0aCB1cGRhdGVkIHZhbHVlcyB3aXRob3V0IGVtaXR0aW5nIGFuIGV2ZW50XG5cdCAqIEBwYXJhbSBjaGFuZ2VzXG5cdCAqL1xuXHRuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG5cdFx0Ly8gQ2xvc2UgYW5kIHJlb3BlbiB0aGUgcG9wb3ZlciwgaGFuZGxlIGFsaWdubWVudC9wcm9ncmFtbWF0aWMgb3Blbi9jbG9zZVxuXHRcdGNvbnN0IG9yaWdpbmFsU3RhdGUgPSB0aGlzLmlzT3Blbjtcblx0XHR0aGlzLmhhbmRsZUNoYW5nZShmYWxzZSk7XG5cblx0XHQvLyBJZ25vcmUgZmlyc3QgY2hhbmdlIHNpbmNlIGNvbnRlbnQgaXMgbm90IGluaXRpYWxpemVkXG5cdFx0aWYgKGNoYW5nZXMuYXV0b0FsaWduICYmICFjaGFuZ2VzLmF1dG9BbGlnbi5maXJzdENoYW5nZSkge1xuXHRcdFx0Ly8gUmVzZXQgdGhlIGlubGluZSBzdHlsZXNcblx0XHRcdHRoaXMucG9wb3ZlckNvbnRlbnRSZWYgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiLmNkcy0tcG9wb3Zlci1jb250ZW50XCIpO1xuXHRcdFx0dGhpcy5wb3BvdmVyQ29udGVudFJlZi5zZXRBdHRyaWJ1dGUoXCJzdHlsZVwiLCBcIlwiKTtcblx0XHRcdHRoaXMuY2FyZXRSZWYgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwic3Bhbi5jZHMtLXBvcG92ZXItY2FyZXRcIik7XG5cdFx0fVxuXG5cdFx0dGhpcy5oYW5kbGVDaGFuZ2Uob3JpZ2luYWxTdGF0ZSk7XG5cdH1cblxuXHQvKipcblx0ICogSGFuZGxlIGluaXRpYWxpemF0aW9uIG9mIGVsZW1lbnRcblx0ICovXG5cdG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcblx0XHR0aGlzLmluaXRpYWxpemVSZWZlcmVuY2VzKCk7XG5cdH1cblxuXHRpbml0aWFsaXplUmVmZXJlbmNlcygpOiB2b2lkIHtcblx0XHR0aGlzLnVwZGF0ZUFsaWdubWVudENsYXNzKHRoaXMuX2FsaWduKTtcblxuXHRcdC8vIEluaXRpYWxpemUgaHRtbCByZWZlcmVuY2VzIHNpbmNlIHRoZXkgd2lsbCBub3QgY2hhbmdlIGFuZCBhcmUgcmVxdWlyZWQgZm9yIHBvcG92ZXIgY29tcG9uZW50c1xuXHRcdHRoaXMucG9wb3ZlckNvbnRlbnRSZWYgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwiLmNkcy0tcG9wb3Zlci1jb250ZW50XCIpO1xuXHRcdHRoaXMuY2FyZXRSZWYgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKFwic3Bhbi5jZHMtLXBvcG92ZXItY2FyZXRcIik7XG5cblx0XHQvLyBIYW5kbGUgaW5pdGlhbCBpc09wZW5cblx0XHR0aGlzLmhhbmRsZUNoYW5nZSh0aGlzLmlzT3Blbik7XG5cdH1cblxuXHQvKipcblx0ICogQ2xlYW4gdXBcblx0ICovXG5cdG5nT25EZXN0cm95KCk6IHZvaWQge1xuXHRcdHRoaXMuY2xlYW5VcCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENsZWFuIHVwIGBhdXRvVXBkYXRlYCBpZiBhdXRvIGFsaWdubWVudCBpcyBlbmFibGVkXG5cdCAqL1xuXHRjbGVhblVwKCkge1xuXHRcdGlmICh0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQpIHtcblx0XHRcdHRoaXMudW5tb3VudEZsb2F0aW5nRWxlbWVudCgpO1xuXHRcdH1cblx0XHR0aGlzLnVubW91bnRGbG9hdGluZ0VsZW1lbnQgPSB1bmRlZmluZWQ7XG5cdH1cblxuXHQvKipcblx0ICogUmVwbGFjZSBleGlzdGluZyBwcmV2aW91cyBhbGlnbm1lbnQgY2xhc3Mgd2l0aCBuZXdcblx0ICogQHBhcmFtIHByZXZpb3VzQWxpZ25tZW50XG5cdCAqL1xuXHR1cGRhdGVBbGlnbm1lbnRDbGFzcyhuZXdBbGlnbm1lbnQ6IHN0cmluZywgcHJldmlvdXNBbGlnbm1lbnQ/OiBzdHJpbmcpIHtcblx0XHRpZiAodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgJiYgcHJldmlvdXNBbGlnbm1lbnQgIT09IG5ld0FsaWdubWVudCkge1xuXHRcdFx0Y29uc3QgcmVnZXhwID0gbmV3IFJlZ0V4cChcInJpZ2h0fHRvcHxsZWZ0fGJvdHRvbVwiKTtcblx0XHRcdC8vIFNpbmNlIHdlIGFyZSBjb25zdGFudGx5IHN3aXRjaGluZywgaXQncyBzYWZlciB0byBkZWxldGUgYWxsIG1hdGNoaW5nIGNsYXNzIG5hbWVzXG5cdFx0XHR0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jbGFzc0xpc3QuZm9yRWFjaChjbGFzc05hbWUgPT4ge1xuXHRcdFx0XHRpZiAocmVnZXhwLnRlc3QoY2xhc3NOYW1lKSkge1xuXHRcdFx0XHRcdHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3ModGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsIGAke2NsYXNzTmFtZX1gKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0XHR0aGlzLnJlbmRlcmVyLmFkZENsYXNzKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCBgJHt0aGlzLmFsaWdubWVudENsYXNzUHJlZml4fSR7bmV3QWxpZ25tZW50fWApO1xuXHRcdH1cblx0fVxufVxuIl19