@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
93 lines • 21.9 kB
JavaScript
import { ChangeDetectionStrategy, Component, inject, Input } from '@angular/core';
import { ColorService } from '../../services/color/index';
import * as i0 from "@angular/core";
import * as i1 from "../tooltip/tooltip.directive";
export class SparkComponent {
constructor() {
this._colorService = inject(ColorService);
this.values = [];
this.barHeight = 10;
this._theme = 'primary';
this._barColor = [];
}
set theme(value) {
this._theme = this._colorService.resolveColorName(value);
}
get theme() {
return this._theme;
}
set trackColor(value) {
this._trackColor = this._colorService.resolve(value);
}
get trackColor() {
return this._trackColor;
}
set barColor(value) {
if (Array.isArray(value)) {
this._barColor = value.map(color => this._colorService.resolve(color));
}
else {
this._barColor = [this._colorService.resolve(value)];
}
}
get barColor() {
return this._barColor;
}
set value(value) {
// ensure 'value' is an array at this point
const values = Array.isArray(value) ? value : [value];
// get the total value of all lines
const total = Math.max(values.reduce((previous, current) => previous + current, 0), 100);
// figure out the percentages for each spark line
this.values = values.map(val => (val / total) * 100);
}
get value() {
return this.values;
}
/**
* Get the aria label for the spark chart
*/
getAriaLabel() {
if (!Array.isArray(this.ariaLabel)) {
return this.ariaLabel || this.tooltip;
}
else {
return this.ariaLabel.join(', ');
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SparkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: SparkComponent, selector: "ux-spark", inputs: { barHeight: "barHeight", inlineLabel: "inlineLabel", topLeftLabel: "topLeftLabel", topRightLabel: "topRightLabel", bottomLeftLabel: "bottomLeftLabel", bottomRightLabel: "bottomRightLabel", tooltip: "tooltip", ariaLabel: ["aria-label", "ariaLabel"], ariaDescription: ["aria-description", "ariaDescription"], theme: "theme", trackColor: "trackColor", barColor: "barColor", value: "value" }, ngImport: i0, template: "<!-- Inline Spark Chart -->\n@if (inlineLabel) {\n <div class=\"ux-spark-inline-label-container\">\n <div class=\"ux-spark-inline-label-left\" [innerHtml]=\"inlineLabel\"></div>\n <div class=\"ux-spark-line\">\n @if (topLeftLabel || topRightLabel) {\n <div class=\"ux-spark-top-container\">\n @if (topLeftLabel) {\n <div class=\"ux-spark-label-top-left\" [innerHtml]=\"topLeftLabel\"></div>\n }\n @if (topRightLabel) {\n <div class=\"ux-spark-label-top-right\" [innerHtml]=\"topRightLabel\"></div>\n }\n </div>\n }\n <div role=\"progressbar\"\n [attr.aria-label]=\"getAriaLabel()\"\n [attr.aria-description]=\"ariaDescription\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"values.length === 1 ? values[0] : undefined\"\n class=\"ux-spark ux-inline ux-spark-theme-{{theme}}\"\n [style.height.px]=\"barHeight\"\n [style.backgroundColor]=\"trackColor\"\n [uxTooltip]=\"tooltip\">\n @for (line of values; track line; let idx = $index) {\n <div class=\"ux-spark-bar\"\n [style.width.%]=\"line\"\n [style.backgroundColor]=\"barColor[idx]\">\n </div>\n }\n </div>\n @if (bottomLeftLabel || bottomRightLabel) {\n <div class=\"ux-spark-bottom-container\">\n @if (bottomLeftLabel) {\n <div class=\"ux-spark-label-bottom-left\" [innerHtml]=\"bottomLeftLabel\"></div>\n }\n @if (bottomRightLabel) {\n <div class=\"ux-spark-label-bottom-right\" [innerHtml]=\"bottomRightLabel\"></div>\n }\n </div>\n }\n </div>\n </div>\n}\n\n<!-- End Inline Spark Chart -->\n\n\n<!-- Non Inline Spark Chart -->\n@if (!inlineLabel) {\n <div>\n @if (topLeftLabel || topRightLabel) {\n <div class=\"ux-spark-top-container\">\n @if (topLeftLabel) {\n <div class=\"ux-spark-label-top-left\" [innerHtml]=\"topLeftLabel\"></div>\n }\n @if (topRightLabel) {\n <div class=\"ux-spark-label-top-right\" [innerHtml]=\"topRightLabel\"></div>\n }\n </div>\n }\n <div role=\"progressbar\"\n [attr.aria-label]=\"getAriaLabel()\"\n [attr.aria-description]=\"ariaDescription\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"values.length === 1 ? values[0] : undefined\"\n class=\"ux-spark ux-spark-theme-{{theme}}\"\n [class.ux-spark-multi-value]=\"values.length > 1\"\n [style.height.px]=\"barHeight\"\n [style.backgroundColor]=\"trackColor\"\n [uxTooltip]=\"tooltip\">\n @for (line of values; track line; let idx = $index) {\n <div class=\"ux-spark-bar\"\n [style.width.%]=\"line\"\n [style.backgroundColor]=\"barColor[idx]\">\n </div>\n }\n </div>\n @if (bottomLeftLabel || bottomRightLabel) {\n <div class=\"ux-spark-bottom-container\">\n @if (bottomLeftLabel) {\n <div class=\"ux-spark-label-bottom-left\" [innerHtml]=\"bottomLeftLabel\"></div>\n }\n @if (bottomRightLabel) {\n <div class=\"ux-spark-label-bottom-right\" [innerHtml]=\"bottomRightLabel\"></div>\n }\n </div>\n }\n </div>\n}\n\n<!-- End Non Inline Spark Chart -->\n", dependencies: [{ kind: "directive", type: i1.TooltipDirective, selector: "[uxTooltip]", inputs: ["uxTooltip", "tooltipDisabled", "tooltipClass", "tooltipRole", "tooltipContext", "tooltipDelay", "isOpen", "placement", "fallbackPlacement", "alignment", "showTriggers", "hideTriggers"], outputs: ["shown", "hidden", "isOpenChange"], exportAs: ["ux-tooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SparkComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-spark', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Inline Spark Chart -->\n@if (inlineLabel) {\n <div class=\"ux-spark-inline-label-container\">\n <div class=\"ux-spark-inline-label-left\" [innerHtml]=\"inlineLabel\"></div>\n <div class=\"ux-spark-line\">\n @if (topLeftLabel || topRightLabel) {\n <div class=\"ux-spark-top-container\">\n @if (topLeftLabel) {\n <div class=\"ux-spark-label-top-left\" [innerHtml]=\"topLeftLabel\"></div>\n }\n @if (topRightLabel) {\n <div class=\"ux-spark-label-top-right\" [innerHtml]=\"topRightLabel\"></div>\n }\n </div>\n }\n <div role=\"progressbar\"\n [attr.aria-label]=\"getAriaLabel()\"\n [attr.aria-description]=\"ariaDescription\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"values.length === 1 ? values[0] : undefined\"\n class=\"ux-spark ux-inline ux-spark-theme-{{theme}}\"\n [style.height.px]=\"barHeight\"\n [style.backgroundColor]=\"trackColor\"\n [uxTooltip]=\"tooltip\">\n @for (line of values; track line; let idx = $index) {\n <div class=\"ux-spark-bar\"\n [style.width.%]=\"line\"\n [style.backgroundColor]=\"barColor[idx]\">\n </div>\n }\n </div>\n @if (bottomLeftLabel || bottomRightLabel) {\n <div class=\"ux-spark-bottom-container\">\n @if (bottomLeftLabel) {\n <div class=\"ux-spark-label-bottom-left\" [innerHtml]=\"bottomLeftLabel\"></div>\n }\n @if (bottomRightLabel) {\n <div class=\"ux-spark-label-bottom-right\" [innerHtml]=\"bottomRightLabel\"></div>\n }\n </div>\n }\n </div>\n </div>\n}\n\n<!-- End Inline Spark Chart -->\n\n\n<!-- Non Inline Spark Chart -->\n@if (!inlineLabel) {\n <div>\n @if (topLeftLabel || topRightLabel) {\n <div class=\"ux-spark-top-container\">\n @if (topLeftLabel) {\n <div class=\"ux-spark-label-top-left\" [innerHtml]=\"topLeftLabel\"></div>\n }\n @if (topRightLabel) {\n <div class=\"ux-spark-label-top-right\" [innerHtml]=\"topRightLabel\"></div>\n }\n </div>\n }\n <div role=\"progressbar\"\n [attr.aria-label]=\"getAriaLabel()\"\n [attr.aria-description]=\"ariaDescription\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"values.length === 1 ? values[0] : undefined\"\n class=\"ux-spark ux-spark-theme-{{theme}}\"\n [class.ux-spark-multi-value]=\"values.length > 1\"\n [style.height.px]=\"barHeight\"\n [style.backgroundColor]=\"trackColor\"\n [uxTooltip]=\"tooltip\">\n @for (line of values; track line; let idx = $index) {\n <div class=\"ux-spark-bar\"\n [style.width.%]=\"line\"\n [style.backgroundColor]=\"barColor[idx]\">\n </div>\n }\n </div>\n @if (bottomLeftLabel || bottomRightLabel) {\n <div class=\"ux-spark-bottom-container\">\n @if (bottomLeftLabel) {\n <div class=\"ux-spark-label-bottom-left\" [innerHtml]=\"bottomLeftLabel\"></div>\n }\n @if (bottomRightLabel) {\n <div class=\"ux-spark-label-bottom-right\" [innerHtml]=\"bottomRightLabel\"></div>\n }\n </div>\n }\n </div>\n}\n\n<!-- End Non Inline Spark Chart -->\n" }]
}], propDecorators: { barHeight: [{
type: Input
}], inlineLabel: [{
type: Input
}], topLeftLabel: [{
type: Input
}], topRightLabel: [{
type: Input
}], bottomLeftLabel: [{
type: Input
}], bottomRightLabel: [{
type: Input
}], tooltip: [{
type: Input
}], ariaLabel: [{
type: Input,
args: ['aria-label']
}], ariaDescription: [{
type: Input,
args: ['aria-description']
}], theme: [{
type: Input
}], trackColor: [{
type: Input
}], barColor: [{
type: Input
}], value: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcmsuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bhcmsvc3BhcmsuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bhcmsvc3BhcmsuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xGLE9BQU8sRUFBbUIsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7OztBQU8zRSxNQUFNLE9BQU8sY0FBYztJQUwzQjtRQU1xQixrQkFBYSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV0RCxXQUFNLEdBQWEsRUFBRSxDQUFDO1FBRWIsY0FBUyxHQUFXLEVBQUUsQ0FBQztRQVd4QixXQUFNLEdBQW9CLFNBQVMsQ0FBQztRQUNwQyxjQUFTLEdBQXNCLEVBQUUsQ0FBQztLQTJEN0M7SUF6REcsSUFDSSxLQUFLLENBQUMsS0FBYTtRQUNuQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELElBQUksS0FBSztRQUNMLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQsSUFDSSxVQUFVLENBQUMsS0FBYTtRQUN4QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRCxJQUFJLFVBQVU7UUFDVixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDNUIsQ0FBQztJQUVELElBQ0ksUUFBUSxDQUFDLEtBQXdCO1FBQ2pDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDM0UsQ0FBQzthQUFNLENBQUM7WUFDSixJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDO0lBQ0wsQ0FBQztJQUVELElBQUksUUFBUTtRQUNSLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBRUQsSUFDSSxLQUFLLENBQUMsS0FBd0I7UUFDOUIsMkNBQTJDO1FBQzNDLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV0RCxtQ0FBbUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsUUFBUSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUV6RixpREFBaUQ7UUFDakQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELElBQUksS0FBSztRQUNMLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZO1FBQ1IsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDakMsT0FBTyxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDMUMsQ0FBQzthQUFNLENBQUM7WUFDSixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JDLENBQUM7SUFDTCxDQUFDOytHQTNFUSxjQUFjO21HQUFkLGNBQWMsOGJDUjNCLHN5R0E4RkE7OzRGRHRGYSxjQUFjO2tCQUwxQixTQUFTOytCQUNJLFVBQVUsbUJBRUgsdUJBQXVCLENBQUMsTUFBTTs4QkFPdEMsU0FBUztzQkFBakIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ2UsU0FBUztzQkFBN0IsS0FBSzt1QkFBQyxZQUFZO2dCQUNRLGVBQWU7c0JBQXpDLEtBQUs7dUJBQUMsa0JBQWtCO2dCQU9yQixLQUFLO3NCQURSLEtBQUs7Z0JBVUYsVUFBVTtzQkFEYixLQUFLO2dCQVVGLFFBQVE7c0JBRFgsS0FBSztnQkFjRixLQUFLO3NCQURSLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBpbmplY3QsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb2xvcklkZW50aWZpZXIsIENvbG9yU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NvbG9yL2luZGV4JztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1zcGFyaycsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NwYXJrLmNvbXBvbmVudC5odG1sJyxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgU3BhcmtDb21wb25lbnQge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NvbG9yU2VydmljZSA9IGluamVjdChDb2xvclNlcnZpY2UpO1xuXG4gICAgdmFsdWVzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgQElucHV0KCkgYmFySGVpZ2h0OiBudW1iZXIgPSAxMDtcbiAgICBASW5wdXQoKSBpbmxpbmVMYWJlbDogc3RyaW5nO1xuICAgIEBJbnB1dCgpIHRvcExlZnRMYWJlbDogc3RyaW5nO1xuICAgIEBJbnB1dCgpIHRvcFJpZ2h0TGFiZWw6IHN0cmluZztcbiAgICBASW5wdXQoKSBib3R0b21MZWZ0TGFiZWw6IHN0cmluZztcbiAgICBASW5wdXQoKSBib3R0b21SaWdodExhYmVsOiBzdHJpbmc7XG4gICAgQElucHV0KCkgdG9vbHRpcDogc3RyaW5nO1xuICAgIEBJbnB1dCgnYXJpYS1sYWJlbCcpIGFyaWFMYWJlbDogc3RyaW5nIHwgc3RyaW5nW107XG4gICAgQElucHV0KCdhcmlhLWRlc2NyaXB0aW9uJykgYXJpYURlc2NyaXB0aW9uOiBzdHJpbmc7XG5cbiAgICBwcml2YXRlIF90cmFja0NvbG9yOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBfdGhlbWU6IENvbG9ySWRlbnRpZmllciA9ICdwcmltYXJ5JztcbiAgICBwcml2YXRlIF9iYXJDb2xvcjogc3RyaW5nIHwgc3RyaW5nW10gPSBbXTtcblxuICAgIEBJbnB1dCgpXG4gICAgc2V0IHRoZW1lKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fdGhlbWUgPSB0aGlzLl9jb2xvclNlcnZpY2UucmVzb2x2ZUNvbG9yTmFtZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgZ2V0IHRoZW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl90aGVtZTtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCB0cmFja0NvbG9yKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fdHJhY2tDb2xvciA9IHRoaXMuX2NvbG9yU2VydmljZS5yZXNvbHZlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBnZXQgdHJhY2tDb2xvcigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5fdHJhY2tDb2xvcjtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCBiYXJDb2xvcih2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10pIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLl9iYXJDb2xvciA9IHZhbHVlLm1hcChjb2xvciA9PiB0aGlzLl9jb2xvclNlcnZpY2UucmVzb2x2ZShjb2xvcikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fYmFyQ29sb3IgPSBbdGhpcy5fY29sb3JTZXJ2aWNlLnJlc29sdmUodmFsdWUpXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGdldCBiYXJDb2xvcigpOiBzdHJpbmcgfCBzdHJpbmdbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9iYXJDb2xvcjtcbiAgICB9XG5cbiAgICBASW5wdXQoKVxuICAgIHNldCB2YWx1ZSh2YWx1ZTogbnVtYmVyIHwgbnVtYmVyW10pIHtcbiAgICAgICAgLy8gZW5zdXJlICd2YWx1ZScgaXMgYW4gYXJyYXkgYXQgdGhpcyBwb2ludFxuICAgICAgICBjb25zdCB2YWx1ZXMgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW3ZhbHVlXTtcblxuICAgICAgICAvLyBnZXQgdGhlIHRvdGFsIHZhbHVlIG9mIGFsbCBsaW5lc1xuICAgICAgICBjb25zdCB0b3RhbCA9IE1hdGgubWF4KHZhbHVlcy5yZWR1Y2UoKHByZXZpb3VzLCBjdXJyZW50KSA9PiBwcmV2aW91cyArIGN1cnJlbnQsIDApLCAxMDApO1xuXG4gICAgICAgIC8vIGZpZ3VyZSBvdXQgdGhlIHBlcmNlbnRhZ2VzIGZvciBlYWNoIHNwYXJrIGxpbmVcbiAgICAgICAgdGhpcy52YWx1ZXMgPSB2YWx1ZXMubWFwKHZhbCA9PiAodmFsIC8gdG90YWwpICogMTAwKTtcbiAgICB9XG5cbiAgICBnZXQgdmFsdWUoKTogbnVtYmVyIHwgbnVtYmVyW10ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBhcmlhIGxhYmVsIGZvciB0aGUgc3BhcmsgY2hhcnRcbiAgICAgKi9cbiAgICBnZXRBcmlhTGFiZWwoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuYXJpYUxhYmVsKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXJpYUxhYmVsIHx8IHRoaXMudG9vbHRpcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFyaWFMYWJlbC5qb2luKCcsICcpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiPCEtLSBJbmxpbmUgU3BhcmsgQ2hhcnQgLS0+XG5AaWYgKGlubGluZUxhYmVsKSB7XG4gIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay1pbmxpbmUtbGFiZWwtY29udGFpbmVyXCI+XG4gICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWlubGluZS1sYWJlbC1sZWZ0XCIgW2lubmVySHRtbF09XCJpbmxpbmVMYWJlbFwiPjwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay1saW5lXCI+XG4gICAgICBAaWYgKHRvcExlZnRMYWJlbCB8fCB0b3BSaWdodExhYmVsKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay10b3AtY29udGFpbmVyXCI+XG4gICAgICAgICAgQGlmICh0b3BMZWZ0TGFiZWwpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay1sYWJlbC10b3AtbGVmdFwiIFtpbm5lckh0bWxdPVwidG9wTGVmdExhYmVsXCI+PC9kaXY+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBpZiAodG9wUmlnaHRMYWJlbCkge1xuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWxhYmVsLXRvcC1yaWdodFwiIFtpbm5lckh0bWxdPVwidG9wUmlnaHRMYWJlbFwiPjwvZGl2PlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8ZGl2IHJvbGU9XCJwcm9ncmVzc2JhclwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiZ2V0QXJpYUxhYmVsKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWRlc2NyaXB0aW9uXT1cImFyaWFEZXNjcmlwdGlvblwiXG4gICAgICAgIGFyaWEtdmFsdWVtaW49XCIwXCJcbiAgICAgICAgYXJpYS12YWx1ZW1heD1cIjEwMFwiXG4gICAgICAgIFthdHRyLmFyaWEtdmFsdWVub3ddPVwidmFsdWVzLmxlbmd0aCA9PT0gMSA/IHZhbHVlc1swXSA6IHVuZGVmaW5lZFwiXG4gICAgICAgIGNsYXNzPVwidXgtc3BhcmsgdXgtaW5saW5lIHV4LXNwYXJrLXRoZW1lLXt7dGhlbWV9fVwiXG4gICAgICAgIFtzdHlsZS5oZWlnaHQucHhdPVwiYmFySGVpZ2h0XCJcbiAgICAgICAgW3N0eWxlLmJhY2tncm91bmRDb2xvcl09XCJ0cmFja0NvbG9yXCJcbiAgICAgICAgW3V4VG9vbHRpcF09XCJ0b29sdGlwXCI+XG4gICAgICAgIEBmb3IgKGxpbmUgb2YgdmFsdWVzOyB0cmFjayBsaW5lOyBsZXQgaWR4ID0gJGluZGV4KSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWJhclwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJsaW5lXCJcbiAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kQ29sb3JdPVwiYmFyQ29sb3JbaWR4XVwiPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICAgIEBpZiAoYm90dG9tTGVmdExhYmVsIHx8IGJvdHRvbVJpZ2h0TGFiZWwpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWJvdHRvbS1jb250YWluZXJcIj5cbiAgICAgICAgICBAaWYgKGJvdHRvbUxlZnRMYWJlbCkge1xuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWxhYmVsLWJvdHRvbS1sZWZ0XCIgW2lubmVySHRtbF09XCJib3R0b21MZWZ0TGFiZWxcIj48L2Rpdj5cbiAgICAgICAgICB9XG4gICAgICAgICAgQGlmIChib3R0b21SaWdodExhYmVsKSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwidXgtc3BhcmstbGFiZWwtYm90dG9tLXJpZ2h0XCIgW2lubmVySHRtbF09XCJib3R0b21SaWdodExhYmVsXCI+PC9kaXY+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG59XG5cbjwhLS0gRW5kIElubGluZSBTcGFyayBDaGFydCAtLT5cblxuXG48IS0tIE5vbiBJbmxpbmUgU3BhcmsgQ2hhcnQgLS0+XG5AaWYgKCFpbmxpbmVMYWJlbCkge1xuICA8ZGl2PlxuICAgIEBpZiAodG9wTGVmdExhYmVsIHx8IHRvcFJpZ2h0TGFiZWwpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay10b3AtY29udGFpbmVyXCI+XG4gICAgICAgIEBpZiAodG9wTGVmdExhYmVsKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWxhYmVsLXRvcC1sZWZ0XCIgW2lubmVySHRtbF09XCJ0b3BMZWZ0TGFiZWxcIj48L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKHRvcFJpZ2h0TGFiZWwpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidXgtc3BhcmstbGFiZWwtdG9wLXJpZ2h0XCIgW2lubmVySHRtbF09XCJ0b3BSaWdodExhYmVsXCI+PC9kaXY+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICA8ZGl2IHJvbGU9XCJwcm9ncmVzc2JhclwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImdldEFyaWFMYWJlbCgpXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpcHRpb25dPVwiYXJpYURlc2NyaXB0aW9uXCJcbiAgICAgIGFyaWEtdmFsdWVtaW49XCIwXCJcbiAgICAgIGFyaWEtdmFsdWVtYXg9XCIxMDBcIlxuICAgICAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJ2YWx1ZXMubGVuZ3RoID09PSAxID8gdmFsdWVzWzBdIDogdW5kZWZpbmVkXCJcbiAgICAgIGNsYXNzPVwidXgtc3BhcmsgdXgtc3BhcmstdGhlbWUte3t0aGVtZX19XCJcbiAgICAgIFtjbGFzcy51eC1zcGFyay1tdWx0aS12YWx1ZV09XCJ2YWx1ZXMubGVuZ3RoID4gMVwiXG4gICAgICBbc3R5bGUuaGVpZ2h0LnB4XT1cImJhckhlaWdodFwiXG4gICAgICBbc3R5bGUuYmFja2dyb3VuZENvbG9yXT1cInRyYWNrQ29sb3JcIlxuICAgICAgW3V4VG9vbHRpcF09XCJ0b29sdGlwXCI+XG4gICAgICBAZm9yIChsaW5lIG9mIHZhbHVlczsgdHJhY2sgbGluZTsgbGV0IGlkeCA9ICRpbmRleCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidXgtc3BhcmstYmFyXCJcbiAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJsaW5lXCJcbiAgICAgICAgICBbc3R5bGUuYmFja2dyb3VuZENvbG9yXT1cImJhckNvbG9yW2lkeF1cIj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgQGlmIChib3R0b21MZWZ0TGFiZWwgfHwgYm90dG9tUmlnaHRMYWJlbCkge1xuICAgICAgPGRpdiBjbGFzcz1cInV4LXNwYXJrLWJvdHRvbS1jb250YWluZXJcIj5cbiAgICAgICAgQGlmIChib3R0b21MZWZ0TGFiZWwpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidXgtc3BhcmstbGFiZWwtYm90dG9tLWxlZnRcIiBbaW5uZXJIdG1sXT1cImJvdHRvbUxlZnRMYWJlbFwiPjwvZGl2PlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoYm90dG9tUmlnaHRMYWJlbCkge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ1eC1zcGFyay1sYWJlbC1ib3R0b20tcmlnaHRcIiBbaW5uZXJIdG1sXT1cImJvdHRvbVJpZ2h0TGFiZWxcIj48L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbn1cblxuPCEtLSBFbmQgTm9uIElubGluZSBTcGFyayBDaGFydCAtLT5cbiJdfQ==