@timeax/form-palette 0.0.3 → 0.0.5

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.
Files changed (120) hide show
  1. package/{src/schema/adapter.ts → dist/adapters.d.mts} +118 -43
  2. package/dist/adapters.d.ts +292 -0
  3. package/dist/adapters.js +13283 -0
  4. package/dist/adapters.js.map +1 -0
  5. package/dist/adapters.mjs +13269 -0
  6. package/dist/adapters.mjs.map +1 -0
  7. package/dist/index.d.mts +3744 -0
  8. package/dist/index.d.ts +3744 -0
  9. package/dist/index.js +43014 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +42965 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +22 -7
  14. package/.scaffold-cache.json +0 -537
  15. package/src/.scaffold-cache.json +0 -544
  16. package/src/adapters/axios.ts +0 -117
  17. package/src/adapters/index.ts +0 -91
  18. package/src/adapters/inertia.ts +0 -187
  19. package/src/core/adapter-registry.ts +0 -87
  20. package/src/core/bound/bind-host.ts +0 -14
  21. package/src/core/bound/observe-bound-field.ts +0 -172
  22. package/src/core/bound/wait-for-bound-field.ts +0 -57
  23. package/src/core/context.ts +0 -23
  24. package/src/core/core-provider.tsx +0 -818
  25. package/src/core/core-root.tsx +0 -72
  26. package/src/core/core-shell.tsx +0 -44
  27. package/src/core/errors/error-strip.tsx +0 -71
  28. package/src/core/errors/index.ts +0 -2
  29. package/src/core/errors/map-error-bag.ts +0 -51
  30. package/src/core/errors/map-zod.ts +0 -39
  31. package/src/core/hooks/use-button.ts +0 -220
  32. package/src/core/hooks/use-core-context.ts +0 -20
  33. package/src/core/hooks/use-core-utility.ts +0 -0
  34. package/src/core/hooks/use-core.ts +0 -13
  35. package/src/core/hooks/use-field.ts +0 -497
  36. package/src/core/hooks/use-optional-field.ts +0 -28
  37. package/src/core/index.ts +0 -0
  38. package/src/core/registry/binder-registry.ts +0 -82
  39. package/src/core/registry/field-registry.ts +0 -187
  40. package/src/core/test.tsx +0 -17
  41. package/src/global.d.ts +0 -14
  42. package/src/index.ts +0 -68
  43. package/src/input/index.ts +0 -4
  44. package/src/input/input-field.tsx +0 -854
  45. package/src/input/input-layout-graph.ts +0 -230
  46. package/src/input/input-props.ts +0 -190
  47. package/src/lib/get-global-countries.ts +0 -87
  48. package/src/lib/utils.ts +0 -6
  49. package/src/presets/index.ts +0 -0
  50. package/src/presets/shadcn-preset.ts +0 -0
  51. package/src/presets/shadcn-variants/checkbox.tsx +0 -849
  52. package/src/presets/shadcn-variants/chips.tsx +0 -756
  53. package/src/presets/shadcn-variants/color.tsx +0 -284
  54. package/src/presets/shadcn-variants/custom.tsx +0 -227
  55. package/src/presets/shadcn-variants/date.tsx +0 -796
  56. package/src/presets/shadcn-variants/file.tsx +0 -764
  57. package/src/presets/shadcn-variants/keyvalue.tsx +0 -556
  58. package/src/presets/shadcn-variants/multiselect.tsx +0 -1132
  59. package/src/presets/shadcn-variants/number.tsx +0 -176
  60. package/src/presets/shadcn-variants/password.tsx +0 -737
  61. package/src/presets/shadcn-variants/phone.tsx +0 -628
  62. package/src/presets/shadcn-variants/radio.tsx +0 -578
  63. package/src/presets/shadcn-variants/select.tsx +0 -956
  64. package/src/presets/shadcn-variants/slider.tsx +0 -622
  65. package/src/presets/shadcn-variants/text.tsx +0 -343
  66. package/src/presets/shadcn-variants/textarea.tsx +0 -66
  67. package/src/presets/shadcn-variants/toggle.tsx +0 -218
  68. package/src/presets/shadcn-variants/treeselect.tsx +0 -784
  69. package/src/presets/ui/badge.tsx +0 -46
  70. package/src/presets/ui/button.tsx +0 -60
  71. package/src/presets/ui/calendar.tsx +0 -214
  72. package/src/presets/ui/checkbox.tsx +0 -115
  73. package/src/presets/ui/custom.tsx +0 -0
  74. package/src/presets/ui/dialog.tsx +0 -141
  75. package/src/presets/ui/field.tsx +0 -246
  76. package/src/presets/ui/input-mask.tsx +0 -739
  77. package/src/presets/ui/input-otp.tsx +0 -77
  78. package/src/presets/ui/input.tsx +0 -1011
  79. package/src/presets/ui/label.tsx +0 -22
  80. package/src/presets/ui/number.tsx +0 -1370
  81. package/src/presets/ui/popover.tsx +0 -46
  82. package/src/presets/ui/radio-group.tsx +0 -43
  83. package/src/presets/ui/scroll-area.tsx +0 -56
  84. package/src/presets/ui/select.tsx +0 -190
  85. package/src/presets/ui/separator.tsx +0 -28
  86. package/src/presets/ui/slider.tsx +0 -61
  87. package/src/presets/ui/switch.tsx +0 -32
  88. package/src/presets/ui/textarea.tsx +0 -634
  89. package/src/presets/ui/time-dropdowns.tsx +0 -350
  90. package/src/schema/core.ts +0 -429
  91. package/src/schema/field-map.ts +0 -0
  92. package/src/schema/field.ts +0 -224
  93. package/src/schema/index.ts +0 -0
  94. package/src/schema/input-field.ts +0 -260
  95. package/src/schema/presets.ts +0 -0
  96. package/src/schema/variant.ts +0 -216
  97. package/src/variants/core/checkbox.tsx +0 -54
  98. package/src/variants/core/chips.tsx +0 -22
  99. package/src/variants/core/color.tsx +0 -16
  100. package/src/variants/core/custom.tsx +0 -18
  101. package/src/variants/core/date.tsx +0 -25
  102. package/src/variants/core/file.tsx +0 -9
  103. package/src/variants/core/keyvalue.tsx +0 -12
  104. package/src/variants/core/multiselect.tsx +0 -28
  105. package/src/variants/core/number.tsx +0 -115
  106. package/src/variants/core/password.tsx +0 -35
  107. package/src/variants/core/phone.tsx +0 -16
  108. package/src/variants/core/radio.tsx +0 -38
  109. package/src/variants/core/select.tsx +0 -15
  110. package/src/variants/core/slider.tsx +0 -55
  111. package/src/variants/core/text.tsx +0 -114
  112. package/src/variants/core/textarea.tsx +0 -22
  113. package/src/variants/core/toggle.tsx +0 -50
  114. package/src/variants/core/treeselect.tsx +0 -11
  115. package/src/variants/helpers/selection-summary.tsx +0 -236
  116. package/src/variants/index.ts +0 -75
  117. package/src/variants/registry.ts +0 -38
  118. package/src/variants/select-shared.ts +0 -0
  119. package/src/variants/shared.ts +0 -126
  120. package/tsconfig.json +0 -14
@@ -1,739 +0,0 @@
1
- import * as React from "react";
2
- import { Input } from "@/presets/ui/input";
3
-
4
- export interface InputMaskChangeEvent {
5
- originalEvent: React.SyntheticEvent<HTMLInputElement> | Event | undefined;
6
- value: string;
7
- stopPropagation(): void;
8
- preventDefault(): void;
9
- target: {
10
- name?: string;
11
- id?: string;
12
- value: string;
13
- };
14
- }
15
-
16
- export interface InputMaskCompleteEvent {
17
- originalEvent: React.SyntheticEvent<HTMLInputElement> | Event;
18
- value: string;
19
- }
20
-
21
- export interface InputMaskRef {
22
- focus(): void;
23
- getElement(): HTMLInputElement | null;
24
- }
25
-
26
- export interface InputMaskProps
27
- extends Omit<
28
- React.InputHTMLAttributes<HTMLInputElement>,
29
- "onChange" | "value" | "defaultValue"
30
- > {
31
- mask: string | null;
32
- autoClear?: boolean;
33
- autoFocus?: boolean;
34
- invalid?: boolean;
35
- unmask?: boolean;
36
- slotChar?: string;
37
- 'data-slot'?: string;
38
- value?: string | null;
39
- onChange?: (e: InputMaskChangeEvent) => void;
40
- onComplete?: (e: InputMaskCompleteEvent) => void;
41
- }
42
-
43
- const isEmpty = (val: unknown): boolean =>
44
- val === null || val === undefined || val === "";
45
-
46
- const isAndroid = (): boolean =>
47
- typeof navigator !== "undefined" &&
48
- /android/i.test(navigator.userAgent || "");
49
-
50
- const isIOS = (): boolean =>
51
- typeof navigator !== "undefined" &&
52
- /(iphone|ipad|ipod)/i.test(navigator.userAgent || "");
53
-
54
- const isChrome = (): boolean =>
55
- typeof navigator !== "undefined" &&
56
- /chrome/i.test(navigator.userAgent || "");
57
-
58
- const focusEl = (el: HTMLInputElement | null) => {
59
- if (el && typeof el.focus === "function") {
60
- el.focus();
61
- }
62
- };
63
-
64
- function useUpdateEffect(effect: React.EffectCallback, deps: React.DependencyList) {
65
- const mounted = React.useRef(false);
66
-
67
- React.useEffect(() => {
68
- if (mounted.current) {
69
- return effect();
70
- }
71
- mounted.current = true;
72
- // eslint-disable-next-line react-hooks/exhaustive-deps
73
- }, deps);
74
- }
75
-
76
- export const InputMask = React.memo(
77
- React.forwardRef<InputMaskRef, InputMaskProps>((inProps, ref) => {
78
- // merge defaults with incoming props
79
- const props = React.useMemo(
80
- () => ({
81
- autoClear: true,
82
- autoFocus: false,
83
- disabled: false,
84
- invalid: false,
85
- readOnly: false,
86
- required: false,
87
- slotChar: "_",
88
- type: "text",
89
- unmask: false,
90
- ...inProps,
91
- }),
92
- [inProps]
93
- );
94
-
95
- const elementRef = React.useRef<HTMLInputElement | null>(null);
96
- const firstNonMaskPos = React.useRef<number | null>(null);
97
- const lastRequiredNonMaskPos = React.useRef(0);
98
- const tests = React.useRef<(RegExp | null)[]>([]);
99
- const buffer = React.useRef<string[]>([]);
100
- const len = React.useRef(0);
101
- const oldVal = React.useRef<string | null>(null);
102
- const focus = React.useRef(false);
103
- const focusText = React.useRef<string | null>(null);
104
- const isValueChecked = React.useRef<boolean | null>(null);
105
- const partialPosition = React.useRef<number | null>(null);
106
- const defaultBuffer = React.useRef<string | null>(null);
107
- const caretTimeoutId = React.useRef<number | null>(null);
108
- const androidChrome = React.useRef(false);
109
-
110
- const caret = (first?: number, last?: number) => {
111
- let range: any;
112
- let begin: number | null = null;
113
- let end: number | null = null;
114
- const inputEl = elementRef.current;
115
-
116
- if (!inputEl || !inputEl.offsetParent || inputEl !== document.activeElement) {
117
- return null;
118
- }
119
-
120
- if (typeof first === "number") {
121
- begin = first;
122
- end = typeof last === "number" ? last : begin;
123
-
124
- if (inputEl.setSelectionRange) {
125
- inputEl.setSelectionRange(begin, end);
126
- } else if ((inputEl as any).createTextRange) {
127
- range = (inputEl as any).createTextRange();
128
- range.collapse(true);
129
- range.moveEnd("character", end);
130
- range.moveStart("character", begin);
131
- range.select();
132
- }
133
- //@ts-ignore
134
- } else if (inputEl.setSelectionRange) {
135
- begin = inputEl.selectionStart ?? 0;
136
- end = inputEl.selectionEnd ?? begin;
137
- } else if ((document as any).selection && (document as any).selection.createRange) {
138
- range = (document as any).selection.createRange();
139
- begin = 0 - range.duplicate().moveStart("character", -100000);
140
- end = begin + range.text.length;
141
- }
142
-
143
- if (begin === null || end === null) {
144
- return null;
145
- }
146
-
147
- return { begin, end };
148
- };
149
-
150
- const getPlaceholder = React.useCallback(
151
- (i: number): string => {
152
- const slotChar = props.slotChar ?? "_";
153
-
154
- if (i < slotChar.length) {
155
- return slotChar.charAt(i);
156
- }
157
-
158
- return slotChar.charAt(0);
159
- },
160
- [props.slotChar]
161
- );
162
-
163
- const isCompleted = () => {
164
- const first = firstNonMaskPos.current ?? 0;
165
-
166
- for (let i = first; i <= lastRequiredNonMaskPos.current; i++) {
167
- if (tests.current[i] && buffer.current[i] === getPlaceholder(i)) {
168
- return false;
169
- }
170
- }
171
-
172
- return true;
173
- };
174
-
175
- const getValue = () =>
176
- props.unmask ? getUnmaskedValue() : elementRef.current?.value ?? "";
177
-
178
- const seekNext = (pos: number) => {
179
- while (++pos < len.current && !tests.current[pos]) {
180
- /* loop */
181
- }
182
- return pos;
183
- };
184
-
185
- const seekPrev = (pos: number) => {
186
- while (--pos >= 0 && !tests.current[pos]) {
187
- /* loop */
188
- }
189
- return pos;
190
- };
191
-
192
- const shiftL = (begin: number, end: number) => {
193
- if (begin < 0) {
194
- return;
195
- }
196
-
197
- let i: number;
198
- let j: number;
199
-
200
- for (i = begin, j = seekNext(end); i < len.current; i++) {
201
- if (tests.current[i]) {
202
- if (j < len.current && tests.current[i]!.test(buffer.current[j]!)) {
203
- buffer.current[i] = buffer.current[j]!;
204
- buffer.current[j] = getPlaceholder(j);
205
- } else {
206
- break;
207
- }
208
-
209
- j = seekNext(j);
210
- }
211
- }
212
-
213
- writeBuffer();
214
- caret(Math.max(firstNonMaskPos.current ?? 0, begin));
215
- };
216
-
217
- const shiftR = (pos: number) => {
218
- let i: number;
219
- let c: string;
220
- let j: number;
221
- let t: string;
222
-
223
- for (i = pos, c = getPlaceholder(pos); i < len.current; i++) {
224
- if (tests.current[i]) {
225
- j = seekNext(i);
226
- t = buffer.current[i]!;
227
- buffer.current[i] = c;
228
- if (j < len.current && tests.current[j]!.test(t)) {
229
- c = t;
230
- } else {
231
- break;
232
- }
233
- }
234
- }
235
- };
236
-
237
- const clearBuffer = (start: number, end: number) => {
238
- for (let i = start; i < end && i < len.current; i++) {
239
- if (tests.current[i]) {
240
- buffer.current[i] = getPlaceholder(i);
241
- }
242
- }
243
- };
244
-
245
- const writeBuffer = () => {
246
- if (elementRef.current) {
247
- elementRef.current.value = buffer.current.join("");
248
- }
249
- };
250
-
251
- const checkVal = (allow?: boolean): number => {
252
- isValueChecked.current = true;
253
-
254
- const test = elementRef.current?.value ?? "";
255
- let lastMatch = -1;
256
- let i: number;
257
- let c: string;
258
- let pos: number;
259
-
260
- for (i = 0, pos = 0; i < len.current; i++) {
261
- if (tests.current[i]) {
262
- buffer.current[i] = getPlaceholder(i);
263
-
264
- while (pos++ < test.length) {
265
- c = test.charAt(pos - 1);
266
- if (tests.current[i]!.test(c)) {
267
- buffer.current[i] = c;
268
- lastMatch = i;
269
- break;
270
- }
271
- }
272
-
273
- if (pos > test.length) {
274
- clearBuffer(i + 1, len.current);
275
- break;
276
- }
277
- } else {
278
- if (buffer.current[i] === test.charAt(pos)) {
279
- pos++;
280
- }
281
- if (i < (partialPosition.current ?? 0)) {
282
- lastMatch = i;
283
- }
284
- }
285
- }
286
-
287
- if (allow) {
288
- writeBuffer();
289
- } else if (lastMatch + 1 < (partialPosition.current ?? 0)) {
290
- if (props.autoClear || buffer.current.join("") === defaultBuffer.current) {
291
- if (elementRef.current && elementRef.current.value) {
292
- elementRef.current.value = "";
293
- }
294
- clearBuffer(0, len.current);
295
- } else {
296
- writeBuffer();
297
- }
298
- } else {
299
- writeBuffer();
300
- if (elementRef.current) {
301
- elementRef.current.value = elementRef.current.value.substring(0, lastMatch + 1);
302
- }
303
- }
304
-
305
- return partialPosition.current ? i : (firstNonMaskPos.current ?? 0);
306
- };
307
-
308
- const handleAndroidInput = (e: React.SyntheticEvent<HTMLInputElement>) => {
309
- const inputEl = elementRef.current;
310
- if (!inputEl) return;
311
-
312
- const curVal = inputEl.value;
313
- const pos = caret();
314
- if (!pos) return;
315
-
316
- if (oldVal.current && oldVal.current.length > curVal.length) {
317
- // deletion/backspace
318
- checkVal(true);
319
- while (pos.begin > 0 && !tests.current[pos.begin - 1]) {
320
- pos.begin--;
321
- }
322
- if (pos.begin === 0) {
323
- while (
324
- pos.begin < (firstNonMaskPos.current ?? 0) &&
325
- !tests.current[pos.begin]
326
- ) {
327
- pos.begin++;
328
- }
329
- }
330
- caret(pos.begin, pos.begin);
331
- } else {
332
- checkVal(true);
333
- while (pos.begin < len.current && !tests.current[pos.begin]) {
334
- pos.begin++;
335
- }
336
- caret(pos.begin, pos.begin);
337
- }
338
-
339
- if (props.onComplete && isCompleted()) {
340
- props.onComplete({
341
- originalEvent: e,
342
- value: getValue(),
343
- });
344
- }
345
-
346
- updateModel(e);
347
- };
348
-
349
- const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {
350
- console.log("InputMask onBlur");
351
- focus.current = false;
352
- checkVal();
353
- updateModel(e);
354
-
355
- if (props.onBlur) {
356
- props.onBlur(e);
357
- }
358
-
359
- if (elementRef.current && elementRef.current.value !== focusText.current) {
360
- const event = document.createEvent("HTMLEvents");
361
- event.initEvent("change", true, false);
362
- elementRef.current.dispatchEvent(event);
363
- }
364
- };
365
-
366
- const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
367
- if (props.readOnly) {
368
- return;
369
- }
370
-
371
- const k = e.which || e.keyCode;
372
- let pos: { begin: number; end: number } | null;
373
- let begin: number;
374
- let end: number;
375
-
376
- oldVal.current = elementRef.current?.value ?? null;
377
-
378
- // backspace, delete, escape
379
- if (k === 8 || k === 46 || (isIOS() && k === 127)) {
380
- pos = caret();
381
- if (!pos) {
382
- return;
383
- }
384
- begin = pos.begin;
385
- end = pos.end;
386
-
387
- if (end - begin === 0) {
388
- begin = k !== 46 ? seekPrev(begin) : (end = seekNext(begin - 1));
389
- end = k === 46 ? seekNext(end) : end;
390
- }
391
-
392
- clearBuffer(begin, end);
393
- shiftL(begin, end - 1);
394
- updateModel(e as any);
395
- e.preventDefault();
396
- } else if (k === 13) {
397
- // enter
398
- onBlur(e as any);
399
- updateModel(e as any);
400
- } else if (k === 27) {
401
- // escape
402
- if (elementRef.current) {
403
- elementRef.current.value = focusText.current ?? "";
404
- }
405
- caret(0, checkVal());
406
- updateModel(e as any);
407
- e.preventDefault();
408
- }
409
- };
410
-
411
- const onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
412
- if (props.readOnly) {
413
- return;
414
- }
415
-
416
- const pos = caret();
417
- if (!pos) {
418
- return;
419
- }
420
-
421
- const k = e.which || e.keyCode;
422
- let p: number;
423
- let c: string;
424
- let next: number;
425
- let completed = false;
426
-
427
- if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {
428
- return;
429
- } else if (k && k !== 13) {
430
- if (pos.end - pos.begin !== 0) {
431
- clearBuffer(pos.begin, pos.end);
432
- shiftL(pos.begin, pos.end - 1);
433
- }
434
-
435
- p = seekNext(pos.begin - 1);
436
- if (p < len.current) {
437
- c = String.fromCharCode(k);
438
- if (tests.current[p] && tests.current[p]!.test(c)) {
439
- shiftR(p);
440
- buffer.current[p] = c;
441
- writeBuffer();
442
-
443
- next = seekNext(p);
444
- if (isAndroid()) {
445
- const proxy = () => caret(next);
446
- setTimeout(proxy, 0);
447
- } else {
448
- caret(next);
449
- }
450
-
451
- if (pos.begin <= lastRequiredNonMaskPos.current) {
452
- completed = isCompleted();
453
- }
454
- }
455
- }
456
-
457
- e.preventDefault();
458
- }
459
-
460
- updateModel(e as any);
461
-
462
- if (props.onComplete && completed) {
463
- props.onComplete({
464
- originalEvent: e,
465
- value: getValue(),
466
- });
467
- }
468
- };
469
-
470
- const getUnmaskedValue = React.useCallback((): string => {
471
- const unmaskedBuffer: string[] = [];
472
-
473
- for (let i = 0; i < buffer.current.length; i++) {
474
- const c = buffer.current[i]!;
475
- if (tests.current[i] && c !== getPlaceholder(i)) {
476
- unmaskedBuffer.push(c);
477
- }
478
- }
479
-
480
- return unmaskedBuffer.join("");
481
- }, [getPlaceholder]);
482
-
483
- const updateModel = (e?: React.SyntheticEvent<HTMLInputElement>) => {
484
- if (!props.onChange) return;
485
-
486
- const val = props.unmask ? getUnmaskedValue() : e && (e.target as HTMLInputElement)?.value;
487
-
488
- const normalized = defaultBuffer.current !== val ? (val ?? "") : "";
489
- console.log("InputMask updateModel:", { val, normalized });
490
- const payload: InputMaskChangeEvent = {
491
- originalEvent: e,
492
- value: normalized,
493
- stopPropagation: () => {
494
- (e as any)?.stopPropagation?.();
495
- },
496
- preventDefault: () => {
497
- (e as any)?.preventDefault?.();
498
- },
499
- target: {
500
- name: props.name,
501
- id: props.id,
502
- value: normalized,
503
- },
504
- };
505
-
506
- props.onChange(payload);
507
- };
508
-
509
- const updateValue = (allow?: boolean): number | undefined => {
510
- let pos: number | undefined;
511
-
512
- if (elementRef.current) {
513
- if (isEmpty(props.value)) {
514
- elementRef.current.value = "";
515
- } else {
516
- elementRef.current.value = props.value ?? "";
517
- pos = checkVal(allow);
518
- setTimeout(() => {
519
- if (elementRef.current) {
520
- writeBuffer();
521
- return checkVal(allow);
522
- }
523
- }, 10);
524
- }
525
-
526
- focusText.current = elementRef.current.value;
527
- }
528
-
529
- return pos;
530
- };
531
-
532
- const isValueUpdated = React.useCallback(() => {
533
- const elVal = elementRef.current?.value ?? "";
534
- return props.unmask
535
- ? (props.value ?? "") !== getUnmaskedValue()
536
- : defaultBuffer.current !== elVal && elVal !== (props.value ?? "");
537
- }, [props.unmask, props.value, getUnmaskedValue]);
538
-
539
- const init = () => {
540
- const mask = props.mask;
541
- if (!mask) return;
542
-
543
- tests.current = [];
544
- partialPosition.current = mask.length;
545
- len.current = mask.length;
546
- firstNonMaskPos.current = null;
547
-
548
- const defs: Record<string, string> = {
549
- "9": "[0-9]",
550
- a: "[A-Za-z]",
551
- "*": "[A-Za-z0-9]",
552
- };
553
-
554
- androidChrome.current = isChrome() && isAndroid();
555
- const maskTokens = mask.split("");
556
-
557
- for (let i = 0; i < maskTokens.length; i++) {
558
- const c = maskTokens[i]!;
559
-
560
- if (c === "?") {
561
- len.current--;
562
- partialPosition.current = i;
563
- } else if (defs[c]) {
564
- tests.current.push(new RegExp(defs[c]!));
565
- if (firstNonMaskPos.current === null) {
566
- firstNonMaskPos.current = tests.current.length - 1;
567
- }
568
- if (i < (partialPosition.current ?? 0)) {
569
- lastRequiredNonMaskPos.current = tests.current.length - 1;
570
- }
571
- } else {
572
- tests.current.push(null);
573
- }
574
- }
575
-
576
- buffer.current = [];
577
-
578
- for (let i = 0; i < maskTokens.length; i++) {
579
- const c = maskTokens[i]!;
580
- if (c !== "?") {
581
- if (defs[c]) {
582
- buffer.current.push(getPlaceholder(i));
583
- } else {
584
- buffer.current.push(c);
585
- }
586
- }
587
- }
588
-
589
- defaultBuffer.current = buffer.current.join("");
590
- };
591
-
592
- const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {
593
- console.log("InputMask onFocus");
594
- if (props.readOnly) {
595
- return;
596
- }
597
-
598
- focus.current = true;
599
- if (caretTimeoutId.current) {
600
- window.clearTimeout(caretTimeoutId.current);
601
- }
602
-
603
- let pos: number;
604
-
605
- if (elementRef.current) {
606
- focusText.current = elementRef.current.value;
607
- } else {
608
- focusText.current = "";
609
- }
610
-
611
- pos = checkVal() || 0;
612
-
613
- caretTimeoutId.current = window.setTimeout(() => {
614
- if (elementRef.current !== document.activeElement) {
615
- return;
616
- }
617
-
618
- writeBuffer();
619
-
620
- if (props.mask && pos === props.mask.replace("?", "").length) {
621
- caret(0, pos);
622
- } else {
623
- caret(pos);
624
- }
625
- }, 100);
626
-
627
- if (props.onFocus) {
628
- props.onFocus(e);
629
- }
630
- };
631
-
632
- const handleInputChange = (
633
- e: React.FormEvent<HTMLInputElement>,
634
- isOnPaste = false
635
- ) => {
636
- if (props.readOnly) {
637
- return;
638
- }
639
-
640
- if (!isOnPaste) {
641
- const pos = checkVal(true);
642
- caret(pos);
643
- }
644
-
645
- updateModel(e as any);
646
-
647
- if (props.onComplete && isCompleted()) {
648
- props.onComplete({
649
- originalEvent: e,
650
- value: getValue(),
651
- });
652
- }
653
- };
654
-
655
- const onInput = (event: React.FormEvent<HTMLInputElement>) => {
656
- androidChrome.current
657
- ? handleAndroidInput(event as any)
658
- : handleInputChange(event);
659
- };
660
-
661
- React.useImperativeHandle(
662
- ref,
663
- () => ({
664
- focus: () => focusEl(elementRef.current),
665
- getElement: () => elementRef.current,
666
- }),
667
- []
668
- );
669
-
670
- React.useEffect(() => {
671
- if (!elementRef.current) return;
672
- }, []);
673
-
674
- React.useEffect(() => {
675
- init();
676
- updateValue();
677
- // eslint-disable-next-line react-hooks/exhaustive-deps
678
- }, []);
679
-
680
- useUpdateEffect(() => {
681
- init();
682
- const pos = updateValue(true);
683
- if (typeof pos === "number") {
684
- caret(pos);
685
- }
686
- if (props.unmask) {
687
- updateModel();
688
- }
689
- }, [props.mask, props.unmask]);
690
-
691
- useUpdateEffect(() => {
692
- if (isValueUpdated()) {
693
- updateValue();
694
- }
695
- }, [isValueUpdated]);
696
-
697
- const {
698
- mask,
699
- autoClear,
700
- unmask,
701
- slotChar,
702
- onChange,
703
- onComplete,
704
- value,
705
- autoFocus,
706
- onFocus: i,
707
- onBlur: j,
708
- onKeyDown: k,
709
- onKeyPress: l,
710
- onInput: m,
711
- className,
712
- ...restInputProps
713
- } = props;
714
-
715
- return (
716
- <input
717
- ref={elementRef}
718
- autoFocus={autoFocus}
719
- id={props.id}
720
- name={props.name}
721
- style={props.style}
722
- className={className}
723
- placeholder={props.placeholder}
724
- size={props.size}
725
- maxLength={props.maxLength}
726
- tabIndex={props.tabIndex}
727
- onFocus={onFocus}
728
- onBlur={onBlur}
729
- onKeyDown={onKeyDown}
730
- onKeyPress={onKeyPress}
731
- onInput={onInput}
732
- onPaste={(e) => handleInputChange(e, true)}
733
- {...restInputProps}
734
- />
735
- );
736
- })
737
- );
738
-
739
- InputMask.displayName = "InputMask";