UNPKG

ngx-otp-input

Version:

One Time Password input library for Angular (14+)

131 lines 22.4 kB
import { Component, EventEmitter, Input, Output, } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormArray, FormControl, ReactiveFormsModule, Validators, } from '@angular/forms'; import { PasteDirective } from './directives/paste.directive'; import { AutoFocusDirective } from './directives/autoFocus.directive'; import { InputNavigationsDirective, } from './directives/inputNavigations.directive'; import { AutoBlurDirective } from './directives/autoBlur.directive'; import { AriaLabelsDirective } from './directives/ariaLabels.directive'; import { defaultOptions } from './default.config'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/forms"; export var NgxOtpStatus; (function (NgxOtpStatus) { NgxOtpStatus["SUCCESS"] = "success"; NgxOtpStatus["FAILED"] = "failed"; })(NgxOtpStatus || (NgxOtpStatus = {})); export class NgxOtpInputComponent { constructor() { this.ngxOtpOptions = defaultOptions; this.disabled = false; this.otpChange = new EventEmitter(); this.otpComplete = new EventEmitter(); } set options(customOptions) { this.ngxOtpOptions = { ...defaultOptions, ...customOptions }; } // For testing purposes get ngxOtpOptionsInUse() { return this.ngxOtpOptions; } get inputType() { return this.ngxOtpOptions.hideInputValues ? 'password' : 'text'; } get isOTPSuccess() { return this.status === NgxOtpStatus.SUCCESS; } get isOTPFailed() { return this.status === NgxOtpStatus.FAILED; } ngOnInit() { this.initOtpInputArray(); } ngOnChanges(changes) { const otpChange = changes['otp']; if (otpChange?.currentValue) { if (!otpChange.firstChange) { this.setInitialOtp(otpChange.currentValue); } else { this.ngxOtpOptions.autoFocus = false; } } } initOtpInputArray() { this.ngxOtpInputArray = new FormArray(Array.from({ length: this.ngxOtpOptions.otpLength }, () => new FormControl('', Validators.required))); if (this.otp) { this.setInitialOtp(this.otp); } } setInitialOtp(otp) { if (this.ngxOtpOptions.regexp.test(otp)) { const otpValueArray = otp.split(''); otpValueArray.forEach((value, index) => { this.ngxOtpInputArray.controls[index].setValue(value ?? ''); }); this.emitOtpValueChange(); if (otpValueArray.length !== this.ngxOtpOptions.otpLength) { console.warn('OTP length does not match the provided otpLength option!'); } } else { throw new Error('Invalid OTP provided for the component <ngx-otp-input>'); } } handleInputChanges($event) { const [index, value] = $event; this.ngxOtpInputArray.controls[index].setValue(value); this.emitOtpValueChange(); } handlePasteChange($event) { if ($event.length === this.ngxOtpOptions.otpLength) { this.ngxOtpInputArray.setValue($event); } else { $event.map((value, index) => { this.ngxOtpInputArray.controls[index]?.setValue?.(value); }); } this.emitOtpValueChange(); } emitOtpValueChange() { this.otpChange.emit(this.ngxOtpInputArray.value); if (this.ngxOtpInputArray.valid) { this.otpComplete.emit(this.ngxOtpInputArray.value.join('')); } } isInputFilled(index) { return !!this.ngxOtpInputArray.controls[index].value; } reset() { this.ngxOtpInputArray.reset(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: NgxOtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.1", type: NgxOtpInputComponent, isStandalone: true, selector: "ngx-otp-input", inputs: { options: "options", status: "status", disabled: "disabled", otp: "otp" }, outputs: { otpChange: "otpChange", otpComplete: "otpComplete" }, usesOnChanges: true, ngImport: i0, template: "<form\n ngxOtpPaste\n ngxInputNavigations\n [regexp]=\"ngxOtpOptions.regexp!\"\n [isFormValid]=\"ngxOtpInputArray.valid\"\n [ngxAutoFocus]=\"ngxOtpOptions.autoFocus!\"\n [ngxAutoBlur]=\"ngxOtpOptions.autoBlur!\"\n [ngxOtpAriaLabels]=\"ngxOtpOptions.ariaLabels!\"\n [ngClass]=\"{\n 'ngx-blinking-cursor': ngxOtpOptions.showBlinkingCursor\n }\"\n (valueChange)=\"handleInputChanges($event)\"\n (handlePaste)=\"handlePasteChange($event)\"\n class=\"ngx-otp-input-form\"\n data-testid=\"ngx-otp-input-form\"\n>\n <input\n *ngFor=\"let control of ngxOtpInputArray.controls; let i = index\"\n #otpInputElement\n [value]=\"control.value\"\n [type]=\"inputType\"\n [inputMode]=\"ngxOtpOptions.inputMode\"\n [disabled]=\"disabled\"\n [ngClass]=\"{\n 'ngx-otp-input-disabled': disabled,\n 'ngx-otp-input-filled': isInputFilled(i),\n 'ngx-otp-input-success': isOTPSuccess,\n 'ngx-otp-input-failed': isOTPFailed\n }\"\n class=\"ngx-otp-input-box\"\n maxlength=\"1\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n data-testid=\"ngx-otp-input-box\"\n />\n</form>\n", styles: [".ngx-otp-input-form{display:inline-flex;gap:.5rem;caret-color:transparent}.ngx-blinking-cursor{caret-color:initial}.ngx-otp-input-box{width:30px;height:35px;padding:.5rem;font-size:1.5rem;text-align:center;border:1px solid #c4c4c4;border-radius:.5rem;outline:none}.ngx-otp-input-box:focus{border-color:#007bff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: PasteDirective, selector: "[ngxOtpPaste]", inputs: ["regexp"], outputs: ["handlePaste"] }, { kind: "directive", type: AutoFocusDirective, selector: "[ngxAutoFocus]", inputs: ["ngxAutoFocus"] }, { kind: "directive", type: InputNavigationsDirective, selector: "[ngxInputNavigations]", inputs: ["regexp"], outputs: ["valueChange"] }, { kind: "directive", type: AutoBlurDirective, selector: "[ngxAutoBlur]", inputs: ["ngxAutoBlur", "isFormValid"] }, { kind: "directive", type: AriaLabelsDirective, selector: "[ngxOtpAriaLabels]", inputs: ["ngxOtpAriaLabels"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: NgxOtpInputComponent, decorators: [{ type: Component, args: [{ standalone: true, imports: [ CommonModule, ReactiveFormsModule, PasteDirective, AutoFocusDirective, InputNavigationsDirective, AutoBlurDirective, AriaLabelsDirective, ], selector: 'ngx-otp-input', template: "<form\n ngxOtpPaste\n ngxInputNavigations\n [regexp]=\"ngxOtpOptions.regexp!\"\n [isFormValid]=\"ngxOtpInputArray.valid\"\n [ngxAutoFocus]=\"ngxOtpOptions.autoFocus!\"\n [ngxAutoBlur]=\"ngxOtpOptions.autoBlur!\"\n [ngxOtpAriaLabels]=\"ngxOtpOptions.ariaLabels!\"\n [ngClass]=\"{\n 'ngx-blinking-cursor': ngxOtpOptions.showBlinkingCursor\n }\"\n (valueChange)=\"handleInputChanges($event)\"\n (handlePaste)=\"handlePasteChange($event)\"\n class=\"ngx-otp-input-form\"\n data-testid=\"ngx-otp-input-form\"\n>\n <input\n *ngFor=\"let control of ngxOtpInputArray.controls; let i = index\"\n #otpInputElement\n [value]=\"control.value\"\n [type]=\"inputType\"\n [inputMode]=\"ngxOtpOptions.inputMode\"\n [disabled]=\"disabled\"\n [ngClass]=\"{\n 'ngx-otp-input-disabled': disabled,\n 'ngx-otp-input-filled': isInputFilled(i),\n 'ngx-otp-input-success': isOTPSuccess,\n 'ngx-otp-input-failed': isOTPFailed\n }\"\n class=\"ngx-otp-input-box\"\n maxlength=\"1\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n autocapitalize=\"off\"\n autocorrect=\"off\"\n data-testid=\"ngx-otp-input-box\"\n />\n</form>\n", styles: [".ngx-otp-input-form{display:inline-flex;gap:.5rem;caret-color:transparent}.ngx-blinking-cursor{caret-color:initial}.ngx-otp-input-box{width:30px;height:35px;padding:.5rem;font-size:1.5rem;text-align:center;border:1px solid #c4c4c4;border-radius:.5rem;outline:none}.ngx-otp-input-box:focus{border-color:#007bff}\n"] }] }], propDecorators: { options: [{ type: Input }], status: [{ type: Input }], disabled: [{ type: Input }], otp: [{ type: Input }], otpChange: [{ type: Output }], otpComplete: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW90cC1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtb3RwLWlucHV0L3NyYy9saWIvbmd4LW90cC1pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtb3RwLWlucHV0L3NyYy9saWIvbmd4LW90cC1pbnB1dC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsU0FBUyxFQUNULFdBQVcsRUFDWCxtQkFBbUIsRUFDbkIsVUFBVSxHQUNYLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzlELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFDTCx5QkFBeUIsR0FFMUIsTUFBTSx5Q0FBeUMsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN4RSxPQUFPLEVBQStCLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDOzs7O0FBRS9FLE1BQU0sQ0FBTixJQUFZLFlBR1g7QUFIRCxXQUFZLFlBQVk7SUFDdEIsbUNBQW1CLENBQUE7SUFDbkIsaUNBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQUhXLFlBQVksS0FBWixZQUFZLFFBR3ZCO0FBaUJELE1BQU0sT0FBTyxvQkFBb0I7SUFmakM7UUFpQlksa0JBQWEsR0FBZ0MsY0FBYyxDQUFDO1FBTzdELGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFaEIsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFZLENBQUM7UUFDekMsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO0tBOEZwRDtJQXRHQyxJQUFhLE9BQU8sQ0FBQyxhQUEwQztRQUM3RCxJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsR0FBRyxjQUFjLEVBQUUsR0FBRyxhQUFhLEVBQUUsQ0FBQztJQUMvRCxDQUFDO0lBUUQsdUJBQXVCO0lBQ3ZCLElBQUksa0JBQWtCO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBSSxTQUFTO1FBQ1gsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDbEUsQ0FBQztJQUVELElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sS0FBSyxZQUFZLENBQUMsT0FBTyxDQUFDO0lBQzlDLENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxNQUFNLEtBQUssWUFBWSxDQUFDLE1BQU0sQ0FBQztJQUM3QyxDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLElBQUksU0FBUyxFQUFFLFlBQVksRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzdDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7WUFDdkMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8saUJBQWlCO1FBQ3ZCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLFNBQVMsQ0FDbkMsS0FBSyxDQUFDLElBQUksQ0FDUixFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVUsRUFBRSxFQUN6QyxHQUFHLEVBQUUsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUMvQyxDQUNGLENBQUM7UUFDRixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNiLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLENBQUM7SUFDSCxDQUFDO0lBRU8sYUFBYSxDQUFDLEdBQVc7UUFDL0IsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6QyxNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7Z0JBQ3JDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztZQUM5RCxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzFCLElBQUksYUFBYSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUMxRCxPQUFPLENBQUMsSUFBSSxDQUNWLDBEQUEwRCxDQUMzRCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQzVFLENBQUM7SUFDSCxDQUFDO0lBRVMsa0JBQWtCLENBQUMsTUFBMkI7UUFDdEQsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLENBQUM7UUFDOUIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVTLGlCQUFpQixDQUFDLE1BQWdCO1FBQzFDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25ELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDekMsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO2dCQUMxQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUNELElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFTyxrQkFBa0I7UUFDeEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDOUQsQ0FBQztJQUNILENBQUM7SUFFUyxhQUFhLENBQUMsS0FBYTtRQUNuQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUN2RCxDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNoQyxDQUFDOzhHQXpHVSxvQkFBb0I7a0dBQXBCLG9CQUFvQixtUEM5Q2pDLCtwQ0FzQ0EsaVhESkksWUFBWSx5UEFDWixtQkFBbUIsb1NBQ25CLGNBQWMsd0dBQ2Qsa0JBQWtCLHFGQUNsQix5QkFBeUIsZ0hBQ3pCLGlCQUFpQixrR0FDakIsbUJBQW1COzsyRkFNVixvQkFBb0I7a0JBZmhDLFNBQVM7aUNBQ0ksSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osbUJBQW1CO3dCQUNuQixjQUFjO3dCQUNkLGtCQUFrQjt3QkFDbEIseUJBQXlCO3dCQUN6QixpQkFBaUI7d0JBQ2pCLG1CQUFtQjtxQkFDcEIsWUFDUyxlQUFlOzhCQVFaLE9BQU87c0JBQW5CLEtBQUs7Z0JBSUcsTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csR0FBRztzQkFBWCxLQUFLO2dCQUNJLFNBQVM7c0JBQWxCLE1BQU07Z0JBQ0csV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgRm9ybUFycmF5LFxuICBGb3JtQ29udHJvbCxcbiAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgVmFsaWRhdG9ycyxcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgUGFzdGVEaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvcGFzdGUuZGlyZWN0aXZlJztcbmltcG9ydCB7IEF1dG9Gb2N1c0RpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy9hdXRvRm9jdXMuZGlyZWN0aXZlJztcbmltcG9ydCB7XG4gIElucHV0TmF2aWdhdGlvbnNEaXJlY3RpdmUsXG4gIE90cFZhbHVlQ2hhbmdlRXZlbnQsXG59IGZyb20gJy4vZGlyZWN0aXZlcy9pbnB1dE5hdmlnYXRpb25zLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBBdXRvQmx1ckRpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy9hdXRvQmx1ci5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQXJpYUxhYmVsc0RpcmVjdGl2ZSB9IGZyb20gJy4vZGlyZWN0aXZlcy9hcmlhTGFiZWxzLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBOZ3hPdHBJbnB1dENvbXBvbmVudE9wdGlvbnMsIGRlZmF1bHRPcHRpb25zIH0gZnJvbSAnLi9kZWZhdWx0LmNvbmZpZyc7XG5cbmV4cG9ydCBlbnVtIE5neE90cFN0YXR1cyB7XG4gIFNVQ0NFU1MgPSAnc3VjY2VzcycsXG4gIEZBSUxFRCA9ICdmYWlsZWQnLFxufVxuXG5AQ29tcG9uZW50KHtcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFBhc3RlRGlyZWN0aXZlLFxuICAgIEF1dG9Gb2N1c0RpcmVjdGl2ZSxcbiAgICBJbnB1dE5hdmlnYXRpb25zRGlyZWN0aXZlLFxuICAgIEF1dG9CbHVyRGlyZWN0aXZlLFxuICAgIEFyaWFMYWJlbHNEaXJlY3RpdmUsXG4gIF0sXG4gIHNlbGVjdG9yOiAnbmd4LW90cC1pbnB1dCcsXG4gIHRlbXBsYXRlVXJsOiAnbmd4LW90cC1pbnB1dC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWyduZ3gtb3RwLWlucHV0LmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIE5neE90cElucHV0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICBwcm90ZWN0ZWQgbmd4T3RwSW5wdXRBcnJheSE6IEZvcm1BcnJheTtcbiAgcHJvdGVjdGVkIG5neE90cE9wdGlvbnM6IE5neE90cElucHV0Q29tcG9uZW50T3B0aW9ucyA9IGRlZmF1bHRPcHRpb25zO1xuXG4gIEBJbnB1dCgpIHNldCBvcHRpb25zKGN1c3RvbU9wdGlvbnM6IE5neE90cElucHV0Q29tcG9uZW50T3B0aW9ucykge1xuICAgIHRoaXMubmd4T3RwT3B0aW9ucyA9IHsgLi4uZGVmYXVsdE9wdGlvbnMsIC4uLmN1c3RvbU9wdGlvbnMgfTtcbiAgfVxuXG4gIEBJbnB1dCgpIHN0YXR1czogTmd4T3RwU3RhdHVzIHwgbnVsbCB8IHVuZGVmaW5lZDtcbiAgQElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcbiAgQElucHV0KCkgb3RwOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkO1xuICBAT3V0cHV0KCkgb3RwQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmdbXT4oKTtcbiAgQE91dHB1dCgpIG90cENvbXBsZXRlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLy8gRm9yIHRlc3RpbmcgcHVycG9zZXNcbiAgZ2V0IG5neE90cE9wdGlvbnNJblVzZSgpOiBOZ3hPdHBJbnB1dENvbXBvbmVudE9wdGlvbnMge1xuICAgIHJldHVybiB0aGlzLm5neE90cE9wdGlvbnM7XG4gIH1cblxuICBnZXQgaW5wdXRUeXBlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubmd4T3RwT3B0aW9ucy5oaWRlSW5wdXRWYWx1ZXMgPyAncGFzc3dvcmQnIDogJ3RleHQnO1xuICB9XG5cbiAgZ2V0IGlzT1RQU3VjY2VzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0dXMgPT09IE5neE90cFN0YXR1cy5TVUNDRVNTO1xuICB9XG5cbiAgZ2V0IGlzT1RQRmFpbGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnN0YXR1cyA9PT0gTmd4T3RwU3RhdHVzLkZBSUxFRDtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaW5pdE90cElucHV0QXJyYXkoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCBvdHBDaGFuZ2UgPSBjaGFuZ2VzWydvdHAnXTtcbiAgICBpZiAob3RwQ2hhbmdlPy5jdXJyZW50VmFsdWUpIHtcbiAgICAgIGlmICghb3RwQ2hhbmdlLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAgIHRoaXMuc2V0SW5pdGlhbE90cChvdHBDaGFuZ2UuY3VycmVudFZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubmd4T3RwT3B0aW9ucy5hdXRvRm9jdXMgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluaXRPdHBJbnB1dEFycmF5KCk6IHZvaWQge1xuICAgIHRoaXMubmd4T3RwSW5wdXRBcnJheSA9IG5ldyBGb3JtQXJyYXkoXG4gICAgICBBcnJheS5mcm9tKFxuICAgICAgICB7IGxlbmd0aDogdGhpcy5uZ3hPdHBPcHRpb25zLm90cExlbmd0aCEgfSxcbiAgICAgICAgKCkgPT4gbmV3IEZvcm1Db250cm9sKCcnLCBWYWxpZGF0b3JzLnJlcXVpcmVkKSxcbiAgICAgICksXG4gICAgKTtcbiAgICBpZiAodGhpcy5vdHApIHtcbiAgICAgIHRoaXMuc2V0SW5pdGlhbE90cCh0aGlzLm90cCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZXRJbml0aWFsT3RwKG90cDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubmd4T3RwT3B0aW9ucy5yZWdleHAhLnRlc3Qob3RwKSkge1xuICAgICAgY29uc3Qgb3RwVmFsdWVBcnJheSA9IG90cC5zcGxpdCgnJyk7XG4gICAgICBvdHBWYWx1ZUFycmF5LmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICB0aGlzLm5neE90cElucHV0QXJyYXkuY29udHJvbHNbaW5kZXhdLnNldFZhbHVlKHZhbHVlID8/ICcnKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5lbWl0T3RwVmFsdWVDaGFuZ2UoKTtcbiAgICAgIGlmIChvdHBWYWx1ZUFycmF5Lmxlbmd0aCAhPT0gdGhpcy5uZ3hPdHBPcHRpb25zLm90cExlbmd0aCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ09UUCBsZW5ndGggZG9lcyBub3QgbWF0Y2ggdGhlIHByb3ZpZGVkIG90cExlbmd0aCBvcHRpb24hJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIE9UUCBwcm92aWRlZCBmb3IgdGhlIGNvbXBvbmVudCA8bmd4LW90cC1pbnB1dD4nKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlSW5wdXRDaGFuZ2VzKCRldmVudDogT3RwVmFsdWVDaGFuZ2VFdmVudCkge1xuICAgIGNvbnN0IFtpbmRleCwgdmFsdWVdID0gJGV2ZW50O1xuICAgIHRoaXMubmd4T3RwSW5wdXRBcnJheS5jb250cm9sc1tpbmRleF0uc2V0VmFsdWUodmFsdWUpO1xuICAgIHRoaXMuZW1pdE90cFZhbHVlQ2hhbmdlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlUGFzdGVDaGFuZ2UoJGV2ZW50OiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGlmICgkZXZlbnQubGVuZ3RoID09PSB0aGlzLm5neE90cE9wdGlvbnMub3RwTGVuZ3RoKSB7XG4gICAgICB0aGlzLm5neE90cElucHV0QXJyYXkuc2V0VmFsdWUoJGV2ZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgJGV2ZW50Lm1hcCgodmFsdWUsIGluZGV4KSA9PiB7XG4gICAgICAgIHRoaXMubmd4T3RwSW5wdXRBcnJheS5jb250cm9sc1tpbmRleF0/LnNldFZhbHVlPy4odmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuZW1pdE90cFZhbHVlQ2hhbmdlKCk7XG4gIH1cblxuICBwcml2YXRlIGVtaXRPdHBWYWx1ZUNoYW5nZSgpOiB2b2lkIHtcbiAgICB0aGlzLm90cENoYW5nZS5lbWl0KHRoaXMubmd4T3RwSW5wdXRBcnJheS52YWx1ZSk7XG4gICAgaWYgKHRoaXMubmd4T3RwSW5wdXRBcnJheS52YWxpZCkge1xuICAgICAgdGhpcy5vdHBDb21wbGV0ZS5lbWl0KHRoaXMubmd4T3RwSW5wdXRBcnJheS52YWx1ZS5qb2luKCcnKSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGlzSW5wdXRGaWxsZWQoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMubmd4T3RwSW5wdXRBcnJheS5jb250cm9sc1tpbmRleF0udmFsdWU7XG4gIH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLm5neE90cElucHV0QXJyYXkucmVzZXQoKTtcbiAgfVxufVxuIiwiPGZvcm1cbiAgbmd4T3RwUGFzdGVcbiAgbmd4SW5wdXROYXZpZ2F0aW9uc1xuICBbcmVnZXhwXT1cIm5neE90cE9wdGlvbnMucmVnZXhwIVwiXG4gIFtpc0Zvcm1WYWxpZF09XCJuZ3hPdHBJbnB1dEFycmF5LnZhbGlkXCJcbiAgW25neEF1dG9Gb2N1c109XCJuZ3hPdHBPcHRpb25zLmF1dG9Gb2N1cyFcIlxuICBbbmd4QXV0b0JsdXJdPVwibmd4T3RwT3B0aW9ucy5hdXRvQmx1ciFcIlxuICBbbmd4T3RwQXJpYUxhYmVsc109XCJuZ3hPdHBPcHRpb25zLmFyaWFMYWJlbHMhXCJcbiAgW25nQ2xhc3NdPVwie1xuICAgICduZ3gtYmxpbmtpbmctY3Vyc29yJzogbmd4T3RwT3B0aW9ucy5zaG93QmxpbmtpbmdDdXJzb3JcbiAgfVwiXG4gICh2YWx1ZUNoYW5nZSk9XCJoYW5kbGVJbnB1dENoYW5nZXMoJGV2ZW50KVwiXG4gIChoYW5kbGVQYXN0ZSk9XCJoYW5kbGVQYXN0ZUNoYW5nZSgkZXZlbnQpXCJcbiAgY2xhc3M9XCJuZ3gtb3RwLWlucHV0LWZvcm1cIlxuICBkYXRhLXRlc3RpZD1cIm5neC1vdHAtaW5wdXQtZm9ybVwiXG4+XG4gIDxpbnB1dFxuICAgICpuZ0Zvcj1cImxldCBjb250cm9sIG9mIG5neE90cElucHV0QXJyYXkuY29udHJvbHM7IGxldCBpID0gaW5kZXhcIlxuICAgICNvdHBJbnB1dEVsZW1lbnRcbiAgICBbdmFsdWVdPVwiY29udHJvbC52YWx1ZVwiXG4gICAgW3R5cGVdPVwiaW5wdXRUeXBlXCJcbiAgICBbaW5wdXRNb2RlXT1cIm5neE90cE9wdGlvbnMuaW5wdXRNb2RlXCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICduZ3gtb3RwLWlucHV0LWRpc2FibGVkJzogZGlzYWJsZWQsXG4gICAgICAnbmd4LW90cC1pbnB1dC1maWxsZWQnOiBpc0lucHV0RmlsbGVkKGkpLFxuICAgICAgJ25neC1vdHAtaW5wdXQtc3VjY2Vzcyc6IGlzT1RQU3VjY2VzcyxcbiAgICAgICduZ3gtb3RwLWlucHV0LWZhaWxlZCc6IGlzT1RQRmFpbGVkXG4gICAgfVwiXG4gICAgY2xhc3M9XCJuZ3gtb3RwLWlucHV0LWJveFwiXG4gICAgbWF4bGVuZ3RoPVwiMVwiXG4gICAgc3BlbGxjaGVjaz1cImZhbHNlXCJcbiAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgIGF1dG9jYXBpdGFsaXplPVwib2ZmXCJcbiAgICBhdXRvY29ycmVjdD1cIm9mZlwiXG4gICAgZGF0YS10ZXN0aWQ9XCJuZ3gtb3RwLWlucHV0LWJveFwiXG4gIC8+XG48L2Zvcm0+XG4iXX0=