ngx-input-color
Version:
Angular color input component and color picker (with HSL, HSV, RGB, CMYK, HEX, alpha, eye-dropper, etc)
182 lines • 35.8 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, Input, Output, } from '@angular/core';
import { ColorFormats } from '../../models/ColorFormats.enum';
import { NgxColor } from '../../utils/color-helper';
import { NG_VALIDATORS, NG_VALUE_ACCESSOR, } from '@angular/forms';
import { ColorInspector } from '../../models/ColorInspector.enum';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
import * as i3 from "../inspectors/picker/picker.component";
import * as i4 from "../inspectors/cmyk/cmyk.component";
import * as i5 from "../inspectors/hsl/hsl.component";
import * as i6 from "../inspectors/rgb/rgb.component";
import * as i7 from "../../pipes/enum-to-array.pipe";
export class NgxInputColorComponent {
set setTheme(val) {
if (!val || val == 'auto') {
this.theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
else {
this.theme = val;
}
}
constructor(cd) {
this.cd = cd;
this.theme = 'auto';
/** Minifi UI */
this.simpleMode = false;
this.outputType = 'HEX';
/**
* default inspectors
* - ColorInspector.Picker
* - ColorInspector.RGB
* - ColorInspector.HSL
*
* @alias defaultInspector
*/
this.defaultInspector = ColorInspector.Picker;
/** Emitted when the color value changes */
this.change = new EventEmitter();
/** @ignore */
this.format = ColorFormats.HSVA;
/** @ignore */
this.isDarkColor = true;
/** @ignore */
this.rgbaColor = 'rgba(0, 0, 0, 1)';
/** @ignore */
this.hexColor = '#000000';
this.outputColor = '';
/** @ignore */
this.name = 'black';
/** @ignore */
this.color = new NgxColor();
/** @ignore */
this.isDisabled = false;
/**@ignore */
this._onChange = (value) => { };
/**@ignore */
this._onTouched = () => { };
/**@ignore */
this._onValidateChange = () => { };
this.isSupportedEyeDrop = 'EyeDropper' in window;
}
/** @ignore */
ngOnInit() {
if (this.theme == 'auto') {
this.theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
}
/** @ignore */
ngOnDestroy() { }
get ColorFormats() {
return ColorFormats;
}
get ColorInspector() {
return ColorInspector;
}
/** @ignore */
registerOnChange(fn) {
this._onChange = fn;
}
/** @ignore */
registerOnTouched(fn) {
this._onTouched = fn;
}
/** @ignore */
setDisabledState(disabled) {
this.isDisabled = disabled;
}
/** @ignore */
registerOnValidatorChange(fn) {
this._onValidateChange = fn;
}
/** @ignore */
validate(control) {
if (this.color && this.color.isValid === false) {
return { invalid: true };
}
return null;
}
/** @ignore */
writeValue(value) {
try {
const c = value ? new NgxColor(value) : new NgxColor('#000');
this.initColor(c);
this._onValidateChange();
}
catch (e) {
const c = new NgxColor('#000'); // مقدار پیشفرض
this.initColor(c);
}
}
/** @ignore */
openEyeDrop() {
if (this.isSupportedEyeDrop) {
let t = new EyeDropper().open();
t.then(async (result) => {
this.hexColor = result.sRGBHex;
this.initColor(new NgxColor(this.hexColor));
this.cd.detectChanges();
});
}
}
/**
* call from directive
/* @ignore
*/
async initColor(c) {
if (!c)
return;
this.color = c;
this.rgbaColor = this.color.toRgbString();
this.hexColor = this.color.toHexString();
this.outputColor = await this.color.getOutputResult(this.outputType);
this.isDarkColor = this.color.isDark();
this.name = await this.color.name();
this.emitChange();
}
/** @ignore */
stopPropagation(ev) {
ev.stopPropagation();
}
/** @ignore */
async emitChange() {
this.outputColor = await this.color.getOutputResult(this.outputType);
this._onChange(this.outputColor);
this.change.emit(this.outputColor);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxInputColorComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NgxInputColorComponent, selector: "ngx-input-color", inputs: { setTheme: ["theme", "setTheme"], simpleMode: "simpleMode", outputType: "outputType", defaultInspector: "defaultInspector" }, outputs: { change: "change" }, host: { properties: { "class.dark": "theme==\"dark\"" } }, providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxInputColorComponent), multi: true },
{
provide: NG_VALIDATORS,
multi: true,
useExisting: NgxInputColorComponent,
},
], ngImport: i0, template: "<div class=\"ngx-input-color-picker\" (click)=\"stopPropagation($event)\" [class.simple-mode]=\"simpleMode\">\r\n <div class=\"ngx-color-preview\" [style.background]=\"rgbaColor\" [class.is-dark-color]=\"isDarkColor\" *ngIf=\"!simpleMode\">\r\n <div class=\"rgbacode\">{{ outputColor | uppercase }}</div>\r\n <div class=\"hexacode\" *ngIf=\"outputType !== 'HEX'\">{{ hexColor | uppercase }}</div>\r\n <div class=\"colorname\">{{ name }}</div>\r\n <div class=\"color\"></div>\r\n </div>\r\n <div class=\"inner\">\r\n <div class=\"top-actions\">\r\n <select [(ngModel)]=\"defaultInspector\">\r\n <option *ngFor=\"let inspector of ColorInspector | enumToArray\" [value]=\"inspector\">\r\n {{ ColorInspector[+inspector] }}\r\n </option>\r\n </select>\r\n\r\n <button type=\"button\" (click)=\"openEyeDrop()\" class=\"ngx-btn-eyedroper\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <defs>\r\n <style>\r\n .fa-secondary {\r\n opacity: 0.4;\r\n }\r\n </style>\r\n </defs>\r\n <path\r\n class=\"fa-primary\"\r\n d=\"M482.8 29.23C521.7 68.21 521.7 131.4 482.8 170.4L381.2 271.9L390.6 281.4C403.1 293.9 403.1 314.1 390.6 326.6C378.1 339.1 357.9 339.1 345.4 326.6L185.4 166.6C172.9 154.1 172.9 133.9 185.4 121.4C197.9 108.9 218.1 108.9 230.6 121.4L240.1 130.8L341.6 29.23C380.6-9.744 443.8-9.744 482.8 29.23L482.8 29.23zM132.1 416H96V379.9C96 375.6 97.69 371.6 100.7 368.6L149.3 320H234.7L143.4 411.3C140.4 414.3 136.4 416 132.1 416H132.1z\" />\r\n <path\r\n class=\"fa-secondary\"\r\n d=\"M244 225.3L100.7 368.6C97.69 371.6 96 375.6 96 379.9V416H132.1C136.4 416 140.4 414.3 143.4 411.3L286.7 268L332 313.3L188.7 456.6C173.7 471.6 153.3 480 132.1 480H89.69L49.75 506.6C37.06 515.1 20.16 513.4 9.372 502.6C-1.414 491.8-3.087 474.9 5.374 462.2L32 422.3V379.9C32 358.7 40.43 338.3 55.43 323.3L198.7 180L244 225.3z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <ng-container [ngSwitch]=\"+defaultInspector\">\r\n <app-picker\r\n *ngSwitchCase=\"ColorInspector.Picker\"\r\n [color]=\"color\"\r\n (colorChange)=\"initColor($event)\"\r\n [simpleMode]=\"simpleMode\"></app-picker>\r\n <app-hsl *ngSwitchCase=\"ColorInspector.HSL\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-hsl>\r\n <app-rgb *ngSwitchCase=\"ColorInspector.RGB\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-rgb>\r\n <app-cmyk *ngSwitchCase=\"ColorInspector.CMYK\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-cmyk>\r\n </ng-container>\r\n </div>\r\n</div>\r\n", styles: [":host{--ngx-color-bg: #fff;--ngx-color-text: #000}:host-context(.dark){--ngx-color-bg: #222;--ngx-color-text: #fff}.ngx-input-color-picker{width:270px;max-width:100%;border:1px #bfbfbf solid;border-radius:15px;background:var(--ngx-color-bg);color:var(--ngx-color-text);overflow:hidden;box-shadow:0 0 20px #0000004f;direction:ltr;font-family:arial,tahoma}.ngx-input-color-picker .inner{padding:0 12px 12px}.ngx-input-color-picker *{box-sizing:border-box}.ngx-input-color-picker.simple-mode{width:220px;--ngx-thumb-size: 24px}.ngx-input-color-picker.simple-mode .inner{padding:12px}.ngx-color-preview{min-height:100px;padding:10px 36px;line-height:1.6;font-size:14px;font-family:arial,tahoma;font-weight:700;position:relative;color:#353535}.ngx-color-preview.is-dark-color{color:#fff}.ngx-color-preview:after{content:\" \";position:absolute;background-color:var(--ngx-color-bg);bottom:0;width:100%;left:0;right:0;height:15px;border-radius:18px 18px 0 0}.ngx-color-preview:before{content:\" \";background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px;position:absolute;inset:0;z-index:-1}.button-groups{display:flex;border-radius:4px;overflow:hidden;border:1px #d3d3d3 solid}.button-groups button{cursor:pointer;background:#f9f9f9;outline:none;border:none;transition:all .3s;border-left:1px #d3d3d3 solid;padding:10px 12px;flex:auto}.button-groups button:hover{background:#8db6e4}.button-groups button:first-child{border-left-width:0}.ngx-btn-eyedroper{padding:2px;min-width:0;width:45px;cursor:pointer;background-color:transparent;outline:none;transition:all .3s;border:none;border-radius:6px}.ngx-btn-eyedroper svg{width:18px;fill:var(--ngx-color-text)}.top-actions{display:flex;justify-content:space-between;align-items:center;padding:0 0 12px}.top-actions select{outline:none;border:none;border-radius:4px;padding:5px 10px;background:none;color:var(--ngx-color-text)}.top-actions select:focus{cursor:pointer;background:#e5f0ff;color:#06f}.top-actions select option{padding:10px 20px;background:var(--ngx-color-bg);color:var(--ngx-color-text);transition:all .3s}.top-actions select option:hover{background:#f0f0f048}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.PickerComponent, selector: "app-picker", inputs: ["simpleMode", "color"], outputs: ["colorChange"] }, { kind: "component", type: i4.CmykComponent, selector: "app-cmyk", inputs: ["color"], outputs: ["colorChange"] }, { kind: "component", type: i5.HslComponent, selector: "app-hsl", inputs: ["color"], outputs: ["colorChange"] }, { kind: "component", type: i6.RgbComponent, selector: "app-rgb", inputs: ["color"], outputs: ["colorChange"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i7.EnumToArrayPipe, name: "enumToArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxInputColorComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-input-color', providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgxInputColorComponent), multi: true },
{
provide: NG_VALIDATORS,
multi: true,
useExisting: NgxInputColorComponent,
},
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
'[class.dark]': 'theme=="dark"',
}, template: "<div class=\"ngx-input-color-picker\" (click)=\"stopPropagation($event)\" [class.simple-mode]=\"simpleMode\">\r\n <div class=\"ngx-color-preview\" [style.background]=\"rgbaColor\" [class.is-dark-color]=\"isDarkColor\" *ngIf=\"!simpleMode\">\r\n <div class=\"rgbacode\">{{ outputColor | uppercase }}</div>\r\n <div class=\"hexacode\" *ngIf=\"outputType !== 'HEX'\">{{ hexColor | uppercase }}</div>\r\n <div class=\"colorname\">{{ name }}</div>\r\n <div class=\"color\"></div>\r\n </div>\r\n <div class=\"inner\">\r\n <div class=\"top-actions\">\r\n <select [(ngModel)]=\"defaultInspector\">\r\n <option *ngFor=\"let inspector of ColorInspector | enumToArray\" [value]=\"inspector\">\r\n {{ ColorInspector[+inspector] }}\r\n </option>\r\n </select>\r\n\r\n <button type=\"button\" (click)=\"openEyeDrop()\" class=\"ngx-btn-eyedroper\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <defs>\r\n <style>\r\n .fa-secondary {\r\n opacity: 0.4;\r\n }\r\n </style>\r\n </defs>\r\n <path\r\n class=\"fa-primary\"\r\n d=\"M482.8 29.23C521.7 68.21 521.7 131.4 482.8 170.4L381.2 271.9L390.6 281.4C403.1 293.9 403.1 314.1 390.6 326.6C378.1 339.1 357.9 339.1 345.4 326.6L185.4 166.6C172.9 154.1 172.9 133.9 185.4 121.4C197.9 108.9 218.1 108.9 230.6 121.4L240.1 130.8L341.6 29.23C380.6-9.744 443.8-9.744 482.8 29.23L482.8 29.23zM132.1 416H96V379.9C96 375.6 97.69 371.6 100.7 368.6L149.3 320H234.7L143.4 411.3C140.4 414.3 136.4 416 132.1 416H132.1z\" />\r\n <path\r\n class=\"fa-secondary\"\r\n d=\"M244 225.3L100.7 368.6C97.69 371.6 96 375.6 96 379.9V416H132.1C136.4 416 140.4 414.3 143.4 411.3L286.7 268L332 313.3L188.7 456.6C173.7 471.6 153.3 480 132.1 480H89.69L49.75 506.6C37.06 515.1 20.16 513.4 9.372 502.6C-1.414 491.8-3.087 474.9 5.374 462.2L32 422.3V379.9C32 358.7 40.43 338.3 55.43 323.3L198.7 180L244 225.3z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <ng-container [ngSwitch]=\"+defaultInspector\">\r\n <app-picker\r\n *ngSwitchCase=\"ColorInspector.Picker\"\r\n [color]=\"color\"\r\n (colorChange)=\"initColor($event)\"\r\n [simpleMode]=\"simpleMode\"></app-picker>\r\n <app-hsl *ngSwitchCase=\"ColorInspector.HSL\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-hsl>\r\n <app-rgb *ngSwitchCase=\"ColorInspector.RGB\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-rgb>\r\n <app-cmyk *ngSwitchCase=\"ColorInspector.CMYK\" [color]=\"color\" (colorChange)=\"initColor($event)\"></app-cmyk>\r\n </ng-container>\r\n </div>\r\n</div>\r\n", styles: [":host{--ngx-color-bg: #fff;--ngx-color-text: #000}:host-context(.dark){--ngx-color-bg: #222;--ngx-color-text: #fff}.ngx-input-color-picker{width:270px;max-width:100%;border:1px #bfbfbf solid;border-radius:15px;background:var(--ngx-color-bg);color:var(--ngx-color-text);overflow:hidden;box-shadow:0 0 20px #0000004f;direction:ltr;font-family:arial,tahoma}.ngx-input-color-picker .inner{padding:0 12px 12px}.ngx-input-color-picker *{box-sizing:border-box}.ngx-input-color-picker.simple-mode{width:220px;--ngx-thumb-size: 24px}.ngx-input-color-picker.simple-mode .inner{padding:12px}.ngx-color-preview{min-height:100px;padding:10px 36px;line-height:1.6;font-size:14px;font-family:arial,tahoma;font-weight:700;position:relative;color:#353535}.ngx-color-preview.is-dark-color{color:#fff}.ngx-color-preview:after{content:\" \";position:absolute;background-color:var(--ngx-color-bg);bottom:0;width:100%;left:0;right:0;height:15px;border-radius:18px 18px 0 0}.ngx-color-preview:before{content:\" \";background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px;position:absolute;inset:0;z-index:-1}.button-groups{display:flex;border-radius:4px;overflow:hidden;border:1px #d3d3d3 solid}.button-groups button{cursor:pointer;background:#f9f9f9;outline:none;border:none;transition:all .3s;border-left:1px #d3d3d3 solid;padding:10px 12px;flex:auto}.button-groups button:hover{background:#8db6e4}.button-groups button:first-child{border-left-width:0}.ngx-btn-eyedroper{padding:2px;min-width:0;width:45px;cursor:pointer;background-color:transparent;outline:none;transition:all .3s;border:none;border-radius:6px}.ngx-btn-eyedroper svg{width:18px;fill:var(--ngx-color-text)}.top-actions{display:flex;justify-content:space-between;align-items:center;padding:0 0 12px}.top-actions select{outline:none;border:none;border-radius:4px;padding:5px 10px;background:none;color:var(--ngx-color-text)}.top-actions select:focus{cursor:pointer;background:#e5f0ff;color:#06f}.top-actions select option{padding:10px 20px;background:var(--ngx-color-bg);color:var(--ngx-color-text);transition:all .3s}.top-actions select option:hover{background:#f0f0f048}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { setTheme: [{
type: Input,
args: ['theme']
}], simpleMode: [{
type: Input
}], outputType: [{
type: Input
}], defaultInspector: [{
type: Input
}], change: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWlucHV0LWNvbG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1pbnB1dC1jb2xvci9zcmMvbGliL25neC1pbnB1dC1jb2xvci9uZ3gtaW5wdXQtY29sb3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWlucHV0LWNvbG9yL3NyYy9saWIvbmd4LWlucHV0LWNvbG9yL25neC1pbnB1dC1jb2xvci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFHTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxRQUFRLEVBQWMsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBR0wsYUFBYSxFQUNiLGlCQUFpQixHQUdsQixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7Ozs7Ozs7O0FBbUJsRSxNQUFNLE9BQU8sc0JBQXNCO0lBRWpDLElBQW9CLFFBQVEsQ0FBQyxHQUE4QjtRQUN6RCxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsOEJBQThCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQzVGLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7UUFDbkIsQ0FBQztJQUNILENBQUM7SUFnREQsWUFBb0IsRUFBcUI7UUFBckIsT0FB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LENBQUMsTUFBTSxRQUN6Qzt3QkFDSixjQUFjLEVBQUUsZUFBZTtxQkFDaEM7c0ZBSW1CLFFBQVE7c0JBQTNCLEtBQUs7dUJBQUMsT0FBTztnQkFTTCxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBVUcsZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUdJLE1BQU07c0JBQWYsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBmb3J3YXJkUmVmLFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveSxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb2xvckZvcm1hdHMgfSBmcm9tICcuLi8uLi9tb2RlbHMvQ29sb3JGb3JtYXRzLmVudW0nO1xyXG5pbXBvcnQgeyBOZ3hDb2xvciwgT3V0cHV0VHlwZSB9IGZyb20gJy4uLy4uL3V0aWxzL2NvbG9yLWhlbHBlcic7XHJcbmltcG9ydCB7XHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIENvbnRyb2xWYWx1ZUFjY2Vzc29yLFxyXG4gIE5HX1ZBTElEQVRPUlMsXHJcbiAgTkdfVkFMVUVfQUNDRVNTT1IsXHJcbiAgVmFsaWRhdGlvbkVycm9ycyxcclxuICBWYWxpZGF0b3IsXHJcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBDb2xvckluc3BlY3RvciB9IGZyb20gJy4uLy4uL21vZGVscy9Db2xvckluc3BlY3Rvci5lbnVtJztcclxuZGVjbGFyZSBjb25zdCBFeWVEcm9wcGVyOiBhbnk7XHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmd4LWlucHV0LWNvbG9yJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LWlucHV0LWNvbG9yLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZ3gtaW5wdXQtY29sb3IuY29tcG9uZW50LnNjc3MnXSxcclxuICBwcm92aWRlcnM6IFtcclxuICAgIHsgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neElucHV0Q29sb3JDb21wb25lbnQpLCBtdWx0aTogdHJ1ZSB9LFxyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxyXG4gICAgICBtdWx0aTogdHJ1ZSxcclxuICAgICAgdXNlRXhpc3Rpbmc6IE5neElucHV0Q29sb3JDb21wb25lbnQsXHJcbiAgICB9LFxyXG4gIF0sXHJcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXHJcbiAgaG9zdDoge1xyXG4gICAgJ1tjbGFzcy5kYXJrXSc6ICd0aGVtZT09XCJkYXJrXCInLFxyXG4gIH0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBOZ3hJbnB1dENvbG9yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBWYWxpZGF0b3Ige1xyXG4gIHRoZW1lOiAnbGlnaHQnIHwgJ2RhcmsnIHwgJ2F1dG8nID0gJ2F1dG8nO1xyXG4gIEBJbnB1dCgndGhlbWUnKSBzZXQgc2V0VGhlbWUodmFsOiAnbGlnaHQnIHwgJ2RhcmsnIHwgJ2F1dG8nKSB7XHJcbiAgICBpZiAoIXZhbCB8fCB2YWwgPT0gJ2F1dG8nKSB7XHJcbiAgICAgIHRoaXMudGhlbWUgPSB3aW5kb3cubWF0Y2hNZWRpYSgnKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKScpLm1hdGNoZXMgPyAnZGFyaycgOiAnbGlnaHQnO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy50aGVtZSA9IHZhbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBNaW5pZmkgVUkgICovXHJcbiAgQElucHV0KCkgc2ltcGxlTW9kZSA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKSBvdXRwdXRUeXBlOiBPdXRwdXRUeXBlID0gJ0hFWCc7XHJcblxyXG4gIC8qKlxyXG4gICAqIGRlZmF1bHQgaW5zcGVjdG9yc1xyXG4gICAqIC0gQ29sb3JJbnNwZWN0b3IuUGlja2VyXHJcbiAgICogLSBDb2xvckluc3BlY3Rvci5SR0JcclxuICAgKiAtIENvbG9ySW5zcGVjdG9yLkhTTFxyXG4gICAqXHJcbiAgICogQGFsaWFzIGRlZmF1bHRJbnNwZWN0b3JcclxuICAgKi9cclxuICBASW5wdXQoKSBkZWZhdWx0SW5zcGVjdG9yOiBDb2xvckluc3BlY3RvciA9IENvbG9ySW5zcGVjdG9yLlBpY2tlcjtcclxuXHJcbiAgLyoqIEVtaXR0ZWQgd2hlbiB0aGUgY29sb3IgdmFsdWUgY2hhbmdlcyAqL1xyXG4gIEBPdXRwdXQoKSBjaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBmb3JtYXQ6IENvbG9yRm9ybWF0cyA9IENvbG9yRm9ybWF0cy5IU1ZBO1xyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgaXNEYXJrQ29sb3IgPSB0cnVlO1xyXG5cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHJnYmFDb2xvciA9ICdyZ2JhKDAsIDAsIDAsIDEpJztcclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIGhleENvbG9yID0gJyMwMDAwMDAnO1xyXG4gIG91dHB1dENvbG9yID0gJyc7XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgbmFtZSA9ICdibGFjayc7XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgaXNTdXBwb3J0ZWRFeWVEcm9wOiBib29sZWFuO1xyXG5cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIGNvbG9yOiBOZ3hDb2xvciA9IG5ldyBOZ3hDb2xvcigpO1xyXG5cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIGlzRGlzYWJsZWQgPSBmYWxzZTtcclxuICAvKipAaWdub3JlICovXHJcbiAgcHJpdmF0ZSBfb25DaGFuZ2UgPSAodmFsdWU6IHN0cmluZykgPT4ge307XHJcbiAgLyoqQGlnbm9yZSAqL1xyXG4gIHByaXZhdGUgX29uVG91Y2hlZCA9ICgpID0+IHt9O1xyXG4gIC8qKkBpZ25vcmUgKi9cclxuICBwcml2YXRlIF9vblZhbGlkYXRlQ2hhbmdlID0gKCkgPT4ge307XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZDogQ2hhbmdlRGV0ZWN0b3JSZWYpIHtcclxuICAgIHRoaXMuaXNTdXBwb3J0ZWRFeWVEcm9wID0gJ0V5ZURyb3BwZXInIGluIHdpbmRvdztcclxuICB9XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy50aGVtZSA9PSAnYXV0bycpIHtcclxuICAgICAgdGhpcy50aGVtZSA9IHdpbmRvdy5tYXRjaE1lZGlhKCcocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspJykubWF0Y2hlcyA/ICdkYXJrJyA6ICdsaWdodCc7XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7fVxyXG4gIHB1YmxpYyBnZXQgQ29sb3JGb3JtYXRzKCk6IHR5cGVvZiBDb2xvckZvcm1hdHMge1xyXG4gICAgcmV0dXJuIENvbG9yRm9ybWF0cztcclxuICB9XHJcbiAgcHVibGljIGdldCBDb2xvckluc3BlY3RvcigpOiB0eXBlb2YgQ29sb3JJbnNwZWN0b3Ige1xyXG4gICAgcmV0dXJuIENvbG9ySW5zcGVjdG9yO1xyXG4gIH1cclxuICAvKiogQGlnbm9yZSAqL1xyXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5fb25DaGFuZ2UgPSBmbjtcclxuICB9XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBzZXREaXNhYmxlZFN0YXRlKGRpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRGlzYWJsZWQgPSBkaXNhYmxlZDtcclxuICB9XHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICByZWdpc3Rlck9uVmFsaWRhdG9yQ2hhbmdlKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICB0aGlzLl9vblZhbGlkYXRlQ2hhbmdlID0gZm47XHJcbiAgfVxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgdmFsaWRhdGUoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwge1xyXG4gICAgaWYgKHRoaXMuY29sb3IgJiYgdGhpcy5jb2xvci5pc1ZhbGlkID09PSBmYWxzZSkge1xyXG4gICAgICByZXR1cm4geyBpbnZhbGlkOiB0cnVlIH07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBjID0gdmFsdWUgPyBuZXcgTmd4Q29sb3IodmFsdWUpIDogbmV3IE5neENvbG9yKCcjMDAwJyk7XHJcbiAgICAgIHRoaXMuaW5pdENvbG9yKGMpO1xyXG4gICAgICB0aGlzLl9vblZhbGlkYXRlQ2hhbmdlKCk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIGNvbnN0IGMgPSBuZXcgTmd4Q29sb3IoJyMwMDAnKTsgLy8g2YXZgtiv2KfYsSDZvtuM2LTigIzZgdix2LZcclxuICAgICAgdGhpcy5pbml0Q29sb3IoYyk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgb3BlbkV5ZURyb3AoKSB7XHJcbiAgICBpZiAodGhpcy5pc1N1cHBvcnRlZEV5ZURyb3ApIHtcclxuICAgICAgbGV0IHQgPSBuZXcgRXllRHJvcHBlcigpLm9wZW4oKTtcclxuICAgICAgdC50aGVuKGFzeW5jIChyZXN1bHQ6IHsgc1JHQkhleDogc3RyaW5nIH0pID0+IHtcclxuICAgICAgICB0aGlzLmhleENvbG9yID0gcmVzdWx0LnNSR0JIZXg7XHJcbiAgICAgICAgdGhpcy5pbml0Q29sb3IobmV3IE5neENvbG9yKHRoaXMuaGV4Q29sb3IpKTtcclxuICAgICAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAgY2FsbCBmcm9tIGRpcmVjdGl2ZVxyXG4gIC8qIEBpZ25vcmUgXHJcbiAgICovXHJcbiAgYXN5bmMgaW5pdENvbG9yKGM/OiBOZ3hDb2xvcikge1xyXG4gICAgaWYgKCFjKSByZXR1cm47XHJcbiAgICB0aGlzLmNvbG9yID0gYztcclxuICAgIHRoaXMucmdiYUNvbG9yID0gdGhpcy5jb2xvci50b1JnYlN0cmluZygpO1xyXG4gICAgdGhpcy5oZXhDb2xvciA9IHRoaXMuY29sb3IudG9IZXhTdHJpbmcoKTtcclxuICAgIHRoaXMub3V0cHV0Q29sb3IgPSBhd2FpdCB0aGlzLmNvbG9yLmdldE91dHB1dFJlc3VsdCh0aGlzLm91dHB1dFR5cGUpO1xyXG4gICAgdGhpcy5pc0RhcmtDb2xvciA9IHRoaXMuY29sb3IuaXNEYXJrKCk7XHJcbiAgICB0aGlzLm5hbWUgPSBhd2FpdCB0aGlzLmNvbG9yLm5hbWUoKTtcclxuICAgIHRoaXMuZW1pdENoYW5nZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEBpZ25vcmUgKi9cclxuICBzdG9wUHJvcGFnYXRpb24oZXY6IEV2ZW50KSB7XHJcbiAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcclxuICB9XHJcblxyXG4gIC8qKiBAaWdub3JlICovXHJcbiAgYXN5bmMgZW1pdENoYW5nZSgpIHtcclxuICAgIHRoaXMub3V0cHV0Q29sb3IgPSBhd2FpdCB0aGlzLmNvbG9yLmdldE91dHB1dFJlc3VsdCh0aGlzLm91dHB1dFR5cGUpO1xyXG4gICAgdGhpcy5fb25DaGFuZ2UodGhpcy5vdXRwdXRDb2xvcik7XHJcbiAgICB0aGlzLmNoYW5nZS5lbWl0KHRoaXMub3V0cHV0Q29sb3IpO1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwibmd4LWlucHV0LWNvbG9yLXBpY2tlclwiIChjbGljayk9XCJzdG9wUHJvcGFnYXRpb24oJGV2ZW50KVwiIFtjbGFzcy5zaW1wbGUtbW9kZV09XCJzaW1wbGVNb2RlXCI+XHJcbiAgPGRpdiBjbGFzcz1cIm5neC1jb2xvci1wcmV2aWV3XCIgW3N0eWxlLmJhY2tncm91bmRdPVwicmdiYUNvbG9yXCIgW2NsYXNzLmlzLWRhcmstY29sb3JdPVwiaXNEYXJrQ29sb3JcIiAqbmdJZj1cIiFzaW1wbGVNb2RlXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwicmdiYWNvZGVcIj57eyBvdXRwdXRDb2xvciB8IHVwcGVyY2FzZSB9fTwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImhleGFjb2RlXCIgKm5nSWY9XCJvdXRwdXRUeXBlICE9PSAnSEVYJ1wiPnt7IGhleENvbG9yIHwgdXBwZXJjYXNlIH19PC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sb3JuYW1lXCI+e3sgbmFtZSB9fTwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbG9yXCI+PC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cImlubmVyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwidG9wLWFjdGlvbnNcIj5cclxuICAgICAgPHNlbGVjdCBbKG5nTW9kZWwpXT1cImRlZmF1bHRJbnNwZWN0b3JcIj5cclxuICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBpbnNwZWN0b3Igb2YgQ29sb3JJbnNwZWN0b3IgfCBlbnVtVG9BcnJheVwiIFt2YWx1ZV09XCJpbnNwZWN0b3JcIj5cclxuICAgICAgICAgIHt7IENvbG9ySW5zcGVjdG9yWytpbnNwZWN0b3JdIH19XHJcbiAgICAgICAgPC9vcHRpb24+XHJcbiAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cIm9wZW5FeWVEcm9wKClcIiBjbGFzcz1cIm5neC1idG4tZXllZHJvcGVyXCI+XHJcbiAgICAgICAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgdmlld0JveD1cIjAgMCA1MTIgNTEyXCI+XHJcbiAgICAgICAgICA8ZGVmcz5cclxuICAgICAgICAgICAgPHN0eWxlPlxyXG4gICAgICAgICAgICAgIC5mYS1zZWNvbmRhcnkge1xyXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMC40O1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgPC9zdHlsZT5cclxuICAgICAgICAgIDwvZGVmcz5cclxuICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgIGNsYXNzPVwiZmEtcHJpbWFyeVwiXHJcbiAgICAgICAgICAgIGQ9XCJNNDgyLjggMjkuMjNDNTIxLjcgNjguMjEgNTIxLjcgMTMxLjQgNDgyLjggMTcwLjRMMzgxLjIgMjcxLjlMMzkwLjYgMjgxLjRDNDAzLjEgMjkzLjkgNDAzLjEgMzE0LjEgMzkwLjYgMzI2LjZDMzc4LjEgMzM5LjEgMzU3LjkgMzM5LjEgMzQ1LjQgMzI2LjZMMTg1LjQgMTY2LjZDMTcyLjkgMTU0LjEgMTcyLjkgMTMzLjkgMTg1LjQgMTIxLjRDMTk3LjkgMTA4LjkgMjE4LjEgMTA4LjkgMjMwLjYgMTIxLjRMMjQwLjEgMTMwLjhMMzQxLjYgMjkuMjNDMzgwLjYtOS43NDQgNDQzLjgtOS43NDQgNDgyLjggMjkuMjNMNDgyLjggMjkuMjN6TTEzMi4xIDQxNkg5NlYzNzkuOUM5NiAzNzUuNiA5Ny42OSAzNzEuNiAxMDAuNyAzNjguNkwxNDkuMyAzMjBIMjM0LjdMMTQzLjQgNDExLjNDMTQwLjQgNDE0LjMgMTM2LjQgNDE2IDEzMi4xIDQxNkgxMzIuMXpcIiAvPlxyXG4gICAgICAgICAgPHBhdGhcclxuICAgICAgICAgICAgY2xhc3M9XCJmYS1zZWNvbmRhcnlcIlxyXG4gICAgICAgICAgICBkPVwiTTI0NCAyMjUuM0wxMDAuNyAzNjguNkM5Ny42OSAzNzEuNiA5NiAzNzUuNiA5NiAzNzkuOVY0MTZIMTMyLjFDMTM2LjQgNDE2IDE0MC40IDQxNC4zIDE0My40IDQxMS4zTDI4Ni43IDI2OEwzMzIgMzEzLjNMMTg4LjcgNDU2LjZDMTczLjcgNDcxLjYgMTUzLjMgNDgwIDEzMi4xIDQ4MEg4OS42OUw0OS43NSA1MDYuNkMzNy4wNiA1MTUuMSAyMC4xNiA1MTMuNCA5LjM3MiA1MDIuNkMtMS40MTQgNDkxLjgtMy4wODcgNDc0LjkgNS4zNzQgNDYyLjJMMzIgNDIyLjNWMzc5LjlDMzIgMzU4LjcgNDAuNDMgMzM4LjMgNTUuNDMgMzIzLjNMMTk4LjcgMTgwTDI0NCAyMjUuM3pcIiAvPlxyXG4gICAgICAgIDwvc3ZnPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cIitkZWZhdWx0SW5zcGVjdG9yXCI+XHJcbiAgICAgIDxhcHAtcGlja2VyXHJcbiAgICAgICAgKm5nU3dpdGNoQ2FzZT1cIkNvbG9ySW5zcGVjdG9yLlBpY2tlclwiXHJcbiAgICAgICAgW2NvbG9yXT1cImNvbG9yXCJcclxuICAgICAgICAoY29sb3JDaGFuZ2UpPVwiaW5pdENvbG9yKCRldmVudClcIlxyXG4gICAgICAgIFtzaW1wbGVNb2RlXT1cInNpbXBsZU1vZGVcIj48L2FwcC1waWNrZXI+XHJcbiAgICAgIDxhcHAtaHNsICpuZ1N3aXRjaENhc2U9XCJDb2xvckluc3BlY3Rvci5IU0xcIiBbY29sb3JdPVwiY29sb3JcIiAoY29sb3JDaGFuZ2UpPVwiaW5pdENvbG9yKCRldmVudClcIj48L2FwcC1oc2w+XHJcbiAgICAgIDxhcHAtcmdiICpuZ1N3aXRjaENhc2U9XCJDb2xvckluc3BlY3Rvci5SR0JcIiBbY29sb3JdPVwiY29sb3JcIiAoY29sb3JDaGFuZ2UpPVwiaW5pdENvbG9yKCRldmVudClcIj48L2FwcC1yZ2I+XHJcbiAgICAgIDxhcHAtY215ayAqbmdTd2l0Y2hDYXNlPVwiQ29sb3JJbnNwZWN0b3IuQ01ZS1wiIFtjb2xvcl09XCJjb2xvclwiIChjb2xvckNoYW5nZSk9XCJpbml0Q29sb3IoJGV2ZW50KVwiPjwvYXBwLWNteWs+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==