@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,628 +0,0 @@
1
- // src/presets/shadcn-variants/phone.tsx
2
-
3
- import * as React from "react";
4
-
5
- import type { VariantModule } from "@/schema/variant";
6
- import type { VariantBaseProps, ChangeDetail } from "@/variants/shared";
7
- import type { ShadcnTextVariantProps } from "@/presets/shadcn-variants/text";
8
- import { Input } from "@/presets/ui/input";
9
- import {
10
- Select,
11
- SelectTrigger,
12
- SelectValue,
13
- SelectContent,
14
- SelectItem,
15
- } from "@/presets/ui/select";
16
- import { cn } from "@/lib/utils";
17
- import { getGlobalCountryList } from "@/lib/get-global-countries";
18
-
19
- type BaseProps = VariantBaseProps<string | undefined>;
20
-
21
- /**
22
- * Single-country phone config.
23
- *
24
- * - code: ISO 3166-1 alpha-2 ("NG", "US", "GB", ...)
25
- * - dial: dial code without "+" ("234", "1", "44", ...)
26
- * - mask: NATIONAL portion mask only (no dial), e.g. "999 999 9999"
27
- */
28
- export interface PhoneCountry {
29
- code: string;
30
- label: string;
31
- dial: string;
32
- mask: string;
33
- flag?: React.ReactNode;
34
- }
35
-
36
- /**
37
- * How the variant emits the form value.
38
- *
39
- * - "masked" → "+234 801 234 5678"
40
- * - "e164" → "2348012345678" (dial + national digits, no "+")
41
- * - "national"→ "8012345678"
42
- */
43
- export type PhoneValueMode = "masked" | "e164" | "national";
44
-
45
- export interface PhoneSpecificProps {
46
- countries?: PhoneCountry[];
47
- defaultCountry?: string;
48
- onCountryChange?: (country: PhoneCountry) => void;
49
-
50
- showCountry?: boolean;
51
- countryPlaceholder?: string;
52
- showFlag?: boolean;
53
- showSelectedLabel?: boolean;
54
- showSelectedDial?: boolean;
55
- showDialInList?: boolean;
56
-
57
- /**
58
- * Controls how the emitted value is shaped.
59
- *
60
- * Default mirrors legacy autoUnmask=true + emitE164=true → "e164".
61
- */
62
- valueMode?: PhoneValueMode;
63
-
64
- /**
65
- * When true, the national mask keeps placeholder characters
66
- * for not-yet-filled positions. When false, trailing mask
67
- * fragments are omitted.
68
- */
69
- keepCharPositions?: boolean;
70
-
71
- /**
72
- * Style hooks for the internal country selector.
73
- */
74
- countrySelectClassName?: string;
75
- countryTriggerClassName?: string;
76
- countryValueClassName?: string;
77
- countryContentClassName?: string;
78
- countryItemClassName?: string;
79
- }
80
-
81
- // We still *type* against ShadcnTextVariantProps so the phone variant exposes
82
- // the same visual/text props (size, density, icon props, etc.), but we don't
83
- // use the component itself anymore.
84
- type TextUiProps = Omit<
85
- ShadcnTextVariantProps,
86
- // We control these for phone behaviour
87
- "type" | "inputMode" | "leadingControl" | "value" | "onValue"
88
- >;
89
-
90
- /**
91
- * Full props for the phone variant as seen by the form runtime.
92
- *
93
- * - Keeps the same `value`/`onValue` contract as other variants.
94
- * - Inherits visual/behavioural text props (size, density, className, etc.).
95
- * - Adds phone-specific configuration (countries, valueMode, etc.).
96
- */
97
- export type ShadcnPhoneVariantProps = TextUiProps &
98
- PhoneSpecificProps &
99
- Pick<BaseProps, "value" | "onValue">;
100
-
101
- // ———————————————————————————————
102
- // Defaults
103
- // ———————————————————————————————
104
-
105
-
106
-
107
- // ———————————————————————————————
108
- // Mask helpers (lightweight legacy port)
109
- // ———————————————————————————————
110
-
111
- const TOKEN_CHARS = new Set(["9", "a", "*"] as const);
112
-
113
- interface CompiledMask {
114
- pattern: string;
115
- placeholderChar: string;
116
- }
117
-
118
- /**
119
- * Phone only ever really uses digit masks, so we keep this compact.
120
- */
121
- function compileMask(pattern: string, placeholderChar = "_"): CompiledMask {
122
- return { pattern, placeholderChar };
123
- }
124
-
125
- /**
126
- * Apply a simple token-based mask:
127
- * - '9' → digit
128
- * - 'a' → letter
129
- * - '*' → alphanumeric
130
- *
131
- * `keepCharPositions` keeps literal chars/placeholders even when not filled.
132
- */
133
- function applyMask(
134
- mask: CompiledMask,
135
- raw: string,
136
- keepCharPositions: boolean,
137
- ): string {
138
- const { pattern, placeholderChar } = mask;
139
- let result = "";
140
- let rawIndex = 0;
141
- const len = pattern.length;
142
-
143
- const hasTokenAhead = (pos: number): boolean => {
144
- for (let j = pos + 1; j < len; j++) {
145
- if (TOKEN_CHARS.has(pattern[j] as any)) return true;
146
- }
147
- return false;
148
- };
149
-
150
- for (let i = 0; i < len; i++) {
151
- const ch = pattern[i];
152
- const isToken = TOKEN_CHARS.has(ch as any);
153
-
154
- if (isToken) {
155
- if (rawIndex >= raw.length) {
156
- if (keepCharPositions) {
157
- result += placeholderChar;
158
- continue;
159
- }
160
- break;
161
- }
162
- const next = raw[rawIndex++];
163
- result += next;
164
- continue;
165
- }
166
-
167
- // Literal character in the mask.
168
- const rawRemaining = rawIndex < raw.length;
169
- const tokenAhead = hasTokenAhead(i);
170
-
171
- // No tokens ahead → trailing literal.
172
- if (!tokenAhead) {
173
- if (keepCharPositions) {
174
- result += ch;
175
- continue;
176
- }
177
- break;
178
- }
179
-
180
- if (rawRemaining) {
181
- // We still have digits to place → include the literal.
182
- result += ch;
183
- } else if (keepCharPositions) {
184
- // No digits left, but want full skeleton.
185
- result += ch;
186
- } else {
187
- // No digits left, and we don't keep skeleton → stop.
188
- break;
189
- }
190
- }
191
-
192
- return result;
193
- }
194
-
195
- /**
196
- * Strip everything except digits.
197
- */
198
- function digitsOnly(input: string | undefined | null): string {
199
- return (input ?? "").replace(/\D+/g, "");
200
- }
201
-
202
- // ———————————————————————————————
203
- // Value ↔ display helpers
204
- // ———————————————————————————————
205
-
206
- function dialPrefixFor(country: PhoneCountry): string {
207
- return `+${country.dial} `;
208
- }
209
-
210
- /**
211
- * From any stored value (masked, e164, or national) extract
212
- * the NATIONAL digits for a given country.
213
- *
214
- * Strategy: remove all non-digits, then strip leading dial code
215
- * if present.
216
- */
217
- function valueToNationalDigits(
218
- value: string | undefined,
219
- country: PhoneCountry,
220
- ): string {
221
- const digits = digitsOnly(value);
222
- if (!digits) return "";
223
- if (digits.startsWith(country.dial)) {
224
- return digits.slice(country.dial.length);
225
- }
226
- return digits;
227
- }
228
-
229
- /**
230
- * Build the display string shown in the input for a given value.
231
- *
232
- * Always renders "+<dial> " plus an optionally masked national part.
233
- */
234
- function computeDisplayFromValue(
235
- value: string | undefined,
236
- country: PhoneCountry,
237
- keepCharPositions: boolean,
238
- ): string {
239
- const prefix = dialPrefixFor(country);
240
-
241
- const national = valueToNationalDigits(value, country);
242
- if (!national) {
243
- return prefix;
244
- }
245
-
246
- const mask = compileMask(country.mask);
247
- const maskedNational = applyMask(mask, national, keepCharPositions);
248
- if (!maskedNational) {
249
- return prefix;
250
- }
251
-
252
- return prefix + maskedNational;
253
- }
254
-
255
- /**
256
- * Given raw user input in the field, compute:
257
- * - display string (what we show in the input)
258
- * - next form value (according to valueMode)
259
- * - nationalDigits (for metadata)
260
- */
261
- function computeNextFromInput(
262
- rawInput: string,
263
- country: PhoneCountry,
264
- mode: PhoneValueMode,
265
- keepCharPositions: boolean,
266
- ): {
267
- display: string;
268
- nextValue: string | undefined;
269
- nationalDigits: string;
270
- } {
271
- const prefix = dialPrefixFor(country);
272
- const allDigits = digitsOnly(rawInput);
273
-
274
- let national = allDigits;
275
- if (national.startsWith(country.dial)) {
276
- national = national.slice(country.dial.length);
277
- }
278
-
279
- const mask = compileMask(country.mask);
280
- const maskedNational = applyMask(mask, national, keepCharPositions);
281
-
282
- const display =
283
- national.length === 0 ? prefix : (prefix + maskedNational || prefix);
284
-
285
- let nextValue: string | undefined;
286
- if (!national.length) {
287
- nextValue = undefined;
288
- } else if (mode === "masked") {
289
- nextValue = display;
290
- } else if (mode === "e164") {
291
- nextValue = country.dial + national;
292
- } else {
293
- // "national"
294
- nextValue = national;
295
- }
296
-
297
- return { display, nextValue, nationalDigits: national };
298
- }
299
-
300
- /**
301
- * When the country changes, re-interpret the existing value's
302
- * digits into the new country's mask/dial.
303
- */
304
- function remapToCountry(
305
- value: string | undefined,
306
- from: PhoneCountry,
307
- to: PhoneCountry,
308
- mode: PhoneValueMode,
309
- keepCharPositions: boolean,
310
- ): { display: string; nextValue: string | undefined } {
311
- if (!value) {
312
- const prefix = dialPrefixFor(to);
313
- return { display: prefix, nextValue: undefined };
314
- }
315
-
316
- const digitsAll = digitsOnly(value);
317
-
318
- let national = digitsAll;
319
- if (digitsAll.startsWith(from.dial)) {
320
- national = digitsAll.slice(from.dial.length);
321
- }
322
-
323
- const prefix = dialPrefixFor(to);
324
- const mask = compileMask(to.mask);
325
- const masked = applyMask(mask, national, keepCharPositions);
326
-
327
- const display =
328
- national.length === 0 ? prefix : (prefix + masked || prefix);
329
-
330
- let nextValue: string | undefined;
331
- if (!national.length) {
332
- nextValue = undefined;
333
- } else if (mode === "masked") {
334
- nextValue = display;
335
- } else if (mode === "e164") {
336
- nextValue = to.dial + national;
337
- } else {
338
- nextValue = national;
339
- }
340
-
341
- return { display, nextValue };
342
- }
343
-
344
- /**
345
- * If no placeholder is passed, we show the dial prefix plus an
346
- * underscore-skeleton version of the national mask.
347
- */
348
- function buildPlaceholder(country: PhoneCountry): string {
349
- const prefix = dialPrefixFor(country);
350
- const skeleton = country.mask.replace(/[9a\*]/g, "_");
351
- return prefix + skeleton;
352
- }
353
-
354
- // ———————————————————————————————
355
- // Country select (Shadcn Select)
356
- // ———————————————————————————————
357
-
358
- interface CountrySelectProps {
359
- countries: PhoneCountry[];
360
- value: string;
361
- onChange: (code: string) => void;
362
- showFlag: boolean;
363
- showSelectedLabel: boolean;
364
- showSelectedDial: boolean;
365
- showDialInList: boolean;
366
-
367
- countrySelectClassName?: string;
368
- countryTriggerClassName?: string;
369
- countryValueClassName?: string;
370
- countryContentClassName?: string;
371
- countryItemClassName?: string;
372
- }
373
-
374
- const CountrySelect: React.FC<CountrySelectProps> = ({
375
- countries,
376
- value,
377
- onChange,
378
- showFlag,
379
- showSelectedLabel,
380
- showSelectedDial,
381
- showDialInList,
382
- countrySelectClassName,
383
- countryTriggerClassName,
384
- countryValueClassName,
385
- countryContentClassName,
386
- countryItemClassName,
387
- }) => {
388
- const selected =
389
- countries.find((c) => c.code === value) ?? countries[0] ?? null;
390
-
391
- const triggerLabel = selected
392
- ? [
393
- showFlag && selected.flag ? selected.flag : null,
394
- showSelectedDial ? `+${selected.dial}` : null,
395
- showSelectedLabel ? selected.label : null,
396
- ]
397
- .filter(Boolean)
398
- .join(" ")
399
- : "";
400
-
401
- return (
402
- <div className={countrySelectClassName}>
403
- <Select value={selected?.code ?? ""} onValueChange={onChange}>
404
- <SelectTrigger
405
- className={cn(
406
- "h-full min-w-18 px-2 focus-visible:ring-0 py-0 shadow-none rounded-none border-l-0 border-t-0 border-b-0 border-r text-xs whitespace-nowrap",
407
- countryTriggerClassName,
408
- )}
409
- >
410
- <SelectValue
411
- placeholder="Code"
412
- className={countryValueClassName}
413
- >
414
- {triggerLabel || selected?.code || "—"}
415
- </SelectValue>
416
- </SelectTrigger>
417
- <SelectContent className={countryContentClassName}>
418
- {countries.map((c) => {
419
- const parts: string[] = [];
420
-
421
- if (showFlag && c.flag) {
422
- parts.push(String(c.flag));
423
- }
424
-
425
- if (showDialInList) {
426
- parts.push(`+${c.dial}`);
427
- }
428
-
429
- parts.push(c.label);
430
-
431
- return (
432
- <SelectItem
433
- key={c.code}
434
- value={c.code}
435
- className={countryItemClassName}
436
- >
437
- {parts.join(" ")}
438
- </SelectItem>
439
- );
440
- })}
441
- </SelectContent>
442
- </Select>
443
- </div>
444
- );
445
- };
446
-
447
-
448
-
449
-
450
- // ———————————————————————————————
451
- // Main variant component
452
- // ———————————————————————————————
453
-
454
- export const ShadcnPhoneVariant = React.forwardRef<
455
- HTMLInputElement,
456
- ShadcnPhoneVariantProps
457
- >(function ShadcnPhoneVariant(props, ref) {
458
- const {
459
- countries: countriesProp,
460
- defaultCountry,
461
- onCountryChange,
462
- showCountry = true,
463
- showFlag = true,
464
- showSelectedLabel = false,
465
- showSelectedDial = false,
466
- showDialInList = true,
467
- valueMode = "e164",
468
- keepCharPositions = false,
469
- value,
470
- onValue,
471
- countryPlaceholder: placeholder,
472
- error,
473
-
474
- countrySelectClassName,
475
- countryTriggerClassName,
476
- countryValueClassName,
477
- countryContentClassName,
478
- countryItemClassName,
479
-
480
- ...restTextProps
481
- } = props;
482
-
483
- let DEFAULT_COUNTRIES = getGlobalCountryList();
484
- const countries =
485
- countriesProp && countriesProp.length > 0
486
- ? countriesProp
487
- : DEFAULT_COUNTRIES;
488
-
489
- const [country, setCountry] = React.useState<PhoneCountry>(() => {
490
- if (defaultCountry) {
491
- const found = countries.find((c) => c.code === defaultCountry);
492
- if (found) return found;
493
- }
494
- return countries[0] ?? DEFAULT_COUNTRIES[0];
495
- });
496
-
497
- // Keep active country in sync if list/default changes.
498
- React.useEffect(() => {
499
- setCountry((prev) => {
500
- if (defaultCountry) {
501
- const found = countries.find((c) => c.code === defaultCountry);
502
- if (found) return found;
503
- }
504
- const stillThere = countries.find((c) => c.code === prev.code);
505
- return stillThere ?? countries[0] ?? prev;
506
- });
507
- }, [countries, defaultCountry]);
508
-
509
- const [local, setLocal] = React.useState<string>(() =>
510
- computeDisplayFromValue(value, country, keepCharPositions),
511
- );
512
-
513
- // Sync local display when external value or country changes.
514
- React.useEffect(() => {
515
- setLocal(computeDisplayFromValue(value, country, keepCharPositions));
516
- }, [value, country, keepCharPositions]);
517
-
518
- const handleInputChange = React.useCallback(
519
- (event: React.ChangeEvent<HTMLInputElement>) => {
520
- const rawInput = event.target.value ?? "";
521
- const { display, nextValue, nationalDigits } = computeNextFromInput(
522
- rawInput,
523
- country,
524
- valueMode,
525
- keepCharPositions,
526
- );
527
-
528
- setLocal(display);
529
-
530
- if (onValue) {
531
- const detail: ChangeDetail<{
532
- country: PhoneCountry;
533
- nationalDigits: string;
534
- }> = {
535
- source: "variant",
536
- raw: rawInput,
537
- nativeEvent: event,
538
- meta: {
539
- country,
540
- nationalDigits,
541
- },
542
- };
543
- onValue(nextValue, detail);
544
- }
545
- },
546
- [country, valueMode, keepCharPositions, onValue],
547
- );
548
-
549
- const handleCountryChange = React.useCallback(
550
- (nextCode: string) => {
551
- const nextCountry =
552
- countries.find((c) => c.code === nextCode) ?? countries[0];
553
-
554
- if (!nextCountry) return;
555
-
556
- setCountry(nextCountry);
557
- onCountryChange?.(nextCountry);
558
-
559
- const { display, nextValue } = remapToCountry(
560
- value,
561
- country,
562
- nextCountry,
563
- valueMode,
564
- keepCharPositions,
565
- );
566
-
567
- setLocal(display);
568
-
569
- if (onValue) {
570
- const detail: ChangeDetail<{
571
- from: PhoneCountry;
572
- to: PhoneCountry;
573
- }> = {
574
- source: "variant",
575
- raw: undefined,
576
- meta: {
577
- from: country,
578
- to: nextCountry,
579
- },
580
- };
581
- onValue(nextValue, detail);
582
- }
583
- },
584
- [
585
- countries,
586
- country,
587
- keepCharPositions,
588
- onCountryChange,
589
- onValue,
590
- value,
591
- valueMode,
592
- ],
593
- );
594
-
595
- const effectivePlaceholder =
596
- placeholder ?? buildPlaceholder(country);
597
-
598
- const leadingControl = showCountry ? (
599
- <CountrySelect
600
- countries={countries}
601
- value={country.code}
602
- onChange={handleCountryChange}
603
- showFlag={showFlag}
604
- showSelectedLabel={showSelectedLabel}
605
- showSelectedDial={showSelectedDial}
606
- showDialInList={showDialInList}
607
- countrySelectClassName={countrySelectClassName}
608
- countryTriggerClassName={countryTriggerClassName}
609
- countryValueClassName={countryValueClassName}
610
- countryContentClassName={countryContentClassName}
611
- countryItemClassName={countryItemClassName}
612
- />
613
- ) : undefined;
614
-
615
- return (
616
- <Input
617
- ref={ref}
618
- {...restTextProps}
619
- type="tel"
620
- inputMode="tel"
621
- value={local}
622
- onChange={handleInputChange}
623
- leadingControl={leadingControl}
624
- placeholder={effectivePlaceholder}
625
- aria-invalid={error ? "true" : undefined}
626
- />
627
- );
628
- });