UNPKG

ngx-otp-pin

Version:

A reusable, standalone Angular OTP input component supporting multiple character types, automatic focus movement, and style customization from the parent.

105 lines (100 loc) 6.73 kB
import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { EventEmitter, ViewChildren, Output, Input, Component } from '@angular/core'; import * as i2 from '@angular/forms'; import { FormsModule } from '@angular/forms'; var OTP_TYPE; (function (OTP_TYPE) { OTP_TYPE["DIGITS"] = "DIGITS"; OTP_TYPE["CAPITAL_LETTERS"] = "CAPITAL_LETTERS"; OTP_TYPE["LETTERS"] = "LETTERS"; OTP_TYPE["SMALL_LETTERS"] = "SMALL_LETTERS"; OTP_TYPE["ALPHA_NUMERIC"] = "ALPHA_NUMERIC"; })(OTP_TYPE || (OTP_TYPE = {})); class NgxOtp { size = 4; type = OTP_TYPE.DIGITS; isPassword = false; containerStyles = {}; inputStyles = {}; containerClass = ''; inputClass = ''; opt = []; optValue = new EventEmitter(); constructor() { } ngOnInit() { this.opt = new Array(this.size); console.log(this.opt); } inputRefs; move(currentIndex, $event) { const key = $event.key; if (key === 'Backspace' || key === 'Delete') { this.opt[currentIndex] = ''; const prevInput = this.inputRefs.get(currentIndex - 1); if (this.opt[currentIndex] === '' && prevInput) { prevInput.nativeElement.focus(); } } else if (this.isValidKey(key)) { this.opt[currentIndex] = key; const nextInput = this.inputRefs.get(currentIndex + 1); if (nextInput) { nextInput.nativeElement.focus(); } } this.optValue.emit(this.opt.join('')); $event.preventDefault(); } isValidKey(key) { switch (this.type) { case OTP_TYPE.DIGITS: return /^[0-9]$/.test(key); case OTP_TYPE.CAPITAL_LETTERS: return /^[A-Z]$/.test(key); case OTP_TYPE.SMALL_LETTERS: return /^[a-z]$/.test(key); case OTP_TYPE.LETTERS: return /^[a-zA-Z]$/.test(key); case OTP_TYPE.ALPHA_NUMERIC: return /^[a-zA-Z0-9]$/.test(key); default: return false; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxOtp, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: NgxOtp, isStandalone: true, selector: "ngx-otp", inputs: { size: "size", type: "type", isPassword: "isPassword", containerStyles: "containerStyles", inputStyles: "inputStyles", containerClass: "containerClass", inputClass: "inputClass" }, outputs: { optValue: "opt" }, viewQueries: [{ propertyName: "inputRefs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div>\r\n <div aria-label=\"otp container\" [ngClass]=\"containerClass\" [ngStyle]=\"containerStyles\" class=\"otp-container\">\r\n @for(digit of opt; track $index) {\r\n <div class=\"digital\">\r\n <input #otpInput [attr.aria-label]=\"'opt number ' + $index\" [ngClass]=\"inputClass\" [ngStyle]=\"inputStyles\"\r\n [ngModel]=\"digit\" [id]=\"'input_'+$index\" [type]=\"isPassword? 'password':'text'\"\r\n (keydown)=\"move($index, $event)\" maxlength=\"1\" />\r\n </div>\r\n }\r\n </div>\r\n\r\n</div>", styles: [".otp-container{display:flex;gap:20px;justify-content:center}.otp-container .digital{width:40px;height:40px}.otp-container .digital input{border:0;border:1px solid rgb(177,177,177);border-radius:10px;width:100%;height:100%;text-align:center;font-size:20px}.timer{margin-top:20px;font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { 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.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: NgxOtp, decorators: [{ type: Component, args: [{ selector: 'ngx-otp', standalone: true, imports: [CommonModule, FormsModule], template: "<div>\r\n <div aria-label=\"otp container\" [ngClass]=\"containerClass\" [ngStyle]=\"containerStyles\" class=\"otp-container\">\r\n @for(digit of opt; track $index) {\r\n <div class=\"digital\">\r\n <input #otpInput [attr.aria-label]=\"'opt number ' + $index\" [ngClass]=\"inputClass\" [ngStyle]=\"inputStyles\"\r\n [ngModel]=\"digit\" [id]=\"'input_'+$index\" [type]=\"isPassword? 'password':'text'\"\r\n (keydown)=\"move($index, $event)\" maxlength=\"1\" />\r\n </div>\r\n }\r\n </div>\r\n\r\n</div>", styles: [".otp-container{display:flex;gap:20px;justify-content:center}.otp-container .digital{width:40px;height:40px}.otp-container .digital input{border:0;border:1px solid rgb(177,177,177);border-radius:10px;width:100%;height:100%;text-align:center;font-size:20px}.timer{margin-top:20px;font-size:12px}\n"] }] }], ctorParameters: () => [], propDecorators: { size: [{ type: Input }], type: [{ type: Input }], isPassword: [{ type: Input }], containerStyles: [{ type: Input }], inputStyles: [{ type: Input }], containerClass: [{ type: Input }], inputClass: [{ type: Input }], optValue: [{ type: Output, args: ['opt'] }], inputRefs: [{ type: ViewChildren, args: ['otpInput'] }] } }); /* * Public API Surface of ngx-otp */ /** * Generated bundle index. Do not edit. */ export { NgxOtp, OTP_TYPE }; //# sourceMappingURL=ngx-otp-pin.mjs.map