ng-otp-box 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # NgOtpBox
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.1.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project ng-otp-box` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ng-otp-box`.
8
+ > Note: Don't forget to add `--project ng-otp-box` or else it will be added to the default project in your `angular.json` file.
9
+
10
+ ## Build
11
+
12
+ Run `ng build ng-otp-box` to build the project. The build artifacts will be stored in the `dist/` directory.
13
+
14
+ ## Publishing
15
+
16
+ After building your library with `ng build ng-otp-box`, go to the dist folder `cd dist/ng-otp-box` and run `npm publish`.
17
+
18
+ ## Running unit tests
19
+
20
+ Run `ng test ng-otp-box` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
+
22
+ ## Further help
23
+
24
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,19 @@
1
+ import { Component } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class NgOtpBoxComponent {
4
+ }
5
+ NgOtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6
+ NgOtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NgOtpBoxComponent, selector: "lib-ng-otp-box", ngImport: i0, template: `
7
+ <p>
8
+ ng-otp-box works!
9
+ </p>
10
+ `, isInline: true });
11
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, decorators: [{
12
+ type: Component,
13
+ args: [{ selector: 'lib-ng-otp-box', template: `
14
+ <p>
15
+ ng-otp-box works!
16
+ </p>
17
+ ` }]
18
+ }] });
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctb3RwLWJveC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1vdHAtYm94L3NyYy9saWIvbmctb3RwLWJveC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFZMUMsTUFBTSxPQUFPLGlCQUFpQjs7K0dBQWpCLGlCQUFpQjttR0FBakIsaUJBQWlCLHNEQVJsQjs7OztHQUlUOzRGQUlVLGlCQUFpQjtrQkFWN0IsU0FBUzsrQkFDRSxnQkFBZ0IsWUFDaEI7Ozs7R0FJVCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItbmctb3RwLWJveCcsXG4gIHRlbXBsYXRlOiBgXG4gICAgPHA+XG4gICAgICBuZy1vdHAtYm94IHdvcmtzIVxuICAgIDwvcD5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmdPdHBCb3hDb21wb25lbnQge1xuXG59XG4iXX0=
@@ -0,0 +1,31 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4
+ import { MatInputModule } from '@angular/material/input';
5
+ import { OtpBoxComponent } from './otp-box/otp-box.component';
6
+ import * as i0 from "@angular/core";
7
+ export class NgOtpBoxModule {
8
+ }
9
+ NgOtpBoxModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
10
+ NgOtpBoxModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, declarations: [OtpBoxComponent], imports: [CommonModule,
11
+ ReactiveFormsModule,
12
+ FormsModule,
13
+ MatInputModule], exports: [OtpBoxComponent] });
14
+ NgOtpBoxModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, imports: [CommonModule,
15
+ ReactiveFormsModule,
16
+ FormsModule,
17
+ MatInputModule] });
18
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, decorators: [{
19
+ type: NgModule,
20
+ args: [{
21
+ declarations: [OtpBoxComponent],
22
+ imports: [
23
+ CommonModule,
24
+ ReactiveFormsModule,
25
+ FormsModule,
26
+ MatInputModule,
27
+ ],
28
+ exports: [OtpBoxComponent],
29
+ }]
30
+ }] });
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctb3RwLWJveC5tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1vdHAtYm94L3NyYy9saWIvbmctb3RwLWJveC5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWxFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7O0FBWTlELE1BQU0sT0FBTyxjQUFjOzs0R0FBZCxjQUFjOzZHQUFkLGNBQWMsaUJBVFYsZUFBZSxhQUU1QixZQUFZO1FBQ1osbUJBQW1CO1FBQ25CLFdBQVc7UUFDWCxjQUFjLGFBRU4sZUFBZTs2R0FFZCxjQUFjLFlBUHZCLFlBQVk7UUFDWixtQkFBbUI7UUFDbkIsV0FBVztRQUNYLGNBQWM7NEZBSUwsY0FBYztrQkFWMUIsUUFBUTttQkFBQztvQkFDUixZQUFZLEVBQUUsQ0FBQyxlQUFlLENBQUM7b0JBQy9CLE9BQU8sRUFBRTt3QkFDUCxZQUFZO3dCQUNaLG1CQUFtQjt3QkFDbkIsV0FBVzt3QkFDWCxjQUFjO3FCQUNmO29CQUNELE9BQU8sRUFBRSxDQUFDLGVBQWUsQ0FBQztpQkFDM0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcblxuaW1wb3J0IHsgT3RwQm94Q29tcG9uZW50IH0gZnJvbSAnLi9vdHAtYm94L290cC1ib3guY29tcG9uZW50JztcblxuQE5nTW9kdWxlKHtcbiAgZGVjbGFyYXRpb25zOiBbT3RwQm94Q29tcG9uZW50XSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIEZvcm1zTW9kdWxlLFxuICAgIE1hdElucHV0TW9kdWxlLFxuICBdLFxuICBleHBvcnRzOiBbT3RwQm94Q29tcG9uZW50XSxcbn0pXG5leHBvcnQgY2xhc3MgTmdPdHBCb3hNb2R1bGUge31cbiJdfQ==
@@ -0,0 +1,14 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export class NgOtpBoxService {
4
+ constructor() { }
5
+ }
6
+ NgOtpBoxService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
7
+ NgOtpBoxService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, providedIn: 'root' });
8
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, decorators: [{
9
+ type: Injectable,
10
+ args: [{
11
+ providedIn: 'root'
12
+ }]
13
+ }], ctorParameters: function () { return []; } });
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctb3RwLWJveC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctb3RwLWJveC9zcmMvbGliL25nLW90cC1ib3guc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDOztBQUszQyxNQUFNLE9BQU8sZUFBZTtJQUUxQixnQkFBZ0IsQ0FBQzs7NkdBRk4sZUFBZTtpSEFBZixlQUFlLGNBRmQsTUFBTTs0RkFFUCxlQUFlO2tCQUgzQixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgTmdPdHBCb3hTZXJ2aWNlIHtcblxuICBjb25zdHJ1Y3RvcigpIHsgfVxufVxuIl19
@@ -0,0 +1,148 @@
1
+ import { Input, Output, ViewChildren } from '@angular/core';
2
+ import { Component, EventEmitter } from '@angular/core';
3
+ import { Validators } from '@angular/forms';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/forms";
6
+ import * as i2 from "@angular/common";
7
+ import * as i3 from "@angular/material/input";
8
+ import * as i4 from "@angular/material/form-field";
9
+ export class OtpBoxComponent {
10
+ constructor(fb) {
11
+ this.fb = fb;
12
+ this.otpChange = new EventEmitter();
13
+ this.otpLength = 6;
14
+ this.inputType = 'number';
15
+ // @Input() allowUppercase: boolean = true;
16
+ // @Input() showUnMaskCheckBoxYN : boolean = false;
17
+ this.unmaskPassword = false;
18
+ }
19
+ ngOnInit() {
20
+ this.otpForm = this.fb.group({
21
+ otp: this.fb.array([]),
22
+ });
23
+ }
24
+ ngAfterViewInit() {
25
+ this.buildOtpControls();
26
+ // this.otpForm.valueChanges.subscribe((val) => {
27
+ // this.emitOtp();
28
+ // });
29
+ }
30
+ get otpArray() {
31
+ return this.otpForm.get('otp');
32
+ }
33
+ getInputPattern() {
34
+ const alpha = 'a-zA-Z';
35
+ const alphanumeric = 'a-zA-Z0-9';
36
+ switch (this.inputType) {
37
+ case 'text':
38
+ return new RegExp(`^[${alpha}]$`);
39
+ case 'number':
40
+ return /^[0-9+]$/;
41
+ case 'mixed':
42
+ return /^[a-zA-Z0-9]$/;
43
+ case 'masked':
44
+ return new RegExp(`^[${alphanumeric}]$`);
45
+ default:
46
+ return /^[0-9]$/;
47
+ }
48
+ }
49
+ buildOtpControls() {
50
+ this.otpArray.clear();
51
+ const pattern = this.getInputPattern();
52
+ for (let i = 0; i < this.otpLength; i++) {
53
+ this.otpArray.push(this.fb.control('', [Validators.required, Validators.pattern(pattern)]));
54
+ }
55
+ }
56
+ togglePasswordVisibility() {
57
+ this.unmaskPassword = !this.unmaskPassword;
58
+ }
59
+ focusFirstInput() {
60
+ if (this.inputs && this.inputs.length > 0) {
61
+ this.inputs.first.nativeElement.focus();
62
+ }
63
+ }
64
+ onInput(event, index) {
65
+ const input = event.target;
66
+ const { value, message } = this.sanitizeWithMessage(input.value);
67
+ this.emitChange(message);
68
+ this.otpArray.at(index).setValue(value, { emitEvent: false });
69
+ if (value && index < this.otpLength - 1) {
70
+ this.inputs.toArray()[index + 1].nativeElement.focus();
71
+ }
72
+ }
73
+ sanitizeWithMessage(rawValue) {
74
+ switch (this.inputType) {
75
+ case 'number':
76
+ if (/[^0-9]/.test(rawValue)) {
77
+ return {
78
+ value: rawValue.replace(/\D/g, ''),
79
+ message: 'Only numbers are allowed'
80
+ };
81
+ }
82
+ return { value: rawValue };
83
+ case 'text':
84
+ if (/[^a-zA-Z]/.test(rawValue)) {
85
+ return {
86
+ value: rawValue.replace(/[^a-zA-Z]/g, ''),
87
+ message: 'Only letters are allowed'
88
+ };
89
+ }
90
+ return { value: rawValue, message: 'success' };
91
+ case 'mixed':
92
+ case 'masked':
93
+ if (/[^a-zA-Z0-9]/.test(rawValue)) {
94
+ return {
95
+ value: rawValue.replace(/[^a-zA-Z0-9]/g, ''),
96
+ message: 'Only letters and numbers are allowed'
97
+ };
98
+ }
99
+ return { value: rawValue, message: 'success' };
100
+ default:
101
+ return { value: rawValue, message: 'success' };
102
+ }
103
+ }
104
+ onKeyDown(event, index) {
105
+ if (event.key === 'Backspace' &&
106
+ !this.otpArray.at(index).value &&
107
+ index > 0) {
108
+ this.inputs.toArray()[index - 1].nativeElement.focus();
109
+ }
110
+ }
111
+ onPaste(event) {
112
+ event.preventDefault();
113
+ const pasteData = event.clipboardData?.getData('text') ?? '';
114
+ const { value, message } = this.sanitizeWithMessage(pasteData);
115
+ if (value.length !== this.otpLength) {
116
+ this.emitChange('Invalid OTP length');
117
+ return;
118
+ }
119
+ value.split('').forEach((char, i) => {
120
+ this.otpArray.at(i).setValue(char, { emitEvent: false });
121
+ });
122
+ this.emitChange(message);
123
+ }
124
+ emitChange(message) {
125
+ const otp = this.otpArray.value.join('');
126
+ this.otpChange.emit({
127
+ value: otp,
128
+ isValid: this.otpForm.valid,
129
+ message: message
130
+ });
131
+ }
132
+ }
133
+ OtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
134
+ OtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpBoxComponent, selector: "lib-otp-box", inputs: { otpLength: "otpLength", inputType: "inputType" }, outputs: { otpChange: "otpChange" }, viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }] });
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, decorators: [{
136
+ type: Component,
137
+ args: [{ selector: 'lib-otp-box', template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"] }]
138
+ }], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { otpChange: [{
139
+ type: Output
140
+ }], otpLength: [{
141
+ type: Input
142
+ }], inputType: [{
143
+ type: Input
144
+ }], inputs: [{
145
+ type: ViewChildren,
146
+ args: ['otpInput']
147
+ }] } });
148
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLWJveC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1vdHAtYm94L3NyYy9saWIvb3RwLWJveC9vdHAtYm94LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLW90cC1ib3gvc3JjL2xpYi9vdHAtYm94L290cC1ib3guY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxTQUFTLEVBQWMsWUFBWSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBcUMsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7OztBQWEvRSxNQUFNLE9BQU8sZUFBZTtJQVkxQixZQUFvQixFQUFlO1FBQWYsT0FBRSxHQUFGLEVBQUUsQ0FBYTtRQVh6QixjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUNyQyxjQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsY0FBUyxHQUEyQyxRQUFRLENBQUM7UUFDdEUsMkNBQTJDO1FBQzNDLG1EQUFtRDtRQUNuRCxtQkFBYyxHQUFZLEtBQUssQ0FBQztJQU1NLENBQUM7SUFFdkMsUUFBUTtRQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDM0IsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztTQUN2QixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBRXhCLGlEQUFpRDtRQUNqRCxvQkFBb0I7UUFDcEIsTUFBTTtJQUNSLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMs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b20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQnVpbGRlciwgRm9ybUFycmF5LCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIG90cE1vZGVsIHtcbiAgaXNWYWxpZDogYm9vbGVhbjtcbiAgdmFsdWU6IG51bWJlcjtcbiAgbWVzc2FnZT8gOiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1vdHAtYm94JyxcbiAgdGVtcGxhdGVVcmw6ICcuL290cC1ib3guY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9vdHAtYm94LmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBPdHBCb3hDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBAT3V0cHV0KCkgb3RwQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBJbnB1dCgpIG90cExlbmd0aCA9IDY7XG4gIEBJbnB1dCgpIGlucHV0VHlwZTogJ3RleHQnIHwgJ251bWJlcicgfCAnbWl4ZWQnIHwgJ21hc2tlZCcgPSAnbnVtYmVyJztcbiAgLy8gQElucHV0KCkgYWxsb3dVcHBlcmNhc2U6IGJvb2xlYW4gPSB0cnVlO1xuICAvLyBASW5wdXQoKSBzaG93VW5NYXNrQ2hlY2tCb3hZTiA6IGJvb2xlYW4gPSBmYWxzZTtcbiAgdW5tYXNrUGFzc3dvcmQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBvdHBGb3JtITogRm9ybUdyb3VwO1xuXG4gIEBWaWV3Q2hpbGRyZW4oJ290cElucHV0JykgaW5wdXRzITogUXVlcnlMaXN0PEVsZW1lbnRSZWY+O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMub3RwRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgb3RwOiB0aGlzLmZiLmFycmF5KFtdKSxcbiAgICB9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmJ1aWxkT3RwQ29udHJvbHMoKTtcblxuICAgIC8vIHRoaXMub3RwRm9ybS52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCh2YWwpID0+IHtcbiAgICAvLyAgIHRoaXMuZW1pdE90cCgpO1xuICAgIC8vIH0pO1xuICB9XG5cbiAgZ2V0IG90cEFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgcmV0dXJuIHRoaXMub3RwRm9ybS5nZXQoJ290cCcpIGFzIEZvcm1BcnJheTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SW5wdXRQYXR0ZXJuKCk6IFJlZ0V4cCB7XG4gICAgY29uc3QgYWxwaGEgPSAgJ2EtekEtWic7XG4gICAgY29uc3QgYWxwaGFudW1lcmljID0gJ2EtekEtWjAtOSc7XG4gICAgc3dpdGNoICh0aGlzLmlucHV0VHlwZSkge1xuICAgICAgY2FzZSAndGV4dCc6XG4gICAgICAgIHJldHVybiBuZXcgUmVnRXhwKGBeWyR7YWxwaGF9XSRgKTtcblxuICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgcmV0dXJuIC9eWzAtOStdJC87XG5cbiAgICAgIGNhc2UgJ21peGVkJzpcbiAgICAgICAgcmV0dXJuIC9eW2EtekEtWjAtOV0kLztcblxuICAgICAgY2FzZSAnbWFza2VkJzpcbiAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoYF5bJHthbHBoYW51bWVyaWN9XSRgKTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIC9eWzAtOV0kLztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkT3RwQ29udHJvbHMoKTogdm9pZCB7XG4gICAgdGhpcy5vdHBBcnJheS5jbGVhcigpO1xuICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLmdldElucHV0UGF0dGVybigpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm90cExlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLm90cEFycmF5LnB1c2goXG4gICAgICAgIHRoaXMuZmIuY29udHJvbCgnJywgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMucGF0dGVybihwYXR0ZXJuKV0pXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZVBhc3N3b3JkVmlzaWJpbGl0eSgpOiB2b2lkIHtcbiAgICB0aGlzLnVubWFza1Bhc3N3b3JkID0gIXRoaXMudW5tYXNrUGFzc3dvcmQ7XG4gIH1cblxuICBmb2N1c0ZpcnN0SW5wdXQoKSB7XG4gICAgaWYgKHRoaXMuaW5wdXRzICYmIHRoaXMuaW5wdXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuaW5wdXRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICBvbklucHV0KGV2ZW50OiBFdmVudCwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgY29uc3QgeyB2YWx1ZSwgbWVzc2FnZSB9ID0gdGhpcy5zYW5pdGl6ZVdpdGhNZXNzYWdlKGlucHV0LnZhbHVlKTtcbiAgICB0aGlzLmVtaXRDaGFuZ2UobWVzc2FnZSk7XG4gICAgdGhpcy5vdHBBcnJheS5hdChpbmRleCkuc2V0VmFsdWUodmFsdWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcblxuICAgIGlmICh2YWx1ZSAmJiBpbmRleCA8IHRoaXMub3RwTGVuZ3RoIC0gMSkge1xuICAgICAgdGhpcy5pbnB1dHMudG9BcnJheSgpW2luZGV4ICsgMV0ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2FuaXRpemVXaXRoTWVzc2FnZShyYXdWYWx1ZTogc3RyaW5nKTogeyB2YWx1ZTogc3RyaW5nOyBtZXNzYWdlPzogc3RyaW5nIH0ge1xuICBzd2l0Y2ggKHRoaXMuaW5wdXRUeXBlKSB7XG4gICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgIGlmICgvW14wLTldLy50ZXN0KHJhd1ZhbHVlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHZhbHVlOiByYXdWYWx1ZS5yZXBsYWNlKC9cXEQvZywgJycpLFxuICAgICAgICAgIG1lc3NhZ2U6ICdPbmx5IG51bWJlcnMgYXJlIGFsbG93ZWQnXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4geyB2YWx1ZTogcmF3VmFsdWUgfTtcblxuICAgIGNhc2UgJ3RleHQnOlxuICAgICAgaWYgKC9bXmEtekEtWl0vLnRlc3QocmF3VmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmFsdWU6IHJhd1ZhbHVlLnJlcGxhY2UoL1teYS16QS1aXS9nLCAnJyksXG4gICAgICAgICAgbWVzc2FnZTogJ09ubHkgbGV0dGVycyBhcmUgYWxsb3dlZCdcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IHZhbHVlOiByYXdWYWx1ZSwgbWVzc2FnZTogJ3N1Y2Nlc3MnIH07XG5cbiAgICBjYXNlICdtaXhlZCc6XG4gICAgY2FzZSAnbWFza2VkJzpcbiAgICAgIGlmICgvW15hLXpBLVowLTldLy50ZXN0KHJhd1ZhbHVlKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHZhbHVlOiByYXdWYWx1ZS5yZXBsYWNlKC9bXmEtekEtWjAtOV0vZywgJycpLFxuICAgICAgICAgIG1lc3NhZ2U6ICdPbmx5IGxldHRlcnMgYW5kIG51bWJlcnMgYXJlIGFsbG93ZWQnXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4geyB2YWx1ZTogcmF3VmFsdWUsIG1lc3NhZ2U6ICdzdWNjZXNzJyB9O1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB7IHZhbHVlOiByYXdWYWx1ZSwgbWVzc2FnZTogJ3N1Y2Nlc3MnIH07XG4gIH1cbn1cblxuICBvbktleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICBldmVudC5rZXkgPT09ICdCYWNrc3BhY2UnICYmXG4gICAgICAhdGhpcy5vdHBBcnJheS5hdChpbmRleCkudmFsdWUgJiZcbiAgICAgIGluZGV4ID4gMFxuICAgICkge1xuICAgICAgdGhpcy5pbnB1dHMudG9BcnJheSgpW2luZGV4IC0gMV0ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG5vblBhc3RlKGV2ZW50OiBDbGlwYm9hcmRFdmVudCk6IHZvaWQge1xuICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gIGNvbnN0IHBhc3RlRGF0YSA9IGV2ZW50LmNsaXBib2FyZERhdGE/LmdldERhdGEoJ3RleHQnKSA/PyAnJztcbiAgY29uc3QgeyB2YWx1ZSwgbWVzc2FnZSB9ID0gdGhpcy5zYW5pdGl6ZVdpdGhNZXNzYWdlKHBhc3RlRGF0YSk7XG5cbiAgaWYgKHZhbHVlLmxlbmd0aCAhPT0gdGhpcy5vdHBMZW5ndGgpIHtcbiAgICB0aGlzLmVtaXRDaGFuZ2UoJ0ludmFsaWQgT1RQIGxlbmd0aCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHZhbHVlLnNwbGl0KCcnKS5mb3JFYWNoKChjaGFyLCBpKSA9PiB7XG4gICAgdGhpcy5vdHBBcnJheS5hdChpKS5zZXRWYWx1ZShjaGFyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gIH0pO1xuXG4gIHRoaXMuZW1pdENoYW5nZShtZXNzYWdlKTtcbn1cblxuICBwcml2YXRlIGVtaXRDaGFuZ2UobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgY29uc3Qgb3RwID0gdGhpcy5vdHBBcnJheS52YWx1ZS5qb2luKCcnKTtcbiAgICB0aGlzLm90cENoYW5nZS5lbWl0KHtcbiAgICAgIHZhbHVlOiBvdHAsXG4gICAgICBpc1ZhbGlkOiB0aGlzLm90cEZvcm0udmFsaWQsXG4gICAgICBtZXNzYWdlOiBtZXNzYWdlXG4gICAgfSk7XG4gIH1cbn1cbiIsIjxkaXY+XG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwib3RwRm9ybVwiIChwYXN0ZSk9XCJvblBhc3RlKCRldmVudClcIj5cblxuICAgIDxkaXYgY2xhc3M9XCJvdHAtY29udGFpbmVyXCIgZm9ybUFycmF5TmFtZT1cIm90cFwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgY3RybCBvZiBvdHBBcnJheS5jb250cm9sczsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cIm90cC1tYXQtZmllbGRcIiBbY2xhc3MubWF0LWZvcm0tZmllbGQtaW52YWxpZF09XCJcbiAgICAgICAgICBvdHBGb3JtLmludmFsaWQgJiYgKG90cEZvcm0udG91Y2hlZCB8fCBvdHBGb3JtLmRpcnR5KVwiPlxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbdHlwZV09XCJpbnB1dFR5cGUgPT09ICdtYXNrZWQnID8gJ3Bhc3N3b3JkJyA6ICd0ZXh0J1wiIG1heGxlbmd0aD1cIjFcIlxuICAgICAgICAgICAgI290cElucHV0IGNka0ZvY3VzSW5pdGlhbCBbZm9ybUNvbnRyb2xOYW1lXT1cImlcIiAoaW5wdXQpPVwib25JbnB1dCgkZXZlbnQsIGkpXCJcbiAgICAgICAgICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigkZXZlbnQsIGkpXCIgLz5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuICAgIDwhLS0gPGRpdiBjbGFzcz1cIm90cC1wYXNzd29yZC10b2dnbGVcIiAqbmdJZj1cImlucHV0VHlwZSA9PT0gJ3Bhc3N3b3JkJyAmJiBzaG93VW5NYXNrQ2hlY2tCb3hZTlwiPlxuICAgICAgPG1hdC1jaGVja2JveCBbY2hlY2tlZF09XCJ1bm1hc2tQYXNzd29yZFwiIChjaGFuZ2UpPVwidG9nZ2xlUGFzc3dvcmRWaXNpYmlsaXR5KClcIj5cbiAgICAgICAgU2hvdyBwYXNzd29yZFxuICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgPC9kaXY+IC0tPlxuXG4gIDwvZm9ybT5cbjwvZGl2PiJdfQ==
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctb3RwLWJveC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25nLW90cC1ib3gvc3JjL25nLW90cC1ib3gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Public API Surface of ng-otp-box
3
+ */
4
+ export * from './lib/ng-otp-box.service';
5
+ export * from './lib/ng-otp-box.component';
6
+ export * from './lib/ng-otp-box.module';
7
+ export * from './lib/otp-box/otp-box.component';
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25nLW90cC1ib3gvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLGlDQUFpQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiBuZy1vdHAtYm94XG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9saWIvbmctb3RwLWJveC5zZXJ2aWNlJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL25nLW90cC1ib3guY29tcG9uZW50JztcbmV4cG9ydCAqIGZyb20gJy4vbGliL25nLW90cC1ib3gubW9kdWxlJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL290cC1ib3gvb3RwLWJveC5jb21wb25lbnQnO1xuIl19
@@ -0,0 +1,215 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, Component, EventEmitter, Output, Input, ViewChildren, NgModule } from '@angular/core';
3
+ import * as i2 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i1 from '@angular/forms';
6
+ import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
7
+ import * as i3 from '@angular/material/input';
8
+ import { MatInputModule } from '@angular/material/input';
9
+ import * as i4 from '@angular/material/form-field';
10
+
11
+ class NgOtpBoxService {
12
+ constructor() { }
13
+ }
14
+ NgOtpBoxService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
15
+ NgOtpBoxService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, providedIn: 'root' });
16
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, decorators: [{
17
+ type: Injectable,
18
+ args: [{
19
+ providedIn: 'root'
20
+ }]
21
+ }], ctorParameters: function () { return []; } });
22
+
23
+ class NgOtpBoxComponent {
24
+ }
25
+ NgOtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
26
+ NgOtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NgOtpBoxComponent, selector: "lib-ng-otp-box", ngImport: i0, template: `
27
+ <p>
28
+ ng-otp-box works!
29
+ </p>
30
+ `, isInline: true });
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, decorators: [{
32
+ type: Component,
33
+ args: [{ selector: 'lib-ng-otp-box', template: `
34
+ <p>
35
+ ng-otp-box works!
36
+ </p>
37
+ ` }]
38
+ }] });
39
+
40
+ class OtpBoxComponent {
41
+ constructor(fb) {
42
+ this.fb = fb;
43
+ this.otpChange = new EventEmitter();
44
+ this.otpLength = 6;
45
+ this.inputType = 'number';
46
+ // @Input() allowUppercase: boolean = true;
47
+ // @Input() showUnMaskCheckBoxYN : boolean = false;
48
+ this.unmaskPassword = false;
49
+ }
50
+ ngOnInit() {
51
+ this.otpForm = this.fb.group({
52
+ otp: this.fb.array([]),
53
+ });
54
+ }
55
+ ngAfterViewInit() {
56
+ this.buildOtpControls();
57
+ // this.otpForm.valueChanges.subscribe((val) => {
58
+ // this.emitOtp();
59
+ // });
60
+ }
61
+ get otpArray() {
62
+ return this.otpForm.get('otp');
63
+ }
64
+ getInputPattern() {
65
+ const alpha = 'a-zA-Z';
66
+ const alphanumeric = 'a-zA-Z0-9';
67
+ switch (this.inputType) {
68
+ case 'text':
69
+ return new RegExp(`^[${alpha}]$`);
70
+ case 'number':
71
+ return /^[0-9+]$/;
72
+ case 'mixed':
73
+ return /^[a-zA-Z0-9]$/;
74
+ case 'masked':
75
+ return new RegExp(`^[${alphanumeric}]$`);
76
+ default:
77
+ return /^[0-9]$/;
78
+ }
79
+ }
80
+ buildOtpControls() {
81
+ this.otpArray.clear();
82
+ const pattern = this.getInputPattern();
83
+ for (let i = 0; i < this.otpLength; i++) {
84
+ this.otpArray.push(this.fb.control('', [Validators.required, Validators.pattern(pattern)]));
85
+ }
86
+ }
87
+ togglePasswordVisibility() {
88
+ this.unmaskPassword = !this.unmaskPassword;
89
+ }
90
+ focusFirstInput() {
91
+ if (this.inputs && this.inputs.length > 0) {
92
+ this.inputs.first.nativeElement.focus();
93
+ }
94
+ }
95
+ onInput(event, index) {
96
+ const input = event.target;
97
+ const { value, message } = this.sanitizeWithMessage(input.value);
98
+ this.emitChange(message);
99
+ this.otpArray.at(index).setValue(value, { emitEvent: false });
100
+ if (value && index < this.otpLength - 1) {
101
+ this.inputs.toArray()[index + 1].nativeElement.focus();
102
+ }
103
+ }
104
+ sanitizeWithMessage(rawValue) {
105
+ switch (this.inputType) {
106
+ case 'number':
107
+ if (/[^0-9]/.test(rawValue)) {
108
+ return {
109
+ value: rawValue.replace(/\D/g, ''),
110
+ message: 'Only numbers are allowed'
111
+ };
112
+ }
113
+ return { value: rawValue };
114
+ case 'text':
115
+ if (/[^a-zA-Z]/.test(rawValue)) {
116
+ return {
117
+ value: rawValue.replace(/[^a-zA-Z]/g, ''),
118
+ message: 'Only letters are allowed'
119
+ };
120
+ }
121
+ return { value: rawValue, message: 'success' };
122
+ case 'mixed':
123
+ case 'masked':
124
+ if (/[^a-zA-Z0-9]/.test(rawValue)) {
125
+ return {
126
+ value: rawValue.replace(/[^a-zA-Z0-9]/g, ''),
127
+ message: 'Only letters and numbers are allowed'
128
+ };
129
+ }
130
+ return { value: rawValue, message: 'success' };
131
+ default:
132
+ return { value: rawValue, message: 'success' };
133
+ }
134
+ }
135
+ onKeyDown(event, index) {
136
+ if (event.key === 'Backspace' &&
137
+ !this.otpArray.at(index).value &&
138
+ index > 0) {
139
+ this.inputs.toArray()[index - 1].nativeElement.focus();
140
+ }
141
+ }
142
+ onPaste(event) {
143
+ var _a, _b;
144
+ event.preventDefault();
145
+ const pasteData = (_b = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) !== null && _b !== void 0 ? _b : '';
146
+ const { value, message } = this.sanitizeWithMessage(pasteData);
147
+ if (value.length !== this.otpLength) {
148
+ this.emitChange('Invalid OTP length');
149
+ return;
150
+ }
151
+ value.split('').forEach((char, i) => {
152
+ this.otpArray.at(i).setValue(char, { emitEvent: false });
153
+ });
154
+ this.emitChange(message);
155
+ }
156
+ emitChange(message) {
157
+ const otp = this.otpArray.value.join('');
158
+ this.otpChange.emit({
159
+ value: otp,
160
+ isValid: this.otpForm.valid,
161
+ message: message
162
+ });
163
+ }
164
+ }
165
+ OtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
166
+ OtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpBoxComponent, selector: "lib-otp-box", inputs: { otpLength: "otpLength", inputType: "inputType" }, outputs: { otpChange: "otpChange" }, viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }] });
167
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, decorators: [{
168
+ type: Component,
169
+ args: [{ selector: 'lib-otp-box', template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"] }]
170
+ }], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { otpChange: [{
171
+ type: Output
172
+ }], otpLength: [{
173
+ type: Input
174
+ }], inputType: [{
175
+ type: Input
176
+ }], inputs: [{
177
+ type: ViewChildren,
178
+ args: ['otpInput']
179
+ }] } });
180
+
181
+ class NgOtpBoxModule {
182
+ }
183
+ NgOtpBoxModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
184
+ NgOtpBoxModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, declarations: [OtpBoxComponent], imports: [CommonModule,
185
+ ReactiveFormsModule,
186
+ FormsModule,
187
+ MatInputModule], exports: [OtpBoxComponent] });
188
+ NgOtpBoxModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, imports: [CommonModule,
189
+ ReactiveFormsModule,
190
+ FormsModule,
191
+ MatInputModule] });
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, decorators: [{
193
+ type: NgModule,
194
+ args: [{
195
+ declarations: [OtpBoxComponent],
196
+ imports: [
197
+ CommonModule,
198
+ ReactiveFormsModule,
199
+ FormsModule,
200
+ MatInputModule,
201
+ ],
202
+ exports: [OtpBoxComponent],
203
+ }]
204
+ }] });
205
+
206
+ /*
207
+ * Public API Surface of ng-otp-box
208
+ */
209
+
210
+ /**
211
+ * Generated bundle index. Do not edit.
212
+ */
213
+
214
+ export { NgOtpBoxComponent, NgOtpBoxModule, NgOtpBoxService, OtpBoxComponent };
215
+ //# sourceMappingURL=ng-otp-box.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-otp-box.mjs","sources":["../../../projects/ng-otp-box/src/lib/ng-otp-box.service.ts","../../../projects/ng-otp-box/src/lib/ng-otp-box.component.ts","../../../projects/ng-otp-box/src/lib/otp-box/otp-box.component.ts","../../../projects/ng-otp-box/src/lib/otp-box/otp-box.component.html","../../../projects/ng-otp-box/src/lib/ng-otp-box.module.ts","../../../projects/ng-otp-box/src/public-api.ts","../../../projects/ng-otp-box/src/ng-otp-box.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class NgOtpBoxService {\n\n constructor() { }\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-ng-otp-box',\n template: `\n <p>\n ng-otp-box works!\n </p>\n `,\n styles: [\n ]\n})\nexport class NgOtpBoxComponent {\n\n}\n","import { Input, OnInit, Output, ViewChildren } from '@angular/core';\nimport { Component, ElementRef, EventEmitter, QueryList } from '@angular/core';\nimport { FormGroup, FormBuilder, FormArray, Validators } from '@angular/forms';\n\nexport interface otpModel {\n isValid: boolean;\n value: number;\n message? : string;\n}\n\n@Component({\n selector: 'lib-otp-box',\n templateUrl: './otp-box.component.html',\n styleUrls: ['./otp-box.component.css']\n})\nexport class OtpBoxComponent implements OnInit {\n @Output() otpChange = new EventEmitter<any>();\n @Input() otpLength = 6;\n @Input() inputType: 'text' | 'number' | 'mixed' | 'masked' = 'number';\n // @Input() allowUppercase: boolean = true;\n // @Input() showUnMaskCheckBoxYN : boolean = false;\n unmaskPassword: boolean = false;\n\n otpForm!: FormGroup;\n\n @ViewChildren('otpInput') inputs!: QueryList<ElementRef>;\n\n constructor(private fb: FormBuilder) {}\n\n ngOnInit(): void {\n this.otpForm = this.fb.group({\n otp: this.fb.array([]),\n });\n }\n\n ngAfterViewInit(): void {\n this.buildOtpControls();\n\n // this.otpForm.valueChanges.subscribe((val) => {\n // this.emitOtp();\n // });\n }\n\n get otpArray(): FormArray {\n return this.otpForm.get('otp') as FormArray;\n }\n\n private getInputPattern(): RegExp {\n const alpha = 'a-zA-Z';\n const alphanumeric = 'a-zA-Z0-9';\n switch (this.inputType) {\n case 'text':\n return new RegExp(`^[${alpha}]$`);\n\n case 'number':\n return /^[0-9+]$/;\n\n case 'mixed':\n return /^[a-zA-Z0-9]$/;\n\n case 'masked':\n return new RegExp(`^[${alphanumeric}]$`);\n\n default:\n return /^[0-9]$/;\n }\n }\n\n private buildOtpControls(): void {\n this.otpArray.clear();\n const pattern = this.getInputPattern();\n\n for (let i = 0; i < this.otpLength; i++) {\n this.otpArray.push(\n this.fb.control('', [Validators.required, Validators.pattern(pattern)])\n );\n }\n }\n\n togglePasswordVisibility(): void {\n this.unmaskPassword = !this.unmaskPassword;\n }\n\n focusFirstInput() {\n if (this.inputs && this.inputs.length > 0) {\n this.inputs.first.nativeElement.focus();\n }\n }\n\n onInput(event: Event, index: number): void {\n const input = event.target as HTMLInputElement;\n const { value, message } = this.sanitizeWithMessage(input.value);\n this.emitChange(message);\n this.otpArray.at(index).setValue(value, { emitEvent: false });\n\n if (value && index < this.otpLength - 1) {\n this.inputs.toArray()[index + 1].nativeElement.focus();\n }\n }\n\n private sanitizeWithMessage(rawValue: string): { value: string; message?: string } {\n switch (this.inputType) {\n case 'number':\n if (/[^0-9]/.test(rawValue)) {\n return {\n value: rawValue.replace(/\\D/g, ''),\n message: 'Only numbers are allowed'\n };\n }\n return { value: rawValue };\n\n case 'text':\n if (/[^a-zA-Z]/.test(rawValue)) {\n return {\n value: rawValue.replace(/[^a-zA-Z]/g, ''),\n message: 'Only letters are allowed'\n };\n }\n return { value: rawValue, message: 'success' };\n\n case 'mixed':\n case 'masked':\n if (/[^a-zA-Z0-9]/.test(rawValue)) {\n return {\n value: rawValue.replace(/[^a-zA-Z0-9]/g, ''),\n message: 'Only letters and numbers are allowed'\n };\n }\n return { value: rawValue, message: 'success' };\n\n default:\n return { value: rawValue, message: 'success' };\n }\n}\n\n onKeyDown(event: KeyboardEvent, index: number): void {\n if (\n event.key === 'Backspace' &&\n !this.otpArray.at(index).value &&\n index > 0\n ) {\n this.inputs.toArray()[index - 1].nativeElement.focus();\n }\n }\n\nonPaste(event: ClipboardEvent): void {\n event.preventDefault();\n\n const pasteData = event.clipboardData?.getData('text') ?? '';\n const { value, message } = this.sanitizeWithMessage(pasteData);\n\n if (value.length !== this.otpLength) {\n this.emitChange('Invalid OTP length');\n return;\n }\n\n value.split('').forEach((char, i) => {\n this.otpArray.at(i).setValue(char, { emitEvent: false });\n });\n\n this.emitChange(message);\n}\n\n private emitChange(message: any): void {\n const otp = this.otpArray.value.join('');\n this.otpChange.emit({\n value: otp,\n isValid: this.otpForm.valid,\n message: message\n });\n }\n}\n","<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { MatInputModule } from '@angular/material/input';\n\nimport { OtpBoxComponent } from './otp-box/otp-box.component';\n\n@NgModule({\n declarations: [OtpBoxComponent],\n imports: [\n CommonModule,\n ReactiveFormsModule,\n FormsModule,\n MatInputModule,\n ],\n exports: [OtpBoxComponent],\n})\nexport class NgOtpBoxModule {}\n","/*\n * Public API Surface of ng-otp-box\n */\n\nexport * from './lib/ng-otp-box.service';\nexport * from './lib/ng-otp-box.component';\nexport * from './lib/ng-otp-box.module';\nexport * from './lib/otp-box/otp-box.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, Component, EventEmitter, Output, Input, ViewChildren, NgModule } from '@angular/core';
3
+ import * as i2 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i1 from '@angular/forms';
6
+ import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
7
+ import * as i3 from '@angular/material/input';
8
+ import { MatInputModule } from '@angular/material/input';
9
+ import * as i4 from '@angular/material/form-field';
10
+
11
+ class NgOtpBoxService {
12
+ constructor() { }
13
+ }
14
+ NgOtpBoxService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
15
+ NgOtpBoxService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, providedIn: 'root' });
16
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxService, decorators: [{
17
+ type: Injectable,
18
+ args: [{
19
+ providedIn: 'root'
20
+ }]
21
+ }], ctorParameters: function () { return []; } });
22
+
23
+ class NgOtpBoxComponent {
24
+ }
25
+ NgOtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
26
+ NgOtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NgOtpBoxComponent, selector: "lib-ng-otp-box", ngImport: i0, template: `
27
+ <p>
28
+ ng-otp-box works!
29
+ </p>
30
+ `, isInline: true });
31
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxComponent, decorators: [{
32
+ type: Component,
33
+ args: [{ selector: 'lib-ng-otp-box', template: `
34
+ <p>
35
+ ng-otp-box works!
36
+ </p>
37
+ ` }]
38
+ }] });
39
+
40
+ class OtpBoxComponent {
41
+ constructor(fb) {
42
+ this.fb = fb;
43
+ this.otpChange = new EventEmitter();
44
+ this.otpLength = 6;
45
+ this.inputType = 'number';
46
+ // @Input() allowUppercase: boolean = true;
47
+ // @Input() showUnMaskCheckBoxYN : boolean = false;
48
+ this.unmaskPassword = false;
49
+ }
50
+ ngOnInit() {
51
+ this.otpForm = this.fb.group({
52
+ otp: this.fb.array([]),
53
+ });
54
+ }
55
+ ngAfterViewInit() {
56
+ this.buildOtpControls();
57
+ // this.otpForm.valueChanges.subscribe((val) => {
58
+ // this.emitOtp();
59
+ // });
60
+ }
61
+ get otpArray() {
62
+ return this.otpForm.get('otp');
63
+ }
64
+ getInputPattern() {
65
+ const alpha = 'a-zA-Z';
66
+ const alphanumeric = 'a-zA-Z0-9';
67
+ switch (this.inputType) {
68
+ case 'text':
69
+ return new RegExp(`^[${alpha}]$`);
70
+ case 'number':
71
+ return /^[0-9+]$/;
72
+ case 'mixed':
73
+ return /^[a-zA-Z0-9]$/;
74
+ case 'masked':
75
+ return new RegExp(`^[${alphanumeric}]$`);
76
+ default:
77
+ return /^[0-9]$/;
78
+ }
79
+ }
80
+ buildOtpControls() {
81
+ this.otpArray.clear();
82
+ const pattern = this.getInputPattern();
83
+ for (let i = 0; i < this.otpLength; i++) {
84
+ this.otpArray.push(this.fb.control('', [Validators.required, Validators.pattern(pattern)]));
85
+ }
86
+ }
87
+ togglePasswordVisibility() {
88
+ this.unmaskPassword = !this.unmaskPassword;
89
+ }
90
+ focusFirstInput() {
91
+ if (this.inputs && this.inputs.length > 0) {
92
+ this.inputs.first.nativeElement.focus();
93
+ }
94
+ }
95
+ onInput(event, index) {
96
+ const input = event.target;
97
+ const { value, message } = this.sanitizeWithMessage(input.value);
98
+ this.emitChange(message);
99
+ this.otpArray.at(index).setValue(value, { emitEvent: false });
100
+ if (value && index < this.otpLength - 1) {
101
+ this.inputs.toArray()[index + 1].nativeElement.focus();
102
+ }
103
+ }
104
+ sanitizeWithMessage(rawValue) {
105
+ switch (this.inputType) {
106
+ case 'number':
107
+ if (/[^0-9]/.test(rawValue)) {
108
+ return {
109
+ value: rawValue.replace(/\D/g, ''),
110
+ message: 'Only numbers are allowed'
111
+ };
112
+ }
113
+ return { value: rawValue };
114
+ case 'text':
115
+ if (/[^a-zA-Z]/.test(rawValue)) {
116
+ return {
117
+ value: rawValue.replace(/[^a-zA-Z]/g, ''),
118
+ message: 'Only letters are allowed'
119
+ };
120
+ }
121
+ return { value: rawValue, message: 'success' };
122
+ case 'mixed':
123
+ case 'masked':
124
+ if (/[^a-zA-Z0-9]/.test(rawValue)) {
125
+ return {
126
+ value: rawValue.replace(/[^a-zA-Z0-9]/g, ''),
127
+ message: 'Only letters and numbers are allowed'
128
+ };
129
+ }
130
+ return { value: rawValue, message: 'success' };
131
+ default:
132
+ return { value: rawValue, message: 'success' };
133
+ }
134
+ }
135
+ onKeyDown(event, index) {
136
+ if (event.key === 'Backspace' &&
137
+ !this.otpArray.at(index).value &&
138
+ index > 0) {
139
+ this.inputs.toArray()[index - 1].nativeElement.focus();
140
+ }
141
+ }
142
+ onPaste(event) {
143
+ event.preventDefault();
144
+ const pasteData = event.clipboardData?.getData('text') ?? '';
145
+ const { value, message } = this.sanitizeWithMessage(pasteData);
146
+ if (value.length !== this.otpLength) {
147
+ this.emitChange('Invalid OTP length');
148
+ return;
149
+ }
150
+ value.split('').forEach((char, i) => {
151
+ this.otpArray.at(i).setValue(char, { emitEvent: false });
152
+ });
153
+ this.emitChange(message);
154
+ }
155
+ emitChange(message) {
156
+ const otp = this.otpArray.value.join('');
157
+ this.otpChange.emit({
158
+ value: otp,
159
+ isValid: this.otpForm.valid,
160
+ message: message
161
+ });
162
+ }
163
+ }
164
+ OtpBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
165
+ OtpBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpBoxComponent, selector: "lib-otp-box", inputs: { otpLength: "otpLength", inputType: "inputType" }, outputs: { otpChange: "otpChange" }, viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }] });
166
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpBoxComponent, decorators: [{
167
+ type: Component,
168
+ args: [{ selector: 'lib-otp-box', template: "<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>", styles: [".otp-container{display:flex;gap:10px;align-items:center}.otp-mat-field{width:46px}.otp-mat-field input{text-align:center;font-size:18px}.otp-mat-field.mat-form-field-appearance-fill .mat-form-field-flex{background-color:#f2f2f2;border-radius:6px}.otp-mat-field.mat-form-field-invalid .mat-form-field-flex{background-color:#fdecea}\n"] }]
169
+ }], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { otpChange: [{
170
+ type: Output
171
+ }], otpLength: [{
172
+ type: Input
173
+ }], inputType: [{
174
+ type: Input
175
+ }], inputs: [{
176
+ type: ViewChildren,
177
+ args: ['otpInput']
178
+ }] } });
179
+
180
+ class NgOtpBoxModule {
181
+ }
182
+ NgOtpBoxModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
183
+ NgOtpBoxModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, declarations: [OtpBoxComponent], imports: [CommonModule,
184
+ ReactiveFormsModule,
185
+ FormsModule,
186
+ MatInputModule], exports: [OtpBoxComponent] });
187
+ NgOtpBoxModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, imports: [CommonModule,
188
+ ReactiveFormsModule,
189
+ FormsModule,
190
+ MatInputModule] });
191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NgOtpBoxModule, decorators: [{
192
+ type: NgModule,
193
+ args: [{
194
+ declarations: [OtpBoxComponent],
195
+ imports: [
196
+ CommonModule,
197
+ ReactiveFormsModule,
198
+ FormsModule,
199
+ MatInputModule,
200
+ ],
201
+ exports: [OtpBoxComponent],
202
+ }]
203
+ }] });
204
+
205
+ /*
206
+ * Public API Surface of ng-otp-box
207
+ */
208
+
209
+ /**
210
+ * Generated bundle index. Do not edit.
211
+ */
212
+
213
+ export { NgOtpBoxComponent, NgOtpBoxModule, NgOtpBoxService, OtpBoxComponent };
214
+ //# sourceMappingURL=ng-otp-box.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-otp-box.mjs","sources":["../../../projects/ng-otp-box/src/lib/ng-otp-box.service.ts","../../../projects/ng-otp-box/src/lib/ng-otp-box.component.ts","../../../projects/ng-otp-box/src/lib/otp-box/otp-box.component.ts","../../../projects/ng-otp-box/src/lib/otp-box/otp-box.component.html","../../../projects/ng-otp-box/src/lib/ng-otp-box.module.ts","../../../projects/ng-otp-box/src/public-api.ts","../../../projects/ng-otp-box/src/ng-otp-box.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\n@Injectable({\n providedIn: 'root'\n})\nexport class NgOtpBoxService {\n\n constructor() { }\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-ng-otp-box',\n template: `\n <p>\n ng-otp-box works!\n </p>\n `,\n styles: [\n ]\n})\nexport class NgOtpBoxComponent {\n\n}\n","import { Input, OnInit, Output, ViewChildren } from '@angular/core';\nimport { Component, ElementRef, EventEmitter, QueryList } from '@angular/core';\nimport { FormGroup, FormBuilder, FormArray, Validators } from '@angular/forms';\n\nexport interface otpModel {\n isValid: boolean;\n value: number;\n message? : string;\n}\n\n@Component({\n selector: 'lib-otp-box',\n templateUrl: './otp-box.component.html',\n styleUrls: ['./otp-box.component.css']\n})\nexport class OtpBoxComponent implements OnInit {\n @Output() otpChange = new EventEmitter<any>();\n @Input() otpLength = 6;\n @Input() inputType: 'text' | 'number' | 'mixed' | 'masked' = 'number';\n // @Input() allowUppercase: boolean = true;\n // @Input() showUnMaskCheckBoxYN : boolean = false;\n unmaskPassword: boolean = false;\n\n otpForm!: FormGroup;\n\n @ViewChildren('otpInput') inputs!: QueryList<ElementRef>;\n\n constructor(private fb: FormBuilder) {}\n\n ngOnInit(): void {\n this.otpForm = this.fb.group({\n otp: this.fb.array([]),\n });\n }\n\n ngAfterViewInit(): void {\n this.buildOtpControls();\n\n // this.otpForm.valueChanges.subscribe((val) => {\n // this.emitOtp();\n // });\n }\n\n get otpArray(): FormArray {\n return this.otpForm.get('otp') as FormArray;\n }\n\n private getInputPattern(): RegExp {\n const alpha = 'a-zA-Z';\n const alphanumeric = 'a-zA-Z0-9';\n switch (this.inputType) {\n case 'text':\n return new RegExp(`^[${alpha}]$`);\n\n case 'number':\n return /^[0-9+]$/;\n\n case 'mixed':\n return /^[a-zA-Z0-9]$/;\n\n case 'masked':\n return new RegExp(`^[${alphanumeric}]$`);\n\n default:\n return /^[0-9]$/;\n }\n }\n\n private buildOtpControls(): void {\n this.otpArray.clear();\n const pattern = this.getInputPattern();\n\n for (let i = 0; i < this.otpLength; i++) {\n this.otpArray.push(\n this.fb.control('', [Validators.required, Validators.pattern(pattern)])\n );\n }\n }\n\n togglePasswordVisibility(): void {\n this.unmaskPassword = !this.unmaskPassword;\n }\n\n focusFirstInput() {\n if (this.inputs && this.inputs.length > 0) {\n this.inputs.first.nativeElement.focus();\n }\n }\n\n onInput(event: Event, index: number): void {\n const input = event.target as HTMLInputElement;\n const { value, message } = this.sanitizeWithMessage(input.value);\n this.emitChange(message);\n this.otpArray.at(index).setValue(value, { emitEvent: false });\n\n if (value && index < this.otpLength - 1) {\n this.inputs.toArray()[index + 1].nativeElement.focus();\n }\n }\n\n private sanitizeWithMessage(rawValue: string): { value: string; message?: string } {\n switch (this.inputType) {\n case 'number':\n if (/[^0-9]/.test(rawValue)) {\n return {\n value: rawValue.replace(/\\D/g, ''),\n message: 'Only numbers are allowed'\n };\n }\n return { value: rawValue };\n\n case 'text':\n if (/[^a-zA-Z]/.test(rawValue)) {\n return {\n value: rawValue.replace(/[^a-zA-Z]/g, ''),\n message: 'Only letters are allowed'\n };\n }\n return { value: rawValue, message: 'success' };\n\n case 'mixed':\n case 'masked':\n if (/[^a-zA-Z0-9]/.test(rawValue)) {\n return {\n value: rawValue.replace(/[^a-zA-Z0-9]/g, ''),\n message: 'Only letters and numbers are allowed'\n };\n }\n return { value: rawValue, message: 'success' };\n\n default:\n return { value: rawValue, message: 'success' };\n }\n}\n\n onKeyDown(event: KeyboardEvent, index: number): void {\n if (\n event.key === 'Backspace' &&\n !this.otpArray.at(index).value &&\n index > 0\n ) {\n this.inputs.toArray()[index - 1].nativeElement.focus();\n }\n }\n\nonPaste(event: ClipboardEvent): void {\n event.preventDefault();\n\n const pasteData = event.clipboardData?.getData('text') ?? '';\n const { value, message } = this.sanitizeWithMessage(pasteData);\n\n if (value.length !== this.otpLength) {\n this.emitChange('Invalid OTP length');\n return;\n }\n\n value.split('').forEach((char, i) => {\n this.otpArray.at(i).setValue(char, { emitEvent: false });\n });\n\n this.emitChange(message);\n}\n\n private emitChange(message: any): void {\n const otp = this.otpArray.value.join('');\n this.otpChange.emit({\n value: otp,\n isValid: this.otpForm.valid,\n message: message\n });\n }\n}\n","<div>\n <form [formGroup]=\"otpForm\" (paste)=\"onPaste($event)\">\n\n <div class=\"otp-container\" formArrayName=\"otp\">\n <ng-container *ngFor=\"let ctrl of otpArray.controls; let i = index\">\n <mat-form-field appearance=\"outline\" class=\"otp-mat-field\" [class.mat-form-field-invalid]=\"\n otpForm.invalid && (otpForm.touched || otpForm.dirty)\">\n <input matInput [type]=\"inputType === 'masked' ? 'password' : 'text'\" maxlength=\"1\"\n #otpInput cdkFocusInitial [formControlName]=\"i\" (input)=\"onInput($event, i)\"\n (keydown)=\"onKeyDown($event, i)\" />\n </mat-form-field>\n </ng-container>\n </div>\n <!-- <div class=\"otp-password-toggle\" *ngIf=\"inputType === 'password' && showUnMaskCheckBoxYN\">\n <mat-checkbox [checked]=\"unmaskPassword\" (change)=\"togglePasswordVisibility()\">\n Show password\n </mat-checkbox>\n </div> -->\n\n </form>\n</div>","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\n\nimport { MatInputModule } from '@angular/material/input';\n\nimport { OtpBoxComponent } from './otp-box/otp-box.component';\n\n@NgModule({\n declarations: [OtpBoxComponent],\n imports: [\n CommonModule,\n ReactiveFormsModule,\n FormsModule,\n MatInputModule,\n ],\n exports: [OtpBoxComponent],\n})\nexport class NgOtpBoxModule {}\n","/*\n * Public API Surface of ng-otp-box\n */\n\nexport * from './lib/ng-otp-box.service';\nexport * from './lib/ng-otp-box.component';\nexport * from './lib/ng-otp-box.module';\nexport * from './lib/otp-box/otp-box.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="ng-otp-box" />
5
+ export * from './public-api';
@@ -0,0 +1,5 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class NgOtpBoxComponent {
3
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgOtpBoxComponent, never>;
4
+ static ɵcmp: i0.ɵɵComponentDeclaration<NgOtpBoxComponent, "lib-ng-otp-box", never, {}, {}, never, never, false, never>;
5
+ }
@@ -0,0 +1,10 @@
1
+ import * as i0 from "@angular/core";
2
+ import * as i1 from "./otp-box/otp-box.component";
3
+ import * as i2 from "@angular/common";
4
+ import * as i3 from "@angular/forms";
5
+ import * as i4 from "@angular/material/input";
6
+ export declare class NgOtpBoxModule {
7
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgOtpBoxModule, never>;
8
+ static ɵmod: i0.ɵɵNgModuleDeclaration<NgOtpBoxModule, [typeof i1.OtpBoxComponent], [typeof i2.CommonModule, typeof i3.ReactiveFormsModule, typeof i3.FormsModule, typeof i4.MatInputModule], [typeof i1.OtpBoxComponent]>;
9
+ static ɵinj: i0.ɵɵInjectorDeclaration<NgOtpBoxModule>;
10
+ }
@@ -0,0 +1,6 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class NgOtpBoxService {
3
+ constructor();
4
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgOtpBoxService, never>;
5
+ static ɵprov: i0.ɵɵInjectableDeclaration<NgOtpBoxService>;
6
+ }
@@ -0,0 +1,33 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { ElementRef, EventEmitter, QueryList } from '@angular/core';
3
+ import { FormGroup, FormBuilder, FormArray } from '@angular/forms';
4
+ import * as i0 from "@angular/core";
5
+ export interface otpModel {
6
+ isValid: boolean;
7
+ value: number;
8
+ message?: string;
9
+ }
10
+ export declare class OtpBoxComponent implements OnInit {
11
+ private fb;
12
+ otpChange: EventEmitter<any>;
13
+ otpLength: number;
14
+ inputType: 'text' | 'number' | 'mixed' | 'masked';
15
+ unmaskPassword: boolean;
16
+ otpForm: FormGroup;
17
+ inputs: QueryList<ElementRef>;
18
+ constructor(fb: FormBuilder);
19
+ ngOnInit(): void;
20
+ ngAfterViewInit(): void;
21
+ get otpArray(): FormArray;
22
+ private getInputPattern;
23
+ private buildOtpControls;
24
+ togglePasswordVisibility(): void;
25
+ focusFirstInput(): void;
26
+ onInput(event: Event, index: number): void;
27
+ private sanitizeWithMessage;
28
+ onKeyDown(event: KeyboardEvent, index: number): void;
29
+ onPaste(event: ClipboardEvent): void;
30
+ private emitChange;
31
+ static ɵfac: i0.ɵɵFactoryDeclaration<OtpBoxComponent, never>;
32
+ static ɵcmp: i0.ɵɵComponentDeclaration<OtpBoxComponent, "lib-otp-box", never, { "otpLength": "otpLength"; "inputType": "inputType"; }, { "otpChange": "otpChange"; }, never, never, false, never>;
33
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "ng-otp-box",
3
+ "version": "0.0.1",
4
+ "peerDependencies": {
5
+ "@angular/common": "^15.1.0",
6
+ "@angular/core": "^15.1.0",
7
+ "@angular/cdk": "^15.0.0",
8
+ "@angular/material": "^15.0.0"
9
+ },
10
+ "dependencies": {
11
+ "tslib": "^2.3.0"
12
+ },
13
+ "sideEffects": false,
14
+ "module": "fesm2015/ng-otp-box.mjs",
15
+ "es2020": "fesm2020/ng-otp-box.mjs",
16
+ "esm2020": "esm2020/ng-otp-box.mjs",
17
+ "fesm2020": "fesm2020/ng-otp-box.mjs",
18
+ "fesm2015": "fesm2015/ng-otp-box.mjs",
19
+ "typings": "index.d.ts",
20
+ "exports": {
21
+ "./package.json": {
22
+ "default": "./package.json"
23
+ },
24
+ ".": {
25
+ "types": "./index.d.ts",
26
+ "esm2020": "./esm2020/ng-otp-box.mjs",
27
+ "es2020": "./fesm2020/ng-otp-box.mjs",
28
+ "es2015": "./fesm2015/ng-otp-box.mjs",
29
+ "node": "./fesm2015/ng-otp-box.mjs",
30
+ "default": "./fesm2020/ng-otp-box.mjs"
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ export * from './lib/ng-otp-box.service';
2
+ export * from './lib/ng-otp-box.component';
3
+ export * from './lib/ng-otp-box.module';
4
+ export * from './lib/otp-box/otp-box.component';