@tailng-ui/primitives 0.29.0 → 0.30.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailng-ui/primitives",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -3,17 +3,34 @@ export declare function normalizeTngOtpLength(value: number): number;
3
3
  export type TngOtpCompletionState = 'complete' | 'empty' | 'partial';
4
4
  export declare function normalizeTngOtpValue(value: unknown): string;
5
5
  export declare function clampTngOtpValue(value: string, length: number): string;
6
+ export type TngInputOtpType = 'numeric' | 'alphanumeric' | 'custom';
7
+ export declare function sanitizeTngOtpCharacters(value: string, mode: TngInputOtpType, pattern: string | RegExp | null): readonly string[];
8
+ export declare function toTngOtpSlots(length: number, value: string): readonly string[];
9
+ export declare function applyTngOtpCharacters(value: string, startIndex: number, characters: readonly string[], maxLength: number): string;
10
+ export declare function removeTngOtpCharacter(value: string, index: number): string;
11
+ export declare function resolveTngOtpEntryIndex(value: string, length: number): number;
12
+ export declare function resolveTngOtpEndIndex(value: string, length: number): number;
13
+ export type TngOtpBackspaceResult = Readonly<{
14
+ focusIndex: number;
15
+ value: string;
16
+ }>;
6
17
  export declare function resolveTngOtpState(length: number, value: string): TngOtpCompletionState;
18
+ export declare function resolveTngOtpBackspaceResult(value: string, index: number, length: number): TngOtpBackspaceResult | null;
7
19
  export declare class TngInputOtp {
20
+ readonly hostElement: any;
8
21
  readonly length: import("@angular/core").InputSignalWithTransform<number, string | number>;
9
- readonly value: import("@angular/core").InputSignal<string>;
22
+ readonly value: import("@angular/core").ModelSignal<string>;
10
23
  readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
11
24
  readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
12
25
  readonly required: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
13
26
  readonly invalid: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
14
27
  readonly focused: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
15
28
  readonly focusVisible: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
16
- readonly activeIndex: import("@angular/core").InputSignal<number | null>;
29
+ readonly activeIndex: import("@angular/core").ModelSignal<number | null>;
30
+ readonly type: import("@angular/core").InputSignal<TngInputOtpType>;
31
+ readonly pattern: import("@angular/core").InputSignal<string | RegExp | null>;
32
+ readonly selectOnFocus: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
33
+ readonly complete: import("@angular/core").OutputEmitterRef<string>;
17
34
  protected readonly dataSlot: "input-otp";
18
35
  protected readonly roleAttr: "group";
19
36
  protected get dataEmptyAttr(): '' | null;
@@ -26,7 +43,36 @@ export declare class TngInputOtp {
26
43
  protected get dataFocusedAttr(): '' | null;
27
44
  protected get dataFocusVisibleAttr(): '' | null;
28
45
  protected get dataActiveAttr(): string | null;
46
+ slotValue(index: number): string;
47
+ isSlotTabbable(index: number): boolean;
48
+ handleSlotFocus(index: number, target: HTMLInputElement | null): void;
49
+ handleSlotKeydown(index: number, event: KeyboardEvent): void;
50
+ handleSlotInput(index: number, target: HTMLInputElement | null): void;
51
+ handleSlotPaste(index: number, event: ClipboardEvent): void;
52
+ private normalizedValue;
53
+ private resolvedActiveIndex;
54
+ private resolveEditableIndex;
55
+ private handleBackspace;
56
+ private handleDelete;
57
+ private commitValue;
58
+ private focusSlot;
59
+ private syncSlotInputValues;
29
60
  static ɵfac: i0.ɵɵFactoryDeclaration<TngInputOtp, never>;
30
- static ɵdir: i0.ɵɵDirectiveDeclaration<TngInputOtp, "[tngInputOtp]", ["tngInputOtp"], { "length": { "alias": "length"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; "focusVisible": { "alias": "focusVisible"; "required": false; "isSignal": true; }; "activeIndex": { "alias": "activeIndex"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
61
+ static ɵdir: i0.ɵɵDirectiveDeclaration<TngInputOtp, "[tngInputOtp]", ["tngInputOtp"], { "length": { "alias": "length"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "focused": { "alias": "focused"; "required": false; "isSignal": true; }; "focusVisible": { "alias": "focusVisible"; "required": false; "isSignal": true; }; "activeIndex": { "alias": "activeIndex"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "pattern": { "alias": "pattern"; "required": false; "isSignal": true; }; "selectOnFocus": { "alias": "selectOnFocus"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "activeIndex": "activeIndexChange"; "complete": "complete"; }, never, never, true, never>;
62
+ }
63
+ export declare class TngInputOtpSlot {
64
+ private readonly otp;
65
+ private readonly elementRef;
66
+ readonly index: import("@angular/core").InputSignalWithTransform<number, string | number>;
67
+ protected readonly dataSlot: "input-otp-slot";
68
+ protected get dataIndexAttr(): string;
69
+ protected get valueProp(): string;
70
+ protected get tabIndexProp(): number;
71
+ protected onFocus(): void;
72
+ protected onKeydown(event: KeyboardEvent): void;
73
+ protected onInput(): void;
74
+ protected onPaste(event: ClipboardEvent): void;
75
+ static ɵfac: i0.ɵɵFactoryDeclaration<TngInputOtpSlot, never>;
76
+ static ɵdir: i0.ɵɵDirectiveDeclaration<TngInputOtpSlot, "input[tngInputOtpSlot]", ["tngInputOtpSlot"], { "index": { "alias": "tngInputOtpSlot"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
31
77
  }
32
78
  //# sourceMappingURL=tng-input-otp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tng-input-otp.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input-otp/tng-input-otp.ts"],"names":[],"mappings":";AAEA,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAW3D;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAErE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM3D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,qBAAqB,CASvF;AAED,qBAIa,WAAW;IACtB,SAAgB,MAAM,4EAGnB;IACH,SAAgB,KAAK,8CAAqB;IAC1C,SAAgB,QAAQ,8EAErB;IACH,SAAgB,QAAQ,8EAErB;IACH,SAAgB,QAAQ,8EAErB;IACH,SAAgB,OAAO,8EAEpB;IACH,SAAgB,OAAO,8EAEpB;IACH,SAAgB,YAAY,8EAEzB;IACH,SAAgB,WAAW,qDAA8B;IAGzD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,WAAW,CAAU;IAGnD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;IAG/C,SAAS,KAAK,aAAa,IAAI,EAAE,GAAG,IAAI,CAEvC;IAGD,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,IAAI,CAEzC;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,IAAI,CAEzC;IAGD,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,IAAI,CAEzC;IAGD,SAAS,KAAK,oBAAoB,IAAI,EAAE,GAAG,IAAI,CAE9C;IAGD,SAAS,KAAK,cAAc,IAAI,MAAM,GAAG,IAAI,CAW5C;yCAzFU,WAAW;2CAAX,WAAW;CA0FvB"}
1
+ {"version":3,"file":"tng-input-otp.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input-otp/tng-input-otp.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Directive, HostBinding, booleanAttribute, input } from '@angular/core';
1
+ import { Directive, ElementRef, HostBinding, HostListener, booleanAttribute, inject, input, model, output, } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  export function normalizeTngOtpLength(value) {
4
4
  if (!Number.isFinite(value)) {
@@ -19,6 +19,103 @@ export function normalizeTngOtpValue(value) {
19
19
  export function clampTngOtpValue(value, length) {
20
20
  return Array.from(value).slice(0, length).join('');
21
21
  }
22
+ const tngOtpDigitPattern = /^\d$/;
23
+ const tngOtpAlphanumericPattern = /^[a-zA-Z0-9]$/;
24
+ function toNonGlobalRegex(pattern) {
25
+ const flags = pattern.flags.replace(/g/g, '');
26
+ return new RegExp(pattern.source, flags);
27
+ }
28
+ export function sanitizeTngOtpCharacters(value, mode, pattern) {
29
+ const compiledPattern = mode !== 'custom'
30
+ ? null
31
+ : typeof pattern === 'string'
32
+ ? new RegExp(pattern)
33
+ : pattern === null
34
+ ? null
35
+ : toNonGlobalRegex(pattern);
36
+ const acceptedChars = [];
37
+ for (const char of Array.from(value)) {
38
+ if (mode === 'numeric' && !tngOtpDigitPattern.test(char)) {
39
+ continue;
40
+ }
41
+ if (mode === 'alphanumeric' && !tngOtpAlphanumericPattern.test(char)) {
42
+ continue;
43
+ }
44
+ if (compiledPattern && !compiledPattern.test(char)) {
45
+ continue;
46
+ }
47
+ acceptedChars.push(char);
48
+ }
49
+ return acceptedChars;
50
+ }
51
+ export function toTngOtpSlots(length, value) {
52
+ const safeLength = normalizeTngOtpLength(length);
53
+ const slots = Array.from({ length: safeLength }, () => '');
54
+ const chars = Array.from(clampTngOtpValue(value, safeLength));
55
+ for (const [index, char] of chars.entries()) {
56
+ if (index >= safeLength) {
57
+ break;
58
+ }
59
+ slots[index] = char;
60
+ }
61
+ return slots;
62
+ }
63
+ export function applyTngOtpCharacters(value, startIndex, characters, maxLength) {
64
+ const safeLength = normalizeTngOtpLength(maxLength);
65
+ const nextChars = Array.from(clampTngOtpValue(value, safeLength));
66
+ const safeStart = Math.max(0, Math.min(startIndex, safeLength - 1));
67
+ let cursor = nextChars.length < safeLength ? Math.min(safeStart, nextChars.length) : safeStart;
68
+ for (const char of characters) {
69
+ if (cursor >= safeLength) {
70
+ break;
71
+ }
72
+ if (cursor < nextChars.length) {
73
+ nextChars[cursor] = char;
74
+ }
75
+ else {
76
+ nextChars.push(char);
77
+ }
78
+ cursor += 1;
79
+ }
80
+ return nextChars.slice(0, safeLength).join('');
81
+ }
82
+ export function removeTngOtpCharacter(value, index) {
83
+ const chars = Array.from(value);
84
+ if (index < 0 || index >= chars.length) {
85
+ return value;
86
+ }
87
+ chars.splice(index, 1);
88
+ return chars.join('');
89
+ }
90
+ export function resolveTngOtpEntryIndex(value, length) {
91
+ const safeLength = normalizeTngOtpLength(length);
92
+ const safeValue = clampTngOtpValue(value, safeLength);
93
+ if (safeValue.length >= safeLength) {
94
+ return safeLength - 1;
95
+ }
96
+ return safeValue.length;
97
+ }
98
+ export function resolveTngOtpEndIndex(value, length) {
99
+ const safeLength = normalizeTngOtpLength(length);
100
+ const safeValue = clampTngOtpValue(value, safeLength);
101
+ if (safeValue.length === 0) {
102
+ return safeLength - 1;
103
+ }
104
+ return Math.max(0, safeValue.length - 1);
105
+ }
106
+ function clampOtpIndex(index, length) {
107
+ const safeLength = normalizeTngOtpLength(length);
108
+ if (!Number.isFinite(index)) {
109
+ return 0;
110
+ }
111
+ if (index < 0) {
112
+ return 0;
113
+ }
114
+ if (index >= safeLength) {
115
+ return safeLength - 1;
116
+ }
117
+ return Math.trunc(index);
118
+ }
22
119
  export function resolveTngOtpState(length, value) {
23
120
  const normalizedLength = normalizeTngOtpLength(length);
24
121
  const clampedValue = clampTngOtpValue(normalizeTngOtpValue(value), normalizedLength);
@@ -27,26 +124,55 @@ export function resolveTngOtpState(length, value) {
27
124
  }
28
125
  return clampedValue.length >= normalizedLength ? 'complete' : 'partial';
29
126
  }
127
+ export function resolveTngOtpBackspaceResult(value, index, length) {
128
+ const normalizedLength = normalizeTngOtpLength(length);
129
+ const normalizedValue = clampTngOtpValue(normalizeTngOtpValue(value), normalizedLength);
130
+ if (normalizedValue.length === 0) {
131
+ return null;
132
+ }
133
+ const boundedIndex = Number.isFinite(index)
134
+ ? Math.max(0, Math.min(Math.trunc(index), normalizedLength - 1))
135
+ : 0;
136
+ const nextChars = Array.from(normalizedValue);
137
+ if (boundedIndex < normalizedValue.length) {
138
+ nextChars.splice(boundedIndex, 1);
139
+ return {
140
+ focusIndex: Math.max(0, boundedIndex - 1),
141
+ value: nextChars.join(''),
142
+ };
143
+ }
144
+ const previousIndex = Math.max(0, normalizedValue.length - 1);
145
+ nextChars.splice(previousIndex, 1);
146
+ return {
147
+ focusIndex: Math.max(0, previousIndex),
148
+ value: nextChars.join(''),
149
+ };
150
+ }
30
151
  export class TngInputOtp {
152
+ hostElement = inject((ElementRef)).nativeElement;
31
153
  length = input(6, { ...(ngDevMode ? { debugName: "length" } : {}), transform: (value) => normalizeTngOtpLength(typeof value === 'number' ? value : Number(value)) });
32
- value = input('', ...(ngDevMode ? [{ debugName: "value" }] : []));
154
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
33
155
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}), transform: booleanAttribute });
34
156
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
35
157
  required = input(false, { ...(ngDevMode ? { debugName: "required" } : {}), transform: booleanAttribute });
36
158
  invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : {}), transform: booleanAttribute });
37
159
  focused = input(false, { ...(ngDevMode ? { debugName: "focused" } : {}), transform: booleanAttribute });
38
160
  focusVisible = input(false, { ...(ngDevMode ? { debugName: "focusVisible" } : {}), transform: booleanAttribute });
39
- activeIndex = input(null, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
161
+ activeIndex = model(null, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
162
+ type = input('numeric', ...(ngDevMode ? [{ debugName: "type" }] : []));
163
+ pattern = input(null, ...(ngDevMode ? [{ debugName: "pattern" }] : []));
164
+ selectOnFocus = input(true, { ...(ngDevMode ? { debugName: "selectOnFocus" } : {}), transform: booleanAttribute });
165
+ complete = output();
40
166
  dataSlot = 'input-otp';
41
167
  roleAttr = 'group';
42
168
  get dataEmptyAttr() {
43
- return resolveTngOtpState(this.length(), this.value()) === 'empty' ? '' : null;
169
+ return resolveTngOtpState(this.length(), this.normalizedValue()) === 'empty' ? '' : null;
44
170
  }
45
171
  get dataPartialAttr() {
46
- return resolveTngOtpState(this.length(), this.value()) === 'partial' ? '' : null;
172
+ return resolveTngOtpState(this.length(), this.normalizedValue()) === 'partial' ? '' : null;
47
173
  }
48
174
  get dataCompleteAttr() {
49
- return resolveTngOtpState(this.length(), this.value()) === 'complete' ? '' : null;
175
+ return resolveTngOtpState(this.length(), this.normalizedValue()) === 'complete' ? '' : null;
50
176
  }
51
177
  get dataDisabledAttr() {
52
178
  return this.disabled() ? '' : null;
@@ -74,10 +200,184 @@ export class TngInputOtp {
74
200
  if (index < 0 || index >= this.length()) {
75
201
  return null;
76
202
  }
77
- return String(index);
203
+ return String(clampOtpIndex(index, this.length()));
204
+ }
205
+ slotValue(index) {
206
+ const slot = toTngOtpSlots(this.length(), this.normalizedValue())[index];
207
+ return slot ?? '';
208
+ }
209
+ isSlotTabbable(index) {
210
+ return this.resolvedActiveIndex() === index;
211
+ }
212
+ handleSlotFocus(index, target) {
213
+ const nextIndex = this.resolveEditableIndex(index);
214
+ this.activeIndex.set(nextIndex);
215
+ if (this.selectOnFocus() && target instanceof HTMLInputElement) {
216
+ target.select();
217
+ }
218
+ }
219
+ handleSlotKeydown(index, event) {
220
+ const editableIndex = this.resolveEditableIndex(index);
221
+ const total = this.length();
222
+ if (event.key === 'ArrowLeft') {
223
+ event.preventDefault();
224
+ this.focusSlot(Math.max(0, editableIndex - 1), true);
225
+ return;
226
+ }
227
+ if (event.key === 'ArrowRight') {
228
+ event.preventDefault();
229
+ this.focusSlot(Math.min(total - 1, editableIndex + 1), true);
230
+ return;
231
+ }
232
+ if (event.key === 'Home') {
233
+ event.preventDefault();
234
+ this.focusSlot(0, true);
235
+ return;
236
+ }
237
+ if (event.key === 'End') {
238
+ event.preventDefault();
239
+ this.focusSlot(resolveTngOtpEndIndex(this.normalizedValue(), total), true);
240
+ return;
241
+ }
242
+ if (event.key === 'Backspace') {
243
+ event.preventDefault();
244
+ this.handleBackspace(editableIndex);
245
+ return;
246
+ }
247
+ if (event.key === 'Delete') {
248
+ event.preventDefault();
249
+ this.handleDelete(editableIndex);
250
+ return;
251
+ }
252
+ if ((this.disabled() || this.readonly()) && event.key.length === 1) {
253
+ event.preventDefault();
254
+ }
255
+ }
256
+ handleSlotInput(index, target) {
257
+ if (!(target instanceof HTMLInputElement)) {
258
+ return;
259
+ }
260
+ if (this.disabled() || this.readonly()) {
261
+ target.value = this.slotValue(this.resolveEditableIndex(index));
262
+ return;
263
+ }
264
+ const chars = sanitizeTngOtpCharacters(target.value, this.type(), this.pattern());
265
+ if (chars.length === 0) {
266
+ const nextValue = removeTngOtpCharacter(this.normalizedValue(), this.resolveEditableIndex(index));
267
+ this.commitValue(nextValue, this.resolveEditableIndex(index));
268
+ return;
269
+ }
270
+ const previousValue = this.normalizedValue();
271
+ const totalLength = this.length();
272
+ const editableIndex = this.resolveEditableIndex(index);
273
+ const wasCompleteBeforeInput = previousValue.length >= totalLength;
274
+ const wasReplacingExistingCharacter = editableIndex < previousValue.length;
275
+ const nextValue = applyTngOtpCharacters(previousValue, editableIndex, chars, totalLength);
276
+ const nextFocus = wasCompleteBeforeInput || wasReplacingExistingCharacter
277
+ ? Math.min(totalLength - 1, editableIndex + chars.length)
278
+ : nextValue.length >= totalLength
279
+ ? totalLength - 1
280
+ : Math.min(totalLength - 1, Math.max(editableIndex + chars.length, nextValue.length));
281
+ this.commitValue(nextValue, nextFocus);
282
+ }
283
+ handleSlotPaste(index, event) {
284
+ if (this.disabled() || this.readonly()) {
285
+ return;
286
+ }
287
+ const clipboardValue = event.clipboardData?.getData('text') ?? '';
288
+ const chars = sanitizeTngOtpCharacters(clipboardValue, this.type(), this.pattern());
289
+ if (chars.length === 0) {
290
+ event.preventDefault();
291
+ return;
292
+ }
293
+ event.preventDefault();
294
+ const editableIndex = this.resolveEditableIndex(index);
295
+ const nextValue = applyTngOtpCharacters(this.normalizedValue(), editableIndex, chars, this.length());
296
+ const nextFocus = nextValue.length >= this.length()
297
+ ? this.length() - 1
298
+ : Math.min(this.length() - 1, nextValue.length);
299
+ this.commitValue(nextValue, nextFocus);
300
+ }
301
+ normalizedValue() {
302
+ const chars = sanitizeTngOtpCharacters(normalizeTngOtpValue(this.value()), this.type(), this.pattern());
303
+ return chars.slice(0, this.length()).join('');
304
+ }
305
+ resolvedActiveIndex() {
306
+ const current = this.activeIndex();
307
+ if (typeof current === 'number' && Number.isFinite(current)) {
308
+ return clampOtpIndex(current, this.length());
309
+ }
310
+ return resolveTngOtpEntryIndex(this.normalizedValue(), this.length());
311
+ }
312
+ resolveEditableIndex(index) {
313
+ const safeIndex = clampOtpIndex(index, this.length());
314
+ const currentValueLength = this.normalizedValue().length;
315
+ if (currentValueLength >= this.length()) {
316
+ return safeIndex;
317
+ }
318
+ return Math.min(safeIndex, currentValueLength);
319
+ }
320
+ handleBackspace(index) {
321
+ if (this.disabled() || this.readonly()) {
322
+ return;
323
+ }
324
+ const nextState = resolveTngOtpBackspaceResult(this.normalizedValue(), index, this.length());
325
+ if (nextState === null) {
326
+ return;
327
+ }
328
+ this.commitValue(nextState.value, nextState.focusIndex);
329
+ }
330
+ handleDelete(index) {
331
+ if (this.disabled() || this.readonly()) {
332
+ return;
333
+ }
334
+ if (index >= this.normalizedValue().length) {
335
+ return;
336
+ }
337
+ const nextValue = removeTngOtpCharacter(this.normalizedValue(), index);
338
+ this.commitValue(nextValue, index);
339
+ }
340
+ commitValue(nextValue, nextFocusIndex) {
341
+ const previousValue = this.normalizedValue();
342
+ const normalized = clampTngOtpValue(sanitizeTngOtpCharacters(nextValue, this.type(), this.pattern()).join(''), this.length());
343
+ const didChange = normalized !== previousValue;
344
+ this.value.set(normalized);
345
+ this.activeIndex.set(clampOtpIndex(nextFocusIndex, this.length()));
346
+ if (didChange && resolveTngOtpState(this.length(), normalized) === 'complete') {
347
+ this.complete.emit(normalized);
348
+ }
349
+ queueMicrotask(() => {
350
+ this.syncSlotInputValues();
351
+ this.focusSlot(this.resolvedActiveIndex(), this.selectOnFocus());
352
+ });
353
+ }
354
+ focusSlot(index, select) {
355
+ const safeIndex = clampOtpIndex(index, this.length());
356
+ const slot = this.hostElement.querySelector(`[data-tng-otp-slot='${safeIndex}']`);
357
+ if (!(slot instanceof HTMLInputElement)) {
358
+ return;
359
+ }
360
+ slot.focus();
361
+ if (select) {
362
+ slot.select();
363
+ }
364
+ this.activeIndex.set(safeIndex);
365
+ }
366
+ syncSlotInputValues() {
367
+ const slotInputs = this.hostElement.querySelectorAll('[data-tng-otp-slot]');
368
+ slotInputs.forEach((slotInput) => {
369
+ if (!(slotInput instanceof HTMLInputElement)) {
370
+ return;
371
+ }
372
+ const slotIndex = Number(slotInput.getAttribute('data-tng-otp-slot'));
373
+ if (!Number.isFinite(slotIndex)) {
374
+ return;
375
+ }
376
+ slotInput.value = this.slotValue(slotIndex);
377
+ });
78
378
  }
79
379
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputOtp, deps: [], target: i0.ɵɵFactoryTarget.Directive });
80
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", type: TngInputOtp, isStandalone: true, selector: "[tngInputOtp]", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, focusVisible: { classPropertyName: "focusVisible", publicName: "focusVisible", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-slot": "this.dataSlot", "attr.role": "this.roleAttr", "attr.data-empty": "this.dataEmptyAttr", "attr.data-partial": "this.dataPartialAttr", "attr.data-complete": "this.dataCompleteAttr", "attr.data-disabled": "this.dataDisabledAttr", "attr.data-readonly": "this.dataReadonlyAttr", "attr.data-required": "this.dataRequiredAttr", "attr.data-invalid": "this.dataInvalidAttr", "attr.data-focused": "this.dataFocusedAttr", "attr.data-focus-visible": "this.dataFocusVisibleAttr", "attr.data-active": "this.dataActiveAttr" } }, exportAs: ["tngInputOtp"], ngImport: i0 });
380
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", type: TngInputOtp, isStandalone: true, selector: "[tngInputOtp]", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, focused: { classPropertyName: "focused", publicName: "focused", isSignal: true, isRequired: false, transformFunction: null }, focusVisible: { classPropertyName: "focusVisible", publicName: "focusVisible", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, selectOnFocus: { classPropertyName: "selectOnFocus", publicName: "selectOnFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", activeIndex: "activeIndexChange", complete: "complete" }, host: { properties: { "attr.data-slot": "this.dataSlot", "attr.role": "this.roleAttr", "attr.data-empty": "this.dataEmptyAttr", "attr.data-partial": "this.dataPartialAttr", "attr.data-complete": "this.dataCompleteAttr", "attr.data-disabled": "this.dataDisabledAttr", "attr.data-readonly": "this.dataReadonlyAttr", "attr.data-required": "this.dataRequiredAttr", "attr.data-invalid": "this.dataInvalidAttr", "attr.data-focused": "this.dataFocusedAttr", "attr.data-focus-visible": "this.dataFocusVisibleAttr", "attr.data-active": "this.dataActiveAttr" } }, exportAs: ["tngInputOtp"], ngImport: i0 });
81
381
  }
82
382
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputOtp, decorators: [{
83
383
  type: Directive,
@@ -85,7 +385,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
85
385
  selector: '[tngInputOtp]',
86
386
  exportAs: 'tngInputOtp',
87
387
  }]
88
- }], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], focusVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusVisible", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], dataSlot: [{
388
+ }], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], focused: [{ type: i0.Input, args: [{ isSignal: true, alias: "focused", required: false }] }], focusVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusVisible", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], selectOnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectOnFocus", required: false }] }], complete: [{ type: i0.Output, args: ["complete"] }], dataSlot: [{
89
389
  type: HostBinding,
90
390
  args: ['attr.data-slot']
91
391
  }], roleAttr: [{
@@ -122,4 +422,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
122
422
  type: HostBinding,
123
423
  args: ['attr.data-active']
124
424
  }] } });
425
+ export class TngInputOtpSlot {
426
+ otp = inject(TngInputOtp);
427
+ elementRef = inject(ElementRef);
428
+ index = input(0, { ...(ngDevMode ? { debugName: "index" } : {}), alias: 'tngInputOtpSlot',
429
+ transform: (value) => Number.isFinite(typeof value === 'number' ? value : Number(value))
430
+ ? Math.trunc(typeof value === 'number' ? value : Number(value))
431
+ : 0 });
432
+ dataSlot = 'input-otp-slot';
433
+ get dataIndexAttr() {
434
+ return String(this.index());
435
+ }
436
+ get valueProp() {
437
+ return this.otp.slotValue(this.index());
438
+ }
439
+ get tabIndexProp() {
440
+ return this.otp.isSlotTabbable(this.index()) ? 0 : -1;
441
+ }
442
+ onFocus() {
443
+ this.otp.handleSlotFocus(this.index(), this.elementRef.nativeElement);
444
+ }
445
+ onKeydown(event) {
446
+ this.otp.handleSlotKeydown(this.index(), event);
447
+ }
448
+ onInput() {
449
+ this.otp.handleSlotInput(this.index(), this.elementRef.nativeElement);
450
+ }
451
+ onPaste(event) {
452
+ this.otp.handleSlotPaste(this.index(), event);
453
+ }
454
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputOtpSlot, deps: [], target: i0.ɵɵFactoryTarget.Directive });
455
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.1", type: TngInputOtpSlot, isStandalone: true, selector: "input[tngInputOtpSlot]", inputs: { index: { classPropertyName: "index", publicName: "tngInputOtpSlot", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focus": "onFocus()", "keydown": "onKeydown($event)", "input": "onInput()", "paste": "onPaste($event)" }, properties: { "attr.data-slot": "this.dataSlot", "attr.data-tng-otp-slot": "this.dataIndexAttr", "value": "this.valueProp", "tabIndex": "this.tabIndexProp" } }, exportAs: ["tngInputOtpSlot"], ngImport: i0 });
456
+ }
457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputOtpSlot, decorators: [{
458
+ type: Directive,
459
+ args: [{
460
+ selector: 'input[tngInputOtpSlot]',
461
+ exportAs: 'tngInputOtpSlot',
462
+ }]
463
+ }], propDecorators: { index: [{ type: i0.Input, args: [{ isSignal: true, alias: "tngInputOtpSlot", required: false }] }], dataSlot: [{
464
+ type: HostBinding,
465
+ args: ['attr.data-slot']
466
+ }], dataIndexAttr: [{
467
+ type: HostBinding,
468
+ args: ['attr.data-tng-otp-slot']
469
+ }], valueProp: [{
470
+ type: HostBinding,
471
+ args: ['value']
472
+ }], tabIndexProp: [{
473
+ type: HostBinding,
474
+ args: ['tabIndex']
475
+ }], onFocus: [{
476
+ type: HostListener,
477
+ args: ['focus']
478
+ }], onKeydown: [{
479
+ type: HostListener,
480
+ args: ['keydown', ['$event']]
481
+ }], onInput: [{
482
+ type: HostListener,
483
+ args: ['input']
484
+ }], onPaste: [{
485
+ type: HostListener,
486
+ args: ['paste', ['$event']]
487
+ }] } });
125
488
  //# sourceMappingURL=tng-input-otp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tng-input-otp.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input-otp/tng-input-otp.ts"],"names":[],"mappings":"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","sourcesContent":["import { Directive, HostBinding, booleanAttribute, input } from '@angular/core';\n\nexport function normalizeTngOtpLength(value: number): number {\n if (!Number.isFinite(value)) {\n return 6;\n }\n\n const rounded = Math.trunc(value);\n if (rounded < 1) {\n return 1;\n }\n\n return rounded > 12 ? 12 : rounded;\n}\n\nexport type TngOtpCompletionState = 'complete' | 'empty' | 'partial';\n\nexport function normalizeTngOtpValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '';\n }\n\n return value;\n}\n\nexport function clampTngOtpValue(value: string, length: number): string {\n return Array.from(value).slice(0, length).join('');\n}\n\nexport function resolveTngOtpState(length: number, value: string): TngOtpCompletionState {\n const normalizedLength = normalizeTngOtpLength(length);\n const clampedValue = clampTngOtpValue(normalizeTngOtpValue(value), normalizedLength);\n\n if (clampedValue.length === 0) {\n return 'empty';\n }\n\n return clampedValue.length >= normalizedLength ? 'complete' : 'partial';\n}\n\n@Directive({\n selector: '[tngInputOtp]',\n exportAs: 'tngInputOtp',\n})\nexport class TngInputOtp {\n public readonly length = input<number, number | string>(6, {\n transform: (value: number | string): number =>\n normalizeTngOtpLength(typeof value === 'number' ? value : Number(value)),\n });\n public readonly value = input<string>('');\n public readonly disabled = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly readonly = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly required = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly invalid = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly focused = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly focusVisible = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly activeIndex = input<number | null>(null);\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-otp' as const;\n\n @HostBinding('attr.role')\n protected readonly roleAttr = 'group' as const;\n\n @HostBinding('attr.data-empty')\n protected get dataEmptyAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.value()) === 'empty' ? '' : null;\n }\n\n @HostBinding('attr.data-partial')\n protected get dataPartialAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.value()) === 'partial' ? '' : null;\n }\n\n @HostBinding('attr.data-complete')\n protected get dataCompleteAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.value()) === 'complete' ? '' : null;\n }\n\n @HostBinding('attr.data-disabled')\n protected get dataDisabledAttr(): '' | null {\n return this.disabled() ? '' : null;\n }\n\n @HostBinding('attr.data-readonly')\n protected get dataReadonlyAttr(): '' | null {\n return this.readonly() ? '' : null;\n }\n\n @HostBinding('attr.data-required')\n protected get dataRequiredAttr(): '' | null {\n return this.required() ? '' : null;\n }\n\n @HostBinding('attr.data-invalid')\n protected get dataInvalidAttr(): '' | null {\n return this.invalid() ? '' : null;\n }\n\n @HostBinding('attr.data-focused')\n protected get dataFocusedAttr(): '' | null {\n return this.focused() ? '' : null;\n }\n\n @HostBinding('attr.data-focus-visible')\n protected get dataFocusVisibleAttr(): '' | null {\n return this.focusVisible() ? '' : null;\n }\n\n @HostBinding('attr.data-active')\n protected get dataActiveAttr(): string | null {\n const index = this.activeIndex();\n if (typeof index !== 'number' || !Number.isFinite(index)) {\n return null;\n }\n\n if (index < 0 || index >= this.length()) {\n return null;\n }\n\n return String(index);\n }\n}\n"]}
1
+ {"version":3,"file":"tng-input-otp.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input-otp/tng-input-otp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n ElementRef,\n HostBinding,\n HostListener,\n booleanAttribute,\n inject,\n input,\n model,\n output,\n} from '@angular/core';\n\nexport function normalizeTngOtpLength(value: number): number {\n if (!Number.isFinite(value)) {\n return 6;\n }\n\n const rounded = Math.trunc(value);\n if (rounded < 1) {\n return 1;\n }\n\n return rounded > 12 ? 12 : rounded;\n}\n\nexport type TngOtpCompletionState = 'complete' | 'empty' | 'partial';\n\nexport function normalizeTngOtpValue(value: unknown): string {\n if (typeof value !== 'string') {\n return '';\n }\n\n return value;\n}\n\nexport function clampTngOtpValue(value: string, length: number): string {\n return Array.from(value).slice(0, length).join('');\n}\n\nexport type TngInputOtpType = 'numeric' | 'alphanumeric' | 'custom';\n\nconst tngOtpDigitPattern = /^\\d$/;\nconst tngOtpAlphanumericPattern = /^[a-zA-Z0-9]$/;\n\nfunction toNonGlobalRegex(pattern: RegExp): RegExp {\n const flags = pattern.flags.replace(/g/g, '');\n return new RegExp(pattern.source, flags);\n}\n\nexport function sanitizeTngOtpCharacters(\n value: string,\n mode: TngInputOtpType,\n pattern: string | RegExp | null,\n): readonly string[] {\n const compiledPattern =\n mode !== 'custom'\n ? null\n : typeof pattern === 'string'\n ? new RegExp(pattern)\n : pattern === null\n ? null\n : toNonGlobalRegex(pattern);\n\n const acceptedChars: string[] = [];\n for (const char of Array.from(value)) {\n if (mode === 'numeric' && !tngOtpDigitPattern.test(char)) {\n continue;\n }\n\n if (mode === 'alphanumeric' && !tngOtpAlphanumericPattern.test(char)) {\n continue;\n }\n\n if (compiledPattern && !compiledPattern.test(char)) {\n continue;\n }\n\n acceptedChars.push(char);\n }\n\n return acceptedChars;\n}\n\nexport function toTngOtpSlots(length: number, value: string): readonly string[] {\n const safeLength = normalizeTngOtpLength(length);\n const slots = Array.from({ length: safeLength }, () => '');\n const chars = Array.from(clampTngOtpValue(value, safeLength));\n\n for (const [index, char] of chars.entries()) {\n if (index >= safeLength) {\n break;\n }\n\n slots[index] = char;\n }\n\n return slots;\n}\n\nexport function applyTngOtpCharacters(\n value: string,\n startIndex: number,\n characters: readonly string[],\n maxLength: number,\n): string {\n const safeLength = normalizeTngOtpLength(maxLength);\n const nextChars = Array.from(clampTngOtpValue(value, safeLength));\n const safeStart = Math.max(0, Math.min(startIndex, safeLength - 1));\n\n let cursor = nextChars.length < safeLength ? Math.min(safeStart, nextChars.length) : safeStart;\n for (const char of characters) {\n if (cursor >= safeLength) {\n break;\n }\n\n if (cursor < nextChars.length) {\n nextChars[cursor] = char;\n } else {\n nextChars.push(char);\n }\n\n cursor += 1;\n }\n\n return nextChars.slice(0, safeLength).join('');\n}\n\nexport function removeTngOtpCharacter(value: string, index: number): string {\n const chars = Array.from(value);\n if (index < 0 || index >= chars.length) {\n return value;\n }\n\n chars.splice(index, 1);\n return chars.join('');\n}\n\nexport function resolveTngOtpEntryIndex(value: string, length: number): number {\n const safeLength = normalizeTngOtpLength(length);\n const safeValue = clampTngOtpValue(value, safeLength);\n if (safeValue.length >= safeLength) {\n return safeLength - 1;\n }\n\n return safeValue.length;\n}\n\nexport function resolveTngOtpEndIndex(value: string, length: number): number {\n const safeLength = normalizeTngOtpLength(length);\n const safeValue = clampTngOtpValue(value, safeLength);\n if (safeValue.length === 0) {\n return safeLength - 1;\n }\n\n return Math.max(0, safeValue.length - 1);\n}\n\nfunction clampOtpIndex(index: number, length: number): number {\n const safeLength = normalizeTngOtpLength(length);\n if (!Number.isFinite(index)) {\n return 0;\n }\n\n if (index < 0) {\n return 0;\n }\n\n if (index >= safeLength) {\n return safeLength - 1;\n }\n\n return Math.trunc(index);\n}\n\nexport type TngOtpBackspaceResult = Readonly<{\n focusIndex: number;\n value: string;\n}>;\n\nexport function resolveTngOtpState(length: number, value: string): TngOtpCompletionState {\n const normalizedLength = normalizeTngOtpLength(length);\n const clampedValue = clampTngOtpValue(normalizeTngOtpValue(value), normalizedLength);\n\n if (clampedValue.length === 0) {\n return 'empty';\n }\n\n return clampedValue.length >= normalizedLength ? 'complete' : 'partial';\n}\n\nexport function resolveTngOtpBackspaceResult(\n value: string,\n index: number,\n length: number,\n): TngOtpBackspaceResult | null {\n const normalizedLength = normalizeTngOtpLength(length);\n const normalizedValue = clampTngOtpValue(normalizeTngOtpValue(value), normalizedLength);\n if (normalizedValue.length === 0) {\n return null;\n }\n\n const boundedIndex = Number.isFinite(index)\n ? Math.max(0, Math.min(Math.trunc(index), normalizedLength - 1))\n : 0;\n const nextChars = Array.from(normalizedValue);\n\n if (boundedIndex < normalizedValue.length) {\n nextChars.splice(boundedIndex, 1);\n return {\n focusIndex: Math.max(0, boundedIndex - 1),\n value: nextChars.join(''),\n };\n }\n\n const previousIndex = Math.max(0, normalizedValue.length - 1);\n nextChars.splice(previousIndex, 1);\n return {\n focusIndex: Math.max(0, previousIndex),\n value: nextChars.join(''),\n };\n}\n\n@Directive({\n selector: '[tngInputOtp]',\n exportAs: 'tngInputOtp',\n})\nexport class TngInputOtp {\n readonly hostElement = inject(ElementRef<HTMLElement>).nativeElement;\n\n public readonly length = input<number, number | string>(6, {\n transform: (value: number | string): number =>\n normalizeTngOtpLength(typeof value === 'number' ? value : Number(value)),\n });\n public readonly value = model<string>('');\n public readonly disabled = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly readonly = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly required = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly invalid = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly focused = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly focusVisible = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n public readonly activeIndex = model<number | null>(null);\n public readonly type = input<TngInputOtpType>('numeric');\n public readonly pattern = input<string | RegExp | null>(null);\n public readonly selectOnFocus = input<boolean, boolean | string>(true, {\n transform: booleanAttribute,\n });\n\n public readonly complete = output<string>();\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-otp' as const;\n\n @HostBinding('attr.role')\n protected readonly roleAttr = 'group' as const;\n\n @HostBinding('attr.data-empty')\n protected get dataEmptyAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.normalizedValue()) === 'empty' ? '' : null;\n }\n\n @HostBinding('attr.data-partial')\n protected get dataPartialAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.normalizedValue()) === 'partial' ? '' : null;\n }\n\n @HostBinding('attr.data-complete')\n protected get dataCompleteAttr(): '' | null {\n return resolveTngOtpState(this.length(), this.normalizedValue()) === 'complete' ? '' : null;\n }\n\n @HostBinding('attr.data-disabled')\n protected get dataDisabledAttr(): '' | null {\n return this.disabled() ? '' : null;\n }\n\n @HostBinding('attr.data-readonly')\n protected get dataReadonlyAttr(): '' | null {\n return this.readonly() ? '' : null;\n }\n\n @HostBinding('attr.data-required')\n protected get dataRequiredAttr(): '' | null {\n return this.required() ? '' : null;\n }\n\n @HostBinding('attr.data-invalid')\n protected get dataInvalidAttr(): '' | null {\n return this.invalid() ? '' : null;\n }\n\n @HostBinding('attr.data-focused')\n protected get dataFocusedAttr(): '' | null {\n return this.focused() ? '' : null;\n }\n\n @HostBinding('attr.data-focus-visible')\n protected get dataFocusVisibleAttr(): '' | null {\n return this.focusVisible() ? '' : null;\n }\n\n @HostBinding('attr.data-active')\n protected get dataActiveAttr(): string | null {\n const index = this.activeIndex();\n if (typeof index !== 'number' || !Number.isFinite(index)) {\n return null;\n }\n\n if (index < 0 || index >= this.length()) {\n return null;\n }\n\n return String(clampOtpIndex(index, this.length()));\n }\n\n public slotValue(index: number): string {\n const slot = toTngOtpSlots(this.length(), this.normalizedValue())[index];\n return slot ?? '';\n }\n\n public isSlotTabbable(index: number): boolean {\n return this.resolvedActiveIndex() === index;\n }\n\n public handleSlotFocus(index: number, target: HTMLInputElement | null): void {\n const nextIndex = this.resolveEditableIndex(index);\n this.activeIndex.set(nextIndex);\n\n if (this.selectOnFocus() && target instanceof HTMLInputElement) {\n target.select();\n }\n }\n\n public handleSlotKeydown(index: number, event: KeyboardEvent): void {\n const editableIndex = this.resolveEditableIndex(index);\n const total = this.length();\n\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n this.focusSlot(Math.max(0, editableIndex - 1), true);\n return;\n }\n\n if (event.key === 'ArrowRight') {\n event.preventDefault();\n this.focusSlot(Math.min(total - 1, editableIndex + 1), true);\n return;\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n this.focusSlot(0, true);\n return;\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n this.focusSlot(resolveTngOtpEndIndex(this.normalizedValue(), total), true);\n return;\n }\n\n if (event.key === 'Backspace') {\n event.preventDefault();\n this.handleBackspace(editableIndex);\n return;\n }\n\n if (event.key === 'Delete') {\n event.preventDefault();\n this.handleDelete(editableIndex);\n return;\n }\n\n if ((this.disabled() || this.readonly()) && event.key.length === 1) {\n event.preventDefault();\n }\n }\n\n public handleSlotInput(index: number, target: HTMLInputElement | null): void {\n if (!(target instanceof HTMLInputElement)) {\n return;\n }\n\n if (this.disabled() || this.readonly()) {\n target.value = this.slotValue(this.resolveEditableIndex(index));\n return;\n }\n\n const chars = sanitizeTngOtpCharacters(target.value, this.type(), this.pattern());\n if (chars.length === 0) {\n const nextValue = removeTngOtpCharacter(this.normalizedValue(), this.resolveEditableIndex(index));\n this.commitValue(nextValue, this.resolveEditableIndex(index));\n return;\n }\n\n const previousValue = this.normalizedValue();\n const totalLength = this.length();\n const editableIndex = this.resolveEditableIndex(index);\n const wasCompleteBeforeInput = previousValue.length >= totalLength;\n const wasReplacingExistingCharacter = editableIndex < previousValue.length;\n const nextValue = applyTngOtpCharacters(previousValue, editableIndex, chars, totalLength);\n const nextFocus =\n wasCompleteBeforeInput || wasReplacingExistingCharacter\n ? Math.min(totalLength - 1, editableIndex + chars.length)\n : nextValue.length >= totalLength\n ? totalLength - 1\n : Math.min(totalLength - 1, Math.max(editableIndex + chars.length, nextValue.length));\n\n this.commitValue(nextValue, nextFocus);\n }\n\n public handleSlotPaste(index: number, event: ClipboardEvent): void {\n if (this.disabled() || this.readonly()) {\n return;\n }\n\n const clipboardValue = event.clipboardData?.getData('text') ?? '';\n const chars = sanitizeTngOtpCharacters(clipboardValue, this.type(), this.pattern());\n if (chars.length === 0) {\n event.preventDefault();\n return;\n }\n\n event.preventDefault();\n const editableIndex = this.resolveEditableIndex(index);\n const nextValue = applyTngOtpCharacters(this.normalizedValue(), editableIndex, chars, this.length());\n const nextFocus =\n nextValue.length >= this.length()\n ? this.length() - 1\n : Math.min(this.length() - 1, nextValue.length);\n\n this.commitValue(nextValue, nextFocus);\n }\n\n private normalizedValue(): string {\n const chars = sanitizeTngOtpCharacters(normalizeTngOtpValue(this.value()), this.type(), this.pattern());\n return chars.slice(0, this.length()).join('');\n }\n\n private resolvedActiveIndex(): number {\n const current = this.activeIndex();\n if (typeof current === 'number' && Number.isFinite(current)) {\n return clampOtpIndex(current, this.length());\n }\n\n return resolveTngOtpEntryIndex(this.normalizedValue(), this.length());\n }\n\n private resolveEditableIndex(index: number): number {\n const safeIndex = clampOtpIndex(index, this.length());\n const currentValueLength = this.normalizedValue().length;\n\n if (currentValueLength >= this.length()) {\n return safeIndex;\n }\n\n return Math.min(safeIndex, currentValueLength);\n }\n\n private handleBackspace(index: number): void {\n if (this.disabled() || this.readonly()) {\n return;\n }\n\n const nextState = resolveTngOtpBackspaceResult(this.normalizedValue(), index, this.length());\n if (nextState === null) {\n return;\n }\n\n this.commitValue(nextState.value, nextState.focusIndex);\n }\n\n private handleDelete(index: number): void {\n if (this.disabled() || this.readonly()) {\n return;\n }\n\n if (index >= this.normalizedValue().length) {\n return;\n }\n\n const nextValue = removeTngOtpCharacter(this.normalizedValue(), index);\n this.commitValue(nextValue, index);\n }\n\n private commitValue(nextValue: string, nextFocusIndex: number): void {\n const previousValue = this.normalizedValue();\n const normalized = clampTngOtpValue(\n sanitizeTngOtpCharacters(nextValue, this.type(), this.pattern()).join(''),\n this.length(),\n );\n const didChange = normalized !== previousValue;\n\n this.value.set(normalized);\n this.activeIndex.set(clampOtpIndex(nextFocusIndex, this.length()));\n\n if (didChange && resolveTngOtpState(this.length(), normalized) === 'complete') {\n this.complete.emit(normalized);\n }\n\n queueMicrotask(() => {\n this.syncSlotInputValues();\n this.focusSlot(this.resolvedActiveIndex(), this.selectOnFocus());\n });\n }\n\n private focusSlot(index: number, select: boolean): void {\n const safeIndex = clampOtpIndex(index, this.length());\n const slot = this.hostElement.querySelector(\n `[data-tng-otp-slot='${safeIndex}']`,\n ) as HTMLInputElement | null;\n\n if (!(slot instanceof HTMLInputElement)) {\n return;\n }\n\n slot.focus();\n if (select) {\n slot.select();\n }\n\n this.activeIndex.set(safeIndex);\n }\n\n private syncSlotInputValues(): void {\n const slotInputs = this.hostElement.querySelectorAll('[data-tng-otp-slot]');\n slotInputs.forEach((slotInput: Element) => {\n if (!(slotInput instanceof HTMLInputElement)) {\n return;\n }\n\n const slotIndex = Number(slotInput.getAttribute('data-tng-otp-slot'));\n if (!Number.isFinite(slotIndex)) {\n return;\n }\n\n slotInput.value = this.slotValue(slotIndex);\n });\n }\n}\n\n@Directive({\n selector: 'input[tngInputOtpSlot]',\n exportAs: 'tngInputOtpSlot',\n})\nexport class TngInputOtpSlot {\n private readonly otp = inject(TngInputOtp);\n private readonly elementRef = inject<ElementRef<HTMLInputElement>>(ElementRef);\n\n public readonly index = input<number, number | string>(0, {\n alias: 'tngInputOtpSlot',\n transform: (value: number | string): number =>\n Number.isFinite(typeof value === 'number' ? value : Number(value))\n ? Math.trunc(typeof value === 'number' ? value : Number(value))\n : 0,\n });\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-otp-slot' as const;\n\n @HostBinding('attr.data-tng-otp-slot')\n protected get dataIndexAttr(): string {\n return String(this.index());\n }\n\n @HostBinding('value')\n protected get valueProp(): string {\n return this.otp.slotValue(this.index());\n }\n\n @HostBinding('tabIndex')\n protected get tabIndexProp(): number {\n return this.otp.isSlotTabbable(this.index()) ? 0 : -1;\n }\n\n @HostListener('focus')\n protected onFocus(): void {\n this.otp.handleSlotFocus(this.index(), this.elementRef.nativeElement);\n }\n\n @HostListener('keydown', ['$event'])\n protected onKeydown(event: KeyboardEvent): void {\n this.otp.handleSlotKeydown(this.index(), event);\n }\n\n @HostListener('input')\n protected onInput(): void {\n this.otp.handleSlotInput(this.index(), this.elementRef.nativeElement);\n }\n\n @HostListener('paste', ['$event'])\n protected onPaste(event: ClipboardEvent): void {\n this.otp.handleSlotPaste(this.index(), event);\n }\n}\n"]}