UNPKG

ng-toggle-button

Version:
304 lines 41.4 kB
import { Component, Input, forwardRef, Output, EventEmitter } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { CommonModule } from '@angular/common'; import * as i0 from "@angular/core"; import * as i1 from "./ng-toggle.config"; import * as i2 from "@angular/common"; const DEFAULT_COLOR_CHECKED = '#0099CC'; const DEFAULT_COLOR_UNCHECKED = '#e0e0e0'; const DEFAULT_LABEL_CHECKED = ''; const DEFAULT_LABEL_UNCHECKED = ''; const DEFAULT_SWITCH_COLOR = '#fff'; const DISABLED_COLOR = '#dbdbdb'; const DISABLED_BUTTON_COLOR = 'silver'; let nextUniqueId = 0; export class NgToggleComponent { constructor(config, _elementRef) { this.config = config; this._elementRef = _elementRef; this.value = this.config.value || true; this.name = this.config.name || ''; this.disabled = this.config.disabled || false; this.height = this.config.height || 25; this.width = this.config.width || 45; this.margin = this.config.margin || 2; this.fontSize = this.config.fontSize || undefined; this.speed = this.config.speed || 300; this.color = this.config.color; this.switchColor = this.config.switchColor; this.labels = this.config.labels || true; this.fontColor = this.config.fontColor || undefined; this.values = this.config.values || { checked: true, unchecked: false }; this.textAlign = this.config.textAlign || { checked: 'left', unchecked: 'right', }; this.id = ''; this.ariaLabel = null; this.ariaLabelledby = null; this.cssColors = false; this.change = new EventEmitter(); this.valueChange = new EventEmitter(); this.onChange = (_) => { }; this.onTouch = () => { }; this._uniqueId = 'ng-toggle-' + (++nextUniqueId); this.id = this.id || this._uniqueId; this.ariaLabel = this.ariaLabel || this.name || this.id; } ngOnInit() { this.setToogle(); } onInput(value) { this.value = value; this.onTouch(); this.onChange(this.value); } writeValue(value) { this.value = value; this.setToogle(); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouch = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; } setToogle() { const value = this.value; let index = Object.values(this.values).findIndex(el => el == value); if (index > -1) this.toggled = Object.keys(this.values)[index] == 'checked' ? true : false; } ngOnChanges(changes) { for (const propName in changes) { const chng = changes[propName]; if (propName == 'value') this.writeValue(chng.currentValue); } } get coreStyle() { return { width: px(this.width), height: px(this.height), transition: `all ${this.speed}ms`, backgroundColor: this.cssColors ? null : (this.disabled ? this.colorDisabled : this.colorCurrent), borderRadius: px(Math.round(this.height / 2)) }; } get buttonRadius() { const radius = this.height - this.margin * 2; return radius > 0 ? radius : 0; } get distance() { return px(this.width - this.height + this.margin); } get buttonStyle() { const transition = `all ${this.speed}ms`; const margin = px(this.margin); const transform = this.toggled ? translate(this.distance, margin) : translate(margin, margin); let background = this.switchColor ? this.switchColorCurrent : null; background = this.disabled ? this.switchColorDisabled : background; return { width: px(this.buttonRadius), height: px(this.buttonRadius), transition, transform, background, }; } get labelStyle() { return { lineHeight: px(this.height), fontSize: this.fontSize ? px(this.fontSize) : null, color: this.fontColor ? this.fontColorCurrent : null, width: px(this.width - this.buttonRadius - this.margin), }; } get labelLeftStyle() { return { ...this.labelStyle, textAlign: this.textAlign.checked || this.textAlign }; } get labelRightStyle() { return { ...this.labelStyle, textAlign: this.textAlign.unchecked || this.textAlign }; } get colorChecked() { let { color } = this; if (!isObject(color)) { return color || DEFAULT_COLOR_CHECKED; } return get(color, 'checked', DEFAULT_COLOR_CHECKED); } get colorUnchecked() { return get(this.color, 'unchecked', DEFAULT_COLOR_UNCHECKED); } get colorDisabled() { return get(this.color, 'disabled', DISABLED_COLOR); } get colorCurrent() { return this.toggled ? this.colorChecked : this.colorUnchecked; } get labelChecked() { return get(this.labels, 'checked', DEFAULT_LABEL_CHECKED); } get labelUnchecked() { return get(this.labels, 'unchecked', DEFAULT_LABEL_UNCHECKED); } get switchColorChecked() { return get(this.switchColor, 'checked', DEFAULT_SWITCH_COLOR); } get switchColorUnchecked() { return get(this.switchColor, 'unchecked', DEFAULT_SWITCH_COLOR); } get switchColorDisabled() { return get(this.switchColor, 'disabled', DISABLED_BUTTON_COLOR); } get switchColorCurrent() { if (!isObject(this.switchColor)) { return this.switchColor || DEFAULT_SWITCH_COLOR; } return this.toggled ? this.switchColorChecked : this.switchColorUnchecked; } get fontColorChecked() { return get(this.fontColor, 'checked', DEFAULT_SWITCH_COLOR); } get fontColorUnchecked() { return get(this.fontColor, 'unchecked', DEFAULT_SWITCH_COLOR); } get fontColorDisabled() { return get(this.fontColor, 'disabled', DEFAULT_SWITCH_COLOR); } get fontColorCurrent() { if (!isObject(this.fontColor)) { return this.fontColor || DEFAULT_SWITCH_COLOR; } if (this.disabled) { return this.fontColorDisabled; } return this.toggled ? this.fontColorChecked : this.fontColorUnchecked; } get label() { if (this.ariaLabelledby) { return this.ariaLabelledby; } return this.ariaLabel ? null : `${this._uniqueId}-label`; } toggle(event) { const toggled = !this.toggled; this.toggled = toggled; this.value = this.getValue(toggled); this.onTouch(); this.onChange(this.value); this.valueChange.emit(this.value); } getValue(key) { return key === true ? this.values['checked'] : this.values['unchecked']; } onFocus(event) { if (!this.focused && event.relatedTarget) { this.focused = true; } } onFocusout(event) { if (!this._elementRef.nativeElement.contains(event.relatedTarget)) { this.focused = false; this.onTouch(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgToggleComponent, deps: [{ token: i1.NgToggleConfig }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NgToggleComponent, isStandalone: true, selector: "ng-toggle", inputs: { value: "value", name: "name", disabled: "disabled", height: "height", width: "width", margin: "margin", fontSize: "fontSize", speed: "speed", color: "color", switchColor: "switchColor", labels: "labels", fontColor: "fontColor", values: "values", textAlign: "textAlign", id: "id", ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], ariaDescribedby: ["aria-describedby", "ariaDescribedby"] }, outputs: { change: "change", valueChange: "valueChange" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgToggleComponent), multi: true } ], usesOnChanges: true, ngImport: i0, template: "<label class=\"ng-toggle-switch\" [for]=\"id\" [attr.id]=\"label\">\n <input\n type=\"checkbox\"\n class=\"ng-toggle-switch-input\"\n [checked]=\"value\"\n [disabled]=\"disabled\"\n (change)=\"toggle($event)\"\n (focusin)=\"onFocus($event)\"\n (focusout)=\"onFocusout($event)\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-labelledby]=\"label\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-checked]=\"toggled\"\n role=\"checkbox\"\n >\n <div\n class=\"ng-toggle-switch-core\"\n [ngClass]=\"{'ng-toggle-focused': focused}\"\n [ngStyle]=\"coreStyle\"\n >\n <div\n class=\"ng-toggle-switch-button\"\n [ngStyle]=\"buttonStyle\">\n </div>\n </div>\n <ng-container *ngIf=\"labels\">\n <span\n class=\"ng-toggle-switch-label ng-toggle-left\"\n [ngStyle]=\"labelLeftStyle\"\n *ngIf=\"toggled\"\n >\n {{labelChecked}}\n </span>\n <span\n class=\"ng-toggle-switch-label ng-toggle-right\"\n [ngStyle]=\"labelRightStyle\"\n *ngIf=\"!toggled\"\n >\n {{labelUnchecked}}\n </span>\n </ng-container>\n</label>", styles: ["label{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}.ng-toggle-switch{display:inline-block;position:relative;vertical-align:middle;-webkit-user-select:none;user-select:none;font-size:10px;cursor:pointer}.ng-toggle-switch .ng-toggle-switch-input{opacity:0;position:absolute;width:1px;height:1px}.ng-toggle-switch .ng-toggle-switch-label{position:absolute;top:0;font-weight:600;color:#fff;z-index:1;padding:0 10px;box-sizing:border-box}.ng-toggle-switch .ng-toggle-switch-label.ng-toggle-left{left:0}.ng-toggle-switch .ng-toggle-switch-label.ng-toggle-right{right:0}.ng-toggle-switch .ng-toggle-switch-core{display:block;position:relative;box-sizing:border-box;outline:0;margin:0;transition:border-color .3s,background-color .3s;-webkit-user-select:none;user-select:none}.ng-toggle-switch .ng-toggle-switch-core .ng-toggle-switch-button{display:block;position:absolute;overflow:hidden;top:0;left:0;border-radius:100%;background-color:#fff;z-index:2}.ng-toggle-switch.disabled{pointer-events:none;opacity:.6}.ng-toggle-focused{box-shadow:0 0 4px 3px #999}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgToggleComponent, decorators: [{ type: Component, args: [{ selector: 'ng-toggle', standalone: true, imports: [CommonModule], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgToggleComponent), multi: true } ], template: "<label class=\"ng-toggle-switch\" [for]=\"id\" [attr.id]=\"label\">\n <input\n type=\"checkbox\"\n class=\"ng-toggle-switch-input\"\n [checked]=\"value\"\n [disabled]=\"disabled\"\n (change)=\"toggle($event)\"\n (focusin)=\"onFocus($event)\"\n (focusout)=\"onFocusout($event)\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-labelledby]=\"label\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-checked]=\"toggled\"\n role=\"checkbox\"\n >\n <div\n class=\"ng-toggle-switch-core\"\n [ngClass]=\"{'ng-toggle-focused': focused}\"\n [ngStyle]=\"coreStyle\"\n >\n <div\n class=\"ng-toggle-switch-button\"\n [ngStyle]=\"buttonStyle\">\n </div>\n </div>\n <ng-container *ngIf=\"labels\">\n <span\n class=\"ng-toggle-switch-label ng-toggle-left\"\n [ngStyle]=\"labelLeftStyle\"\n *ngIf=\"toggled\"\n >\n {{labelChecked}}\n </span>\n <span\n class=\"ng-toggle-switch-label ng-toggle-right\"\n [ngStyle]=\"labelRightStyle\"\n *ngIf=\"!toggled\"\n >\n {{labelUnchecked}}\n </span>\n </ng-container>\n</label>", styles: ["label{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}.ng-toggle-switch{display:inline-block;position:relative;vertical-align:middle;-webkit-user-select:none;user-select:none;font-size:10px;cursor:pointer}.ng-toggle-switch .ng-toggle-switch-input{opacity:0;position:absolute;width:1px;height:1px}.ng-toggle-switch .ng-toggle-switch-label{position:absolute;top:0;font-weight:600;color:#fff;z-index:1;padding:0 10px;box-sizing:border-box}.ng-toggle-switch .ng-toggle-switch-label.ng-toggle-left{left:0}.ng-toggle-switch .ng-toggle-switch-label.ng-toggle-right{right:0}.ng-toggle-switch .ng-toggle-switch-core{display:block;position:relative;box-sizing:border-box;outline:0;margin:0;transition:border-color .3s,background-color .3s;-webkit-user-select:none;user-select:none}.ng-toggle-switch .ng-toggle-switch-core .ng-toggle-switch-button{display:block;position:absolute;overflow:hidden;top:0;left:0;border-radius:100%;background-color:#fff;z-index:2}.ng-toggle-switch.disabled{pointer-events:none;opacity:.6}.ng-toggle-focused{box-shadow:0 0 4px 3px #999}\n"] }] }], ctorParameters: () => [{ type: i1.NgToggleConfig }, { type: i0.ElementRef }], propDecorators: { value: [{ type: Input }], name: [{ type: Input }], disabled: [{ type: Input }], height: [{ type: Input }], width: [{ type: Input }], margin: [{ type: Input }], fontSize: [{ type: Input }], speed: [{ type: Input }], color: [{ type: Input }], switchColor: [{ type: Input }], labels: [{ type: Input }], fontColor: [{ type: Input }], values: [{ type: Input }], textAlign: [{ type: Input }], id: [{ type: Input }], ariaLabel: [{ type: Input, args: ['aria-label'] }], ariaLabelledby: [{ type: Input, args: ['aria-labelledby'] }], ariaDescribedby: [{ type: Input, args: ['aria-describedby'] }], change: [{ type: Output }], valueChange: [{ type: Output }] } }); export const isObject = (value) => { return typeof value === 'object'; }; export const has = (object, key) => { return isObject(object) && object.hasOwnProperty(key); }; export const get = (object, key, defaultValue) => { return has(object, key) ? object[key] : defaultValue; }; export const px = value => { return `${value}px`; }; export const translate = (x, y) => { return `translate(${x}, ${y})`; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctdG9nZ2xlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLXRvZ2dsZS9zcmMvbGliL25nLXRvZ2dsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy10b2dnbGUvc3JjL2xpYi9uZy10b2dnbGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQXdDLE1BQU0sZUFBZSxDQUFDO0FBQ2pJLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7Ozs7QUFFL0MsTUFBTSxxQkFBcUIsR0FBRyxTQUFTLENBQUE7QUFDdkMsTUFBTSx1QkFBdUIsR0FBRyxTQUFTLENBQUE7QUFDekMsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUE7QUFDaEMsTUFBTSx1QkFBdUIsR0FBRyxFQUFFLENBQUE7QUFDbEMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUE7QUFDbkMsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFBO0FBQ2hDLE1BQU0scUJBQXFCLEdBQUcsUUFBUSxDQUFBO0FBQ3RDLElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQztBQWdCckIsTUFBTSxPQUFPLGlCQUFpQjtJQWdDNUIsWUFDVSxNQUFzQixFQUN0QixXQUFvQztRQURwQyxXQUFNLEdBQU4sTUFBTSxDQUFnQjtRQUN0QixnQkFBVyxHQUFYLFdBQVcsQ0FBeUI7UUFoQ3JDLFVBQUssR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUE7UUFDdEMsU0FBSSxHQUFXLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQTtRQUNyQyxhQUFRLEdBQVksSUFB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LENBQUMsQ0FBQTtBQUVELE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLEVBQUU7SUFDL0MsT0FBTyxHQUFHLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQTtBQUN0RCxDQUFDLENBQUE7QUFFRCxNQUFNLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLEVBQUU7SUFDeEIsT0FBTyxHQUFHLEtBQUssSUFBSSxDQUFBO0FBQ3JCLENBQUMsQ0FBQTtBQUVELE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNoQyxPQUFPLGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFBO0FBQ2hDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgZm9yd2FyZFJlZiwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTmdUb2dnbGVDb25maWcgfSBmcm9tICcuL25nLXRvZ2dsZS5jb25maWcnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuY29uc3QgREVGQVVMVF9DT0xPUl9DSEVDS0VEID0gJyMwMDk5Q0MnXG5jb25zdCBERUZBVUxUX0NPTE9SX1VOQ0hFQ0tFRCA9ICcjZTBlMGUwJ1xuY29uc3QgREVGQVVMVF9MQUJFTF9DSEVDS0VEID0gJydcbmNvbnN0IERFRkFVTFRfTEFCRUxfVU5DSEVDS0VEID0gJydcbmNvbnN0IERFRkFVTFRfU1dJVENIX0NPTE9SID0gJyNmZmYnXG5jb25zdCBESVNBQkxFRF9DT0xPUiA9ICcjZGJkYmRiJ1xuY29uc3QgRElTQUJMRURfQlVUVE9OX0NPTE9SID0gJ3NpbHZlcidcbmxldCBuZXh0VW5pcXVlSWQgPSAwO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZy10b2dnbGUnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL25nLXRvZ2dsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25nLXRvZ2dsZS5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5nVG9nZ2xlQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIE5nVG9nZ2xlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25DaGFuZ2VzIHtcblxuICBASW5wdXQoKSB2YWx1ZTogYW55ID0gdGhpcy5jb25maWcudmFsdWUgfHwgdHJ1ZVxuICBASW5wdXQoKSBuYW1lOiBzdHJpbmcgPSB0aGlzLmNvbmZpZy5uYW1lIHx8ICcnXG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gdGhpcy5jb25maWcuZGlzYWJsZWQgfHwgZmFsc2VcblxuICBASW5wdXQoKSBoZWlnaHQ6IG51bWJlciA9IHRoaXMuY29uZmlnLmhlaWdodCB8fCAyNVxuICBASW5wdXQoKSB3aWR0aDogbnVtYmVyID0gdGhpcy5jb25maWcud2lkdGggfHwgNDVcbiAgQElucHV0KCkgbWFyZ2luOiBudW1iZXIgPSB0aGlzLmNvbmZpZy5tYXJnaW4gfHwgMlxuICBASW5wdXQoKSBmb250U2l6ZTogbnVtYmVyID0gdGhpcy5jb25maWcuZm9udFNpemUgfHwgdW5kZWZpbmVkXG4gIEBJbnB1dCgpIHNwZWVkOiBudW1iZXIgPSB0aGlzLmNvbmZpZy5zcGVlZCB8fCAzMDBcbiAgQElucHV0KCkgY29sb3I6IHN0cmluZyB8IHRvZ2dsZUNvbmZpZyA9IHRoaXMuY29uZmlnLmNvbG9yXG4gIEBJbnB1dCgpIHN3aXRjaENvbG9yOiBzdHJpbmcgfCB0b2dnbGVDb25maWcgPSB0aGlzLmNvbmZpZy5zd2l0Y2hDb2xvclxuICBASW5wdXQoKSBsYWJlbHM6IGJvb2xlYW4gfCB0b2dnbGVDb25maWcgPSB0aGlzLmNvbmZpZy5sYWJlbHMgfHwgdHJ1ZVxuICBASW5wdXQoKSBmb250Q29sb3I6IHN0cmluZyB8IHRvZ2dsZUNvbmZpZyA9IHRoaXMuY29uZmlnLmZvbnRDb2xvciB8fCB1bmRlZmluZWRcbiAgQElucHV0KCkgdmFsdWVzOiB2YWx1ZUNvbmZpZyA9IHRoaXMuY29uZmlnLnZhbHVlcyB8fCB7Y2hlY2tlZDogdHJ1ZSwgdW5jaGVja2VkOiBmYWxzZX1cbiAgQElucHV0KCkgdGV4dEFsaWduOiBzdHJpbmcgfCB0b2dnbGVDb25maWcgPSB0aGlzLmNvbmZpZy50ZXh0QWxpZ24gfHwge1xuICAgIGNoZWNrZWQ6ICdsZWZ0JyxcbiAgICB1bmNoZWNrZWQ6ICdyaWdodCcsXG4gIH1cbiAgQElucHV0KCkgaWQ6IHN0cmluZyA9ICcnXG4gIEBJbnB1dCgnYXJpYS1sYWJlbCcpIGFyaWFMYWJlbDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgnYXJpYS1sYWJlbGxlZGJ5JykgYXJpYUxhYmVsbGVkYnk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoJ2FyaWEtZGVzY3JpYmVkYnknKSBhcmlhRGVzY3JpYmVkYnk6IHN0cmluZztcbiAgY3NzQ29sb3JzOiBib29sZWFuID0gZmFsc2VcblxuICBAT3V0cHV0KCkgY2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKVxuICB0b2dnbGVkOiBib29sZWFuXG4gIGZvY3VzZWQ6IGJvb2xlYW47XG4gIHByaXZhdGUgX3VuaXF1ZUlkOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBjb25maWc6IE5nVG9nZ2xlQ29uZmlnLFxuICAgIHByaXZhdGUgX2VsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICApIHtcbiAgICB0aGlzLl91bmlxdWVJZCA9ICduZy10b2dnbGUtJysoKytuZXh0VW5pcXVlSWQpO1xuICAgIHRoaXMuaWQgPSB0aGlzLmlkIHx8IHRoaXMuX3VuaXF1ZUlkXG4gICAgdGhpcy5hcmlhTGFiZWwgPSB0aGlzLmFyaWFMYWJlbCB8fCB0aGlzLm5hbWUgfHwgdGhpcy5pZFxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5zZXRUb29nbGUoKVxuICB9XG5cbiAgb25DaGFuZ2UgPSAoXzphbnkpID0+IHsgfVxuICBvblRvdWNoID0gKCkgPT4geyB9XG5cbiAgb25JbnB1dCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB0aGlzLm9uVG91Y2goKTtcbiAgICB0aGlzLm9uQ2hhbmdlKHRoaXMudmFsdWUpO1xuICB9XG5cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgIHRoaXMuc2V0VG9vZ2xlKCk7XG4gIH1cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2ggPSBmbjtcbiAgfVxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgfVxuXG4gIHNldFRvb2dsZSgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMudmFsdWVcbiAgICBsZXQgaW5kZXggPSBPYmplY3QudmFsdWVzKHRoaXMudmFsdWVzKS5maW5kSW5kZXgoZWwgPT4gZWwgPT0gdmFsdWUpXG4gICAgaWYoaW5kZXggPiAtMSlcbiAgICAgIHRoaXMudG9nZ2xlZCA9IE9iamVjdC5rZXlzKHRoaXMudmFsdWVzKVtpbmRleF0gPT0gJ2NoZWNrZWQnID8gdHJ1ZSA6IGZhbHNlXG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgZm9yIChjb25zdCBwcm9wTmFtZSBpbiBjaGFuZ2VzKSB7XG4gICAgICBjb25zdCBjaG5nID0gY2hhbmdlc1twcm9wTmFtZV07XG4gICAgICBpZihwcm9wTmFtZSA9PSAndmFsdWUnKVxuICAgICAgICB0aGlzLndyaXRlVmFsdWUoY2huZy5jdXJyZW50VmFsdWUpXG4gICAgfVxuICB9XG5cbiAgZ2V0IGNvcmVTdHlsZSAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoOiBweCh0aGlzLndpZHRoKSxcbiAgICAgIGhlaWdodDogcHgodGhpcy5oZWlnaHQpLFxuICAgICAgdHJhbnNpdGlvbjogYGFsbCAke3RoaXMuc3BlZWR9bXNgLFxuICAgICAgYmFja2dyb3VuZENvbG9yOiB0aGlzLmNzc0NvbG9yc1xuICAgICAgICA/IG51bGxcbiAgICAgICAgOiAodGhpcy5kaXNhYmxlZCA/IHRoaXMuY29sb3JEaXNhYmxlZCA6IHRoaXMuY29sb3JDdXJyZW50KSxcbiAgICAgIGJvcmRlclJhZGl1czogcHgoTWF0aC5yb3VuZCh0aGlzLmhlaWdodCAvIDIpKVxuICAgIH1cbiAgfVxuICBnZXQgYnV0dG9uUmFkaXVzICgpIHtcbiAgICBjb25zdCByYWRpdXMgPSB0aGlzLmhlaWdodCAtIHRoaXMubWFyZ2luICogMjtcbiAgICByZXR1cm4gcmFkaXVzID4gMCA/IHJhZGl1cyA6IDA7XG4gIH1cbiAgZ2V0IGRpc3RhbmNlICgpIHtcbiAgICByZXR1cm4gcHgodGhpcy53aWR0aCAtIHRoaXMuaGVpZ2h0ICsgdGhpcy5tYXJnaW4pXG4gIH1cbiAgZ2V0IGJ1dHRvblN0eWxlICgpIHtcbiAgICBjb25zdCB0cmFuc2l0aW9uID0gYGFsbCAke3RoaXMuc3BlZWR9bXNgXG4gICAgY29uc3QgbWFyZ2luID0gcHgodGhpcy5tYXJnaW4pXG4gICAgY29uc3QgdHJhbnNmb3JtID0gdGhpcy50b2dnbGVkXG4gICAgICA/IHRyYW5zbGF0ZSh0aGlzLmRpc3RhbmNlLCBtYXJnaW4pXG4gICAgICA6IHRyYW5zbGF0ZShtYXJnaW4sIG1hcmdpbilcbiAgICBsZXQgYmFja2dyb3VuZCA9IHRoaXMuc3dpdGNoQ29sb3JcbiAgICAgID8gdGhpcy5zd2l0Y2hDb2xvckN1cnJlbnRcbiAgICAgIDogbnVsbFxuICAgIGJhY2tncm91bmQgPSB0aGlzLmRpc2FibGVkID8gdGhpcy5zd2l0Y2hDb2xvckRpc2FibGVkIDogYmFja2dyb3VuZFxuICAgIHJldHVybiB7XG4gICAgICB3aWR0aDogcHgodGhpcy5idXR0b25SYWRpdXMpLFxuICAgICAgaGVpZ2h0OiBweCh0aGlzLmJ1dHRvblJhZGl1cyksXG4gICAgICB0cmFuc2l0aW9uLFxuICAgICAgdHJhbnNmb3JtLFxuICAgICAgYmFja2dyb3VuZCxcbiAgICB9XG4gIH1cbiAgZ2V0IGxhYmVsU3R5bGUgKCkge1xuICAgIHJldHVybiB7XG4gICAgICBsaW5lSGVpZ2h0OiBweCh0aGlzLmhlaWdodCksXG4gICAgICBmb250U2l6ZTogdGhpcy5mb250U2l6ZSA/IHB4KHRoaXMuZm9udFNpemUpIDogbnVsbCxcbiAgICAgIGNvbG9yOiB0aGlzLmZvbnRDb2xvciA/IHRoaXMuZm9udENvbG9yQ3VycmVudCA6IG51bGwsXG4gICAgICB3aWR0aDogcHgodGhpcy53aWR0aCAtIHRoaXMuYnV0dG9uUmFkaXVzIC0gdGhpcy5tYXJnaW4pLFxuICAgIH1cbiAgfVxuICBnZXQgbGFiZWxMZWZ0U3R5bGUgKCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmxhYmVsU3R5bGUsXG4gICAgICB0ZXh0QWxpZ246ICh0aGlzLnRleHRBbGlnbiBhcyB0b2dnbGVDb25maWcpLmNoZWNrZWQgfHwgdGhpcy50ZXh0QWxpZ25cbiAgICB9XG4gIH1cbiAgZ2V0IGxhYmVsUmlnaHRTdHlsZSAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnRoaXMubGFiZWxTdHlsZSxcbiAgICAgIHRleHRBbGlnbjogKHRoaXMudGV4dEFsaWduIGFzIHRvZ2dsZUNvbmZpZykudW5jaGVja2VkIHx8IHRoaXMudGV4dEFsaWduXG4gICAgfVxuICB9XG5cbiAgZ2V0IGNvbG9yQ2hlY2tlZCAoKSB7XG4gICAgbGV0IHsgY29sb3IgfSA9IHRoaXNcbiAgICBpZiAoIWlzT2JqZWN0KGNvbG9yKSkge1xuICAgICAgcmV0dXJuIGNvbG9yIHx8IERFRkFVTFRfQ09MT1JfQ0hFQ0tFRFxuICAgIH1cbiAgICByZXR1cm4gZ2V0KGNvbG9yLCAnY2hlY2tlZCcsIERFRkFVTFRfQ09MT1JfQ0hFQ0tFRClcbiAgfVxuICBnZXQgY29sb3JVbmNoZWNrZWQgKCkge1xuICAgIHJldHVybiBnZXQodGhpcy5jb2xvciwgJ3VuY2hlY2tlZCcsIERFRkFVTFRfQ09MT1JfVU5DSEVDS0VEKVxuICB9XG4gIGdldCBjb2xvckRpc2FibGVkICgpIHtcbiAgICByZXR1cm4gZ2V0KHRoaXMuY29sb3IsICdkaXNhYmxlZCcsIERJU0FCTEVEX0NPTE9SKVxuICB9XG4gIGdldCBjb2xvckN1cnJlbnQgKCkge1xuICAgIHJldHVybiB0aGlzLnRvZ2dsZWRcbiAgICAgID8gdGhpcy5jb2xvckNoZWNrZWRcbiAgICAgIDogdGhpcy5jb2xvclVuY2hlY2tlZFxuICB9XG4gIGdldCBsYWJlbENoZWNrZWQgKCkge1xuICAgIHJldHVybiBnZXQodGhpcy5sYWJlbHMsICdjaGVja2VkJywgREVGQVVMVF9MQUJFTF9DSEVDS0VEKVxuICB9XG4gIGdldCBsYWJlbFVuY2hlY2tlZCAoKSB7XG4gICAgcmV0dXJuIGdldCh0aGlzLmxhYmVscywgJ3VuY2hlY2tlZCcsIERFRkFVTFRfTEFCRUxfVU5DSEVDS0VEKVxuICB9XG4gIGdldCBzd2l0Y2hDb2xvckNoZWNrZWQgKCkge1xuICAgIHJldHVybiBnZXQodGhpcy5zd2l0Y2hDb2xvciwgJ2NoZWNrZWQnLCBERUZBVUxUX1NXSVRDSF9DT0xPUilcbiAgfVxuICBnZXQgc3dpdGNoQ29sb3JVbmNoZWNrZWQgKCkge1xuICAgIHJldHVybiBnZXQodGhpcy5zd2l0Y2hDb2xvciwgJ3VuY2hlY2tlZCcsIERFRkFVTFRfU1dJVENIX0NPTE9SKVxuICB9XG4gIGdldCBzd2l0Y2hDb2xvckRpc2FibGVkKCl7XG4gICAgcmV0dXJuIGdldCh0aGlzLnN3aXRjaENvbG9yLCAnZGlzYWJsZWQnLCBESVNBQkxFRF9CVVRUT05fQ09MT1IpXG4gIH1cblxuICBnZXQgc3dpdGNoQ29sb3JDdXJyZW50ICgpIHtcbiAgICBpZiAoIWlzT2JqZWN0KHRoaXMuc3dpdGNoQ29sb3IpKSB7XG4gICAgICByZXR1cm4gdGhpcy5zd2l0Y2hDb2xvciB8fCBERUZBVUxUX1NXSVRDSF9DT0xPUlxuICAgIH1cbiAgICByZXR1cm4gdGhpcy50b2dnbGVkXG4gICAgICA/IHRoaXMuc3dpdGNoQ29sb3JDaGVja2VkXG4gICAgICA6IHRoaXMuc3dpdGNoQ29sb3JVbmNoZWNrZWRcbiAgfVxuXG4gIGdldCBmb250Q29sb3JDaGVja2VkICgpIHtcbiAgICByZXR1cm4gZ2V0KHRoaXMuZm9udENvbG9yLCAnY2hlY2tlZCcsIERFRkFVTFRfU1dJVENIX0NPTE9SKVxuICB9XG4gIGdldCBmb250Q29sb3JVbmNoZWNrZWQgKCkge1xuICAgIHJldHVybiBnZXQodGhpcy5mb250Q29sb3IsICd1bmNoZWNrZWQnLCBERUZBVUxUX1NXSVRDSF9DT0xPUilcbiAgfVxuXG4gIGdldCBmb250Q29sb3JEaXNhYmxlZCgpe1xuICAgIHJldHVybiBnZXQodGhpcy5mb250Q29sb3IsICdkaXNhYmxlZCcsIERFRkFVTFRfU1dJVENIX0NPTE9SKVxuICB9XG4gIGdldCBmb250Q29sb3JDdXJyZW50ICgpIHtcbiAgICBpZiAoIWlzT2JqZWN0KHRoaXMuZm9udENvbG9yKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZm9udENvbG9yIHx8IERFRkFVTFRfU1dJVENIX0NPTE9SXG4gICAgfVxuICAgIGlmKHRoaXMuZGlzYWJsZWQpe1xuICAgICAgcmV0dXJuIHRoaXMuZm9udENvbG9yRGlzYWJsZWRcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudG9nZ2xlZFxuICAgICAgPyB0aGlzLmZvbnRDb2xvckNoZWNrZWRcbiAgICAgIDogdGhpcy5mb250Q29sb3JVbmNoZWNrZWRcbiAgfVxuXG4gIGdldCBsYWJlbCgpIHtcbiAgICBpZiAodGhpcy5hcmlhTGFiZWxsZWRieSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXJpYUxhYmVsbGVkYnk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFyaWFMYWJlbCA/IG51bGwgOiBgJHt0aGlzLl91bmlxdWVJZH0tbGFiZWxgO1xuICB9XG5cbiAgdG9nZ2xlKGV2ZW50KSB7XG4gICAgY29uc3QgdG9nZ2xlZCA9ICF0aGlzLnRvZ2dsZWQ7XG4gICAgdGhpcy50b2dnbGVkID0gdG9nZ2xlZDtcblxuICAgIHRoaXMudmFsdWUgPSB0aGlzLmdldFZhbHVlKHRvZ2dsZWQpXG4gICAgdGhpcy5vblRvdWNoKCk7XG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQodGhpcy52YWx1ZSlcbiAgfVxuXG4gIGdldFZhbHVlKGtleTogYm9vbGVhbikge1xuICAgIHJldHVybiBrZXkgPT09IHRydWUgPyB0aGlzLnZhbHVlc1snY2hlY2tlZCddIDogdGhpcy52YWx1ZXNbJ3VuY2hlY2tlZCddXG4gIH1cblxuICBvbkZvY3VzKGV2ZW50OiBGb2N1c0V2ZW50KSB7XG4gICAgaWYgKCF0aGlzLmZvY3VzZWQgJiYgZXZlbnQucmVsYXRlZFRhcmdldCkge1xuICAgICAgdGhpcy5mb2N1c2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBvbkZvY3Vzb3V0KGV2ZW50OiBGb2N1c0V2ZW50KSB7XG4gICAgaWYgKCF0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQucmVsYXRlZFRhcmdldCBhcyBFbGVtZW50KSkge1xuICAgICAgdGhpcy5mb2N1c2VkID0gZmFsc2U7XG4gICAgICB0aGlzLm9uVG91Y2goKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGlzT2JqZWN0ID0gKHZhbHVlKSA9PiB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnXG59XG5cbmV4cG9ydCBjb25zdCBoYXMgPSAob2JqZWN0LCBrZXkpID0+IHtcbiAgcmV0dXJuIGlzT2JqZWN0KG9iamVjdCkgJiYgb2JqZWN0Lmhhc093blByb3BlcnR5KGtleSlcbn1cblxuZXhwb3J0IGNvbnN0IGdldCA9IChvYmplY3QsIGtleSwgZGVmYXVsdFZhbHVlKSA9PiB7XG4gIHJldHVybiBoYXMob2JqZWN0LCBrZXkpID8gb2JqZWN0W2tleV0gOiBkZWZhdWx0VmFsdWVcbn1cblxuZXhwb3J0IGNvbnN0IHB4ID0gdmFsdWUgPT4ge1xuICByZXR1cm4gYCR7dmFsdWV9cHhgXG59XG5cbmV4cG9ydCBjb25zdCB0cmFuc2xhdGUgPSAoeCwgeSkgPT4ge1xuICByZXR1cm4gYHRyYW5zbGF0ZSgke3h9LCAke3l9KWBcbn1cblxuZXhwb3J0IHR5cGUgdG9nZ2xlQ29uZmlnID0ge1xuICBjaGVja2VkOiBzdHJpbmc7XG4gIHVuY2hlY2tlZDogc3RyaW5nO1xuICBkaXNhYmxlZD86IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIHZhbHVlQ29uZmlnID0ge1xuICBjaGVja2VkOiBhbnk7XG4gIHVuY2hlY2tlZDogYW55O1xufTtcbiIsIjxsYWJlbCBjbGFzcz1cIm5nLXRvZ2dsZS1zd2l0Y2hcIiBbZm9yXT1cImlkXCIgW2F0dHIuaWRdPVwibGFiZWxcIj5cbiAgPGlucHV0XG4gICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICBjbGFzcz1cIm5nLXRvZ2dsZS1zd2l0Y2gtaW5wdXRcIlxuICAgIFtjaGVja2VkXT1cInZhbHVlXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIChjaGFuZ2UpPVwidG9nZ2xlKCRldmVudClcIlxuICAgIChmb2N1c2luKT1cIm9uRm9jdXMoJGV2ZW50KVwiXG4gICAgKGZvY3Vzb3V0KT1cIm9uRm9jdXNvdXQoJGV2ZW50KVwiXG4gICAgW2F0dHIuaWRdPVwiaWRcIlxuICAgIFthdHRyLm5hbWVdPVwibmFtZVwiXG4gICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWxcIlxuICAgIFthdHRyLmFyaWEtbGFiZWxsZWRieV09XCJsYWJlbFwiXG4gICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJhcmlhRGVzY3JpYmVkYnlcIlxuICAgIFthdHRyLmFyaWEtY2hlY2tlZF09XCJ0b2dnbGVkXCJcbiAgICByb2xlPVwiY2hlY2tib3hcIlxuICA+XG4gIDxkaXZcbiAgICBjbGFzcz1cIm5nLXRvZ2dsZS1zd2l0Y2gtY29yZVwiXG4gICAgW25nQ2xhc3NdPVwieyduZy10b2dnbGUtZm9jdXNlZCc6IGZvY3VzZWR9XCJcbiAgICBbbmdTdHlsZV09XCJjb3JlU3R5bGVcIlxuICA+XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJuZy10b2dnbGUtc3dpdGNoLWJ1dHRvblwiXG4gICAgICBbbmdTdHlsZV09XCJidXR0b25TdHlsZVwiPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImxhYmVsc1wiPlxuICAgIDxzcGFuXG4gICAgICBjbGFzcz1cIm5nLXRvZ2dsZS1zd2l0Y2gtbGFiZWwgbmctdG9nZ2xlLWxlZnRcIlxuICAgICAgW25nU3R5bGVdPVwibGFiZWxMZWZ0U3R5bGVcIlxuICAgICAgKm5nSWY9XCJ0b2dnbGVkXCJcbiAgICA+XG4gICAgICB7e2xhYmVsQ2hlY2tlZH19XG4gICAgPC9zcGFuPlxuICAgIDxzcGFuXG4gICAgICBjbGFzcz1cIm5nLXRvZ2dsZS1zd2l0Y2gtbGFiZWwgbmctdG9nZ2xlLXJpZ2h0XCJcbiAgICAgIFtuZ1N0eWxlXT1cImxhYmVsUmlnaHRTdHlsZVwiXG4gICAgICAqbmdJZj1cIiF0b2dnbGVkXCJcbiAgICA+XG4gICAgICB7e2xhYmVsVW5jaGVja2VkfX1cbiAgICA8L3NwYW4+XG4gIDwvbmctY29udGFpbmVyPlxuPC9sYWJlbD4iXX0=