UNPKG

@nova-ui/charts

Version:

Nova Charts is a library created to provide potential consumers with solutions for various data visualizations that conform with the Nova Design Language. It's designed to solve common patterns identified by UX designers, but also be very flexible so that

90 lines 16.3 kB
// © 2022 SolarWinds Worldwide, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, Output, TemplateRef, ViewChild, } from "@angular/core"; import { Subject } from "rxjs"; import { takeUntil } from "rxjs/operators"; import { PopoverComponent } from "@nova-ui/bits"; import { ChartPopoverPlugin } from "../core/plugins/chart-popover-plugin"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@nova-ui/bits"; export class ChartPopoverComponent { changeDetector; element; plugin; template; update = new EventEmitter(); popover; destroy$ = new Subject(); initPlugin$ = new Subject(); constructor(changeDetector, element) { this.changeDetector = changeDetector; this.element = element; } ngOnChanges(changes) { if (changes.plugin && !changes.plugin.isFirstChange()) { this.initPlugin(); } } ngOnInit() { this.initPlugin(); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); this.initPlugin$.complete(); } initPlugin() { this.initPlugin$.next(); this.plugin?.openPopoverSubject .pipe(takeUntil(this.initPlugin$), takeUntil(this.destroy$)) .subscribe(() => { this.changeDetector.markForCheck(); }); this.plugin?.updatePositionSubject .pipe(takeUntil(this.initPlugin$), takeUntil(this.destroy$)) .subscribe((position) => { this.popover?.resetSize(); // calculating a width offset to position the popover's host element at the midpoint of the popover target const widthOffset = position.width / 2; this.element.nativeElement.style.left = position.left + widthOffset + "px"; this.element.nativeElement.style.top = position.top + "px"; this.popover?.updatePosition(); this.update.next(this.plugin?.dataPoints); }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChartPopoverComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ChartPopoverComponent, selector: "nui-chart-popover", inputs: { plugin: "plugin", template: "template" }, outputs: { update: "update" }, viewQueries: [{ propertyName: "popover", first: true, predicate: PopoverComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"plugin && plugin.dataPoints\">\n <nui-popover\n class=\"chart-popover__popover\"\n trigger=\"openPopoverSubject\"\n placement=\"top\"\n [unlimited]=\"true\"\n [template]=\"popoverTemplate\"\n [openPopover]=\"plugin.openPopoverSubject\"\n [closePopover]=\"plugin.closePopoverSubject\"\n [hasPadding]=\"false\"\n [container]=\"element.nativeElement\"\n [style.height.px]=\"plugin.popoverTargetPosition.height\"\n [withGrowAfterOpen]=\"true\"\n >\n </nui-popover>\n\n <ng-template #popoverTemplate>\n <ng-container\n *ngTemplateOutlet=\"\n template;\n context: { dataPoints: plugin.dataPoints }\n \"\n ></ng-container>\n </ng-template>\n</div>\n", styles: [":host{position:absolute}.chart-popover__popover{position:absolute;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.PopoverComponent, selector: "nui-popover", inputs: ["closePopover", "openPopover", "disabled", "trigger", "template", "placement", "popoverTitle", "icon", "modal", "container", "hasPadding", "preventClosing", "unlimited", "delay", "withGrowAfterOpen", "popoverOverlayPosition"], outputs: ["shown", "hidden"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ChartPopoverComponent, decorators: [{ type: Component, args: [{ selector: "nui-chart-popover", template: "<div *ngIf=\"plugin && plugin.dataPoints\">\n <nui-popover\n class=\"chart-popover__popover\"\n trigger=\"openPopoverSubject\"\n placement=\"top\"\n [unlimited]=\"true\"\n [template]=\"popoverTemplate\"\n [openPopover]=\"plugin.openPopoverSubject\"\n [closePopover]=\"plugin.closePopoverSubject\"\n [hasPadding]=\"false\"\n [container]=\"element.nativeElement\"\n [style.height.px]=\"plugin.popoverTargetPosition.height\"\n [withGrowAfterOpen]=\"true\"\n >\n </nui-popover>\n\n <ng-template #popoverTemplate>\n <ng-container\n *ngTemplateOutlet=\"\n template;\n context: { dataPoints: plugin.dataPoints }\n \"\n ></ng-container>\n </ng-template>\n</div>\n", styles: [":host{position:absolute}.chart-popover__popover{position:absolute;pointer-events:none}\n"] }] }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { plugin: [{ type: Input }], template: [{ type: Input }], update: [{ type: Output }], popover: [{ type: ViewChild, args: [PopoverComponent] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnQtcG9wb3Zlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2hhcnQtcG9wb3Zlci9jaGFydC1wb3BvdmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uL3NyYy9jaGFydC1wb3BvdmVyL2NoYXJ0LXBvcG92ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEseURBQXlEO0FBQ3pELEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLDREQUE0RDtBQUM1RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLGlGQUFpRjtBQUNqRiw2RUFBNkU7QUFDN0UsaUJBQWlCO0FBRWpCLE9BQU8sRUFDSCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUlMLE1BQU0sRUFFTixXQUFXLEVBQ1gsU0FBUyxHQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUdqRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQzs7OztBQVExRSxNQUFNLE9BQU8scUJBQXFCO0lBYWxCO0lBQ0Q7SUFiRixNQUFNLENBQXFCO0lBRTNCLFFBQVEsQ0FBbUI7SUFFMUIsTUFBTSxHQUFHLElBQUksWUFBWSxFQUFzQixDQUFDO0lBRTdCLE9BQU8sQ0FBbUI7SUFFdEMsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFDeEMsV0FBVyxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFFMUMsWUFDWSxjQUFpQyxFQUNsQyxPQUFtQjtRQURsQixtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUFDbEMsWUFBTyxHQUFQLE9BQU8sQ0FBWTtJQUMzQixDQUFDO0lBRUcsV0FBVyxDQUFDLE9BQXNCO1FBQ3JDLElBQUksT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLEVBQUU7WUFDbkQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1NBQ3JCO0lBQ0wsQ0FBQztJQUVNLFFBQVE7UUFDWCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVNLFdBQVc7UUFDZCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRU8sVUFBVTtRQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFeEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxrQkFBa0I7YUFDMUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUMzRCxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ1osSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztRQUVQLElBQUksQ0FBQyxNQUFNLEVBQUUscUJBQXFCO2FBQzdCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDM0QsU0FBUyxDQUFDLENBQUMsUUFBMEIsRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLENBQUM7WUFDMUIsMEdBQTBHO1lBQzFHLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJO2dCQUNqQyxRQUFRLENBQUMsSUFBSSxHQUFHLFdBQVcsR0FBRyxJQUFJLENBQUM7WUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxRQUFRLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztZQUMzRCxJQUFJLENBQUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFDWCxDQUFDO3dHQXREUSxxQkFBcUI7NEZBQXJCLHFCQUFxQixxTEFPbkIsZ0JBQWdCLHFFQ3ZEL0IsK3lCQXlCQTs7NEZEdUJhLHFCQUFxQjtrQkFMakMsU0FBUzsrQkFDSSxtQkFBbUI7K0dBS3BCLE1BQU07c0JBQWQsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVJLE1BQU07c0JBQWYsTUFBTTtnQkFFc0IsT0FBTztzQkFBbkMsU0FBUzt1QkFBQyxnQkFBZ0IiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDCqSAyMDIyIFNvbGFyV2luZHMgV29ybGR3aWRlLCBMTEMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvXG4vLyAgZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGVcbi8vICByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vICBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vICBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyAgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHtcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFNpbXBsZUNoYW5nZXMsXG4gICAgVGVtcGxhdGVSZWYsXG4gICAgVmlld0NoaWxkLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgUG9wb3ZlckNvbXBvbmVudCB9IGZyb20gXCJAbm92YS11aS9iaXRzXCI7XG5cbmltcG9ydCB7IElEYXRhUG9pbnRzUGF5bG9hZCB9IGZyb20gXCIuLi9jb3JlL2NvbW1vbi90eXBlc1wiO1xuaW1wb3J0IHsgQ2hhcnRQb3BvdmVyUGx1Z2luIH0gZnJvbSBcIi4uL2NvcmUvcGx1Z2lucy9jaGFydC1wb3BvdmVyLXBsdWdpblwiO1xuaW1wb3J0IHsgSUVsZW1lbnRQb3NpdGlvbiB9IGZyb20gXCIuLi9jb3JlL3BsdWdpbnMvdHlwZXNcIjtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6IFwibnVpLWNoYXJ0LXBvcG92ZXJcIixcbiAgICB0ZW1wbGF0ZVVybDogXCIuL2NoYXJ0LXBvcG92ZXIuY29tcG9uZW50Lmh0bWxcIixcbiAgICBzdHlsZVVybHM6IFtcIi4vY2hhcnQtcG9wb3Zlci5jb21wb25lbnQubGVzc1wiXSxcbn0pXG5leHBvcnQgY2xhc3MgQ2hhcnRQb3BvdmVyQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSB7XG4gICAgQElucHV0KCkgcGx1Z2luOiBDaGFydFBvcG92ZXJQbHVnaW47XG5cbiAgICBASW5wdXQoKSB0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICAgIEBPdXRwdXQoKSB1cGRhdGUgPSBuZXcgRXZlbnRFbWl0dGVyPElEYXRhUG9pbnRzUGF5bG9hZD4oKTtcblxuICAgIEBWaWV3Q2hpbGQoUG9wb3ZlckNvbXBvbmVudCkgcG9wb3ZlcjogUG9wb3ZlckNvbXBvbmVudDtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAgIHByaXZhdGUgaW5pdFBsdWdpbiQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgICBwdWJsaWMgZWxlbWVudDogRWxlbWVudFJlZlxuICAgICkge31cblxuICAgIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGlmIChjaGFuZ2VzLnBsdWdpbiAmJiAhY2hhbmdlcy5wbHVnaW4uaXNGaXJzdENoYW5nZSgpKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRQbHVnaW4oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pbml0UGx1Z2luKCk7XG4gICAgfVxuXG4gICAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcbiAgICAgICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLmluaXRQbHVnaW4kLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpbml0UGx1Z2luKCkge1xuICAgICAgICB0aGlzLmluaXRQbHVnaW4kLm5leHQoKTtcblxuICAgICAgICB0aGlzLnBsdWdpbj8ub3BlblBvcG92ZXJTdWJqZWN0XG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5pbml0UGx1Z2luJCksIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnBsdWdpbj8udXBkYXRlUG9zaXRpb25TdWJqZWN0XG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5pbml0UGx1Z2luJCksIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKHBvc2l0aW9uOiBJRWxlbWVudFBvc2l0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3BvdmVyPy5yZXNldFNpemUoKTtcbiAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGluZyBhIHdpZHRoIG9mZnNldCB0byBwb3NpdGlvbiB0aGUgcG9wb3ZlcidzIGhvc3QgZWxlbWVudCBhdCB0aGUgbWlkcG9pbnQgb2YgdGhlIHBvcG92ZXIgdGFyZ2V0XG4gICAgICAgICAgICAgICAgY29uc3Qgd2lkdGhPZmZzZXQgPSBwb3NpdGlvbi53aWR0aCAvIDI7XG4gICAgICAgICAgICAgICAgdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc3R5bGUubGVmdCA9XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uLmxlZnQgKyB3aWR0aE9mZnNldCArIFwicHhcIjtcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSBwb3NpdGlvbi50b3AgKyBcInB4XCI7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3BvdmVyPy51cGRhdGVQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlLm5leHQodGhpcy5wbHVnaW4/LmRhdGFQb2ludHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxufVxuIiwiPGRpdiAqbmdJZj1cInBsdWdpbiAmJiBwbHVnaW4uZGF0YVBvaW50c1wiPlxuICAgIDxudWktcG9wb3ZlclxuICAgICAgICBjbGFzcz1cImNoYXJ0LXBvcG92ZXJfX3BvcG92ZXJcIlxuICAgICAgICB0cmlnZ2VyPVwib3BlblBvcG92ZXJTdWJqZWN0XCJcbiAgICAgICAgcGxhY2VtZW50PVwidG9wXCJcbiAgICAgICAgW3VubGltaXRlZF09XCJ0cnVlXCJcbiAgICAgICAgW3RlbXBsYXRlXT1cInBvcG92ZXJUZW1wbGF0ZVwiXG4gICAgICAgIFtvcGVuUG9wb3Zlcl09XCJwbHVnaW4ub3BlblBvcG92ZXJTdWJqZWN0XCJcbiAgICAgICAgW2Nsb3NlUG9wb3Zlcl09XCJwbHVnaW4uY2xvc2VQb3BvdmVyU3ViamVjdFwiXG4gICAgICAgIFtoYXNQYWRkaW5nXT1cImZhbHNlXCJcbiAgICAgICAgW2NvbnRhaW5lcl09XCJlbGVtZW50Lm5hdGl2ZUVsZW1lbnRcIlxuICAgICAgICBbc3R5bGUuaGVpZ2h0LnB4XT1cInBsdWdpbi5wb3BvdmVyVGFyZ2V0UG9zaXRpb24uaGVpZ2h0XCJcbiAgICAgICAgW3dpdGhHcm93QWZ0ZXJPcGVuXT1cInRydWVcIlxuICAgID5cbiAgICA8L251aS1wb3BvdmVyPlxuXG4gICAgPG5nLXRlbXBsYXRlICNwb3BvdmVyVGVtcGxhdGU+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICAgICAgdGVtcGxhdGU7XG4gICAgICAgICAgICAgICAgY29udGV4dDogeyBkYXRhUG9pbnRzOiBwbHVnaW4uZGF0YVBvaW50cyB9XG4gICAgICAgICAgICBcIlxuICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbjwvZGl2PlxuIl19