UNPKG

angular-otp-box

Version:

Angular otp input field component for web applications. Easy to integrate and use.

271 lines (260 loc) 12.3 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('rxjs'), require('rxjs/operators'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('angular-otp-box', ['exports', '@angular/core', '@angular/forms', 'rxjs', 'rxjs/operators', '@angular/common'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['angular-otp-box'] = {}, global.ng.core, global.ng.forms, global.rxjs, global.rxjs.operators, global.ng.common)); }(this, (function (exports, core, forms, rxjs, operators, common) { 'use strict'; var KeysPipe = /** @class */ (function () { function KeysPipe() { } KeysPipe.prototype.transform = function (value) { return Object.keys(value); }; return KeysPipe; }()); KeysPipe.decorators = [ { type: core.Pipe, args: [{ name: 'keys' },] } ]; var CounterDirective = /** @class */ (function () { function CounterDirective() { var _this = this; this._counterSource$ = new rxjs.Subject(); this._subscription = rxjs.Subscription.EMPTY; this.interval = 1000; this.value = new core.EventEmitter(); this._subscription = this._counterSource$.pipe(operators.switchMap(function (_a) { var interval = _a.interval, count = _a.count; return rxjs.timer(0, interval).pipe(operators.take(count), operators.tap(function () { return _this.value.emit(--count); })); })).subscribe(); } CounterDirective.prototype.ngOnChanges = function (changes) { this.startTimer(); }; CounterDirective.prototype.startTimer = function () { this._counterSource$.next({ count: this.counter, interval: this.interval }); }; CounterDirective.prototype.ngOnDestroy = function () { this._subscription.unsubscribe(); }; return CounterDirective; }()); CounterDirective.decorators = [ { type: core.Directive, args: [{ selector: '[counter]' },] } ]; CounterDirective.ctorParameters = function () { return []; }; CounterDirective.propDecorators = { counter: [{ type: core.Input }], value: [{ type: core.Output }] }; var OtpInputComponent = /** @class */ (function () { function OtpInputComponent(keysPipe) { this.keysPipe = keysPipe; this.setting = { length: 4, timer: 0, timerType: 0 }; this.onValueChange = new core.EventEmitter(); this.inputControls = new Array(this.setting.length); this.componentKey = Math.random().toString(36).substring(2) + (new Date()).getTime().toString(36); } OtpInputComponent.prototype.ngOnInit = function () { console.log(this.setting); this.otpForm = new forms.FormGroup({}); for (var index = 0; index < this.setting.length; index++) { this.otpForm.addControl(this.getControlName(index), new forms.FormControl()); } }; OtpInputComponent.prototype.ngAfterViewInit = function () { var containerItem = document.getElementById("c_" + this.componentKey); if (containerItem) { var ele = containerItem.getElementsByClassName('.otp-input')[0]; if (ele && ele.focus) { ele.focus(); } } }; OtpInputComponent.prototype.getControlName = function (idx) { return "ctrl_" + idx; }; OtpInputComponent.prototype.isLeftArrow = function (e) { return this.isKeyCode(e, 37); }; OtpInputComponent.prototype.isRightArrow = function (e) { return this.isKeyCode(e, 39); }; OtpInputComponent.prototype.isBackspaceOrDelete = function (e) { return e.key === "Backspace" || e.key === "Delete" || this.isKeyCode(e, 8) || this.isKeyCode(e, 46); }; OtpInputComponent.prototype.isKeyCode = function (e, targetCode) { var key = e.keyCode || e.charCode; if (key == targetCode) { return true; } return false; }; OtpInputComponent.prototype.keyUp = function (e, inputIdx) { var nextInputId = this.appendKey("otp_" + (inputIdx + 1)); var prevInputId = this.appendKey("otp_" + (inputIdx - 1)); if (this.isRightArrow(e)) { this.setSelected(nextInputId); return; } if (this.isLeftArrow(e)) { this.setSelected(prevInputId); return; } var isBackspace = this.isBackspaceOrDelete(e); if (isBackspace && !e.target.value) { this.setSelected(prevInputId); this.rebuildValue(); return; } if (!e.target.value) { return; } if (this.isValidEntry(e)) { this.focusTo(nextInputId); } this.rebuildValue(); }; OtpInputComponent.prototype.appendKey = function (id) { return id + "_" + this.componentKey; }; OtpInputComponent.prototype.setSelected = function (eleId) { this.focusTo(eleId); var ele = document.getElementById(eleId); if (ele && ele.setSelectionRange) { setTimeout(function () { ele.setSelectionRange(0, 1); }, 0); } }; OtpInputComponent.prototype.isValidEntry = function (e) { var inp = String.fromCharCode(e.keyCode); var isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); return isMobile || /[a-zA-Z0-9-_]/.test(inp) || (this.setting.allowKeyCodes && this.setting.allowKeyCodes.includes(e.keyCode)) || (e.keyCode >= 96 && e.keyCode <= 105); }; OtpInputComponent.prototype.focusTo = function (eleId) { var ele = document.getElementById(eleId); if (ele) { ele.focus(); ele.selectionStart = ele.selectionEnd = 100; } }; OtpInputComponent.prototype.rebuildValue = function () { var _this = this; var val = ''; this.keysPipe.transform(this.otpForm.controls).forEach(function (k) { if (_this.otpForm.controls[k].value) { val += _this.otpForm.controls[k].value; } }); this.onValueChange.emit(val); }; OtpInputComponent.prototype.onCounterChange = function (e) { this.counter = e; if (this.counter == 0) { this.onValueChange.emit(-1); } }; OtpInputComponent.prototype.ressendOtp = function () { this.CounterDirective.first.startTimer(); this.onValueChange.emit(-2); }; OtpInputComponent.prototype.formatSecsToMins = function (time) { // Hours, minutes and seconds var hrs = ~~(time / 3600); var mins = ~~((time % 3600) / 60); var secs = ~~time % 60; // Output like "1:01" or "4:03:59" or "123:03:59" var ret = ""; if (hrs > 0) { ret += "" + hrs + ":" + (mins < 10 ? "0" : ""); } ret += "" + mins + ":" + (secs < 10 ? "0" : ""); ret += "" + secs; return ret; }; return OtpInputComponent; }()); OtpInputComponent.decorators = [ { type: core.Component, args: [{ selector: 'otp', template: "<div class=\"otp-container {{setting.wrapperClass}}\" id=\"c_{{componentKey}}\" *ngIf=\"otpForm?.controls\"\n [ngStyle]=\"setting.wrapperStyles\">\n <input \n [type]=\"setting.numbersOnly ? 'tel' : 'text'\" \n numberOnly [disabledNumberOnly]=\"!setting.numbersOnly\"\n [ngStyle]=\"setting.inputStyles\" \n maxlength=\"1\" \n class=\"otp-input {{setting.inputClass}}\" \n autocomplete=\"off\"\n *ngFor=\"let item of otpForm?.controls | keys; let i = index\" \n [formControl]=\"otpForm.controls[item]\"\n id=\"otp_{{i}}_{{componentKey}}\" \n (keyup)=\"keyUp($event, i)\"\n >\n <ng-container counter [counter]=\"setting.timer\" (value)=\"onCounterChange($event)\">\n <div>\n <button class=\"btn {{setting.btnClass}}\" [disabled]=\"counter != 0\" (click)=\"ressendOtp()\">\n Resend OTP \n <span *ngIf=\"counter != 0\">\n <ng-container *ngIf=\"!setting.timerType\">\n in {{ counter }} seconds.\n </ng-container>\n <ng-container *ngIf=\"setting.timerType\">\n in {{ formatSecsToMins(counter) }} minutes.\n </ng-container>\n </span>\n </button>\n </div>\n </ng-container>\n</div>", styles: [".otp-input{width:2em;height:2em;border-radius:4px;border:1px solid #c5c5c5;text-align:center;font-size:28px}.otp-input:focus{outline-offset:0;outline-color:#2b91e2;outline-style:auto;outline-width:5px}.otp-container .otp-input:not(:last-child){margin-right:8px}@media screen and (max-width:767px){.otp-input{font-size:24px}}@media screen and (max-width:420px){.otp-input{font-size:18px}}"] },] } ]; OtpInputComponent.ctorParameters = function () { return [ { type: KeysPipe } ]; }; OtpInputComponent.propDecorators = { setting: [{ type: core.Input }], onValueChange: [{ type: core.Output }], CounterDirective: [{ type: core.ViewChildren, args: [CounterDirective,] }] }; var NumberOnly = /** @class */ (function () { function NumberOnly(_elRef, _renderer) { this._elRef = _elRef; this._renderer = _renderer; } NumberOnly.prototype.ngOnInit = function () { if (!this.disabledNumberOnly) { this._renderer.setAttribute(this._elRef.nativeElement, 'onkeypress', 'return (event.charCode >= 48 && event.charCode <= 57) || event.charCode == 0'); } }; return NumberOnly; }()); NumberOnly.decorators = [ { type: core.Directive, args: [{ selector: '[numberOnly]' },] } ]; NumberOnly.ctorParameters = function () { return [ { type: core.ElementRef }, { type: core.Renderer2 } ]; }; NumberOnly.propDecorators = { disabledNumberOnly: [{ type: core.Input }] }; var AngularOtpLibModule = /** @class */ (function () { function AngularOtpLibModule() { } return AngularOtpLibModule; }()); AngularOtpLibModule.decorators = [ { type: core.NgModule, args: [{ declarations: [ OtpInputComponent, KeysPipe, NumberOnly, CounterDirective ], imports: [ common.CommonModule, forms.FormsModule, forms.ReactiveFormsModule ], exports: [ OtpInputComponent ], providers: [KeysPipe] },] } ]; /* * Public API Surface of angular-otp-box */ /** * Generated bundle index. Do not edit. */ exports.AngularOtpLibModule = AngularOtpLibModule; exports.OtpInputComponent = OtpInputComponent; exports.ɵa = CounterDirective; exports.ɵb = KeysPipe; exports.ɵc = NumberOnly; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=angular-otp-box.umd.js.map