@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.
- package/esm2020/index.mjs +2 -0
- package/esm2020/lib/otp-input/otp-input.component.mjs +191 -0
- package/esm2020/muxima-ui-otp-input.mjs +5 -0
- package/fesm2015/muxima-ui-otp-input.mjs +199 -0
- package/fesm2015/muxima-ui-otp-input.mjs.map +1 -0
- package/fesm2020/muxima-ui-otp-input.mjs +198 -0
- package/fesm2020/muxima-ui-otp-input.mjs.map +1 -0
- package/index.d.ts +1 -0
- package/lib/otp-input/otp-input.component.d.ts +32 -0
- package/package.json +57 -0
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3RwLWlucHV0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2Zvcm0vb3RwLWlucHV0L3NyYy9saWIvb3RwLWlucHV0L290cC1pbnB1dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9mb3JtL290cC1pbnB1dC9zcmMvbGliL290cC1pbnB1dC9vdHAtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUF3QyxNQUFNLGVBQWUsQ0FBQztBQUN2SSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFnQnpFLE1BQU0sT0FBTyxpQkFBaUI7SUFkOUI7UUFlVyxXQUFNLEdBQVcsQ0FBQyxDQUFDO1FBQ25CLFNBQUksR0FBc0IsUUFBUSxDQUFDO1FBQ25DLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFDMUIsV0FBTSxHQUFZLEtBQUssQ0FBQztRQUN4QixjQUFTLEdBQVksSUFBSSxDQUFDO1FBQzFCLFNBQUksR0FBaUMsUUFBUSxDQUFDO1FBRTdDLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUN6QyxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUlqRCxjQUFTLEdBQWEsRUFBRSxDQUFDO1FBQ2pCLGFBQVEsR0FBNEIsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQzdDLGNBQVMsR0FBZSxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7S0F5SjFDO0lBdkpDLGVBQWU7UUFDYixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtZQUN2QyxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ2hFO0lBQ0gsQ0FBQztJQUVELFVBQVUsQ0FBQyxLQUFhO1FBQ3RCLElBQUksS0FBSyxFQUFFO1lBQ1QsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3ZELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDMUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDekI7U0FDRjthQUFNO1lBQ0wsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUM5QztJQUNILENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUFPO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxFQUFPO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxVQUFtQjtRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQztJQUM3QixDQUFDO0lBRUQsT0FBTyxDQUFDLEtBQVksRUFBRSxLQUFhO1FBQ2pDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUEwQixDQUFDO1FBQy9DLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFFeEIsMkNBQTJDO1FBQzNDLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUU7WUFDMUIsS0FBSyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQ3RDO1FBRUQsdURBQXVEO1FBQ3ZELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDcEIsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN6QjtRQUVELElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQzlCLEtBQUssQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRXBCLHlDQUF5QztRQUN6QyxJQUFJLEtBQUssSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDcEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDbkQsSUFBSSxTQUFTLEVBQUU7Z0JBQ2IsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQzthQUNqQztTQUNGO1FBRUQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFRCxTQUFTLENBQUMsS0FBb0IsRUFBRSxLQUFhO1FBQzNDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUEwQixDQUFDO1FBRS9DLG1CQUFtQjtRQUNuQixJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssV0FBVyxFQUFFO1lBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUU7Z0JBQ3ZDLDZDQUE2QztnQkFDN0MsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ25ELElBQUksU0FBUyxFQUFFO29CQUNiLFNBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ2hDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztvQkFDL0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2lCQUNsQjthQUNGO2lCQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDaEMsc0JBQXNCO2dCQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2FBQ2xCO1lBQ0QsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1NBQ3hCO1FBRUQsb0JBQW9CO1FBQ3BCLElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxXQUFXLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRTtZQUMxQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDeEQ7UUFDRCxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssWUFBWSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6RCxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDeEQ7SUFDSCxDQUFDO0lBRUQsT0FBTyxDQUFDLEtBQXFCO1FBQzNCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDOUQsSUFBSSxNQUFNLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV4RCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO1lBQzFCLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1NBQ3BEO1FBRUQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUM5QixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFO2dCQUN2QixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQztnQkFDOUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDM0MsSUFBSSxLQUFLLEVBQUU7b0JBQ1QsS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2lCQUNuQzthQUNGO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCw4Q0FBOEM7UUFDOUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sVUFBVSxHQUFHLGNBQWMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUM1RSxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3ZELElBQUksWUFBWSxFQUFFO1lBQ2hCLFlBQVksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDcEM7UUFFRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sQ0FBQyxLQUFhO1FBQ25CLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDM0MsSUFBSSxLQUFLLEVBQUU7WUFDVCxLQUFLLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzlCO1FBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQ25CLENBQUM7SUFFTyxTQUFTO1FBQ2YsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN4QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU5QiwrQ0FBK0M7UUFDL0MsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDakM7SUFDSCxDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDcEMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtZQUNyQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDekM7UUFDRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELFlBQVksQ0FBQyxLQUFhO1FBQ3hCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzs7K0dBeEtVLGlCQUFpQjttR0FBakIsaUJBQWlCLHNSQVJqQjtRQUNUO1lBQ0UsT0FBTyxFQUFFLGlCQUFpQjtZQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLGlCQUFpQixDQUFDO1lBQ2hELEtBQUssRUFBRSxJQUFJO1NBQ1o7S0FDRixpSENoQkgsMm9CQWtCQSxrbUREWFksWUFBWTs0RkFXWCxpQkFBaUI7a0JBZDdCLFNBQVM7K0JBQ0Usa0JBQWtCLGNBQ2hCLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyxhQUdaO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLGtCQUFrQixDQUFDOzRCQUNoRCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjs4QkFHUSxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csSUFBSTtzQkFBWixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNO2dCQUVtQixNQUFNO3NCQUEvQixZQUFZO3VCQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgZm9yd2FyZFJlZiwgVmlld0NoaWxkcmVuLCBRdWVyeUxpc3QsIEVsZW1lbnRSZWYsIEFmdGVyVmlld0luaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdtdXhpbWEtb3RwLWlucHV0JyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9vdHAtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL290cC1pbnB1dC5jb21wb25lbnQuc2NzcyddLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gT3RwSW5wdXRDb21wb25lbnQpLFxyXG4gICAgICBtdWx0aTogdHJ1ZVxyXG4gICAgfVxyXG4gIF1cclxufSlcclxuZXhwb3J0IGNsYXNzIE90cElucHV0Q29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEFmdGVyVmlld0luaXQge1xyXG4gIEBJbnB1dCgpIGxlbmd0aDogbnVtYmVyID0gNjtcclxuICBASW5wdXQoKSB0eXBlOiAnbnVtYmVyJyB8ICd0ZXh0JyA9ICdudW1iZXInO1xyXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnJztcclxuICBASW5wdXQoKSBkaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNlY3VyZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGF1dG9Gb2N1czogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgc2l6ZTogJ3NtYWxsJyB8ICdtZWRpdW0nIHwgJ2xhcmdlJyA9ICdtZWRpdW0nO1xyXG4gIFxyXG4gIEBPdXRwdXQoKSBvdHBDb21wbGV0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG4gIEBPdXRwdXQoKSBvdHBDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuICBcclxuICBAVmlld0NoaWxkcmVuKCdvdHBJbnB1dCcpIGlucHV0cyE6IFF1ZXJ5TGlzdDxFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+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":";;;;;;MAkBa,iBAAiB,CAAA;AAd9B,IAAA,WAAA,GAAA;AAeW,QAAA,IAAM,CAAA,MAAA,GAAW,CAAC,CAAC;AACnB,QAAA,IAAI,CAAA,IAAA,GAAsB,QAAQ,CAAC;AACnC,QAAA,IAAW,CAAA,WAAA,GAAW,EAAE,CAAC;AACzB,QAAA,IAAQ,CAAA,QAAA,GAAY,KAAK,CAAC;AAC1B,QAAA,IAAM,CAAA,MAAA,GAAY,KAAK,CAAC;AACxB,QAAA,IAAS,CAAA,SAAA,GAAY,IAAI,CAAC;AAC1B,QAAA,IAAI,CAAA,IAAA,GAAiC,QAAQ,CAAC;AAE7C,QAAA,IAAA,CAAA,WAAW,GAAG,IAAI,YAAY,EAAU,CAAC;AACzC,QAAA,IAAA,CAAA,SAAS,GAAG,IAAI,YAAY,EAAU,CAAC;AAIjD,QAAA,IAAS,CAAA,SAAA,GAAa,EAAE,CAAC;AACjB,QAAA,IAAA,CAAA,QAAQ,GAA4B,MAAK,GAAG,CAAC;AAC7C,QAAA,IAAA,CAAA,SAAS,GAAe,MAAK,GAAG,CAAC;KAyJ1C;IAvJC,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACvC,YAAA,UAAU,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;AAChE,SAAA;KACF;AAED,IAAA,UAAU,CAAC,KAAa,EAAA;AACtB,QAAA,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;AAC1C,gBAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,aAAA;AACF,SAAA;AAAM,aAAA;AACL,YAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9C,SAAA;KACF;AAED,IAAA,gBAAgB,CAAC,EAAO,EAAA;AACtB,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;KACpB;AAED,IAAA,iBAAiB,CAAC,EAAO,EAAA;AACvB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;KACrB;AAED,IAAA,gBAAgB,CAAC,UAAmB,EAAA;AAClC,QAAA,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;KAC5B;IAED,OAAO,CAAC,KAAY,EAAE,KAAa,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;AAC/C,QAAA,IAAI,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;;AAGxB,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;YAC1B,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACtC,SAAA;;AAGD,QAAA,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;YACpB,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzB,SAAA;AAED,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AAC9B,QAAA,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;;QAGpB,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACpC,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACnD,YAAA,IAAI,SAAS,EAAE;AACb,gBAAA,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACjC,aAAA;AACF,SAAA;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;KAClB;IAED,SAAS,CAAC,KAAoB,EAAE,KAAa,EAAA;AAC3C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;;AAG/C,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE;YAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE;;AAEvC,gBAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AACnD,gBAAA,IAAI,SAAS,EAAE;AACb,oBAAA,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;oBAChC,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;oBAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;AAClB,iBAAA;AACF,aAAA;AAAM,iBAAA,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE;;AAEhC,gBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC3B,IAAI,CAAC,SAAS,EAAE,CAAC;AAClB,aAAA;YACD,KAAK,CAAC,cAAc,EAAE,CAAC;AACxB,SAAA;;QAGD,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,IAAI,KAAK,GAAG,CAAC,EAAE;AAC1C,YAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACxD,SAAA;AACD,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,YAAY,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACzD,YAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACxD,SAAA;KACF;AAED,IAAA,OAAO,CAAC,KAAqB,EAAA;;QAC3B,KAAK,CAAC,cAAc,EAAE,CAAC;AACvB,QAAA,MAAM,UAAU,GAAG,CAAA,CAAA,EAAA,GAAA,KAAK,CAAC,aAAa,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,OAAO,CAAC,MAAM,CAAC,KAAI,EAAE,CAAC;AAC9D,QAAA,IAAI,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAExD,QAAA,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;AAC1B,YAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACpD,SAAA;QAED,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,KAAI;AAC9B,YAAA,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AACvB,gBAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;AAC3C,gBAAA,IAAI,KAAK,EAAE;AACT,oBAAA,KAAK,CAAC,aAAa,CAAC,KAAK,GAAG,KAAK,CAAC;AACnC,iBAAA;AACF,aAAA;AACH,SAAC,CAAC,CAAC;;AAGH,QAAA,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzD,QAAA,MAAM,UAAU,GAAG,cAAc,KAAK,CAAC,CAAC,GAAG,cAAc,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5E,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC;AACvD,QAAA,IAAI,YAAY,EAAE;AAChB,YAAA,YAAY,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACpC,SAAA;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;KAClB;AAED,IAAA,OAAO,CAAC,KAAa,EAAA;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;AAC3C,QAAA,IAAI,KAAK,EAAE;AACT,YAAA,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;AAC9B,SAAA;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;KAClB;IAEO,SAAS,GAAA;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzC,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACxB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;;AAG9B,QAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE;AACnC,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACjC,SAAA;KACF;IAED,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,IAAG;AACpC,YAAA,KAAK,CAAC,aAAa,CAAC,KAAK,GAAG,EAAE,CAAC;AACjC,SAAC,CAAC,CAAC;AACH,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;YACrB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;AACzC,SAAA;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;KAClB;AAED,IAAA,YAAY,CAAC,KAAa,EAAA;AACxB,QAAA,OAAO,KAAK,CAAC;KACd;;+GAxKU,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAjB,iBAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,iBAAiB,EARjB,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,WAAA,EAAA,aAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,SAAA,EAAA,WAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,SAAA,EAAA;AACT,QAAA;AACE,YAAA,OAAO,EAAE,iBAAiB;AAC1B,YAAA,WAAW,EAAE,UAAU,CAAC,MAAM,iBAAiB,CAAC;AAChD,YAAA,KAAK,EAAE,IAAI;AACZ,SAAA;AACF,KAAA,EChBH,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,QAAA,EAAA,SAAA,EAAA,CAAA,UAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA,2oBAkBA,kmDDXY,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,eAAA,CAAA,EAAA,CAAA,EAAA,CAAA,CAAA;4FAWX,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAd7B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,cAChB,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,CAAC,EAGZ,SAAA,EAAA;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,uBAAuB,CAAC;AAChD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;qBACF,EAAA,QAAA,EAAA,2oBAAA,EAAA,MAAA,EAAA,CAAA,2iDAAA,CAAA,EAAA,CAAA;8BAGQ,MAAM,EAAA,CAAA;sBAAd,KAAK;gBACG,IAAI,EAAA,CAAA;sBAAZ,KAAK;gBACG,WAAW,EAAA,CAAA;sBAAnB,KAAK;gBACG,QAAQ,EAAA,CAAA;sBAAhB,KAAK;gBACG,MAAM,EAAA,CAAA;sBAAd,KAAK;gBACG,SAAS,EAAA,CAAA;sBAAjB,KAAK;gBACG,IAAI,EAAA,CAAA;sBAAZ,KAAK;gBAEI,WAAW,EAAA,CAAA;sBAApB,MAAM;gBACG,SAAS,EAAA,CAAA;sBAAlB,MAAM;gBAEmB,MAAM,EAAA,CAAA;sBAA/B,YAAY;uBAAC,UAAU,CAAA;;;AE9B1B;;AAEG;;;;"}
|
|
@@ -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
|
+
}
|