@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
169 lines • 26 kB
JavaScript
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bpbi1idXR0b24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bpbi1idXR0b24vc3Bpbi1idXR0b24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvc3Bpbi1idXR0b24vc3Bpbi1idXR0b24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFKLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFFekUsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUc7SUFDdEMsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDO0lBQ2xELEtBQUssRUFBRSxJQUFJO0NBQ2QsQ0FBQztBQVNGLE1BQU0sT0FBTyxtQkFBbUI7SUFQaEM7UUFRcUIsb0JBQWUsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQVlwRCxTQUFJLEdBQVcsTUFBTSxDQUFDO1FBR3RCLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFDMUIsYUFBUSxHQUFZLElBQUksQ0FBQztRQUN6QixhQUFRLEdBQVksSUFBSSxDQUFDO1FBQ3pCLGNBQVMsR0FBWSxJQUFJLENBQUM7UUFDMUIsY0FBUyxHQUFZLElBQUksQ0FBQztRQUMxQixjQUFTLEdBQVcsUUFBUSxDQUFDO1FBTTVCLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7UUFFbEQsY0FBUyxHQUFHLElBQUksWUFBWSxF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QjtrQkFQL0IsU0FBUzsrQkFDSSxnQkFBZ0IsaUJBRVgsaUJBQWlCLENBQUMsSUFBSSxtQkFDcEIsdUJBQXVCLENBQUMsTUFBTSxhQUNwQyxDQUFDLDBCQUEwQixDQUFDOzhCQUsxQixLQUFLO3NCQUFqQixLQUFLO2dCQVVHLElBQUk7c0JBQVosS0FBSztnQkFDRyxHQUFHO3NCQUFYLEtBQUs7Z0JBQ0csR0FBRztzQkFBWCxLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUVJLFdBQVc7c0JBQXBCLE1BQU07Z0JBRUcsU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgZm9yd2FyZFJlZiwgaW5qZWN0LCBJbnB1dCwgT3V0cHV0LCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5leHBvcnQgY29uc3QgU1BJTl9CVVRUT05fVkFMVUVfQUNDRVNTT1IgPSB7XG4gICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gU3BpbkJ1dHRvbkNvbXBvbmVudCksXG4gICAgbXVsdGk6IHRydWVcbn07XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAndXgtc3Bpbi1idXR0b24nLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zcGluLWJ1dHRvbi5jb21wb25lbnQuaHRtbCcsXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgICBwcm92aWRlcnM6IFtTUElOX0JVVFRPTl9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgU3BpbkJ1dHRvbkNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgICBASW5wdXQoKSBzZXQgdmFsdWUodmFsdWU6IHN0cmluZyB8IG51bWJlcikge1xuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sodmFsdWUpO1xuICAgICAgICB0aGlzLm9uVG91Y2hlZENhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgZ2V0IHZhbHVlKCk6IHN0cmluZyB8IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZTtcbiAgICB9XG5cbiAgICBASW5wdXQoKSB0eXBlOiBzdHJpbmcgPSAndGV4dCc7XG4gICAgQElucHV0KCkgbWluOiBudW1iZXI7XG4gICAgQElucHV0KCkgbWF4OiBudW1iZXI7XG4gICAgQElucHV0KCkgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICcnO1xuICAgIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG4gICAgQElucHV0KCkgc3Bpbm5lcnM6IGJvb2xlYW4gPSB0cnVlO1xuICAgIEBJbnB1dCgpIHJlYWRPbmx5OiBib29sZWFuID0gdHJ1ZTtcbiAgICBASW5wdXQoKSBzY3JvbGxpbmc6IGJvb2xlYW4gPSB0cnVlO1xuICAgIEBJbnB1dCgpIGFycm93a2V5czogYm9vbGVhbiA9IHRydWU7XG4gICAgQElucHV0KCkgbWF4TGVuZ3RoOiBudW1iZXIgPSBJbmZpbml0eTtcblxuICAgIEBJbnB1dCgpIGluY3JlbWVudEFyaWFMYWJlbDogc3RyaW5nO1xuICAgIEBJbnB1dCgpIGlucHV0QXJpYUxhYmVsOiBzdHJpbmc7XG4gICAgQElucHV0KCkgZGVjcmVtZW50QXJpYUxhYmVsOiBzdHJpbmc7XG5cbiAgICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bWJlcj4oKTtcblxuICAgIEBPdXRwdXQoKSBpbmNyZW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gICAgQE91dHB1dCgpIGRlY3JlbWVudCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvblRvdWNoZWRDYWxsYmFjazogKCkgPT4gdm9pZCA9ICgpID0+IHsgfTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gICAgb25DaGFuZ2VDYWxsYmFjazogKF86IHN0cmluZyB8IG51bWJlcikgPT4gdm9pZCA9ICgpID0+IHsgfTtcblxuICAgIHByaXZhdGUgX3ZhbHVlOiBzdHJpbmcgfCBudW1iZXI7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVnZXhLZXlwcmVzcyA9IFJlZ0V4cCgvXlswLTkuLC1dKyQvKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1lc2NhcGVcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yZWdleFBhc3RlID0gUmVnRXhwKC9eXFwtP1xcZCsoXFwuXFxkKyk/JC8pO1xuXG4gICAgc2Nyb2xsKGV2ZW50OiBXaGVlbEV2ZW50KTogdm9pZCB7XG5cbiAgICAgICAgaWYgKCF0aGlzLnNjcm9sbGluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50LmRlbHRhWSA+IDApIHtcbiAgICAgICAgICAgIHRoaXMudHJpZ2dlckRlY3JlbWVudCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VySW5jcmVtZW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIHRyaWdnZXJJbmNyZW1lbnQoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5pbmNyZW1lbnQuZW1pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdHJpZ2dlckRlY3JlbWVudCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLmRlY3JlbWVudC5lbWl0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3cml0ZVZhbHVlKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKTtcbiAgICB9XG5cbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoXzogc3RyaW5nIHwgbnVtYmVyKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayA9IGZuO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkQ2FsbGJhY2sgPSBmbjtcbiAgICB9XG5cbiAgICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgICAgIHRoaXMuX2NoYW5nZURldGVjdG9yLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cblxuICAgIG9uS2V5cHJlc3MoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiBib29sZWFuIHtcblxuICAgICAgICAvLyB3ZSBvbmx5IG5lZWQgdG8gcGVyZm9ybSBjaGVja3MgaWYgdGhlIHR5cGUgaXMgbnVtYmVyXG4gICAgICAgIGlmICh0aGlzLnR5cGUgIT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuX3JlZ2V4S2V5cHJlc3MudGVzdChldmVudC5rZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBvblBhc3RlKGV2ZW50OiBDbGlwYm9hcmRFdmVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIHdlIG9ubHkgbmVlZCB0byBwZXJmb3JtIGNoZWNrcyBpZiB0aGUgdHlwZSBpcyBudW1iZXJcbiAgICAgICAgaWYgKHRoaXMudHlwZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGdldCB0aGUgdmFsdWUgYmVpbmcgcGFzdGVkXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZXZlbnQuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCd0ZXh0Jyk7XG5cbiAgICAgICAgLy8gY2hlY2sgaWYgaXQgY29udGFpbnMgdGhlIGNoYXJhY3RlclxuICAgICAgICBpZiAoIXRoaXMuX3JlZ2V4UGFzdGUudGVzdCh2YWx1ZSkpIHtcblxuICAgICAgICAgICAgLy8gaW5zZXQgdGhlIG51bWVyaWMgdmFsdWUgb25seSBpZiB0aGVyZSBpcyBvbmVcbiAgICAgICAgICAgIGNvbnN0IG51bWVyaWNWYWx1ZSA9IHBhcnNlRmxvYXQodmFsdWUpO1xuXG4gICAgICAgICAgICBpZiAoIWlzTmFOKG51bWVyaWNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gbnVtZXJpY1ZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblZhbHVlQ2hhbmdlKGlucHV0OiBIVE1MSW5wdXRFbGVtZW50LCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgLy8gZW5zdXJlIHRoZSB2YWx1ZSBpcyBub3QgbG9uZ2VyIHRoYW4gdGhlIG1heExlbmd0aCAodmVyaWZ5IHZhbHVlIGlzIGEgc3RyaW5nIGluIGNhc2UgaXQgaXNcbiAgICAgICAgLy8gbnVsbCBvciB1bmRlZmluZWQsIGJlZm9yZSB0cnlpbmcgdG8gY2hlY2sgdGhlIGxlbmd0aC5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUubGVuZ3RoID4gdGhpcy5tYXhMZW5ndGgpIHtcblxuICAgICAgICAgICAgLy8gaWYgdGhlIHR5cGUgc3BlY2lmaWVkIGlzIGEgbnVtYmVyIHRoZW4gaXQgbWF5IGJlZ2luIHdpdGggYSAwXG4gICAgICAgICAgICAvLyBlLmcuIFwiMDJcIiwgaW4gd2hpY2ggY2FzZSBpZiB3ZSBhZGQgYSBzZWNvbmQgZGlnaXQgd2Ugc2hvdWxkIGRyb3BcbiAgICAgICAgICAgIC8vIHRoZSBsZWFkaW5nIFwiMFwiIGFuZCBhbGxvdyB0aGUgbm9uLXplcm8gbnVtYmVyIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICBpZiAodGhpcy50eXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcmVtb3ZlIGFueSBjaGFyYWN0ZXJzIG92ZXIgdGhlIG1heCBsZW5ndGhcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3Vic3RyaW5nKDAsIHRoaXMubWF4TGVuZ3RoKTtcblxuICAgICAgICAgICAgLy8gV2UgbXVzdCBtYW51YWxseSB1cGRhdGUgdGhlIGlucHV0IHZhbHVlIGluIHRoaXMgY2FzZSByYXRoZXIgdGhhbiByZWx5aW5nXG4gICAgICAgICAgICAvLyBvbiBBbmd1bGFyLCBhcyBpZiB2YWx1ZSB3YXMgcHJldmlvdXNseSBcIjExXCIgYW5kIHdlIGFkZCBhbiBhZGRpdGlvbmFsIGRpZ2l0XG4gICAgICAgICAgICAvLyBlLmcuIFwiMTEyXCIsIGFmdGVyIHBlcmZvcm1pbmcgdGhlIHN1YnN0cmluZywgdGhlIG91dHB1dHRlZCB2YWx1ZSB3b3VsZCBhZ2FpblxuICAgICAgICAgICAgLy8gYmUgXCIxMVwiIHdoaWNoIEFuZ3VsYXIgd291bGQgbm90IHJlY29nbml6ZSBhcyBoYXZpbmcgY2hhbmdlZCBzbyBpdCB3aWxsIG5vdFxuICAgICAgICAgICAgLy8gdXBkYXRlIHRoZSB2YWx1ZSBkaXNwbGF5ZWQgaW4gdGhlIGlucHV0LlxuICAgICAgICAgICAgaW5wdXQudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVtaXQgdGhlIHZhbHVlIGFmdGVyIGFsbCBsZW5ndGggY2hlY2tzXG4gICAgICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gICAgfVxufVxuIiwiQGlmIChzcGlubmVycykge1xuICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgIHV4Rm9jdXNJbmRpY2F0b3JcbiAgICBjbGFzcz1cInNwaW4tYnV0dG9uXCJcbiAgICB0YWJpbmRleD1cIi0xXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiaW5jcmVtZW50QXJpYUxhYmVsXCJcbiAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAoY2xpY2spPVwidHJpZ2dlckluY3JlbWVudCgpXCI+XG4gICAgPHV4LWljb24gbmFtZT1cInVwXCIgY2xhc3M9XCJzcGluLWJ1dHRvbi11cC1pY29uXCI+PC91eC1pY29uPlxuICA8L2J1dHRvbj5cbn1cblxuPGlucHV0ICNpbnB1dFxuICB0eXBlPVwidGV4dFwiXG4gIHJvbGU9XCJzcGluYnV0dG9uXCJcbiAgW21pbl09XCJtaW5cIlxuICBbbWF4XT1cIm1heFwiXG4gIFt0YWJpbmRleF09XCIwXCJcbiAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICBbcmVhZE9ubHldPVwicmVhZE9ubHlcIlxuICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICBbYXR0ci5hcmlhLWxhYmVsXT1cImlucHV0QXJpYUxhYmVsXCJcbiAgW2F0dHIuYXJpYS1kaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gIFthdHRyLmFyaWEtdmFsdWVtaW5dPVwibWluXCJcbiAgW2F0dHIuYXJpYS12YWx1ZW5vd109XCJ2YWx1ZVwiXG4gIFthdHRyLmFyaWEtdmFsdWVtYXhdPVwibWF4XCJcbiAgW2F0dHIuYXJpYS1yZWFkb25seV09XCJyZWFkT25seVwiXG4gIFtuZ01vZGVsXT1cInZhbHVlXCJcbiAgKG5nTW9kZWxDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZShpbnB1dCwgJGV2ZW50KVwiXG4gICh3aGVlbCk9XCJzY3JvbGwoJGV2ZW50KVwiXG4gIChrZXlwcmVzcyk9XCJvbktleXByZXNzKCRldmVudClcIlxuICAocGFzdGUpPVwib25QYXN0ZSgkZXZlbnQpXCJcbiAgKGtleWRvd24uYXJyb3d1cCk9XCJhcnJvd2tleXMgPyB0cmlnZ2VySW5jcmVtZW50KCkgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG4gIChrZXlkb3duLmFycm93ZG93bik9XCJhcnJvd2tleXMgPyB0cmlnZ2VyRGVjcmVtZW50KCkgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiPlxuXG4gIEBpZiAoc3Bpbm5lcnMpIHtcbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgdXhGb2N1c0luZGljYXRvclxuICAgICAgY2xhc3M9XCJzcGluLWJ1dHRvblwiXG4gICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImRlY3JlbWVudEFyaWFMYWJlbFwiXG4gICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIChjbGljayk9XCJ0cmlnZ2VyRGVjcmVtZW50KClcIj5cbiAgICAgIDx1eC1pY29uIG5hbWU9XCJkb3duXCIgY2xhc3M9XCJzcGluLWJ1dHRvbi1kb3duLWljb25cIj48L3V4LWljb24+XG4gICAgPC9idXR0b24+XG4gIH1cbiJdfQ==