UNPKG

ngx-otp-pin-input

Version:

An Angular library for OTP input fields, providing a customizable and user-friendly way to handle one-time passwords.

210 lines (203 loc) 8.82 kB
import * as i0 from '@angular/core'; import { EventEmitter, QueryList, forwardRef, ViewChildren, Output, Input, Component, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; const DEFAULT_CONFIG = { length: 4, className: 'input', style: { width: 40, height: 40, fontSize: 26, spacing: 12, borderWidth: 2, borderRadius: 4, borderColor: '#BDBDBD', borderFocusColor: '#3700B3' } }; class OtpInputComponent { constructor() { this.config = { length: 4, className: 'input', style: { width: 40, height: 40, fontSize: 26, spacing: 12, borderWidth: 2, borderRadius: 4, borderColor: '#BDBDBD', borderFocusColor: '#3700B3' } }; this.disabled = false; this.onOtpChange = new EventEmitter(); this.defaultConfig = DEFAULT_CONFIG; this.controls = Array.from({ length: this.config.length || this.defaultConfig.length }, () => ''); this.currentIndex = 0; this.otpInputs = new QueryList(); this.onChange = () => { }; this.onTouched = () => { }; this.value = ''; } ngOnChanges(changes) { if (changes['config']) { this.controls = Array.from({ length: this.config.length || this.defaultConfig.length }, () => ''); this.config = { ...this.defaultConfig, ...this.config }; } } writeValue(value) { this.value = value?.toString() || ''; this.otpInputs.forEach((input, index) => { input.nativeElement.value = this.value[index] || ''; }); } registerOnChange(fn) { this.onChange = fn; } registerOnTouched(fn) { this.onTouched = fn; } setDisabledState(isDisabled) { this.disabled = isDisabled; } onInput(event) { if (this.disabled) return; const target = event.target; const val = target.value; if (isNaN(Number(val))) { target.value = ''; return; } if (val !== '') { const next = target.nextElementSibling; if (next) { next.focus(); } this.emitOtpChange(); } } onKeyup(event) { if (this.disabled) return; const target = event.target; const key = event.key.toLowerCase(); if (key === 'backspace' || key === 'delete') { target.value = ''; const prev = target.previousElementSibling; if (prev) { prev.focus(); } this.emitOtpChange(); return; } else if (key === 'arrowleft') { const prev = target.previousElementSibling; if (prev) { prev.focus(); } return; } else if (key === 'arrowright') { const next = target.nextElementSibling; if (next) { next.focus(); } return; } } onPaste(event) { if (this.disabled) return; const clipboardData = event.clipboardData; if (!clipboardData) return; const pastedData = clipboardData.getData('text'); if (!/^\d+$/.test(pastedData)) { event.preventDefault(); return; } this.otpInputs.forEach((input, index) => { if (index < pastedData.length) { input.nativeElement.value = pastedData[index]; } else { input.nativeElement.value = ''; } input.nativeElement.dispatchEvent(new Event('input')); }); this.emitOtpChange(); } inputStyle(index) { return { 'width': `${this.config?.style?.width ?? this.defaultConfig.style.width}px`, 'height': `${this.config?.style?.height ?? this.defaultConfig.style.height}px`, 'font-size': `${this.config?.style?.fontSize ?? this.defaultConfig.style.fontSize}px`, 'border-width': `${this.config?.style?.borderWidth ?? this.defaultConfig.style.borderWidth}px`, 'border-radius': `${this.config?.style?.borderRadius ?? this.defaultConfig.style.borderRadius}px`, 'border-color': !this.disabled && this.currentIndex == index ? (this.config?.style?.borderFocusColor ?? this.defaultConfig.style.borderFocusColor) : (this.config?.style?.borderColor ?? this.defaultConfig.style.borderColor), }; } emitOtpChange() { if (this.disabled) return; let otp = ''; this.otpInputs.forEach((input, index) => { otp += input.nativeElement.value; }); this.value = otp; this.onOtpChange.emit(otp); this.onChange(otp); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: OtpInputComponent, selector: "ngx-otp-input", inputs: { config: "config", disabled: "disabled" }, outputs: { onOtpChange: "onOtpChange" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => OtpInputComponent), multi: true } ], viewQueries: [{ propertyName: "otpInputs", predicate: ["otpInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"inputs\" [style.gap.px]=\"config.style?.spacing || defaultConfig.style.spacing\">\r\n @for (input of controls;let i = $index; track i) {\r\n <input (input)=\"onInput($event)\" (keyup)=\"onKeyup($event)\" (paste)=\"onPaste($event)\" (focus)=\"currentIndex = i\"\r\n type=\"text\" inputmode=\"numeric\" maxlength=\"1\" class=\"input {{config.className}}\" [style]=\"inputStyle(i)\"\r\n [disabled]=\"disabled\" #otpInput />\r\n }\r\n</div>", styles: [".inputs{display:inline-flex}.input{border:none;border-style:solid;text-align:center;outline:none}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OtpInputComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-otp-input', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => OtpInputComponent), multi: true } ], template: "<div class=\"inputs\" [style.gap.px]=\"config.style?.spacing || defaultConfig.style.spacing\">\r\n @for (input of controls;let i = $index; track i) {\r\n <input (input)=\"onInput($event)\" (keyup)=\"onKeyup($event)\" (paste)=\"onPaste($event)\" (focus)=\"currentIndex = i\"\r\n type=\"text\" inputmode=\"numeric\" maxlength=\"1\" class=\"input {{config.className}}\" [style]=\"inputStyle(i)\"\r\n [disabled]=\"disabled\" #otpInput />\r\n }\r\n</div>", styles: [".inputs{display:inline-flex}.input{border:none;border-style:solid;text-align:center;outline:none}\n"] }] }], propDecorators: { config: [{ type: Input }], disabled: [{ type: Input }], onOtpChange: [{ type: Output }], otpInputs: [{ type: ViewChildren, args: ['otpInput'] }] } }); class NgxOtpInput { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxOtpInput, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: NgxOtpInput, declarations: [OtpInputComponent], exports: [OtpInputComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxOtpInput }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgxOtpInput, decorators: [{ type: NgModule, args: [{ declarations: [OtpInputComponent], exports: [OtpInputComponent] }] }] }); /* * Public API Surface of otp-input */ /** * Generated bundle index. Do not edit. */ export { NgxOtpInput, OtpInputComponent }; //# sourceMappingURL=ngx-otp-pin-input.mjs.map