@muxima-ui/otp-input 1.0.0

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.
@@ -0,0 +1,2 @@
1
+ export * from './lib/otp-input/otp-input.component';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9mb3JtL290cC1pbnB1dC9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxxQ0FBcUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vbGliL290cC1pbnB1dC9vdHAtaW5wdXQuY29tcG9uZW50JztcclxuIl19
@@ -0,0 +1,191 @@
1
+ import { Component, Input, Output, EventEmitter, forwardRef, ViewChildren } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+ export class OtpInputComponent {
7
+ constructor() {
8
+ this.length = 6;
9
+ this.type = 'number';
10
+ this.placeholder = '';
11
+ this.disabled = false;
12
+ this.secure = false;
13
+ this.autoFocus = true;
14
+ this.size = 'medium';
15
+ this.otpComplete = new EventEmitter();
16
+ this.otpChange = new EventEmitter();
17
+ this.otpValues = [];
18
+ this.onChange = () => { };
19
+ this.onTouched = () => { };
20
+ }
21
+ ngAfterViewInit() {
22
+ this.otpValues = Array(this.length).fill('');
23
+ if (this.autoFocus && this.inputs.first) {
24
+ setTimeout(() => this.inputs.first.nativeElement.focus(), 100);
25
+ }
26
+ }
27
+ writeValue(value) {
28
+ if (value) {
29
+ this.otpValues = value.split('').slice(0, this.length);
30
+ while (this.otpValues.length < this.length) {
31
+ this.otpValues.push('');
32
+ }
33
+ }
34
+ else {
35
+ this.otpValues = Array(this.length).fill('');
36
+ }
37
+ }
38
+ registerOnChange(fn) {
39
+ this.onChange = fn;
40
+ }
41
+ registerOnTouched(fn) {
42
+ this.onTouched = fn;
43
+ }
44
+ setDisabledState(isDisabled) {
45
+ this.disabled = isDisabled;
46
+ }
47
+ onInput(event, index) {
48
+ const input = event.target;
49
+ let value = input.value;
50
+ // Allow only numbers or text based on type
51
+ if (this.type === 'number') {
52
+ value = value.replace(/[^0-9]/g, '');
53
+ }
54
+ // Take only the last character if multiple are entered
55
+ if (value.length > 1) {
56
+ value = value.slice(-1);
57
+ }
58
+ this.otpValues[index] = value;
59
+ input.value = value;
60
+ // Move to next input if value is entered
61
+ if (value && index < this.length - 1) {
62
+ const nextInput = this.inputs.toArray()[index + 1];
63
+ if (nextInput) {
64
+ nextInput.nativeElement.focus();
65
+ }
66
+ }
67
+ this.emitValue();
68
+ }
69
+ onKeyDown(event, index) {
70
+ const input = event.target;
71
+ // Handle backspace
72
+ if (event.key === 'Backspace') {
73
+ if (!this.otpValues[index] && index > 0) {
74
+ // Move to previous input if current is empty
75
+ const prevInput = this.inputs.toArray()[index - 1];
76
+ if (prevInput) {
77
+ prevInput.nativeElement.focus();
78
+ this.otpValues[index - 1] = '';
79
+ this.emitValue();
80
+ }
81
+ }
82
+ else if (this.otpValues[index]) {
83
+ // Clear current input
84
+ this.otpValues[index] = '';
85
+ this.emitValue();
86
+ }
87
+ event.preventDefault();
88
+ }
89
+ // Handle arrow keys
90
+ if (event.key === 'ArrowLeft' && index > 0) {
91
+ this.inputs.toArray()[index - 1].nativeElement.focus();
92
+ }
93
+ if (event.key === 'ArrowRight' && index < this.length - 1) {
94
+ this.inputs.toArray()[index + 1].nativeElement.focus();
95
+ }
96
+ }
97
+ onPaste(event) {
98
+ event.preventDefault();
99
+ const pastedData = event.clipboardData?.getData('text') || '';
100
+ let values = pastedData.split('').slice(0, this.length);
101
+ if (this.type === 'number') {
102
+ values = values.filter(char => /[0-9]/.test(char));
103
+ }
104
+ values.forEach((value, index) => {
105
+ if (index < this.length) {
106
+ this.otpValues[index] = value;
107
+ const input = this.inputs.toArray()[index];
108
+ if (input) {
109
+ input.nativeElement.value = value;
110
+ }
111
+ }
112
+ });
113
+ // Focus on the next empty input or last input
114
+ const nextEmptyIndex = this.otpValues.findIndex(v => !v);
115
+ const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : this.length - 1;
116
+ const inputToFocus = this.inputs.toArray()[focusIndex];
117
+ if (inputToFocus) {
118
+ inputToFocus.nativeElement.focus();
119
+ }
120
+ this.emitValue();
121
+ }
122
+ onFocus(index) {
123
+ const input = this.inputs.toArray()[index];
124
+ if (input) {
125
+ input.nativeElement.select();
126
+ }
127
+ this.onTouched();
128
+ }
129
+ emitValue() {
130
+ const otpValue = this.otpValues.join('');
131
+ this.onChange(otpValue);
132
+ this.otpChange.emit(otpValue);
133
+ // Emit complete event if all fields are filled
134
+ if (otpValue.length === this.length) {
135
+ this.otpComplete.emit(otpValue);
136
+ }
137
+ }
138
+ clear() {
139
+ this.otpValues = Array(this.length).fill('');
140
+ this.inputs.toArray().forEach(input => {
141
+ input.nativeElement.value = '';
142
+ });
143
+ if (this.inputs.first) {
144
+ this.inputs.first.nativeElement.focus();
145
+ }
146
+ this.emitValue();
147
+ }
148
+ trackByIndex(index) {
149
+ return index;
150
+ }
151
+ }
152
+ OtpInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
153
+ OtpInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpInputComponent, isStandalone: true, selector: "muxima-otp-input", inputs: { length: "length", type: "type", placeholder: "placeholder", disabled: "disabled", secure: "secure", autoFocus: "autoFocus", size: "size" }, outputs: { otpComplete: "otpComplete", otpChange: "otpChange" }, providers: [
154
+ {
155
+ provide: NG_VALUE_ACCESSOR,
156
+ useExisting: forwardRef(() => OtpInputComponent),
157
+ multi: true
158
+ }
159
+ ], viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
160
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, decorators: [{
161
+ type: Component,
162
+ args: [{ selector: 'muxima-otp-input', standalone: true, imports: [CommonModule], providers: [
163
+ {
164
+ provide: NG_VALUE_ACCESSOR,
165
+ useExisting: forwardRef(() => OtpInputComponent),
166
+ multi: true
167
+ }
168
+ ], template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"] }]
169
+ }], propDecorators: { length: [{
170
+ type: Input
171
+ }], type: [{
172
+ type: Input
173
+ }], placeholder: [{
174
+ type: Input
175
+ }], disabled: [{
176
+ type: Input
177
+ }], secure: [{
178
+ type: Input
179
+ }], autoFocus: [{
180
+ type: Input
181
+ }], size: [{
182
+ type: Input
183
+ }], otpComplete: [{
184
+ type: Output
185
+ }], otpChange: [{
186
+ type: Output
187
+ }], inputs: [{
188
+ type: ViewChildren,
189
+ args: ['otpInput']
190
+ }] } });
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2Zvcm0vb3RwLWlucHV0L3NyYy9saWIvb3RwLWlucHV0L290cC1pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9mb3JtL290cC1pbnB1dC9zcmMvbGliL290cC1pbnB1dC9vdHAtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUF3QyxNQUFNLGVBQWUsQ0FBQztBQUN2SSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFnQnpFLE1BQU0sT0FBTyxpQkFBaUI7SUFkOUI7UUFlVyxXQUFNLEdBQVcsQ0FBQyxDQUFDO1FBQ25CLFNBQUksR0FBc0IsUUFBUSxDQUFDO1FBQ25DLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFDMUIsV0FBTSxHQUFZLEtBQUssQ0FBQztRQUN4QixjQUFTLEdBQVksSUFBSSxDQUFDO1FBQzFCLFNBQUksR0FBaUMsUUFBUSxDQUFDO1FBRTdDLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUN6QyxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUlqRCxjQUFTLEdBQWEsRUFBRSxDQUFDO1FBQ2pCLGFBQVEsR0FBNEIsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQzdDLGNBQVMsR0FBZSxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7S0F5SjFDO0lBdkpDLGVBQWU7UUFDYixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFD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Q2YsQ0FBQzs7K0dBeEtVLGlCQUFpQjttR0FBakIsaUJBQWlCLHNSQVJqQjtRQUNUO1lBQ0UsT0FBTyxFQUFFLGlCQUFpQjtZQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixDQUFDO1lBQ2hELEtBQUssRUFBRSxJQUFJO1NBQ1o7S0FDRixpSENoQkgsMm9CQWtCQSxrbUREWFksWUFBWTs0RkFXWCxpQkFBaUI7a0JBZDdCLFNBQVM7K0JBQ0Usa0JBQWtCLGNBQ2hCLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyxhQUdaO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLGtCQUFrQixDQUFDOzRCQUNoRCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjs4QkFHUSxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUVtQixNQUFNO3NCQUEvQixZQUFZO3VCQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgZm9yd2FyZFJlZiwgVmlld0NoaWxkcmVuLCBRdWVyeUxpc3QsIEVsZW1lbnRSZWYsIEFmdGVyVmlld0luaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdtdXhpbWEtb3RwLWlucHV0JyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9vdHAtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL290cC1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gT3RwSW5wdXRDb21wb25lbnQpLFxyXG4gICAgICBtdWx0aTogdHJ1ZVxyXG4gICAgfVxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIE90cElucHV0Q29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEFmdGVyVmlld0luaXQge1xyXG4gIEBJbnB1dCgpIGxlbmd0aDogbnVtYmVyID0gNjtcclxuICBASW5wdXQoKSB0eXBlOiAnbnVtYmVyJyB8ICd0ZXh0JyA9ICdudW1iZXInO1xyXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnJztcclxuICBASW5wdXQoKSBkaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNlY3VyZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGF1dG9Gb2N1czogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgc2l6ZTogJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJyA9ICdtZWRpdW0nO1xyXG4gIFxyXG4gIEBPdXRwdXQoKSBvdHBDb21wbGV0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIEBPdXRwdXQoKSBvdHBDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBcclxuICBAVmlld0NoaWxkcmVuKCdvdHBJbnB1dCcpIGlucHV0cyE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+PjtcclxuICBcclxuICBvdHBWYWx1ZXM6IHN0cmluZ1tdID0gW107XHJcbiAgcHJpdmF0ZSBvbkNoYW5nZTogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWQgPSAoKSA9PiB7fTtcclxuICBwcml2YXRlIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLm90cFZhbHVlcyA9IEFycmF5KHRoaXMubGVuZ3RoKS5maWxsKCcnKTtcclxuICAgIGlmICh0aGlzLmF1dG9Gb2N1cyAmJiB0aGlzLmlucHV0cy5maXJzdCkge1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5wdXRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKSwgMTAwKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHdyaXRlVmFsdWUodmFsdWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgIHRoaXMub3RwVmFsdWVzID0gdmFsdWUuc3BsaXQoJycpLnNsaWNlKDAsIHRoaXMubGVuZ3RoKTtcclxuICAgICAgd2hpbGUgKHRoaXMub3RwVmFsdWVzLmxlbmd0aCA8IHRoaXMubGVuZ3RoKSB7XHJcbiAgICAgICAgdGhpcy5vdHBWYWx1ZXMucHVzaCgnJyk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMub3RwVmFsdWVzID0gQXJyYXkodGhpcy5sZW5ndGgpLmZpbGwoJycpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xyXG4gIH1cclxuXHJcbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcclxuICB9XHJcblxyXG4gIG9uSW5wdXQoZXZlbnQ6IEV2ZW50LCBpbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBjb25zdCBpbnB1dCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG4gICAgbGV0IHZhbHVlID0gaW5wdXQudmFsdWU7XHJcblxyXG4gICAgLy8gQWxsb3cgb25seSBudW1iZXJzIG9yIHRleHQgYmFzZWQgb24gdHlwZVxyXG4gICAgaWYgKHRoaXMudHlwZSA9PT0gJ251bWJlcicpIHtcclxuICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRha2Ugb25seSB0aGUgbGFzdCBjaGFyYWN0ZXIgaWYgbXVsdGlwbGUgYXJlIGVudGVyZWRcclxuICAgIGlmICh2YWx1ZS5sZW5ndGggPiAxKSB7XHJcbiAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoLTEpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMub3RwVmFsdWVzW2luZGV4XSA9IHZhbHVlO1xyXG4gICAgaW5wdXQudmFsdWUgPSB2YWx1ZTtcclxuXHJcbiAgICAvLyBNb3ZlIHRvIG5leHQgaW5wdXQgaWYgdmFsdWUgaXMgZW50ZXJlZFxyXG4gICAgaWYgKHZhbHVlICYmIGluZGV4IDwgdGhpcy5sZW5ndGggLSAxKSB7XHJcbiAgICAgIGNvbnN0IG5leHRJbnB1dCA9IHRoaXMuaW5wdXRzLnRvQXJyYXkoKVtpbmRleCArIDFdO1xyXG4gICAgICBpZiAobmV4dElucHV0KSB7XHJcbiAgICAgICAgbmV4dElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZW1pdFZhbHVlKCk7XHJcbiAgfVxyXG5cclxuICBvbktleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcblxyXG4gICAgLy8gSGFuZGxlIGJhY2tzcGFjZVxyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0JhY2tzcGFjZScpIHtcclxuICAgICAgaWYgKCF0aGlzLm90cFZhbHVlc1tpbmRleF0gJiYgaW5kZXggPiAwKSB7XHJcbiAgICAgICAgLy8gTW92ZSB0byBwcmV2aW91cyBpbnB1dCBpZiBjdXJyZW50IGlzIGVtcHR5XHJcbiAgICAgICAgY29uc3QgcHJldklucHV0ID0gdGhpcy5pbnB1dHMudG9BcnJheSgpW2luZGV4IC0gMV07XHJcbiAgICAgICAgaWYgKHByZXZJbnB1dCkge1xyXG4gICAgICAgICAgcHJldklucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICAgICAgICAgIHRoaXMub3RwVmFsdWVzW2luZGV4IC0gMV0gPSAnJztcclxuICAgICAgICAgIHRoaXMuZW1pdFZhbHVlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMub3RwVmFsdWVzW2luZGV4XSkge1xyXG4gICAgICAgIC8vIENsZWFyIGN1cnJlbnQgaW5wdXRcclxuICAgICAgICB0aGlzLm90cFZhbHVlc1tpbmRleF0gPSAnJztcclxuICAgICAgICB0aGlzLmVtaXRWYWx1ZSgpO1xyXG4gICAgICB9XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gSGFuZGxlIGFycm93IGtleXNcclxuICAgIGlmIChldmVudC5rZXkgPT09ICdBcnJvd0xlZnQnICYmIGluZGV4ID4gMCkge1xyXG4gICAgICB0aGlzLmlucHV0cy50b0FycmF5KClbaW5kZXggLSAxXS5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgICB9XHJcbiAgICBpZiAoZXZlbnQua2V5ID09PSAnQXJyb3dSaWdodCcgJiYgaW5kZXggPCB0aGlzLmxlbmd0aCAtIDEpIHtcclxuICAgICAgdGhpcy5pbnB1dHMudG9BcnJheSgpW2luZGV4ICsgMV0ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25QYXN0ZShldmVudDogQ2xpcGJvYXJkRXZlbnQpOiB2b2lkIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBjb25zdCBwYXN0ZWREYXRhID0gZXZlbnQuY2xpcGJvYXJkRGF0YT8uZ2V0RGF0YSgndGV4dCcpIHx8ICcnO1xyXG4gICAgbGV0IHZhbHVlcyA9IHBhc3RlZERhdGEuc3BsaXQoJycpLnNsaWNlKDAsIHRoaXMubGVuZ3RoKTtcclxuXHJcbiAgICBpZiAodGhpcy50eXBlID09PSAnbnVtYmVyJykge1xyXG4gICAgICB2YWx1ZXMgPSB2YWx1ZXMuZmlsdGVyKGNoYXIgPT4gL1swLTldLy50ZXN0KGNoYXIpKTtcclxuICAgIH1cclxuXHJcbiAgICB2YWx1ZXMuZm9yRWFjaCgodmFsdWUsIGluZGV4KSA9PiB7XHJcbiAgICAgIGlmIChpbmRleCA8IHRoaXMubGVuZ3RoKSB7XHJcbiAgICAgICAgdGhpcy5vdHBWYWx1ZXNbaW5kZXhdID0gdmFsdWU7XHJcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlucHV0cy50b0FycmF5KClbaW5kZXhdO1xyXG4gICAgICAgIGlmIChpbnB1dCkge1xyXG4gICAgICAgICAgaW5wdXQubmF0aXZlRWxlbWVudC52YWx1ZSA9IHZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gRm9jdXMgb24gdGhlIG5leHQgZW1wdHkgaW5wdXQgb3IgbGFzdCBpbnB1dFxyXG4gICAgY29uc3QgbmV4dEVtcHR5SW5kZXggPSB0aGlzLm90cFZhbHVlcy5maW5kSW5kZXgodiA9PiAhdik7XHJcbiAgICBjb25zdCBmb2N1c0luZGV4ID0gbmV4dEVtcHR5SW5kZXggIT09IC0xID8gbmV4dEVtcHR5SW5kZXggOiB0aGlzLmxlbmd0aCAtIDE7XHJcbiAgICBjb25zdCBpbnB1dFRvRm9jdXMgPSB0aGlzLmlucHV0cy50b0FycmF5KClbZm9jdXNJbmRleF07XHJcbiAgICBpZiAoaW5wdXRUb0ZvY3VzKSB7XHJcbiAgICAgIGlucHV0VG9Gb2N1cy5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5lbWl0VmFsdWUoKTtcclxuICB9XHJcblxyXG4gIG9uRm9jdXMoaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgaW5wdXQgPSB0aGlzLmlucHV0cy50b0FycmF5KClbaW5kZXhdO1xyXG4gICAgaWYgKGlucHV0KSB7XHJcbiAgICAgIGlucHV0Lm5hdGl2ZUVsZW1lbnQuc2VsZWN0KCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBlbWl0VmFsdWUoKTogdm9pZCB7XHJcbiAgICBjb25zdCBvdHBWYWx1ZSA9IHRoaXMub3RwVmFsdWVzLmpvaW4oJycpO1xyXG4gICAgdGhpcy5vbkNoYW5nZShvdHBWYWx1ZSk7XHJcbiAgICB0aGlzLm90cENoYW5nZS5lbWl0KG90cFZhbHVlKTtcclxuXHJcbiAgICAvLyBFbWl0IGNvbXBsZXRlIGV2ZW50IGlmIGFsbCBmaWVsZHMgYXJlIGZpbGxlZFxyXG4gICAgaWYgKG90cFZhbHVlLmxlbmd0aCA9PT0gdGhpcy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5vdHBDb21wbGV0ZS5lbWl0KG90cFZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsZWFyKCk6IHZvaWQge1xyXG4gICAgdGhpcy5vdHBWYWx1ZXMgPSBBcnJheSh0aGlzLmxlbmd0aCkuZmlsbCgnJyk7XHJcbiAgICB0aGlzLmlucHV0cy50b0FycmF5KCkuZm9yRWFjaChpbnB1dCA9PiB7XHJcbiAgICAgIGlucHV0Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcclxuICAgIH0pO1xyXG4gICAgaWYgKHRoaXMuaW5wdXRzLmZpcnN0KSB7XHJcbiAgICAgIHRoaXMuaW5wdXRzLmZpcnN0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICAgIH1cclxuICAgIHRoaXMuZW1pdFZhbHVlKCk7XHJcbiAgfVxyXG5cclxuICB0cmFja0J5SW5kZXgoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gaW5kZXg7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJvdHAtY29udGFpbmVyXCIgW2NsYXNzLm90cC1kaXNhYmxlZF09XCJkaXNhYmxlZFwiIFthdHRyLmRhdGEtc2l6ZV09XCJzaXplXCI+XHJcbiAgPGlucHV0XHJcbiAgICAjb3RwSW5wdXRcclxuICAgICpuZ0Zvcj1cImxldCB2YWx1ZSBvZiBvdHBWYWx1ZXM7IGxldCBpID0gaW5kZXg7IHRyYWNrQnk6IHRyYWNrQnlJbmRleFwiXHJcbiAgICBjbGFzcz1cIm90cC1pbnB1dFwiXHJcbiAgICBbdHlwZV09XCJzZWN1cmUgPyAncGFzc3dvcmQnIDogJ3RleHQnXCJcclxuICAgIFthdHRyLmlucHV0bW9kZV09XCJ0eXBlID09PSAnbnVtYmVyJyA/ICdudW1lcmljJyA6ICd0ZXh0J1wiXHJcbiAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxyXG4gICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXHJcbiAgICBtYXhsZW5ndGg9XCIxXCJcclxuICAgIChpbnB1dCk9XCJvbklucHV0KCRldmVudCwgaSlcIlxyXG4gICAgKGtleWRvd24pPVwib25LZXlEb3duKCRldmVudCwgaSlcIlxyXG4gICAgKHBhc3RlKT1cIm9uUGFzdGUoJGV2ZW50KVwiXHJcbiAgICAoZm9jdXMpPVwib25Gb2N1cyhpKVwiXHJcbiAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxyXG4gIC8+XHJcbjwvZGl2PlxyXG4iXX0=
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './index';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXV4aW1hLXVpLW90cC1pbnB1dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2Zvcm0vb3RwLWlucHV0L3NyYy9tdXhpbWEtdWktb3RwLWlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vaW5kZXgnO1xuIl19
@@ -0,0 +1,199 @@
1
+ import * as i0 from '@angular/core';
2
+ import { EventEmitter, forwardRef, Component, Input, Output, ViewChildren } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
+
7
+ class OtpInputComponent {
8
+ constructor() {
9
+ this.length = 6;
10
+ this.type = 'number';
11
+ this.placeholder = '';
12
+ this.disabled = false;
13
+ this.secure = false;
14
+ this.autoFocus = true;
15
+ this.size = 'medium';
16
+ this.otpComplete = new EventEmitter();
17
+ this.otpChange = new EventEmitter();
18
+ this.otpValues = [];
19
+ this.onChange = () => { };
20
+ this.onTouched = () => { };
21
+ }
22
+ ngAfterViewInit() {
23
+ this.otpValues = Array(this.length).fill('');
24
+ if (this.autoFocus && this.inputs.first) {
25
+ setTimeout(() => this.inputs.first.nativeElement.focus(), 100);
26
+ }
27
+ }
28
+ writeValue(value) {
29
+ if (value) {
30
+ this.otpValues = value.split('').slice(0, this.length);
31
+ while (this.otpValues.length < this.length) {
32
+ this.otpValues.push('');
33
+ }
34
+ }
35
+ else {
36
+ this.otpValues = Array(this.length).fill('');
37
+ }
38
+ }
39
+ registerOnChange(fn) {
40
+ this.onChange = fn;
41
+ }
42
+ registerOnTouched(fn) {
43
+ this.onTouched = fn;
44
+ }
45
+ setDisabledState(isDisabled) {
46
+ this.disabled = isDisabled;
47
+ }
48
+ onInput(event, index) {
49
+ const input = event.target;
50
+ let value = input.value;
51
+ // Allow only numbers or text based on type
52
+ if (this.type === 'number') {
53
+ value = value.replace(/[^0-9]/g, '');
54
+ }
55
+ // Take only the last character if multiple are entered
56
+ if (value.length > 1) {
57
+ value = value.slice(-1);
58
+ }
59
+ this.otpValues[index] = value;
60
+ input.value = value;
61
+ // Move to next input if value is entered
62
+ if (value && index < this.length - 1) {
63
+ const nextInput = this.inputs.toArray()[index + 1];
64
+ if (nextInput) {
65
+ nextInput.nativeElement.focus();
66
+ }
67
+ }
68
+ this.emitValue();
69
+ }
70
+ onKeyDown(event, index) {
71
+ const input = event.target;
72
+ // Handle backspace
73
+ if (event.key === 'Backspace') {
74
+ if (!this.otpValues[index] && index > 0) {
75
+ // Move to previous input if current is empty
76
+ const prevInput = this.inputs.toArray()[index - 1];
77
+ if (prevInput) {
78
+ prevInput.nativeElement.focus();
79
+ this.otpValues[index - 1] = '';
80
+ this.emitValue();
81
+ }
82
+ }
83
+ else if (this.otpValues[index]) {
84
+ // Clear current input
85
+ this.otpValues[index] = '';
86
+ this.emitValue();
87
+ }
88
+ event.preventDefault();
89
+ }
90
+ // Handle arrow keys
91
+ if (event.key === 'ArrowLeft' && index > 0) {
92
+ this.inputs.toArray()[index - 1].nativeElement.focus();
93
+ }
94
+ if (event.key === 'ArrowRight' && index < this.length - 1) {
95
+ this.inputs.toArray()[index + 1].nativeElement.focus();
96
+ }
97
+ }
98
+ onPaste(event) {
99
+ var _a;
100
+ event.preventDefault();
101
+ const pastedData = ((_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text')) || '';
102
+ let values = pastedData.split('').slice(0, this.length);
103
+ if (this.type === 'number') {
104
+ values = values.filter(char => /[0-9]/.test(char));
105
+ }
106
+ values.forEach((value, index) => {
107
+ if (index < this.length) {
108
+ this.otpValues[index] = value;
109
+ const input = this.inputs.toArray()[index];
110
+ if (input) {
111
+ input.nativeElement.value = value;
112
+ }
113
+ }
114
+ });
115
+ // Focus on the next empty input or last input
116
+ const nextEmptyIndex = this.otpValues.findIndex(v => !v);
117
+ const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : this.length - 1;
118
+ const inputToFocus = this.inputs.toArray()[focusIndex];
119
+ if (inputToFocus) {
120
+ inputToFocus.nativeElement.focus();
121
+ }
122
+ this.emitValue();
123
+ }
124
+ onFocus(index) {
125
+ const input = this.inputs.toArray()[index];
126
+ if (input) {
127
+ input.nativeElement.select();
128
+ }
129
+ this.onTouched();
130
+ }
131
+ emitValue() {
132
+ const otpValue = this.otpValues.join('');
133
+ this.onChange(otpValue);
134
+ this.otpChange.emit(otpValue);
135
+ // Emit complete event if all fields are filled
136
+ if (otpValue.length === this.length) {
137
+ this.otpComplete.emit(otpValue);
138
+ }
139
+ }
140
+ clear() {
141
+ this.otpValues = Array(this.length).fill('');
142
+ this.inputs.toArray().forEach(input => {
143
+ input.nativeElement.value = '';
144
+ });
145
+ if (this.inputs.first) {
146
+ this.inputs.first.nativeElement.focus();
147
+ }
148
+ this.emitValue();
149
+ }
150
+ trackByIndex(index) {
151
+ return index;
152
+ }
153
+ }
154
+ OtpInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
155
+ OtpInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpInputComponent, isStandalone: true, selector: "muxima-otp-input", inputs: { length: "length", type: "type", placeholder: "placeholder", disabled: "disabled", secure: "secure", autoFocus: "autoFocus", size: "size" }, outputs: { otpComplete: "otpComplete", otpChange: "otpChange" }, providers: [
156
+ {
157
+ provide: NG_VALUE_ACCESSOR,
158
+ useExisting: forwardRef(() => OtpInputComponent),
159
+ multi: true
160
+ }
161
+ ], viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, decorators: [{
163
+ type: Component,
164
+ args: [{ selector: 'muxima-otp-input', standalone: true, imports: [CommonModule], providers: [
165
+ {
166
+ provide: NG_VALUE_ACCESSOR,
167
+ useExisting: forwardRef(() => OtpInputComponent),
168
+ multi: true
169
+ }
170
+ ], template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"] }]
171
+ }], propDecorators: { length: [{
172
+ type: Input
173
+ }], type: [{
174
+ type: Input
175
+ }], placeholder: [{
176
+ type: Input
177
+ }], disabled: [{
178
+ type: Input
179
+ }], secure: [{
180
+ type: Input
181
+ }], autoFocus: [{
182
+ type: Input
183
+ }], size: [{
184
+ type: Input
185
+ }], otpComplete: [{
186
+ type: Output
187
+ }], otpChange: [{
188
+ type: Output
189
+ }], inputs: [{
190
+ type: ViewChildren,
191
+ args: ['otpInput']
192
+ }] } });
193
+
194
+ /**
195
+ * Generated bundle index. Do not edit.
196
+ */
197
+
198
+ export { OtpInputComponent };
199
+ //# sourceMappingURL=muxima-ui-otp-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxima-ui-otp-input.mjs","sources":["../../../../form/otp-input/src/lib/otp-input/otp-input.component.ts","../../../../form/otp-input/src/lib/otp-input/otp-input.component.html","../../../../form/otp-input/src/muxima-ui-otp-input.ts"],"sourcesContent":["import { Component, Input, Output, EventEmitter, forwardRef, ViewChildren, QueryList, ElementRef, AfterViewInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'muxima-otp-input',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './otp-input.component.html',\r\n styleUrls: ['./otp-input.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => OtpInputComponent),\r\n multi: true\r\n }\r\n ]\r\n})\r\nexport class OtpInputComponent implements ControlValueAccessor, AfterViewInit {\r\n @Input() length: number = 6;\r\n @Input() type: 'number' | 'text' = 'number';\r\n @Input() placeholder: string = '';\r\n @Input() disabled: boolean = false;\r\n @Input() secure: boolean = false;\r\n @Input() autoFocus: boolean = true;\r\n @Input() size: 'small' | 'medium' | 'large' = 'medium';\r\n \r\n @Output() otpComplete = new EventEmitter<string>();\r\n @Output() otpChange = new EventEmitter<string>();\r\n \r\n @ViewChildren('otpInput') inputs!: QueryList<ElementRef<HTMLInputElement>>;\r\n \r\n otpValues: string[] = [];\r\n private onChange: (value: string) => void = () => {};\r\n private onTouched: () => void = () => {};\r\n\r\n ngAfterViewInit() {\r\n this.otpValues = Array(this.length).fill('');\r\n if (this.autoFocus && this.inputs.first) {\r\n setTimeout(() => this.inputs.first.nativeElement.focus(), 100);\r\n }\r\n }\r\n\r\n writeValue(value: string): void {\r\n if (value) {\r\n this.otpValues = value.split('').slice(0, this.length);\r\n while (this.otpValues.length < this.length) {\r\n this.otpValues.push('');\r\n }\r\n } else {\r\n this.otpValues = Array(this.length).fill('');\r\n }\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n onInput(event: Event, index: number): void {\r\n const input = event.target as HTMLInputElement;\r\n let value = input.value;\r\n\r\n // Allow only numbers or text based on type\r\n if (this.type === 'number') {\r\n value = value.replace(/[^0-9]/g, '');\r\n }\r\n\r\n // Take only the last character if multiple are entered\r\n if (value.length > 1) {\r\n value = value.slice(-1);\r\n }\r\n\r\n this.otpValues[index] = value;\r\n input.value = value;\r\n\r\n // Move to next input if value is entered\r\n if (value && index < this.length - 1) {\r\n const nextInput = this.inputs.toArray()[index + 1];\r\n if (nextInput) {\r\n nextInput.nativeElement.focus();\r\n }\r\n }\r\n\r\n this.emitValue();\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent, index: number): void {\r\n const input = event.target as HTMLInputElement;\r\n\r\n // Handle backspace\r\n if (event.key === 'Backspace') {\r\n if (!this.otpValues[index] && index > 0) {\r\n // Move to previous input if current is empty\r\n const prevInput = this.inputs.toArray()[index - 1];\r\n if (prevInput) {\r\n prevInput.nativeElement.focus();\r\n this.otpValues[index - 1] = '';\r\n this.emitValue();\r\n }\r\n } else if (this.otpValues[index]) {\r\n // Clear current input\r\n this.otpValues[index] = '';\r\n this.emitValue();\r\n }\r\n event.preventDefault();\r\n }\r\n\r\n // Handle arrow keys\r\n if (event.key === 'ArrowLeft' && index > 0) {\r\n this.inputs.toArray()[index - 1].nativeElement.focus();\r\n }\r\n if (event.key === 'ArrowRight' && index < this.length - 1) {\r\n this.inputs.toArray()[index + 1].nativeElement.focus();\r\n }\r\n }\r\n\r\n onPaste(event: ClipboardEvent): void {\r\n event.preventDefault();\r\n const pastedData = event.clipboardData?.getData('text') || '';\r\n let values = pastedData.split('').slice(0, this.length);\r\n\r\n if (this.type === 'number') {\r\n values = values.filter(char => /[0-9]/.test(char));\r\n }\r\n\r\n values.forEach((value, index) => {\r\n if (index < this.length) {\r\n this.otpValues[index] = value;\r\n const input = this.inputs.toArray()[index];\r\n if (input) {\r\n input.nativeElement.value = value;\r\n }\r\n }\r\n });\r\n\r\n // Focus on the next empty input or last input\r\n const nextEmptyIndex = this.otpValues.findIndex(v => !v);\r\n const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : this.length - 1;\r\n const inputToFocus = this.inputs.toArray()[focusIndex];\r\n if (inputToFocus) {\r\n inputToFocus.nativeElement.focus();\r\n }\r\n\r\n this.emitValue();\r\n }\r\n\r\n onFocus(index: number): void {\r\n const input = this.inputs.toArray()[index];\r\n if (input) {\r\n input.nativeElement.select();\r\n }\r\n this.onTouched();\r\n }\r\n\r\n private emitValue(): void {\r\n const otpValue = this.otpValues.join('');\r\n this.onChange(otpValue);\r\n this.otpChange.emit(otpValue);\r\n\r\n // Emit complete event if all fields are filled\r\n if (otpValue.length === this.length) {\r\n this.otpComplete.emit(otpValue);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.otpValues = Array(this.length).fill('');\r\n this.inputs.toArray().forEach(input => {\r\n input.nativeElement.value = '';\r\n });\r\n if (this.inputs.first) {\r\n this.inputs.first.nativeElement.focus();\r\n }\r\n this.emitValue();\r\n }\r\n\r\n trackByIndex(index: number): number {\r\n return index;\r\n }\r\n}\r\n","<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ import * as i0 from '@angular/core';
2
+ import { EventEmitter, forwardRef, Component, Input, Output, ViewChildren } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
+
7
+ class OtpInputComponent {
8
+ constructor() {
9
+ this.length = 6;
10
+ this.type = 'number';
11
+ this.placeholder = '';
12
+ this.disabled = false;
13
+ this.secure = false;
14
+ this.autoFocus = true;
15
+ this.size = 'medium';
16
+ this.otpComplete = new EventEmitter();
17
+ this.otpChange = new EventEmitter();
18
+ this.otpValues = [];
19
+ this.onChange = () => { };
20
+ this.onTouched = () => { };
21
+ }
22
+ ngAfterViewInit() {
23
+ this.otpValues = Array(this.length).fill('');
24
+ if (this.autoFocus && this.inputs.first) {
25
+ setTimeout(() => this.inputs.first.nativeElement.focus(), 100);
26
+ }
27
+ }
28
+ writeValue(value) {
29
+ if (value) {
30
+ this.otpValues = value.split('').slice(0, this.length);
31
+ while (this.otpValues.length < this.length) {
32
+ this.otpValues.push('');
33
+ }
34
+ }
35
+ else {
36
+ this.otpValues = Array(this.length).fill('');
37
+ }
38
+ }
39
+ registerOnChange(fn) {
40
+ this.onChange = fn;
41
+ }
42
+ registerOnTouched(fn) {
43
+ this.onTouched = fn;
44
+ }
45
+ setDisabledState(isDisabled) {
46
+ this.disabled = isDisabled;
47
+ }
48
+ onInput(event, index) {
49
+ const input = event.target;
50
+ let value = input.value;
51
+ // Allow only numbers or text based on type
52
+ if (this.type === 'number') {
53
+ value = value.replace(/[^0-9]/g, '');
54
+ }
55
+ // Take only the last character if multiple are entered
56
+ if (value.length > 1) {
57
+ value = value.slice(-1);
58
+ }
59
+ this.otpValues[index] = value;
60
+ input.value = value;
61
+ // Move to next input if value is entered
62
+ if (value && index < this.length - 1) {
63
+ const nextInput = this.inputs.toArray()[index + 1];
64
+ if (nextInput) {
65
+ nextInput.nativeElement.focus();
66
+ }
67
+ }
68
+ this.emitValue();
69
+ }
70
+ onKeyDown(event, index) {
71
+ const input = event.target;
72
+ // Handle backspace
73
+ if (event.key === 'Backspace') {
74
+ if (!this.otpValues[index] && index > 0) {
75
+ // Move to previous input if current is empty
76
+ const prevInput = this.inputs.toArray()[index - 1];
77
+ if (prevInput) {
78
+ prevInput.nativeElement.focus();
79
+ this.otpValues[index - 1] = '';
80
+ this.emitValue();
81
+ }
82
+ }
83
+ else if (this.otpValues[index]) {
84
+ // Clear current input
85
+ this.otpValues[index] = '';
86
+ this.emitValue();
87
+ }
88
+ event.preventDefault();
89
+ }
90
+ // Handle arrow keys
91
+ if (event.key === 'ArrowLeft' && index > 0) {
92
+ this.inputs.toArray()[index - 1].nativeElement.focus();
93
+ }
94
+ if (event.key === 'ArrowRight' && index < this.length - 1) {
95
+ this.inputs.toArray()[index + 1].nativeElement.focus();
96
+ }
97
+ }
98
+ onPaste(event) {
99
+ event.preventDefault();
100
+ const pastedData = event.clipboardData?.getData('text') || '';
101
+ let values = pastedData.split('').slice(0, this.length);
102
+ if (this.type === 'number') {
103
+ values = values.filter(char => /[0-9]/.test(char));
104
+ }
105
+ values.forEach((value, index) => {
106
+ if (index < this.length) {
107
+ this.otpValues[index] = value;
108
+ const input = this.inputs.toArray()[index];
109
+ if (input) {
110
+ input.nativeElement.value = value;
111
+ }
112
+ }
113
+ });
114
+ // Focus on the next empty input or last input
115
+ const nextEmptyIndex = this.otpValues.findIndex(v => !v);
116
+ const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : this.length - 1;
117
+ const inputToFocus = this.inputs.toArray()[focusIndex];
118
+ if (inputToFocus) {
119
+ inputToFocus.nativeElement.focus();
120
+ }
121
+ this.emitValue();
122
+ }
123
+ onFocus(index) {
124
+ const input = this.inputs.toArray()[index];
125
+ if (input) {
126
+ input.nativeElement.select();
127
+ }
128
+ this.onTouched();
129
+ }
130
+ emitValue() {
131
+ const otpValue = this.otpValues.join('');
132
+ this.onChange(otpValue);
133
+ this.otpChange.emit(otpValue);
134
+ // Emit complete event if all fields are filled
135
+ if (otpValue.length === this.length) {
136
+ this.otpComplete.emit(otpValue);
137
+ }
138
+ }
139
+ clear() {
140
+ this.otpValues = Array(this.length).fill('');
141
+ this.inputs.toArray().forEach(input => {
142
+ input.nativeElement.value = '';
143
+ });
144
+ if (this.inputs.first) {
145
+ this.inputs.first.nativeElement.focus();
146
+ }
147
+ this.emitValue();
148
+ }
149
+ trackByIndex(index) {
150
+ return index;
151
+ }
152
+ }
153
+ OtpInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
154
+ OtpInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OtpInputComponent, isStandalone: true, selector: "muxima-otp-input", inputs: { length: "length", type: "type", placeholder: "placeholder", disabled: "disabled", secure: "secure", autoFocus: "autoFocus", size: "size" }, outputs: { otpComplete: "otpComplete", otpChange: "otpChange" }, providers: [
155
+ {
156
+ provide: NG_VALUE_ACCESSOR,
157
+ useExisting: forwardRef(() => OtpInputComponent),
158
+ multi: true
159
+ }
160
+ ], viewQueries: [{ propertyName: "inputs", predicate: ["otpInput"], descendants: true }], ngImport: i0, template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OtpInputComponent, decorators: [{
162
+ type: Component,
163
+ args: [{ selector: 'muxima-otp-input', standalone: true, imports: [CommonModule], providers: [
164
+ {
165
+ provide: NG_VALUE_ACCESSOR,
166
+ useExisting: forwardRef(() => OtpInputComponent),
167
+ multi: true
168
+ }
169
+ ], template: "<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n", styles: [".otp-container{display:flex;gap:.75rem;justify-content:center;align-items:center}.otp-container[data-size=small]{gap:.5rem}.otp-container[data-size=small] .otp-input{width:2.5rem;height:2.5rem;font-size:1rem}.otp-container[data-size=medium]{gap:.75rem}.otp-container[data-size=medium] .otp-input{width:3rem;height:3rem;font-size:1.25rem}.otp-container[data-size=large]{gap:1rem}.otp-container[data-size=large] .otp-input{width:3.5rem;height:3.5rem;font-size:1.5rem}.otp-container.otp-disabled{opacity:.6;pointer-events:none}.otp-input{width:3rem;height:3rem;text-align:center;font-size:1.25rem;font-weight:600;color:#1f2937;background:white;border:2px solid #d1d5db;border-radius:8px;outline:none;transition:all .3s ease;font-family:Courier New,Courier,monospace}.otp-input:focus{border-color:#667eea;box-shadow:0 0 0 3px #667eea1a;transform:scale(1.05)}.otp-input:disabled{background:#f3f4f6;cursor:not-allowed}.otp-input::placeholder{color:#9ca3af}.otp-input[type=number]::-webkit-inner-spin-button,.otp-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.otp-input[type=number]{-moz-appearance:textfield}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#f0f4ff 0%,#e9f0ff 100%);border-color:#667eea}@media (prefers-color-scheme: dark){.otp-input{background:#1f2937;color:#f3f4f6;border-color:#4b5563}.otp-input:focus{border-color:#818cf8;box-shadow:0 0 0 3px #818cf81a}.otp-input:disabled{background:#111827}.otp-input:not(:placeholder-shown){background:linear-gradient(135deg,#312e81 0%,#3730a3 100%);border-color:#818cf8}}\n"] }]
170
+ }], propDecorators: { length: [{
171
+ type: Input
172
+ }], type: [{
173
+ type: Input
174
+ }], placeholder: [{
175
+ type: Input
176
+ }], disabled: [{
177
+ type: Input
178
+ }], secure: [{
179
+ type: Input
180
+ }], autoFocus: [{
181
+ type: Input
182
+ }], size: [{
183
+ type: Input
184
+ }], otpComplete: [{
185
+ type: Output
186
+ }], otpChange: [{
187
+ type: Output
188
+ }], inputs: [{
189
+ type: ViewChildren,
190
+ args: ['otpInput']
191
+ }] } });
192
+
193
+ /**
194
+ * Generated bundle index. Do not edit.
195
+ */
196
+
197
+ export { OtpInputComponent };
198
+ //# sourceMappingURL=muxima-ui-otp-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxima-ui-otp-input.mjs","sources":["../../../../form/otp-input/src/lib/otp-input/otp-input.component.ts","../../../../form/otp-input/src/lib/otp-input/otp-input.component.html","../../../../form/otp-input/src/muxima-ui-otp-input.ts"],"sourcesContent":["import { Component, Input, Output, EventEmitter, forwardRef, ViewChildren, QueryList, ElementRef, AfterViewInit } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'muxima-otp-input',\r\n standalone: true,\r\n imports: [CommonModule],\r\n templateUrl: './otp-input.component.html',\r\n styleUrls: ['./otp-input.component.scss'],\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => OtpInputComponent),\r\n multi: true\r\n }\r\n ]\r\n})\r\nexport class OtpInputComponent implements ControlValueAccessor, AfterViewInit {\r\n @Input() length: number = 6;\r\n @Input() type: 'number' | 'text' = 'number';\r\n @Input() placeholder: string = '';\r\n @Input() disabled: boolean = false;\r\n @Input() secure: boolean = false;\r\n @Input() autoFocus: boolean = true;\r\n @Input() size: 'small' | 'medium' | 'large' = 'medium';\r\n \r\n @Output() otpComplete = new EventEmitter<string>();\r\n @Output() otpChange = new EventEmitter<string>();\r\n \r\n @ViewChildren('otpInput') inputs!: QueryList<ElementRef<HTMLInputElement>>;\r\n \r\n otpValues: string[] = [];\r\n private onChange: (value: string) => void = () => {};\r\n private onTouched: () => void = () => {};\r\n\r\n ngAfterViewInit() {\r\n this.otpValues = Array(this.length).fill('');\r\n if (this.autoFocus && this.inputs.first) {\r\n setTimeout(() => this.inputs.first.nativeElement.focus(), 100);\r\n }\r\n }\r\n\r\n writeValue(value: string): void {\r\n if (value) {\r\n this.otpValues = value.split('').slice(0, this.length);\r\n while (this.otpValues.length < this.length) {\r\n this.otpValues.push('');\r\n }\r\n } else {\r\n this.otpValues = Array(this.length).fill('');\r\n }\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n onInput(event: Event, index: number): void {\r\n const input = event.target as HTMLInputElement;\r\n let value = input.value;\r\n\r\n // Allow only numbers or text based on type\r\n if (this.type === 'number') {\r\n value = value.replace(/[^0-9]/g, '');\r\n }\r\n\r\n // Take only the last character if multiple are entered\r\n if (value.length > 1) {\r\n value = value.slice(-1);\r\n }\r\n\r\n this.otpValues[index] = value;\r\n input.value = value;\r\n\r\n // Move to next input if value is entered\r\n if (value && index < this.length - 1) {\r\n const nextInput = this.inputs.toArray()[index + 1];\r\n if (nextInput) {\r\n nextInput.nativeElement.focus();\r\n }\r\n }\r\n\r\n this.emitValue();\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent, index: number): void {\r\n const input = event.target as HTMLInputElement;\r\n\r\n // Handle backspace\r\n if (event.key === 'Backspace') {\r\n if (!this.otpValues[index] && index > 0) {\r\n // Move to previous input if current is empty\r\n const prevInput = this.inputs.toArray()[index - 1];\r\n if (prevInput) {\r\n prevInput.nativeElement.focus();\r\n this.otpValues[index - 1] = '';\r\n this.emitValue();\r\n }\r\n } else if (this.otpValues[index]) {\r\n // Clear current input\r\n this.otpValues[index] = '';\r\n this.emitValue();\r\n }\r\n event.preventDefault();\r\n }\r\n\r\n // Handle arrow keys\r\n if (event.key === 'ArrowLeft' && index > 0) {\r\n this.inputs.toArray()[index - 1].nativeElement.focus();\r\n }\r\n if (event.key === 'ArrowRight' && index < this.length - 1) {\r\n this.inputs.toArray()[index + 1].nativeElement.focus();\r\n }\r\n }\r\n\r\n onPaste(event: ClipboardEvent): void {\r\n event.preventDefault();\r\n const pastedData = event.clipboardData?.getData('text') || '';\r\n let values = pastedData.split('').slice(0, this.length);\r\n\r\n if (this.type === 'number') {\r\n values = values.filter(char => /[0-9]/.test(char));\r\n }\r\n\r\n values.forEach((value, index) => {\r\n if (index < this.length) {\r\n this.otpValues[index] = value;\r\n const input = this.inputs.toArray()[index];\r\n if (input) {\r\n input.nativeElement.value = value;\r\n }\r\n }\r\n });\r\n\r\n // Focus on the next empty input or last input\r\n const nextEmptyIndex = this.otpValues.findIndex(v => !v);\r\n const focusIndex = nextEmptyIndex !== -1 ? nextEmptyIndex : this.length - 1;\r\n const inputToFocus = this.inputs.toArray()[focusIndex];\r\n if (inputToFocus) {\r\n inputToFocus.nativeElement.focus();\r\n }\r\n\r\n this.emitValue();\r\n }\r\n\r\n onFocus(index: number): void {\r\n const input = this.inputs.toArray()[index];\r\n if (input) {\r\n input.nativeElement.select();\r\n }\r\n this.onTouched();\r\n }\r\n\r\n private emitValue(): void {\r\n const otpValue = this.otpValues.join('');\r\n this.onChange(otpValue);\r\n this.otpChange.emit(otpValue);\r\n\r\n // Emit complete event if all fields are filled\r\n if (otpValue.length === this.length) {\r\n this.otpComplete.emit(otpValue);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.otpValues = Array(this.length).fill('');\r\n this.inputs.toArray().forEach(input => {\r\n input.nativeElement.value = '';\r\n });\r\n if (this.inputs.first) {\r\n this.inputs.first.nativeElement.focus();\r\n }\r\n this.emitValue();\r\n }\r\n\r\n trackByIndex(index: number): number {\r\n return index;\r\n }\r\n}\r\n","<div class=\"otp-container\" [class.otp-disabled]=\"disabled\" [attr.data-size]=\"size\">\r\n <input\r\n #otpInput\r\n *ngFor=\"let value of otpValues; let i = index; trackBy: trackByIndex\"\r\n class=\"otp-input\"\r\n [type]=\"secure ? 'password' : 'text'\"\r\n [attr.inputmode]=\"type === 'number' ? 'numeric' : 'text'\"\r\n [placeholder]=\"placeholder\"\r\n [disabled]=\"disabled\"\r\n [value]=\"value\"\r\n maxlength=\"1\"\r\n (input)=\"onInput($event, i)\"\r\n (keydown)=\"onKeyDown($event, i)\"\r\n (paste)=\"onPaste($event)\"\r\n (focus)=\"onFocus(i)\"\r\n autocomplete=\"off\"\r\n />\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './lib/otp-input/otp-input.component';
@@ -0,0 +1,32 @@
1
+ import { EventEmitter, QueryList, ElementRef, AfterViewInit } from '@angular/core';
2
+ import { ControlValueAccessor } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ export declare class OtpInputComponent implements ControlValueAccessor, AfterViewInit {
5
+ length: number;
6
+ type: 'number' | 'text';
7
+ placeholder: string;
8
+ disabled: boolean;
9
+ secure: boolean;
10
+ autoFocus: boolean;
11
+ size: 'small' | 'medium' | 'large';
12
+ otpComplete: EventEmitter<string>;
13
+ otpChange: EventEmitter<string>;
14
+ inputs: QueryList<ElementRef<HTMLInputElement>>;
15
+ otpValues: string[];
16
+ private onChange;
17
+ private onTouched;
18
+ ngAfterViewInit(): void;
19
+ writeValue(value: string): void;
20
+ registerOnChange(fn: any): void;
21
+ registerOnTouched(fn: any): void;
22
+ setDisabledState(isDisabled: boolean): void;
23
+ onInput(event: Event, index: number): void;
24
+ onKeyDown(event: KeyboardEvent, index: number): void;
25
+ onPaste(event: ClipboardEvent): void;
26
+ onFocus(index: number): void;
27
+ private emitValue;
28
+ clear(): void;
29
+ trackByIndex(index: number): number;
30
+ static ɵfac: i0.ɵɵFactoryDeclaration<OtpInputComponent, never>;
31
+ static ɵcmp: i0.ɵɵComponentDeclaration<OtpInputComponent, "muxima-otp-input", never, { "length": "length"; "type": "type"; "placeholder": "placeholder"; "disabled": "disabled"; "secure": "secure"; "autoFocus": "autoFocus"; "size": "size"; }, { "otpComplete": "otpComplete"; "otpChange": "otpChange"; }, never, never, true, never>;
32
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@muxima-ui/otp-input",
3
+ "version": "1.0.0",
4
+ "description": "OTP/PIN input component for Angular 18+ - Muxima UI",
5
+ "keywords": [
6
+ "angular",
7
+ "otp",
8
+ "pin",
9
+ "verification",
10
+ "form",
11
+ "input",
12
+ "muxima-ui"
13
+ ],
14
+ "author": "Muxima UI Team (jokerscript)",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/Aldemiro20/muxima-ui.git",
19
+ "directory": "packages/form/otp-input"
20
+ },
21
+ "homepage": "https://muxima-ui.vercel.app/components/otp-input",
22
+ "bugs": {
23
+ "url": "https://github.com/Aldemiro20/muxima-ui/issues"
24
+ },
25
+ "documentation": "https://muxima-ui.vercel.app",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "peerDependencies": {
30
+ "@angular/common": "^18.0.0",
31
+ "@angular/core": "^18.0.0",
32
+ "@angular/forms": "^18.0.0"
33
+ },
34
+ "dependencies": {
35
+ "tslib": "^2.3.0"
36
+ },
37
+ "sideEffects": false,
38
+ "module": "fesm2015/muxima-ui-otp-input.mjs",
39
+ "es2020": "fesm2020/muxima-ui-otp-input.mjs",
40
+ "esm2020": "esm2020/muxima-ui-otp-input.mjs",
41
+ "fesm2020": "fesm2020/muxima-ui-otp-input.mjs",
42
+ "fesm2015": "fesm2015/muxima-ui-otp-input.mjs",
43
+ "typings": "index.d.ts",
44
+ "exports": {
45
+ "./package.json": {
46
+ "default": "./package.json"
47
+ },
48
+ ".": {
49
+ "types": "./index.d.ts",
50
+ "esm2020": "./esm2020/muxima-ui-otp-input.mjs",
51
+ "es2020": "./fesm2020/muxima-ui-otp-input.mjs",
52
+ "es2015": "./fesm2015/muxima-ui-otp-input.mjs",
53
+ "node": "./fesm2015/muxima-ui-otp-input.mjs",
54
+ "default": "./fesm2020/muxima-ui-otp-input.mjs"
55
+ }
56
+ }
57
+ }