UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

169 lines 26 kB
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, forwardRef, inject, Input, Output, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import * as i0 from "@angular/core"; import * as i1 from "../../directives/accessibility/focus-indicator/focus-indicator.directive"; import * as i2 from "@angular/forms"; import * as i3 from "../icon/icon.component"; export const SPIN_BUTTON_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SpinButtonComponent), multi: true }; export class SpinButtonComponent { constructor() { this._changeDetector = inject(ChangeDetectorRef); this.type = 'text'; this.placeholder = ''; this.disabled = false; this.spinners = true; this.readOnly = true; this.scrolling = true; this.arrowkeys = true; this.maxLength = Infinity; this.valueChange = new EventEmitter(); this.increment = new EventEmitter(); this.decrement = new EventEmitter(); // eslint-disable-next-line @typescript-eslint/no-empty-function this.onTouchedCallback = () => { }; // eslint-disable-next-line @typescript-eslint/no-empty-function this.onChangeCallback = () => { }; this._regexKeypress = RegExp(/^[0-9.,-]+$/); // eslint-disable-next-line no-useless-escape this._regexPaste = RegExp(/^\-?\d+(\.\d+)?$/); } set value(value) { this._value = value; this.onChangeCallback(value); this.onTouchedCallback(); } get value() { return this._value; } scroll(event) { if (!this.scrolling) { return; } if (event.deltaY > 0) { this.triggerDecrement(); } else { this.triggerIncrement(); } event.preventDefault(); } triggerIncrement() { if (!this.disabled) { this.increment.emit(); } } triggerDecrement() { if (!this.disabled) { this.decrement.emit(); } } writeValue(value) { this.value = value; this._changeDetector.markForCheck(); } registerOnChange(fn) { this.onChangeCallback = fn; } registerOnTouched(fn) { this.onTouchedCallback = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; this._changeDetector.markForCheck(); } onKeypress(event) { // we only need to perform checks if the type is number if (this.type !== 'number') { return; } if (!this._regexKeypress.test(event.key)) { return false; } return true; } onPaste(event) { // we only need to perform checks if the type is number if (this.type !== 'number') { return; } // get the value being pasted const value = event.clipboardData.getData('text'); // check if it contains the character if (!this._regexPaste.test(value)) { // inset the numeric value only if there is one const numericValue = parseFloat(value); if (!isNaN(numericValue)) { this.value = numericValue; } event.stopPropagation(); event.preventDefault(); } } onValueChange(input, value) { // ensure the value is not longer than the maxLength (verify value is a string in case it is // null or undefined, before trying to check the length. if (typeof value === 'string' && value.length > this.maxLength) { // if the type specified is a number then it may begin with a 0 // e.g. "02", in which case if we add a second digit we should drop // the leading "0" and allow the non-zero number to be added if (this.type === 'number') { value = parseFloat(value).toString(); } // remove any characters over the max length value = value.substring(0, this.maxLength); // We must manually update the input value in this case rather than relying // on Angular, as if value was previously "11" and we add an additional digit // e.g. "112", after performing the substring, the outputted value would again // be "11" which Angular would not recognize as having changed so it will not // update the value displayed in the input. input.value = value; } // emit the value after all length checks this.valueChange.emit(value); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SpinButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: SpinButtonComponent, selector: "ux-spin-button", inputs: { value: "value", type: "type", min: "min", max: "max", placeholder: "placeholder", disabled: "disabled", spinners: "spinners", readOnly: "readOnly", scrolling: "scrolling", arrowkeys: "arrowkeys", maxLength: "maxLength", incrementAriaLabel: "incrementAriaLabel", inputAriaLabel: "inputAriaLabel", decrementAriaLabel: "decrementAriaLabel" }, outputs: { valueChange: "valueChange", increment: "increment", decrement: "decrement" }, providers: [SPIN_BUTTON_VALUE_ACCESSOR], ngImport: i0, template: "@if (spinners) {\n <button type=\"button\"\n uxFocusIndicator\n class=\"spin-button\"\n tabindex=\"-1\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"incrementAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n (click)=\"triggerIncrement()\">\n <ux-icon name=\"up\" class=\"spin-button-up-icon\"></ux-icon>\n </button>\n}\n\n<input #input\n type=\"text\"\n role=\"spinbutton\"\n [min]=\"min\"\n [max]=\"max\"\n [tabindex]=\"0\"\n class=\"form-control\"\n [placeholder]=\"placeholder\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"inputAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n [attr.aria-valuemin]=\"min\"\n [attr.aria-valuenow]=\"value\"\n [attr.aria-valuemax]=\"max\"\n [attr.aria-readonly]=\"readOnly\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange(input, $event)\"\n (wheel)=\"scroll($event)\"\n (keypress)=\"onKeypress($event)\"\n (paste)=\"onPaste($event)\"\n (keydown.arrowup)=\"arrowkeys ? triggerIncrement() : null; $event.preventDefault()\"\n (keydown.arrowdown)=\"arrowkeys ? triggerDecrement() : null; $event.preventDefault()\">\n\n @if (spinners) {\n <button type=\"button\"\n uxFocusIndicator\n class=\"spin-button\"\n tabindex=\"-1\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"decrementAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n (click)=\"triggerDecrement()\">\n <ux-icon name=\"down\" class=\"spin-button-down-icon\"></ux-icon>\n </button>\n }\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SpinButtonComponent, decorators: [{ type: Component, args: [{ selector: 'ux-spin-button', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [SPIN_BUTTON_VALUE_ACCESSOR], template: "@if (spinners) {\n <button type=\"button\"\n uxFocusIndicator\n class=\"spin-button\"\n tabindex=\"-1\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"incrementAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n (click)=\"triggerIncrement()\">\n <ux-icon name=\"up\" class=\"spin-button-up-icon\"></ux-icon>\n </button>\n}\n\n<input #input\n type=\"text\"\n role=\"spinbutton\"\n [min]=\"min\"\n [max]=\"max\"\n [tabindex]=\"0\"\n class=\"form-control\"\n [placeholder]=\"placeholder\"\n [readOnly]=\"readOnly\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"inputAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n [attr.aria-valuemin]=\"min\"\n [attr.aria-valuenow]=\"value\"\n [attr.aria-valuemax]=\"max\"\n [attr.aria-readonly]=\"readOnly\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onValueChange(input, $event)\"\n (wheel)=\"scroll($event)\"\n (keypress)=\"onKeypress($event)\"\n (paste)=\"onPaste($event)\"\n (keydown.arrowup)=\"arrowkeys ? triggerIncrement() : null; $event.preventDefault()\"\n (keydown.arrowdown)=\"arrowkeys ? triggerDecrement() : null; $event.preventDefault()\">\n\n @if (spinners) {\n <button type=\"button\"\n uxFocusIndicator\n class=\"spin-button\"\n tabindex=\"-1\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"decrementAriaLabel\"\n [attr.aria-disabled]=\"disabled\"\n (click)=\"triggerDecrement()\">\n <ux-icon name=\"down\" class=\"spin-button-down-icon\"></ux-icon>\n </button>\n }\n" }] }], propDecorators: { value: [{ type: Input }], type: [{ type: Input }], min: [{ type: Input }], max: [{ type: Input }], placeholder: [{ type: Input }], disabled: [{ type: Input }], spinners: [{ type: Input }], readOnly: [{ type: Input }], scrolling: [{ type: Input }], arrowkeys: [{ type: Input }], maxLength: [{ type: Input }], incrementAriaLabel: [{ type: Input }], inputAriaLabel: [{ type: Input }], decrementAriaLabel: [{ type: Input }], valueChange: [{ type: Output }], increment: [{ type: Output }], decrement: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bpbi1idXR0b24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bpbi1idXR0b24vc3Bpbi1idXR0b24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bpbi1idXR0b24vc3Bpbi1idXR0b24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFKLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFFekUsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUc7SUFDdEMsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDO0lBQ2xELEtBQUssRUFBRSxJQUFJO0NBQ2QsQ0FBQztBQVNGLE1BQU0sT0FBTyxtQkFBbUI7SUFQaEM7UUFRcUIsb0JBQWUsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQVlwRCxTQUFJLEdBQVcsTUFBTSxDQUFDO1FBR3RCLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFDMUIsYUFBUSxHQUFZLElBQUksQ0FBQztRQUN6QixhQUFRLEdBQVksSUFBSSxDQUFDO1FBQ3pCLGNBQVMsR0FBWSxJQUFJLENBQUM7UUFDMUIsY0FBUyxHQUFZLElBQUksQ0FBQztRQUMxQixjQUFTLEdBQVcsUUFBUSxDQUFDO1FBTTVCLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7UUFFbEQsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFDckMsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFL0MsZ0VBQWdFO1FBQ2hFLHNCQUFpQixHQUFlLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMxQyxnRUFBZ0U7UUFDaEUscUJBQWdCLEdBQWlDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUcxQyxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4RCw2Q0FBNkM7UUFDNUIsZ0JBQVcsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztLQWlIN0Q7SUF2SkcsSUFBYSxLQUFLLENBQUMsS0FBc0I7UUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxJQUFJLEtBQUs7UUFDTCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQWdDRCxNQUFNLENBQUMsS0FBaUI7UUFFcEIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNsQixPQUFPO1FBQ1gsQ0FBQztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUM1QixDQUFDO2FBQU0sQ0FBQztZQUNKLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQzVCLENBQUM7UUFFRCxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELGdCQUFnQjtRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixDQUFDO0lBQ0wsQ0FBQztJQUVELGdCQUFnQjtRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixDQUFDO0lBQ0wsQ0FBQztJQUVELFVBQVUsQ0FBQyxLQUFzQjtRQUM3QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsZUFBZSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUFnQztRQUM3QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxFQUFjO1FBQzVCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxFQUFFLENBQUM7SUFDaEMsQ0FBQztJQUVELGdCQUFnQixDQUFDLFVBQW1CO1FBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO1FBQzNCLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVELFVBQVUsQ0FBQyxLQUFvQjtRQUUzQix1REFBdUQ7UUFDdkQsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3pCLE9BQU87UUFDWCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE9BQU8sS0FBSyxDQUFDO1FBQ2pCLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQsT0FBTyxDQUFDLEtBQXFCO1FBRXpCLHVEQUF1RDtRQUN2RCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDekIsT0FBTztRQUNYLENBQUM7UUFFRCw2QkFBNkI7UUFDN0IsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbEQscUNBQXFDO1FBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBRWhDLCtDQUErQztZQUMvQyxNQUFNLFlBQVksR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUN2QixJQUFJLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQztZQUM5QixDQUFDO1lBRUQsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3hCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUMzQixDQUFDO0lBQ0wsQ0FBQztJQUVELGFBQWEsQ0FBQyxLQUF1QixFQUFFLEtBQWE7UUFFaEQsNEZBQTRGO1FBQzVGLHdEQUF3RDtRQUN4RCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUU3RCwrREFBK0Q7WUFDL0QsbUVBQW1FO1lBQ25FLDREQUE0RDtZQUM1RCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3pCLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDekMsQ0FBQztZQUVELDRDQUE0QztZQUM1QyxLQUFLLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRTNDLDJFQUEyRTtZQUMzRSw2RUFBNkU7WUFDN0UsOEVBQThFO1lBQzlFLDZFQUE2RTtZQUM3RSwyQ0FBMkM7WUFDM0MsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDeEIsQ0FBQztRQUVELHlDQUF5QztRQUN6QyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqQyxDQUFDOytHQXpKUSxtQkFBbUI7bUdBQW5CLG1CQUFtQixnZUFGakIsQ0FBQywwQkFBMEIsQ0FBQywwQkNkM0MsOCtDQWlEQTs7NEZEakNhLG1CQUFtQjtrQkFQL0IsU0FBUzsrQkFDSSxnQkFBZ0IsaUJBRVgsaUJBQWlCLENBQUMsSUFBSSxtQkFDcEIsdUJBQXVCLENBQUMsTUFBTSxhQUNwQyxDQUFDLDBCQUEwQixDQUFDOzhCQUsxQixLQUFLO3NCQUFqQixLQUFLO2dCQVVHLElBQUk7c0JBQVosS0FBSztnQkFDRyxHQUFHO3NCQUFYLEtBQUs7Z0JBQ0csR0FBRztzQkFBWCxLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUVJLFdBQVc7c0JBQXBCLE1BQU07Z0JBRUcsU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgZm9yd2FyZFJlZiwgaW5qZWN0LCBJbnB1dCwgT3V0cHV0LCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5leHBvcnQgY29uc3QgU1BJTl9CVVRUT05fVkFMVUVfQUNDRVNTT1IgPSB7XG4gICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gU3BpbkJ1dHRvbkNvbXBvbmVudCksXG4gICAgbXVsdGk6IHRydWVcbn07XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAndXgtc3Bpbi1idXR0b24nLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zcGluLWJ1dHRvbi5jb21wb25lbnQuaHRtbCcsXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBwcm92aWRlcnM6IFtTUElOX0JVVFRPTl9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgU3BpbkJ1dHRvbkNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgICBASW5wdXQoKSBzZXQgdmFsdWUodmFsdWU6IHN0cmluZyB8IG51bWJlcikge1xuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sodmFsdWUpO1xuICAgICAgICB0aGlzLm9uVG91Y2hlZENhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgZ2V0IHZhbHVlKCk6IHN0cmluZyB8IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSB0eXBlOiBzdHJpbmcgPSAndGV4dCc7XG4gICAgQElucHV0KCkgbWluOiBudW1iZXI7XG4gICAgQElucHV0KCkgbWF4OiBudW1iZXI7XG4gICAgQElucHV0KCkgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICcnO1xuICAgIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgc3Bpbm5lcnM6IGJvb2xlYW4gPSB0cnVlO1xuICAgIEBJbnB1dCgpIHJlYWRPbmx5OiBib29sZWFuID0gdHJ1ZTtcbiAgICBASW5wdXQoKSBzY3JvbGxpbmc6IGJvb2xlYW4gPSB0cnVlO1xuICAgIEBJbnB1dCgpIGFycm93a2V5czogYm9vbGVhbiA9IHRydWU7XG4gICAgQElucHV0KCkgbWF4TGVuZ3RoOiBudW1iZXIgPSBJbmZpbml0eTtcblxuICAgIEBJbnB1dCgpIGluY3JlbWVudEFyaWFMYWJlbDogc3RyaW5nO1xuICAgIEBJbnB1dCgpIGlucHV0QXJpYUxhYmVsOiBzdHJpbmc7XG4gICAgQElucHV0KCkgZGVjcmVtZW50QXJpYUxhYmVsOiBzdHJpbmc7XG5cbiAgICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bWJlcj4oKTtcblxuICAgIEBPdXRwdXQoKSBpbmNyZW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gICAgQE91dHB1dCgpIGRlY3JlbWVudCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvblRvdWNoZWRDYWxsYmFjazogKCkgPT4gdm9pZCA9ICgpID0+IHsgfTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gICAgb25DaGFuZ2VDYWxsYmFjazogKF86IHN0cmluZyB8IG51bWJlcikgPT4gdm9pZCA9ICgpID0+IHsgfTtcblxuICAgIHByaXZhdGUgX3ZhbHVlOiBzdHJpbmcgfCBudW1iZXI7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVnZXhLZXlwcmVzcyA9IFJlZ0V4cCgvXlswLTkuLC1dKyQvKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1lc2NhcGVcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yZWdleFBhc3RlID0gUmVnRXhwKC9eXFwtP1xcZCsoXFwuXFxkKyk/JC8pO1xuXG4gICAgc2Nyb2xsKGV2ZW50OiBXaGVlbEV2ZW50KTogdm9pZCB7XG5cbiAgICAgICAgaWYgKCF0aGlzLnNjcm9sbGluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50LmRlbHRhWSA+IDApIHtcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlckRlY3JlbWVudCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VySW5jcmVtZW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIHRyaWdnZXJJbmNyZW1lbnQoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5pbmNyZW1lbnQuZW1pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdHJpZ2dlckRlY3JlbWVudCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmRlY3JlbWVudC5lbWl0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3cml0ZVZhbHVlKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG5cbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoXzogc3RyaW5nIHwgbnVtYmVyKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayA9IGZuO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkQ2FsbGJhY2sgPSBmbjtcbiAgICB9XG5cbiAgICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cblxuICAgIG9uS2V5cHJlc3MoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcblxuICAgICAgICAvLyB3ZSBvbmx5IG5lZWQgdG8gcGVyZm9ybSBjaGVja3MgaWYgdGhlIHR5cGUgaXMgbnVtYmVyXG4gICAgICAgIGlmICh0aGlzLnR5cGUgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX3JlZ2V4S2V5cHJlc3MudGVzdChldmVudC5rZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBvblBhc3RlKGV2ZW50OiBDbGlwYm9hcmRFdmVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIHdlIG9ubHkgbmVlZCB0byBwZXJmb3JtIGNoZWNrcyBpZiB0aGUgdHlwZSBpcyBudW1iZXJcbiAgICAgICAgaWYgKHRoaXMudHlwZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCB0aGUgdmFsdWUgYmVpbmcgcGFzdGVkXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZXZlbnQuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCd0ZXh0Jyk7XG5cbiAgICAgICAgLy8gY2hlY2sgaWYgaXQgY29udGFpbnMgdGhlIGNoYXJhY3RlclxuICAgICAgICBpZiAoIXRoaXMuX3JlZ2V4UGFzdGUudGVzdCh2YWx1ZSkpIHtcblxuICAgICAgICAgICAgLy8gaW5zZXQgdGhlIG51bWVyaWMgdmFsdWUgb25seSBpZiB0aGVyZSBpcyBvbmVcbiAgICAgICAgICAgIGNvbnN0IG51bWVyaWNWYWx1ZSA9IHBhcnNlRmxvYXQodmFsdWUpO1xuXG4gICAgICAgICAgICBpZiAoIWlzTmFOKG51bWVyaWNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gbnVtZXJpY1ZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblZhbHVlQ2hhbmdlKGlucHV0OiBIVE1MSW5wdXRFbGVtZW50LCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgLy8gZW5zdXJlIHRoZSB2YWx1ZSBpcyBub3QgbG9uZ2VyIHRoYW4gdGhlIG1heExlbmd0aCAodmVyaWZ5IHZhbHVlIGlzIGEgc3RyaW5nIGluIGNhc2UgaXQgaXNcbiAgICAgICAgLy8gbnVsbCBvciB1bmRlZmluZWQsIGJlZm9yZSB0cnlpbmcgdG8gY2hlY2sgdGhlIGxlbmd0aC5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUubGVuZ3RoID4gdGhpcy5tYXhMZW5ndGgpIHtcblxuICAgICAgICAgICAgLy8gaWYgdGhlIHR5cGUgc3BlY2lmaWVkIGlzIGEgbnVtYmVyIHRoZW4gaXQgbWF5IGJlZ2luIHdpdGggYSAwXG4gICAgICAgICAgICAvLyBlLmcuIFwiMDJcIiwgaW4gd2hpY2ggY2FzZSBpZiB3ZSBhZGQgYSBzZWNvbmQgZGlnaXQgd2Ugc2hvdWxkIGRyb3BcbiAgICAgICAgICAgIC8vIHRoZSBsZWFkaW5nIFwiMFwiIGFuZCBhbGxvdyB0aGUgbm9uLXplcm8gbnVtYmVyIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICBpZiAodGhpcy50eXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcmVtb3ZlIGFueSBjaGFyYWN0ZXJzIG92ZXIgdGhlIG1heCBsZW5ndGhcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3Vic3RyaW5nKDAsIHRoaXMubWF4TGVuZ3RoKTtcblxuICAgICAgICAgICAgLy8gV2UgbXVzdCBtYW51YWxseSB1cGRhdGUgdGhlIGlucHV0IHZhbHVlIGluIHRoaXMgY2FzZSByYXRoZXIgdGhhbiByZWx5aW5nXG4gICAgICAgICAgICAvLyBvbiBBbmd1bGFyLCBhcyBpZiB2YWx1ZSB3YXMgcHJldmlvdXNseSBcIjExXCIgYW5kIHdlIGFkZCBhbiBhZGRpdGlvbmFsIGRpZ2l0XG4gICAgICAgICAgICAvLyBlLmcuIFwiMTEyXCIsIGFmdGVyIHBlcmZvcm1pbmcgdGhlIHN1YnN0cmluZywgdGhlIG91dHB1dHRlZCB2YWx1ZSB3b3VsZCBhZ2FpblxuICAgICAgICAgICAgLy8gYmUgXCIxMVwiIHdoaWNoIEFuZ3VsYXIgd291bGQgbm90IHJlY29nbml6ZSBhcyBoYXZpbmcgY2hhbmdlZCBzbyBpdCB3aWxsIG5vdFxuICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSB2YWx1ZSBkaXNwbGF5ZWQgaW4gdGhlIGlucHV0LlxuICAgICAgICAgICAgaW5wdXQudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVtaXQgdGhlIHZhbHVlIGFmdGVyIGFsbCBsZW5ndGggY2hlY2tzXG4gICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gICAgfVxufVxuIiwiQGlmIChzcGlubmVycykge1xuICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgIHV4Rm9jdXNJbmRpY2F0b3JcbiAgICBjbGFzcz1cInNwaW4tYnV0dG9uXCJcbiAgICB0YWJpbmRleD1cIi0xXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiaW5jcmVtZW50QXJpYUxhYmVsXCJcbiAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAoY2xpY2spPVwidHJpZ2dlckluY3JlbWVudCgpXCI+XG4gICAgPHV4LWljb24gbmFtZT1cInVwXCIgY2xhc3M9XCJzcGluLWJ1dHRvbi11cC1pY29uXCI+PC91eC1pY29uPlxuICA8L2J1dHRvbj5cbn1cblxuPGlucHV0ICNpbnB1dFxuICB0eXBlPVwidGV4dFwiXG4gIHJvbGU9XCJzcGluYnV0dG9uXCJcbiAgW21pbl09XCJtaW5cIlxuICBbbWF4XT1cIm1heFwiXG4gIFt0YWJpbmRleF09XCIwXCJcbiAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICBbcmVhZE9ubHldPVwicmVhZE9ubHlcIlxuICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICBbYXR0ci5hcmlhLWxhYmVsXT1cImlucHV0QXJpYUxhYmVsXCJcbiAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gIFthdHRyLmFyaWEtdmFsdWVtaW5dPVwibWluXCJcbiAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJ2YWx1ZVwiXG4gIFthdHRyLmFyaWEtdmFsdWVtYXhdPVwibWF4XCJcbiAgW2F0dHIuYXJpYS1yZWFkb25seV09XCJyZWFkT25seVwiXG4gIFtuZ01vZGVsXT1cInZhbHVlXCJcbiAgKG5nTW9kZWxDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZShpbnB1dCwgJGV2ZW50KVwiXG4gICh3aGVlbCk9XCJzY3JvbGwoJGV2ZW50KVwiXG4gIChrZXlwcmVzcyk9XCJvbktleXByZXNzKCRldmVudClcIlxuICAocGFzdGUpPVwib25QYXN0ZSgkZXZlbnQpXCJcbiAgKGtleWRvd24uYXJyb3d1cCk9XCJhcnJvd2tleXMgPyB0cmlnZ2VySW5jcmVtZW50KCkgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG4gIChrZXlkb3duLmFycm93ZG93bik9XCJhcnJvd2tleXMgPyB0cmlnZ2VyRGVjcmVtZW50KCkgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiPlxuXG4gIEBpZiAoc3Bpbm5lcnMpIHtcbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgdXhGb2N1c0luZGljYXRvclxuICAgICAgY2xhc3M9XCJzcGluLWJ1dHRvblwiXG4gICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImRlY3JlbWVudEFyaWFMYWJlbFwiXG4gICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIChjbGljayk9XCJ0cmlnZ2VyRGVjcmVtZW50KClcIj5cbiAgICAgIDx1eC1pY29uIG5hbWU9XCJkb3duXCIgY2xhc3M9XCJzcGluLWJ1dHRvbi1kb3duLWljb25cIj48L3V4LWljb24+XG4gICAgPC9idXR0b24+XG4gIH1cbiJdfQ==