@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
@@ -0,0 +1,3744 @@
1
+ import * as React from 'react';
2
+ import React__default, { RefObject, ComponentType } from 'react';
3
+ import { z } from 'zod';
4
+ import { Method, AdapterResult, AdapterKey, AdapterSubmit } from './adapters.js';
5
+ export { AdapterCallbacks, AdapterConfig, AdapterError, AdapterFactory, AdapterOk, Adapters, NamedAdapterConfig, NamedAdapterFactory, createAxiosAdapter, createInertiaAdapter, getAdapter, hasAdapter, localAdapter, registerAdapter, registerAxiosAdapter, registerInertiaAdapter, registerKnownAdapter } from './adapters.js';
6
+ import * as react_jsx_runtime from 'react/jsx-runtime';
7
+ import { DayPicker } from 'react-day-picker';
8
+ import * as class_variance_authority_types from 'class-variance-authority/types';
9
+ import { VariantProps } from 'class-variance-authority';
10
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
11
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
12
+ import { $ZodError } from 'zod/v4/core';
13
+ import 'axios';
14
+ import './../../../../node_modules/@inertiajs/core/types/types.d';
15
+
16
+ /**
17
+ * Imperative handle for a submit button registered with the core.
18
+ *
19
+ * This mirrors the legacy `ButtonRef` interface, but is aligned with the
20
+ * current CoreProvider implementation:
21
+ *
22
+ * - The core will try `setLoading(v)` / `setDisabled(v)` if available.
23
+ * - Otherwise, it will fall back to setting `loading` / `disabled` props.
24
+ */
25
+ interface ButtonRef {
26
+ /**
27
+ * Logical name of the button.
28
+ *
29
+ * Used by the core runtime to track the "active" button
30
+ * and to map behaviours to a specific action.
31
+ */
32
+ name: string;
33
+ /**
34
+ * Loading flag. The core may read or assign this directly if
35
+ * no setter is provided.
36
+ */
37
+ loading?: boolean;
38
+ /**
39
+ * Disabled flag. The core may read or assign this directly if
40
+ * no setter is provided.
41
+ */
42
+ disabled?: boolean;
43
+ /**
44
+ * Optional setter used by the core to toggle loading.
45
+ */
46
+ setLoading?(v: boolean): void;
47
+ /**
48
+ * Optional setter used by the core to toggle disabled state.
49
+ */
50
+ setDisabled?(v: boolean): void;
51
+ }
52
+ /**
53
+ * Runtime representation of a single field registered with the core.
54
+ *
55
+ * This is a direct, type-safe evolution of the legacy `Field` interface
56
+ * from the old `types.ts`, updated to match the new core + binder flow.
57
+ */
58
+ interface Field {
59
+ /**
60
+ * Primary field name, used in values, error bags, and schema mapping.
61
+ *
62
+ * May be omitted for purely bound/virtual fields that participate in
63
+ * binder flows but are not directly part of the value bag.
64
+ */
65
+ name?: string;
66
+ /**
67
+ * Internal binding identifier.
68
+ *
69
+ * Used by "bound" helpers (observe-bound-field, wait-for-bound-field)
70
+ * to locate shared/aliased fields without going through the name.
71
+ */
72
+ bindId?: string;
73
+ /**
74
+ * Optional explicit binding identifier.
75
+ * Use to bind to a specific field in a nested object that has bindId
76
+ */
77
+ bind?: string;
78
+ /**
79
+ * Ref to the underlying DOM element used for focus/scroll operations.
80
+ *
81
+ * Implementations typically point this at the outer wrapper of the field.
82
+ */
83
+ ref?: RefObject<HTMLElement> | null;
84
+ /**
85
+ * Whether this field is required.
86
+ *
87
+ * Variant-level and schema-level validation may use this.
88
+ */
89
+ required?: boolean;
90
+ /**
91
+ * Current error message for the field.
92
+ *
93
+ * Undefined or empty string means "no error".
94
+ */
95
+ error?: string;
96
+ /**
97
+ * Current value of the field, as seen by the core runtime.
98
+ *
99
+ * For formatted inputs, this may be the formatted representation.
100
+ */
101
+ value?: unknown;
102
+ /**
103
+ * Initial/default value for the field.
104
+ *
105
+ * This is typically the "un-touched" value coming from props or
106
+ * from a persisted value bag.
107
+ */
108
+ defaultValue?: unknown;
109
+ /**
110
+ * Original, unformatted value as first seen by the core.
111
+ *
112
+ * This allows callers to compare "what changed" relative to the
113
+ * original snapshot, independent of any display formatting.
114
+ */
115
+ originalValue?: unknown;
116
+ /**
117
+ * Whether this field is currently performing an async operation
118
+ * (e.g. remote validation).
119
+ */
120
+ loading?: boolean;
121
+ /**
122
+ * Optional group identifier used to group related fields together
123
+ * (e.g. radio groups, segmented inputs).
124
+ */
125
+ groupId?: string;
126
+ /**
127
+ * Optional alias for this field.
128
+ *
129
+ * Aliases allow mapping server error bags or schema keys that do
130
+ * not strictly match the `name` property.
131
+ */
132
+ alias?: string;
133
+ /**
134
+ * Marks this field as the "main" one in a group.
135
+ *
136
+ * Used by some variants/layouts to determine which field drives
137
+ * overall group state.
138
+ */
139
+ main?: boolean;
140
+ /**
141
+ * If true, this field will be ignored when building values or
142
+ * running certain validation flows.
143
+ */
144
+ ignore?: boolean;
145
+ /**
146
+ * Stable unique key (distinct from `name` and `bindId`).
147
+ *
148
+ * Used internally by registries and React lists.
149
+ */
150
+ key?: string;
151
+ /**
152
+ * Shared key for fields that share their value (e.g. custom views
153
+ * over the same underlying data).
154
+ *
155
+ * This is used by the core when building nested objects, e.g.:
156
+ * shared = "profile", name = "first_name"
157
+ * ⇒ values.profile.first_name
158
+ */
159
+ shared?: string;
160
+ /**
161
+ * Run validation for this field.
162
+ *
163
+ * @param report If true, the field should update its own error state;
164
+ * if false, it may simply return whether it is valid.
165
+ * @returns `true` if the field is currently valid, `false` otherwise.
166
+ */
167
+ validate?(report?: boolean): boolean;
168
+ /**
169
+ * Optional hook used by the core or higher-level utilities to retrieve
170
+ * the current value of the field.
171
+ *
172
+ * If omitted, the core will fall back to the `value` property.
173
+ */
174
+ getValue?(): unknown;
175
+ /**
176
+ * Optional hook used by the core or higher-level utilities to update
177
+ * the current value of the field.
178
+ *
179
+ * If omitted, the core will fall back to mutating the `value` property.
180
+ */
181
+ setValue?(value: unknown): void;
182
+ /**
183
+ * Optional hook used by the core to reset the field back to its
184
+ * default/original value.
185
+ */
186
+ reset?(): void;
187
+ /**
188
+ * Optional hook used by the core to set or clear the field error.
189
+ *
190
+ * If omitted, the core will fall back to assigning the `error` property.
191
+ */
192
+ setError?(message?: string): void;
193
+ /**
194
+ * Optional hook called whenever the field value changes.
195
+ *
196
+ * Used by binder utilities to propagate changes across bound fields.
197
+ *
198
+ * @param value New value.
199
+ * @param old Previous value.
200
+ * @param source Source tag responsible for the change
201
+ * (e.g. "variant", "util", "paste", "programmatic").
202
+ */
203
+ onChange?(value: unknown, old: unknown, source: string): void;
204
+ }
205
+
206
+ /**
207
+ * Minimal surface needed for bound helpers.
208
+ *
209
+ * CoreContext already satisfies this, and FieldRegistry can be made to
210
+ * satisfy it as well (via getBind).
211
+ */
212
+ interface BindHost<V extends Dict = Dict> {
213
+ getBind(id: string): Field | undefined;
214
+ controlButton?(): void;
215
+ }
216
+
217
+ /**
218
+ * BinderRegistry: bound-field utilities for a given host (CoreContext or FieldRegistry).
219
+ *
220
+ * - Hosts must satisfy BindHost (getBind + optional controlButton).
221
+ * - FieldRegistry already does (via getBind() we added).
222
+ * - CoreContext also does.
223
+ *
224
+ * You typically access this via:
225
+ * form.inputs.binding // where inputs is a FieldRegistry
226
+ */
227
+ declare class BinderRegistry<V extends Dict = Dict> {
228
+ private readonly host;
229
+ constructor(host: BindHost<V>);
230
+ /** Raw field access. */
231
+ get(bindId: string): Field | undefined;
232
+ has(bindId: string): boolean;
233
+ /** Read current value. */
234
+ value<T = unknown>(bindId: string): T | undefined;
235
+ /** Set value (and trigger controlButton / onChange). */
236
+ set<T = unknown>(bindId: string, value: T, variant?: string): boolean;
237
+ /** Set error message on the bound field. */
238
+ error(bindId: string, msg: string): boolean;
239
+ /** Run the field’s own validate(). */
240
+ validate(bindId: string, report?: boolean): boolean;
241
+ /** Observe a bound field’s value/error and liveness. */
242
+ observe<T = unknown>(bindId: string, handler: (evt: {
243
+ exists: boolean;
244
+ field?: Field;
245
+ value?: T;
246
+ error?: string;
247
+ }) => void, pollMs?: number): () => void;
248
+ /** Wait for a bound field to appear. */
249
+ wait(bindId: string, timeoutMs?: number): Promise<Field>;
250
+ }
251
+
252
+ /**
253
+ * Central store for all fields registered with the core runtime.
254
+ *
255
+ * Responsibilities:
256
+ * - Keep a stable list of Field instances (no duplicates).
257
+ * - Only track fields that have at least one identifier:
258
+ * - name (non-empty, trimmed)
259
+ * - bindId
260
+ * - groupId
261
+ * - Provide convenient lookup methods:
262
+ * - all / getAllNamed / getAllBound / getAllGrouped
263
+ * - getByName / getAllByName
264
+ * - getByGroupId / getAllByGroupId
265
+ * - getByBind / getAllByBind (binder semantics, prefer mounted)
266
+ */
267
+ declare class FieldRegistry {
268
+ #private;
269
+ private list;
270
+ /**
271
+ * Whether this field should be tracked at all.
272
+ *
273
+ * We require at least one of: name, bindId, groupId.
274
+ */
275
+ hasIdentifier(field: Field): boolean;
276
+ /**
277
+ * Add a field to the registry if it has an identifier.
278
+ * Duplicate instances are ignored.
279
+ */
280
+ add(field: Field): void;
281
+ /**
282
+ * Remove a field from the registry.
283
+ */
284
+ remove(field: Field): void;
285
+ /**
286
+ * Clear all tracked fields.
287
+ */
288
+ clear(): void;
289
+ /**
290
+ * All fields tracked by this registry.
291
+ */
292
+ all(): Field[];
293
+ /** All fields that have a non-empty name. */
294
+ getAllNamed(): Field[];
295
+ /** All fields that have a bindId. */
296
+ getAllBound(): Field[];
297
+ /** All fields that have a groupId. */
298
+ getAllGrouped(): Field[];
299
+ /**
300
+ * First field with a given name (exact, trimmed match).
301
+ *
302
+ * Note: expects the raw name used by the field, e.g.:
303
+ * "email" or "tags[]"
304
+ */
305
+ getByName(name: string): Field | undefined;
306
+ /**
307
+ * All fields with a given name (exact, trimmed match).
308
+ */
309
+ getAllByName(name: string): Field[];
310
+ /** First field with the given groupId. */
311
+ getByGroupId(id: string): Field | undefined;
312
+ /** All fields with the given groupId. */
313
+ getAllByGroupId(id: string): Field[];
314
+ /**
315
+ * All fields that share the given bindId.
316
+ */
317
+ getAllByBind(id: string): Field[];
318
+ /**
319
+ * First field with the given bindId.
320
+ *
321
+ * Behaviour:
322
+ * - Prefer a field whose ref is currently in the DOM.
323
+ * - If none are mounted, fall back to the first matching field.
324
+ */
325
+ getByBind(id: string): Field | undefined;
326
+ getBind(id: string): Field | undefined;
327
+ get binding(): BinderRegistry;
328
+ }
329
+
330
+ /**
331
+ * Generic dictionary type used throughout the core.
332
+ *
333
+ * This matches the legacy Dict<T> from the old types.ts.
334
+ */
335
+ type Dict<T = unknown> = Record<string, T>;
336
+ /**
337
+ * If a Zod schema is present, infer the values from that schema;
338
+ * otherwise use the fallback V type. Ensured to be a Dict so it
339
+ * can safely be used as CoreContext's generic argument.
340
+ */
341
+ type InferFromSchema<S, V extends Dict> = S extends z.ZodType ? z.infer<S> & Dict : V;
342
+ /**
343
+ * Event object passed to onSubmit, matching the legacy SubmitEvent
344
+ * but kept transport-agnostic. The host decides how route/method/xhr
345
+ * are interpreted and which adapter is used.
346
+ *
347
+ * @template TValues Shape of the outbound data for this submit event.
348
+ */
349
+ type SubmitEvent<TValues extends Dict> = {
350
+ /**
351
+ * Prevent the default submit behavior.
352
+ *
353
+ * In practice this prevents the core from continuing with its
354
+ * normal submit/prepare flow.
355
+ */
356
+ preventDefault(): void;
357
+ /**
358
+ * Mutate the outbound data just before it is used.
359
+ *
360
+ * The callback may return a new data object or mutate in-place.
361
+ */
362
+ editData(cb: (data: TValues) => TValues | void): void;
363
+ /**
364
+ * Override the route/URL for this submission only.
365
+ *
366
+ * The core itself does not enforce any semantics here; the host
367
+ * is expected to interpret this when wiring submissions.
368
+ */
369
+ setRoute(route: string): void;
370
+ /**
371
+ * Override the HTTP method for this submission only.
372
+ */
373
+ setMethod(method: Method): void;
374
+ /**
375
+ * The button that triggered this submit, if any.
376
+ */
377
+ button?: ButtonRef;
378
+ /**
379
+ * The current outbound data snapshot (after any internal merges).
380
+ */
381
+ readonly formData: TValues;
382
+ /**
383
+ * The core context associated with this submit event.
384
+ */
385
+ form: CoreContext<TValues>;
386
+ /**
387
+ * If set to false, the core will abort the submit flow after
388
+ * this handler returns.
389
+ */
390
+ continue: boolean;
391
+ };
392
+ /**
393
+ * Shared base props for the core runtime, matching the spirit of
394
+ * the legacy BaseProps, but transport-agnostic.
395
+ *
396
+ * @template V Shape of the underlying value map (pre-schema).
397
+ * @template S Optional Zod schema type.
398
+ */
399
+ type BaseProps$7<V extends Dict, S extends z.ZodType | undefined> = {
400
+ /**
401
+ * Field names that should be ignored when building diffs or snapshots.
402
+ * Useful for excluding secrets like passwords from logs.
403
+ */
404
+ exceptions?: string[];
405
+ /**
406
+ * Whether the core should persist values to the provided valueBag.
407
+ */
408
+ persist?: boolean;
409
+ /**
410
+ * Optional logical name for the core instance.
411
+ */
412
+ name?: string;
413
+ /**
414
+ * If true, a button may be automatically marked as "active" when
415
+ * certain changes occur.
416
+ */
417
+ activateButtonOnChange?: boolean;
418
+ /**
419
+ * Called whenever a field changes.
420
+ *
421
+ * current is the field that changed; options carries any
422
+ * variant-specific metadata.
423
+ */
424
+ onChange?(form: CoreContext<InferFromSchema<S, V>>, current: Field, options: Dict): void;
425
+ /**
426
+ * Called when the overall values snapshot is considered "updated".
427
+ */
428
+ onUpdate?(values: InferFromSchema<S, V>): void;
429
+ /**
430
+ * If true, onChange may run before certain internal updates.
431
+ */
432
+ changeBefore?: boolean;
433
+ /**
434
+ * Optional ref to the core context instance, for imperative access.
435
+ */
436
+ formRef?: React__default.MutableRefObject<CoreContext<InferFromSchema<S, V>> | null>;
437
+ /**
438
+ * Initial value bag for hydration / persistence.
439
+ */
440
+ valueBag?: InferFromSchema<S, V>;
441
+ /**
442
+ * Optional hook used to transform a single value as it is being
443
+ * persisted or fed into the core.
444
+ */
445
+ valueFeed?: <K extends keyof InferFromSchema<S, V>>(name: K, value: InferFromSchema<S, V>[K], form: CoreContext<InferFromSchema<S, V>>) => InferFromSchema<S, V>[K] | undefined;
446
+ /**
447
+ * Called at the end of certain flows (legacy "finish" hook).
448
+ *
449
+ * Receives the core context so you can read values, errors, etc.
450
+ */
451
+ onFinish?(form: CoreContext<InferFromSchema<S, V>>): void;
452
+ /**
453
+ * Called after the core initializes.
454
+ */
455
+ init?(form: CoreContext<InferFromSchema<S, V>>): void;
456
+ /**
457
+ * Intercepts the submit event before the core proceeds.
458
+ *
459
+ * You can:
460
+ * - mutate data,
461
+ * - change route/method/xhr flags,
462
+ * - abort by setting e.continue = false.
463
+ */
464
+ onSubmit?<T extends Dict = InferFromSchema<S, V>>(e: SubmitEvent<T>): Promise<void> | void;
465
+ /**
466
+ * Optional Zod schema used for validation and value inference.
467
+ */
468
+ schema?: S;
469
+ };
470
+ /**
471
+ * Public core props, adapter-centric.
472
+ *
473
+ * - The library defines a built-in 'local' adapter flavour.
474
+ * AdapterSubmit<'local'> is `{ data: unknown }`.
475
+ * - Hosts can extend the Adapters interface (schema/adapter.ts) to add
476
+ * their own adapter flavours (axios, inertia, etc.) and then use
477
+ * those keys here.
478
+ *
479
+ * @template V Shape of the underlying value map (pre-schema).
480
+ * @template S Optional Zod schema type.
481
+ * @template K Adapter key; defaults to 'local'.
482
+ */
483
+ interface CoreProps<V extends Dict, S extends z.ZodType | undefined, K extends AdapterKey = "local"> extends BaseProps$7<V, S> {
484
+ /**
485
+ * Which adapter flavour this core instance should use.
486
+ *
487
+ * - 'local' (default) → library-defined local submission (no URL/method semantics).
488
+ * - extended keys → host-defined adapters via Adapters augmentation.
489
+ */
490
+ adapter?: K;
491
+ /**
492
+ * Called after a submission completes. The payload type is derived from
493
+ * the selected adapter key via the adapter registry:
494
+ *
495
+ * AdapterSubmit<'local'> → { data: unknown }
496
+ * AdapterSubmit<'axios'> → host-defined type, etc.
497
+ */
498
+ onSubmitted?(form: CoreContext<InferFromSchema<S, V>>, payload: AdapterSubmit<K>, resolve?: () => void): void | Promise<void>;
499
+ }
500
+ /**
501
+ * Backwards-compatible alias for legacy naming, if you want it.
502
+ */
503
+ type FormProps<V extends Dict, S extends z.ZodType | undefined, K extends AdapterKey = "local"> = CoreProps<V, S, K>;
504
+ /**
505
+ * Result of a submit operation: values + validity flag.
506
+ */
507
+ type ValuesResult<V extends Dict> = {
508
+ values: V;
509
+ valid: boolean;
510
+ };
511
+ /**
512
+ * Query API for fields, similar to DOM helpers but scoped
513
+ * to the current form instance.
514
+ *
515
+ * "id" here refers to the field's groupId.
516
+ */
517
+ interface InputStore {
518
+ /** All registered inputs (with at least one identifier). */
519
+ all(): Field[];
520
+ /** All inputs that have a non-empty name. */
521
+ getAllNamed(): Field[];
522
+ /** All inputs that have a bindId. */
523
+ getAllBound(): Field[];
524
+ /** All inputs that have a groupId. */
525
+ getAllGrouped(): Field[];
526
+ /** First field matching an exact name. */
527
+ getByName(name: string): Field | undefined;
528
+ /** All fields matching an exact name. */
529
+ getAllByName(name: string): Field[];
530
+ /** First field with this groupId. */
531
+ getById(id: string): Field | undefined;
532
+ /** All fields with this groupId. */
533
+ getAllById(id: string): Field[];
534
+ /** First bound field with this bindId (prefers mounted fields). */
535
+ getByBind(id: string): Field | undefined;
536
+ /** All fields that share this bindId. */
537
+ getAllByBind(id: string): Field[];
538
+ }
539
+ /**
540
+ * Core runtime context, renamed from the legacy FormContext.
541
+ *
542
+ * @template V Shape of the values object produced by this core instance.
543
+ */
544
+ interface CoreContext<V extends Dict> {
545
+ /**
546
+ * Compute the current values snapshot from registered fields.
547
+ */
548
+ values(): V;
549
+ /**
550
+ * Run validation and return the values + validity flag.
551
+ */
552
+ submit(): ValuesResult<V>;
553
+ /**
554
+ * Lookup a field by its binding id.
555
+ */
556
+ getBind(id: string): Field | undefined;
557
+ /**
558
+ * Run validation across fields.
559
+ *
560
+ * @param report If true, fields should update their own error states.
561
+ * @returns true if all fields are valid, false otherwise.
562
+ */
563
+ validate(report?: boolean): boolean;
564
+ /**
565
+ * Register a new field with the core.
566
+ */
567
+ addField(field: Field): void;
568
+ /**
569
+ * Generic internal bucket for arbitrary metadata.
570
+ */
571
+ bucket: Dict;
572
+ /**
573
+ * Set a single field error or map an error bag.
574
+ */
575
+ error(name: string, msg: string): void;
576
+ error(bag: Record<string, string>): void;
577
+ /**
578
+ * Re-run button control logic (which button is active/disabled etc.).
579
+ */
580
+ controlButton(): void;
581
+ /**
582
+ * Prepare an adapter-backed request.
583
+ *
584
+ * This mirrors the legacy prepare method:
585
+ * - Builds a payload from values + extra.
586
+ * - May run validation / beforeSubmit hooks.
587
+ * - Returns an adapter result or undefined if aborted.
588
+ *
589
+ * The concrete adapter wiring is the host's responsibility.
590
+ */
591
+ prepare(type: Method, route: string, extra?: Partial<V>, ignoreForm?: boolean, autoErr?: boolean): Promise<AdapterResult<any> | undefined>;
592
+ /**
593
+ * Persist values to a provided data object, optionally transforming
594
+ * values via the feed function.
595
+ */
596
+ persist(data: Partial<V>, feed?: (name: string, value: unknown, original: unknown) => unknown): void;
597
+ /**
598
+ * Imperatively set a single value by field name.
599
+ */
600
+ setValue(name: string, value: unknown): void;
601
+ /**
602
+ * Kick off a submit flow using optional extra data.
603
+ */
604
+ go(data?: Partial<V>, ignoreForm?: boolean): void;
605
+ /**
606
+ * Reset specific inputs by name.
607
+ */
608
+ reset(inputs: string[]): void;
609
+ /**
610
+ * Register the current active button.
611
+ */
612
+ set button(v: ButtonRef);
613
+ /**
614
+ * Force a submit regardless of validation state.
615
+ */
616
+ forceSubmit(): Promise<void>;
617
+ /**
618
+ * All registered fields.
619
+ */
620
+ readonly fields: Field[];
621
+ /**
622
+ * Effective core props at runtime, excluding internal-only fields.
623
+ *
624
+ * Note: the adapter key parameter is erased here (set to any) because
625
+ * the runtime does not need the specific key for structural typing;
626
+ * hosts can still use more precise generics at the component level.
627
+ */
628
+ readonly props: Omit<CoreProps<V, z.ZodType | undefined, any>, "formRef" | "valueBag">;
629
+ /**
630
+ * Mark a button as active by name.
631
+ */
632
+ setActiveButton(name: string): void;
633
+ /**
634
+ * Return uncaught messages (errors that could not be mapped to a field).
635
+ *
636
+ * Typically used by an error strip component.
637
+ */
638
+ getUncaught(): readonly string[];
639
+ /**
640
+ * Field-query "DOM" for this form.
641
+ *
642
+ * Example:
643
+ * const email = form.inputs.getByName("email");
644
+ * const phoneFields = form.inputs.getAllById("phone-group");
645
+ * const bound = form.inputs.getByBind("shipping");
646
+ */
647
+ inputs: Omit<FieldRegistry, "add" | "remove">;
648
+ /**
649
+ * Checks if the form values have changed
650
+ */
651
+ isDirty(): boolean;
652
+ }
653
+
654
+ /**
655
+ * Size hint for field variants.
656
+ *
657
+ * Presets can interpret these however they like (font size, padding, etc.).
658
+ */
659
+ type FieldSize = "sm" | "md" | "lg";
660
+ /**
661
+ * Density hint for field variants.
662
+ *
663
+ * - "compact" → tight vertical spacing
664
+ * - "comfortable" → default spacing
665
+ * - "loose" → extra breathing room
666
+ */
667
+ type FieldDensity = "compact" | "comfortable" | "loose";
668
+ /**
669
+ * Logical source of a change event.
670
+ *
671
+ * Variants and utilities can tag changes to help the host reason
672
+ * about where a value came from.
673
+ */
674
+ type ChangeSource = "variant" | "paste" | "programmatic" | "util" | (string & {});
675
+ /**
676
+ * Additional context passed along with value changes.
677
+ */
678
+ interface ChangeDetail<TMeta = unknown, TRaw = unknown> {
679
+ /**
680
+ * Logical source for this change.
681
+ */
682
+ source: ChangeSource;
683
+ /**
684
+ * Optional raw input that produced this value.
685
+ *
686
+ * Example: original keyboard input or pasted string.
687
+ */
688
+ raw?: TRaw;
689
+ nativeEvent?: React__default.SyntheticEvent;
690
+ /**
691
+ * Variant-specific metadata (e.g. cursor position).
692
+ */
693
+ meta?: TMeta;
694
+ }
695
+ /**
696
+ * Base props shared by all variant components.
697
+ *
698
+ * Each variant module will extend this with its own props type.
699
+ */
700
+ interface VariantBaseProps<TValue> {
701
+ /**
702
+ * Current logical value for this field.
703
+ */
704
+ value?: TValue | undefined;
705
+ /**
706
+ * Called whenever the variant wants to update the value.
707
+ *
708
+ * The detail payload describes where the change came from.
709
+ */
710
+ onValue?(value: TValue | undefined, detail?: ChangeDetail): void;
711
+ /**
712
+ * State flags.
713
+ */
714
+ disabled?: boolean;
715
+ defaultValue?: TValue;
716
+ readOnly?: boolean;
717
+ required?: boolean;
718
+ alias?: string;
719
+ main?: boolean;
720
+ /**
721
+ * Current error message for this field, if any.
722
+ */
723
+ error?: string;
724
+ /**
725
+ * Size & density hints.
726
+ *
727
+ * Variants are free to ignore these, but presets (e.g. Shadcn)
728
+ * will typically honour them.
729
+ */
730
+ size?: FieldSize;
731
+ density?: FieldDensity;
732
+ }
733
+ interface Extras {
734
+ trailingIcons?: React__default.ReactNode[];
735
+ leadingIcons?: React__default.ReactNode[];
736
+ icon?: React__default.ReactNode;
737
+ iconGap?: number;
738
+ trailingIconSpacing?: number;
739
+ leadingIconSpacing?: number;
740
+ trailingControl?: React__default.ReactNode;
741
+ leadingControl?: React__default.ReactNode;
742
+ /**
743
+ * Optional className applied to the container that wraps the leading control.
744
+ * This does not affect the control node itself, only the wrapper div.
745
+ */
746
+ leadingControlClassName?: string;
747
+ /**
748
+ * Optional className applied to the container that wraps the trailing control.
749
+ * This does not affect the control node itself, only the wrapper div.
750
+ */
751
+ trailingControlClassName?: string;
752
+ px?: number;
753
+ py?: number;
754
+ pb?: number;
755
+ pe?: number;
756
+ ps?: number;
757
+ }
758
+ type ExtraFieldProps<Props> = Extras & Props;
759
+
760
+ /**
761
+ * Result type for validation hooks.
762
+ *
763
+ * Used by:
764
+ * - variant modules (`validate`)
765
+ * - per-field `onValidate` (InputField)
766
+ */
767
+ type ValidateResult = boolean | string | string[] | null | void;
768
+ /**
769
+ * Placement of the main label relative to the field control.
770
+ *
771
+ * This is a macro layout decision: where the label block lives
772
+ * compared to the input/control block.
773
+ */
774
+ type LabelPlacement = "top" | "left" | "right" | "hidden";
775
+ /**
776
+ * Shared placement for helper slots relative to their *root*.
777
+ *
778
+ * Example:
779
+ * - "above" → above the label root or input root
780
+ * - "below" → below the label root or input root
781
+ * - "left" → left of the label root or input root
782
+ * - "right" → right of the label root or input root
783
+ * - "hidden" → not rendered
784
+ */
785
+ type SlotPlacement = "left" | "right" | "above" | "below" | "hidden";
786
+ /**
787
+ * Placement of the sublabel relative to its root block.
788
+ */
789
+ type SublabelPlacement = SlotPlacement;
790
+ /**
791
+ * Placement for the longer description block.
792
+ */
793
+ type DescriptionPlacement = SlotPlacement;
794
+ /**
795
+ * Placement for helper text (typically small, subtle text).
796
+ */
797
+ type HelpTextPlacement = SlotPlacement;
798
+ /**
799
+ * Placement for explicit error text (visual error copy).
800
+ */
801
+ type ErrorTextPlacement = SlotPlacement;
802
+ /**
803
+ * Registry of all logical "slots" a field can render.
804
+ *
805
+ * Hosts can extend this via declaration merging, e.g.:
806
+ *
807
+ * declare module "@/schema/input-field" {
808
+ * interface FieldSlots {
809
+ * charCounter: true;
810
+ * }
811
+ * }
812
+ */
813
+ interface FieldSlots {
814
+ /** The main label text. */
815
+ label: true;
816
+ /** Optional smaller label text. */
817
+ sublabel: true;
818
+ /** Longer, usually multi-line description. */
819
+ description: true;
820
+ /** Small helper text, usually subtle. */
821
+ helpText: true;
822
+ /** Error text (validation message) when present. */
823
+ errorText: true;
824
+ /** The actual control/input element. */
825
+ input: true;
826
+ /**tags */
827
+ tags: true;
828
+ }
829
+ /**
830
+ * Registry of logical "roots" / anchor blocks.
831
+ *
832
+ * Other slots are positioned relative to one of these.
833
+ */
834
+ interface FieldRoots {
835
+ /** Label root block. */
836
+ label: true;
837
+ /** Input/control root block. */
838
+ input: true;
839
+ }
840
+ type FieldSlotId = keyof FieldSlots;
841
+ type FieldRootId = keyof FieldRoots;
842
+ /**
843
+ * Map of which root each *non-root* slot belongs to.
844
+ *
845
+ * Example:
846
+ * relativeRoots: {
847
+ * sublabel: "label",
848
+ * description: "input",
849
+ * helpText: "input",
850
+ * errorText: "input",
851
+ * }
852
+ */
853
+ type RelativeRootsMap = Partial<Record<Exclude<FieldSlotId, FieldRootId>, // non-root slots only
854
+ FieldRootId>>;
855
+ /**
856
+ * Relative ordering of *non-root* slots per root.
857
+ *
858
+ * This is *not* about placement; it only decides "who comes first"
859
+ * when multiple slots share the same:
860
+ * - root (label/input), and
861
+ * - placement (above/below/left/right)
862
+ *
863
+ * Example:
864
+ * ordering: {
865
+ * input: ["errorText", "description", "helpText"],
866
+ * }
867
+ *
868
+ * If description and helpText are both "below" the input, then the
869
+ * above config means:
870
+ * - errorText (below input) first,
871
+ * - then description (below input),
872
+ * - then helpText (below input).
873
+ */
874
+ type FieldOrdering = Partial<Record<FieldRootId, Exclude<FieldSlotId, FieldRootId>[]>>;
875
+ /**
876
+ * Layout defaults for a field/variant.
877
+ *
878
+ * Variants can provide these as defaults; InputField merges them
879
+ * with per-field overrides.
880
+ *
881
+ * The high-level placement props remain the main public API.
882
+ * `relativeRoots` and `ordering` provide a lower-level layout graph
883
+ * that InputField can use to render slots relative to "label" or
884
+ * "input" in a predictable order.
885
+ */
886
+ interface FieldLayoutConfig {
887
+ /**
888
+ * Where to render the main label relative to the control.
889
+ */
890
+ labelPlacement?: LabelPlacement;
891
+ /**
892
+ * Where to render the sublabel relative to its root.
893
+ */
894
+ sublabelPlacement?: SublabelPlacement;
895
+ /**
896
+ * Where to render the description block relative to its root.
897
+ */
898
+ descriptionPlacement?: DescriptionPlacement;
899
+ /**
900
+ * Where to render helper text relative to its root.
901
+ */
902
+ helpTextPlacement?: HelpTextPlacement;
903
+ /**
904
+ * Where to render error text (if any) relative to its root.
905
+ */
906
+ errorTextPlacement?: ErrorTextPlacement;
907
+ /**Where to render the tags (if any) relative to ites root */
908
+ tagPlacement?: SlotPlacement;
909
+ /**
910
+ * Hint that the field should render inline with other controls.
911
+ */
912
+ inline?: boolean;
913
+ /**
914
+ * Hint that the field should stretch to the full available width.
915
+ */
916
+ fullWidth?: boolean;
917
+ /**
918
+ * Optional default size/density hints.
919
+ *
920
+ * These are advisory; variants/presets may override them.
921
+ */
922
+ defaultSize?: FieldSize;
923
+ defaultDensity?: FieldDensity;
924
+ /**
925
+ * Which root each non-root slot is attached to.
926
+ *
927
+ * If omitted, InputField can infer reasonable defaults, e.g.:
928
+ * - sublabel → "label"
929
+ * - description → "input"
930
+ * - helpText → "input"
931
+ * - errorText → "input"
932
+ */
933
+ relativeRoots?: RelativeRootsMap;
934
+ /**
935
+ * Relative ordering of non-root slots per root.
936
+ *
937
+ * Used only when multiple slots share the same
938
+ * root + placement combination.
939
+ */
940
+ ordering?: FieldOrdering;
941
+ }
942
+ /**
943
+ * Effective layout for a field after merging:
944
+ * - variant defaults, and
945
+ * - per-field overrides.
946
+ */
947
+ interface EffectiveFieldLayout extends FieldLayoutConfig {
948
+ /**
949
+ * Concrete size/density after merging defaults + overrides.
950
+ */
951
+ size?: FieldSize;
952
+ density?: FieldDensity;
953
+ }
954
+ /**
955
+ * Context passed to a variant's layout resolver.
956
+ *
957
+ * - `defaults`: layout defaults defined by the variant module.
958
+ * - `overrides`: only the layout keys explicitly set on <InputField />.
959
+ * - `props`: the raw <InputField /> props for this field.
960
+ *
961
+ * The resolver MUST respect host overrides: if a key is present in
962
+ * `overrides`, it should not change it.
963
+ */
964
+ interface LayoutResolveContext<T = unknown> {
965
+ defaults: FieldLayoutConfig;
966
+ overrides: Partial<FieldLayoutConfig>;
967
+ props: T;
968
+ }
969
+ /**
970
+ * Variant-level layout resolver.
971
+ *
972
+ * This allows variants to implement mapping rules such as:
973
+ * - "if labelPlacement is left ⇒ inline=true, error below, etc."
974
+ * while still allowing host overrides to win.
975
+ *
976
+ * Variants may also fill in `relativeRoots` and `ordering` to define
977
+ * how slots are attached to "label" vs "input" and in what relative
978
+ * order they should render.
979
+ */
980
+ type LayoutResolver<T = unknown> = (ctx: LayoutResolveContext<T>) => FieldLayoutConfig;
981
+
982
+ /**
983
+ * Props for the Shadcn-based text variant.
984
+ *
985
+ * This is a *form* wrapper around the base <Input />:
986
+ * - Handles value ↔ ChangeDetail mapping.
987
+ * - Delegates all visual concerns (masking, affixes, icons, controls,
988
+ * size, density) to the Input component.
989
+ */
990
+ type ShadcnTextVariantProps = ExtraFieldProps<VariantBaseProps<string | undefined>> & {
991
+ /**
992
+ * If true and there are controls, the input + controls share one box
993
+ * (borders, radius, focus states).
994
+ *
995
+ * Delegated to the underlying <Input />.
996
+ */
997
+ joinControls?: boolean;
998
+ /**
999
+ * When joinControls is true, whether the box styling extends over controls
1000
+ * (true) or controls are visually separate (false).
1001
+ */
1002
+ extendBoxToControls?: boolean;
1003
+ };
1004
+
1005
+ type InputRef = HTMLInputElement;
1006
+ interface InputNumberValueChangeEvent {
1007
+ originalEvent: React.SyntheticEvent<any> | null;
1008
+ value: number | null;
1009
+ stopPropagation(): void;
1010
+ preventDefault(): void;
1011
+ target: {
1012
+ name?: string | null;
1013
+ id?: string | null;
1014
+ value: number | null;
1015
+ };
1016
+ }
1017
+ interface InputNumberProps extends Omit<ShadcnTextVariantProps, 'min' | 'max' | 'value'>, Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue" | "onChange" | "onInput" | "onKeyDown" | "onKeyUp" | "size" | 'max' | 'min'> {
1018
+ onKeyUp?(event: React.KeyboardEvent<HTMLInputElement>): unknown;
1019
+ onKeyDown?(event: React.KeyboardEvent<HTMLInputElement>): unknown;
1020
+ value?: number | null;
1021
+ /**
1022
+ * Emitted when the numeric value changes (Prime-style).
1023
+ */
1024
+ onValueChange?: (e: InputNumberValueChangeEvent) => void;
1025
+ /**
1026
+ * Optional simple change handler (numeric value).
1027
+ */
1028
+ onChange?: (e: {
1029
+ originalEvent: React.SyntheticEvent<any>;
1030
+ value: number | null;
1031
+ }) => void;
1032
+ locale?: string;
1033
+ localeMatcher?: Intl.NumberFormatOptions["localeMatcher"];
1034
+ mode?: "decimal" | "currency";
1035
+ currency?: string;
1036
+ currencyDisplay?: Intl.NumberFormatOptions["currencyDisplay"];
1037
+ useGrouping?: boolean;
1038
+ minFractionDigits?: number;
1039
+ maxFractionDigits?: number;
1040
+ roundingMode?: Intl.NumberFormatOptions["roundingMode"];
1041
+ min?: number | null;
1042
+ max?: number | null;
1043
+ step?: number;
1044
+ allowEmpty?: boolean;
1045
+ format?: boolean;
1046
+ inputId?: string;
1047
+ inputClassName?: string;
1048
+ inputStyle?: React.CSSProperties;
1049
+ inputRef?: React.Ref<InputRef> | null;
1050
+ /**
1051
+ * String prefix/suffix (like Prime). They are part of formatting logic.
1052
+ * You can ALSO forward them to your text variant as visual adornments.
1053
+ */
1054
+ prefix?: string;
1055
+ suffix?: string;
1056
+ size?: FieldSize;
1057
+ invalid?: boolean;
1058
+ }
1059
+ declare const InputNumber: React.MemoExoticComponent<React.ForwardRefExoticComponent<InputNumberProps & React.RefAttributes<HTMLInputElement>>>;
1060
+
1061
+ type ShadcnNumberVariantProps = Omit<InputNumberProps, "onValueChange" | "onChange" | "leadingControl" | "trailingControl"> & {
1062
+ /**
1063
+ * Show +/- buttons around the numeric field.
1064
+ * Defaults to false.
1065
+ */
1066
+ showButtons?: boolean;
1067
+ /**
1068
+ * How the step buttons are laid out when showButtons is true.
1069
+ *
1070
+ * - 'inline': "-" on the left, "+" on the right
1071
+ * - 'stacked': vertical +/- stack on the right
1072
+ */
1073
+ buttonLayout?: "inline" | "stacked";
1074
+ };
1075
+
1076
+ type BaseProps$6 = VariantBaseProps<string | undefined>;
1077
+ /**
1078
+ * Single-country phone config.
1079
+ *
1080
+ * - code: ISO 3166-1 alpha-2 ("NG", "US", "GB", ...)
1081
+ * - dial: dial code without "+" ("234", "1", "44", ...)
1082
+ * - mask: NATIONAL portion mask only (no dial), e.g. "999 999 9999"
1083
+ */
1084
+ interface PhoneCountry {
1085
+ code: string;
1086
+ label: string;
1087
+ dial: string;
1088
+ mask: string;
1089
+ flag?: React.ReactNode;
1090
+ }
1091
+ /**
1092
+ * How the variant emits the form value.
1093
+ *
1094
+ * - "masked" → "+234 801 234 5678"
1095
+ * - "e164" → "2348012345678" (dial + national digits, no "+")
1096
+ * - "national"→ "8012345678"
1097
+ */
1098
+ type PhoneValueMode = "masked" | "e164" | "national";
1099
+ interface PhoneSpecificProps {
1100
+ countries?: PhoneCountry[];
1101
+ defaultCountry?: string;
1102
+ onCountryChange?: (country: PhoneCountry) => void;
1103
+ showCountry?: boolean;
1104
+ countryPlaceholder?: string;
1105
+ showFlag?: boolean;
1106
+ showSelectedLabel?: boolean;
1107
+ showSelectedDial?: boolean;
1108
+ showDialInList?: boolean;
1109
+ /**
1110
+ * Controls how the emitted value is shaped.
1111
+ *
1112
+ * Default mirrors legacy autoUnmask=true + emitE164=true → "e164".
1113
+ */
1114
+ valueMode?: PhoneValueMode;
1115
+ /**
1116
+ * When true, the national mask keeps placeholder characters
1117
+ * for not-yet-filled positions. When false, trailing mask
1118
+ * fragments are omitted.
1119
+ */
1120
+ keepCharPositions?: boolean;
1121
+ /**
1122
+ * Style hooks for the internal country selector.
1123
+ */
1124
+ countrySelectClassName?: string;
1125
+ countryTriggerClassName?: string;
1126
+ countryValueClassName?: string;
1127
+ countryContentClassName?: string;
1128
+ countryItemClassName?: string;
1129
+ }
1130
+ type TextUiProps$4 = Omit<ShadcnTextVariantProps, "type" | "inputMode" | "leadingControl" | "value" | "onValue">;
1131
+ /**
1132
+ * Full props for the phone variant as seen by the form runtime.
1133
+ *
1134
+ * - Keeps the same `value`/`onValue` contract as other variants.
1135
+ * - Inherits visual/behavioural text props (size, density, className, etc.).
1136
+ * - Adds phone-specific configuration (countries, valueMode, etc.).
1137
+ */
1138
+ type ShadcnPhoneVariantProps = TextUiProps$4 & PhoneSpecificProps & Pick<BaseProps$6, "value" | "onValue">;
1139
+
1140
+ type BaseProps$5 = VariantBaseProps<string | undefined>;
1141
+ /**
1142
+ * Extra options specific to the color variant.
1143
+ */
1144
+ interface ColorSpecificProps {
1145
+ /**
1146
+ * If false, we hide the colour preview box.
1147
+ * Default: true
1148
+ */
1149
+ showPreview?: boolean;
1150
+ /**
1151
+ * If false, we hide the picker toggle control/icon.
1152
+ * Default: true
1153
+ */
1154
+ showPickerToggle?: boolean;
1155
+ /**
1156
+ * Size of the colour swatch in pixels.
1157
+ * Default: 18
1158
+ */
1159
+ previewSize?: number;
1160
+ /**
1161
+ * Optional className for the outer wrapper that hosts
1162
+ * the Input + hidden color input.
1163
+ */
1164
+ wrapperClassName?: string;
1165
+ /**
1166
+ * Optional className for the preview button itself (around the swatch).
1167
+ */
1168
+ previewButtonClassName?: string;
1169
+ /**
1170
+ * Optional className for the swatch box inside the preview button.
1171
+ */
1172
+ previewSwatchClassName?: string;
1173
+ /**
1174
+ * Optional className for the hidden `<input type="color">`.
1175
+ *
1176
+ * By default this input is visually hidden and only used
1177
+ * to invoke the browser/OS colour picker, but you can override
1178
+ * this class to make it visible and style it.
1179
+ */
1180
+ pickerInputClassName?: string;
1181
+ /**
1182
+ * Custom icon shown in the trailing control as the picker toggle.
1183
+ * If omitted, a tiny ▾ triangle is used.
1184
+ */
1185
+ pickerToggleIcon?: React.ReactNode;
1186
+ className?: string;
1187
+ }
1188
+ /**
1189
+ * We inherit the *visual/behavioural* props from ShadcnTextVariant,
1190
+ * but control value / onValue / type / inputMode / leadingControl / trailingControl ourselves.
1191
+ */
1192
+ type TextUiProps$3 = Omit<ShadcnTextVariantProps, "type" | "inputMode" | "leadingControl" | "trailingControl" | "value" | "onValue">;
1193
+ /**
1194
+ * Full props for the color variant as seen by the form runtime.
1195
+ */
1196
+ type ShadcnColorVariantProps = TextUiProps$3 & ColorSpecificProps & Pick<BaseProps$5, "value" | "onValue">;
1197
+
1198
+ type BaseProps$4 = VariantBaseProps<string | undefined>;
1199
+ /**
1200
+ * Options for the built-in password strength meter.
1201
+ *
1202
+ * NOTE: Score is always in the range 0–4 (inclusive).
1203
+ */
1204
+ interface StrengthOptions {
1205
+ /**
1206
+ * Custom scoring function.
1207
+ * Return a number in the range 0–4 (inclusive) where 0 = weakest, 4 = strongest.
1208
+ */
1209
+ calc?: (value: string) => number;
1210
+ /**
1211
+ * Labels for each score bucket (index 0..4).
1212
+ * Defaults to: ["Very weak", "Weak", "Okay", "Good", "Strong"]
1213
+ */
1214
+ labels?: [string, string, string, string, string];
1215
+ /**
1216
+ * Thresholds for score steps using a 0–100 bar.
1217
+ * Defaults to [0, 25, 50, 75, 100] mapping to scores 0..4 respectively.
1218
+ */
1219
+ thresholds?: [number, number, number, number, number];
1220
+ /**
1221
+ * Minimum score required to consider the password acceptable (0–4).
1222
+ * This is purely visual unless you enforce it in validate/onChange.
1223
+ * Default: 2
1224
+ */
1225
+ minScore?: number | 2;
1226
+ /**
1227
+ * Whether to show the textual label next to/under the bar.
1228
+ * Default: true
1229
+ */
1230
+ showLabel?: boolean;
1231
+ /**
1232
+ * Where to render the meter.
1233
+ * - "inline" → compact row under the input
1234
+ * - "block" → stacked with more spacing
1235
+ * Default: "inline"
1236
+ */
1237
+ display?: "inline" | "block";
1238
+ }
1239
+ interface PasswordRuleConfig {
1240
+ /**
1241
+ * Pattern used to decide if the rule passes.
1242
+ */
1243
+ pattern: RegExp;
1244
+ /**
1245
+ * If true, the rule is considered optional (recommendation).
1246
+ * Default: false unless the rule name is not prefixed with "!".
1247
+ */
1248
+ optional?: boolean;
1249
+ /**
1250
+ * Weight in the scoring (relative importance).
1251
+ * Default: 1, doubled if the use key is prefixed with "!".
1252
+ */
1253
+ weight?: number;
1254
+ /**
1255
+ * Short label for the rule (e.g. "At least 8 characters").
1256
+ * Defaults to the map key if omitted.
1257
+ */
1258
+ label?: string;
1259
+ /**
1260
+ * Longer description, used in detailed rule view.
1261
+ */
1262
+ description?: string;
1263
+ }
1264
+ /**
1265
+ * A definition entry can be:
1266
+ * - string → treated as a regex source
1267
+ * - RegExp → used directly
1268
+ * - full config
1269
+ */
1270
+ type PasswordRuleDefinition = string | RegExp | PasswordRuleConfig;
1271
+ /**
1272
+ * Map of alias/keys → definition entries.
1273
+ */
1274
+ type PasswordDefinitionMap = Record<string, PasswordRuleDefinition>;
1275
+ /**
1276
+ * Internal normalized state for a single rule.
1277
+ */
1278
+ interface NormalizedRuleState {
1279
+ key: string;
1280
+ label: string;
1281
+ description?: string;
1282
+ optional: boolean;
1283
+ required: boolean;
1284
+ weight: number;
1285
+ passed: boolean;
1286
+ }
1287
+ /**
1288
+ * Props passed to custom meter renderers.
1289
+ */
1290
+ interface PasswordMeterRenderProps {
1291
+ /** Raw password value. */
1292
+ value: string;
1293
+ /** Bucket score 0..4 based on percent + thresholds. */
1294
+ score: number;
1295
+ /** 0–100 progress used for the bar. */
1296
+ percent: number;
1297
+ /** Human label for the current score. */
1298
+ label: string;
1299
+ /** Whether score >= minScore. */
1300
+ passed: boolean;
1301
+ /** Effective minScore after normalization. */
1302
+ minScore: number;
1303
+ /** Effective thresholds used for bucketing. */
1304
+ thresholds: [number, number, number, number, number];
1305
+ /** Effective labels used. */
1306
+ labels: [string, string, string, string, string];
1307
+ /** Rule-level details when using a definition map. */
1308
+ rules: NormalizedRuleState[];
1309
+ }
1310
+ /**
1311
+ * Password-only props (on top of Shadcn text UI props & VariantBaseProps).
1312
+ *
1313
+ * This is what the form runtime sees as VariantPropsFor<"password">.
1314
+ */
1315
+ interface PasswordVariantProps {
1316
+ /** Maximum number of characters permitted. */
1317
+ maxLength?: number;
1318
+ /** Browser autocomplete hint (e.g., "current-password", "new-password"). */
1319
+ autoComplete?: string;
1320
+ /** Show an eye button to toggle between obscured/plain text. (default: true) */
1321
+ revealToggle?: boolean;
1322
+ /** Start in the revealed (plain text) state. */
1323
+ defaultRevealed?: boolean;
1324
+ /** Called whenever the reveal state changes. */
1325
+ onRevealChange?(revealed: boolean): void;
1326
+ /** Override the icons used for hide/show. */
1327
+ renderToggleIcon?(revealed: boolean): React.ReactNode;
1328
+ /** Accessible label for the toggle button. */
1329
+ toggleAriaLabel?(revealed: boolean): string;
1330
+ /**
1331
+ * Extra className for the reveal toggle button.
1332
+ */
1333
+ toggleButtonClassName?: string;
1334
+ /**
1335
+ * Enable the built-in strength meter (boolean or options).
1336
+ *
1337
+ * - false / undefined → no built-in meter is shown
1338
+ * - true → use defaults
1339
+ * - object → merge with defaults
1340
+ */
1341
+ strengthMeter?: boolean | StrengthOptions;
1342
+ /**
1343
+ * Optional rule definition map.
1344
+ */
1345
+ ruleDefinitions?: PasswordDefinitionMap;
1346
+ /**
1347
+ * Selection of rule aliases to apply.
1348
+ *
1349
+ * - "length" → use ruleDefinitions["length"] with default importance
1350
+ * - "!length" → same rule but treated as more important
1351
+ */
1352
+ ruleUses?: string[];
1353
+ /**
1354
+ * Built-in meter style:
1355
+ * - "simple" → single bar + label
1356
+ * - "rules" → bar + per-rule checklist
1357
+ * Default: "simple"
1358
+ */
1359
+ meterStyle?: "simple" | "rules";
1360
+ /**
1361
+ * Optional custom meter renderer.
1362
+ */
1363
+ renderMeter?(props: PasswordMeterRenderProps): React.ReactNode;
1364
+ /**
1365
+ * ClassNames for the meter and rules UI.
1366
+ */
1367
+ meterWrapperClassName?: string;
1368
+ meterContainerClassName?: string;
1369
+ meterBarClassName?: string;
1370
+ meterLabelClassName?: string;
1371
+ rulesWrapperClassName?: string;
1372
+ rulesHeadingClassName?: string;
1373
+ rulesListClassName?: string;
1374
+ ruleItemClassName?: string;
1375
+ ruleIconClassName?: string;
1376
+ ruleLabelClassName?: string;
1377
+ /**
1378
+ * Extra className for the outer field wrapper.
1379
+ */
1380
+ className?: string;
1381
+ }
1382
+ type TextUiProps$2 = Omit<ShadcnTextVariantProps, "type" | "inputMode" | "leadingControl" | "trailingControl" | "value" | "onValue">;
1383
+ /**
1384
+ * Full props for the Shadcn-based password variant.
1385
+ */
1386
+ type ShadcnPasswordVariantProps = TextUiProps$2 & PasswordVariantProps & Pick<BaseProps$4, "value" | "onValue" | "error">;
1387
+
1388
+ declare const buttonVariants: (props?: ({
1389
+ variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
1390
+ size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
1391
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
1392
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
1393
+ asChild?: boolean;
1394
+ }): react_jsx_runtime.JSX.Element;
1395
+
1396
+ declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
1397
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"];
1398
+ }): react_jsx_runtime.JSX.Element;
1399
+
1400
+ type DateMode = "single" | "range";
1401
+ interface DateRange {
1402
+ from?: Date;
1403
+ to?: Date;
1404
+ }
1405
+ type DateValue = Date | DateRange | undefined;
1406
+ type BaseProps$3 = VariantBaseProps<DateValue>;
1407
+ type DisabledDays = React.ComponentProps<typeof Calendar>["disabled"];
1408
+ /**
1409
+ * Logical temporal "kind" for the field.
1410
+ *
1411
+ * This controls the default mask + formatting/parsing.
1412
+ *
1413
+ * - "date" → yyyy-MM-dd (default)
1414
+ * - "datetime" → yyyy-MM-dd HH:mm
1415
+ * - "time" → HH:mm
1416
+ * - "hour" → HH
1417
+ * - "monthYear" → MM/yyyy
1418
+ * - "year" → yyyy
1419
+ */
1420
+ type DateKind = "date" | "datetime" | "time" | "hour" | "monthYear" | "year" | (string & {});
1421
+ /**
1422
+ * Public props for the date variant (legacy + mask extensions).
1423
+ */
1424
+ interface DateVariantProps {
1425
+ mode?: DateMode;
1426
+ placeholder?: React.ReactNode;
1427
+ clearable?: boolean;
1428
+ minDate?: Date;
1429
+ maxDate?: Date;
1430
+ disabledDays?: DisabledDays;
1431
+ /**
1432
+ * Pattern for single dates.
1433
+ *
1434
+ * Tokens:
1435
+ * - yyyy → full year
1436
+ * - MM → month (01–12)
1437
+ * - dd → day (01–31)
1438
+ * - HH → hours (00–23)
1439
+ * - mm → minutes (00–59)
1440
+ *
1441
+ * Default depends on `kind`:
1442
+ * - date → "yyyy-MM-dd"
1443
+ * - datetime → "yyyy-MM-dd HH:mm"
1444
+ * - time → "HH:mm"
1445
+ * - hour → "HH"
1446
+ * - monthYear → "MM/yyyy"
1447
+ * - year → "yyyy"
1448
+ */
1449
+ formatSingle?: string;
1450
+ /**
1451
+ * String pattern or custom formatter for ranges.
1452
+ *
1453
+ * - string → same token rules as formatSingle, applied to both ends
1454
+ * - function → full control over display text
1455
+ */
1456
+ formatRange?: string | ((range: DateRange | undefined) => string);
1457
+ /**
1458
+ * Separator when formatRange is a string pattern.
1459
+ * Default: " – "
1460
+ */
1461
+ rangeSeparator?: string;
1462
+ /**
1463
+ * When true, keep the calendar open after a selection.
1464
+ *
1465
+ * For range mode, the picker also stays open until both
1466
+ * `from` and `to` are chosen.
1467
+ */
1468
+ stayOpenOnSelect?: boolean;
1469
+ /**
1470
+ * Controlled open state for the popover.
1471
+ */
1472
+ open?: boolean;
1473
+ onOpenChange?(o: boolean): void;
1474
+ /**
1475
+ * Temporal kind (controls default mask + formatting/parsing).
1476
+ *
1477
+ * Default: "date".
1478
+ */
1479
+ kind?: DateKind;
1480
+ /**
1481
+ * Optional explicit input mask pattern for the text input.
1482
+ *
1483
+ * If omitted, a sensible default based on `kind` is used.
1484
+ *
1485
+ * Mask tokens follow the same rules as the underlying Input mask:
1486
+ * 9 = digit, a = letter, * = alphanumeric.
1487
+ */
1488
+ inputMask?: string;
1489
+ /**
1490
+ * Whether to render the calendar popover.
1491
+ *
1492
+ * Defaults:
1493
+ * - true for `kind` = "date" | "datetime"
1494
+ * - false for time-only kinds ("time", "hour", "monthYear", "year")
1495
+ */
1496
+ showCalendar?: boolean;
1497
+ }
1498
+ /**
1499
+ * We still reuse the Shadcn text UI props (size, density, icons, etc.),
1500
+ * but we take over type/value/onValue and the controls.
1501
+ */
1502
+ type TextUiProps$1 = Omit<ShadcnTextVariantProps, "type" | "inputMode" | "leadingControl" | "trailingControl" | "value" | "onValue">;
1503
+ /**
1504
+ * Full props for the Shadcn-based date variant.
1505
+ */
1506
+ type ShadcnDateVariantProps = TextUiProps$1 & DateVariantProps & Pick<BaseProps$3, "value" | "onValue" | "error">;
1507
+
1508
+ type ChipsValue = string[] | undefined;
1509
+ type BaseProps$2 = VariantBaseProps<ChipsValue>;
1510
+ /**
1511
+ * How we split text into chips when committing.
1512
+ */
1513
+ type ChipsSeparator = string | RegExp | (string | RegExp)[];
1514
+ /**
1515
+ * Placement of chips relative to the entry control.
1516
+ *
1517
+ * - "inline" → inside the same visual box (Input) or in the textarea toolbox.
1518
+ * - "below" → chips rendered as a block underneath the field.
1519
+ */
1520
+ type ChipsPlacement = "inline" | "below";
1521
+ /**
1522
+ * Chips-only props, on top of the injected ones.
1523
+ */
1524
+ interface ChipsVariantProps {
1525
+ /**
1526
+ * Placeholder shown when there are no chips and input is empty.
1527
+ */
1528
+ placeholder?: string;
1529
+ /**
1530
+ * Separators used to split raw input into chips.
1531
+ *
1532
+ * - string → split on that string
1533
+ * - RegExp → split with regex
1534
+ * - array → try each in order
1535
+ *
1536
+ * Default: [",", ";"]
1537
+ */
1538
+ separators?: ChipsSeparator;
1539
+ /**
1540
+ * When true, pressing Enter commits the current input as chips.
1541
+ * Default: true
1542
+ */
1543
+ addOnEnter?: boolean;
1544
+ /**
1545
+ * When true, pressing Tab commits the current input as chips.
1546
+ * Default: true
1547
+ */
1548
+ addOnTab?: boolean;
1549
+ /**
1550
+ * When true, blurring the field commits any remaining input as chips.
1551
+ * Default: true
1552
+ */
1553
+ addOnBlur?: boolean;
1554
+ /**
1555
+ * When false, duplicate chips are ignored.
1556
+ * Default: false
1557
+ */
1558
+ allowDuplicates?: boolean;
1559
+ /**
1560
+ * Maximum number of chips allowed.
1561
+ * Undefined → unlimited.
1562
+ */
1563
+ maxChips?: number;
1564
+ /**
1565
+ * When true, Backspace on empty input removes the last chip.
1566
+ * Default: true
1567
+ */
1568
+ backspaceRemovesLast?: boolean;
1569
+ /**
1570
+ * Show a small clear-all button.
1571
+ * Default: false
1572
+ */
1573
+ clearable?: boolean;
1574
+ /**
1575
+ * Called when chips are added.
1576
+ */
1577
+ onAddChips?(added: string[], next: string[]): void;
1578
+ /**
1579
+ * Called when chips are removed.
1580
+ */
1581
+ onRemoveChips?(removed: string[], next: string[]): void;
1582
+ /**
1583
+ * Optional custom chip renderer.
1584
+ *
1585
+ * If provided, you are responsible for calling onRemove(index)
1586
+ * from your UI when you want to remove a chip.
1587
+ */
1588
+ renderChip?(chip: string, index: number, ctx: {
1589
+ remove(): void;
1590
+ chips: string[];
1591
+ }): React.ReactNode;
1592
+ /**
1593
+ * Optional custom overflow chip renderer.
1594
+ *
1595
+ * Receives the hidden count and the full chip list.
1596
+ */
1597
+ renderOverflowChip?(hiddenCount: number, chips: string[]): React.ReactNode;
1598
+ /**
1599
+ * Max number of chips to *render*.
1600
+ * Extra chips are summarized as "+N more".
1601
+ */
1602
+ maxVisibleChips?: number;
1603
+ /**
1604
+ * Max number of characters to *display* per chip.
1605
+ * The underlying value is not truncated.
1606
+ */
1607
+ maxChipChars?: number;
1608
+ /**
1609
+ * CSS max-width for chip labels (e.g. 160 or "12rem").
1610
+ */
1611
+ maxChipWidth?: number | string;
1612
+ /**
1613
+ * When true, the entry control is a Textarea instead of Input.
1614
+ * Good for comment-style chip entry.
1615
+ */
1616
+ textareaMode?: boolean;
1617
+ /**
1618
+ * Where chips are rendered relative to the entry.
1619
+ *
1620
+ * Default:
1621
+ * - Input mode → "inline"
1622
+ * - Textarea mode → "inline"
1623
+ */
1624
+ placement?: ChipsPlacement;
1625
+ className?: string;
1626
+ chipsClassName?: string;
1627
+ chipClassName?: string;
1628
+ chipLabelClassName?: string;
1629
+ chipRemoveClassName?: string;
1630
+ inputClassName?: string;
1631
+ }
1632
+ /**
1633
+ * We still type against ShadcnTextVariantProps so chips can reuse
1634
+ * size/density/icon props etc. We take control of:
1635
+ * - type / value / onValue
1636
+ * - leadingControl / trailingControl
1637
+ */
1638
+ type TextUiProps = Omit<ShadcnTextVariantProps, "type" | "inputMode" | "leadingControl" | "trailingControl" | "value" | "onValue">;
1639
+ /**
1640
+ * Full props for the Shadcn-based chips variant.
1641
+ */
1642
+ type ShadcnChipsVariantProps = TextUiProps & ChipsVariantProps & Pick<BaseProps$2, "value" | "onValue" | "error">;
1643
+
1644
+ interface TextareaIconControlProps {
1645
+ leadingIcons?: React.ReactNode[];
1646
+ trailingIcons?: React.ReactNode[];
1647
+ icon?: React.ReactNode;
1648
+ iconGap?: number;
1649
+ leadingIconSpacing?: number;
1650
+ trailingIconSpacing?: number;
1651
+ leadingControl?: React.ReactNode;
1652
+ trailingControl?: React.ReactNode;
1653
+ leadingControlClassName?: string;
1654
+ trailingControlClassName?: string;
1655
+ /**
1656
+ * If true, move the visual box (border, bg, radius, focus) from
1657
+ * `textarea-field` to `textarea-inner` so the side controls are
1658
+ * inside the same frame.
1659
+ *
1660
+ * Default: false (controls sit outside the border).
1661
+ */
1662
+ extendBoxToControls?: boolean;
1663
+ /**
1664
+ * If true, move the visual box all the way up to `textarea-box`,
1665
+ * so the upper toolbox and the inner row share a single frame.
1666
+ *
1667
+ * When this is true, it overrides `extendBoxToControls`.
1668
+ *
1669
+ * Default: false.
1670
+ */
1671
+ extendBoxToToolbox?: boolean;
1672
+ /**
1673
+ * Extra padding knobs (same semantics as Input).
1674
+ *
1675
+ * px → symmetric horizontal padding
1676
+ * py → symmetric vertical padding
1677
+ * ps/pe → logical start/end padding adjustments
1678
+ * pb → extra bottom padding (stacked with py)
1679
+ */
1680
+ px?: number;
1681
+ py?: number;
1682
+ ps?: number;
1683
+ pe?: number;
1684
+ pb?: number;
1685
+ /**
1686
+ * Extra classes merged into the raw <textarea>.
1687
+ * (The box padding/border live on the wrappers.)
1688
+ */
1689
+ inputClassName?: string;
1690
+ }
1691
+ interface TextareaSizeProps {
1692
+ size?: "sm" | "md" | "lg" | (string & {});
1693
+ density?: "compact" | "normal" | "relaxed" | "dense" | "loose" | (string & {});
1694
+ }
1695
+ interface TextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "size">, TextareaIconControlProps, TextareaSizeProps {
1696
+ /**
1697
+ * Auto-resize based on content.
1698
+ * Default: true.
1699
+ */
1700
+ autoResize?: boolean;
1701
+ /**
1702
+ * Minimum number of visual rows.
1703
+ * Default: 1.
1704
+ */
1705
+ rows?: number;
1706
+ /**
1707
+ * Maximum number of visual rows.
1708
+ * Undefined → unlimited.
1709
+ */
1710
+ maxRows?: number;
1711
+ /**
1712
+ * Optional upper toolbox area.
1713
+ */
1714
+ upperControl?: React.ReactNode;
1715
+ upperControlClassName?: string;
1716
+ }
1717
+ declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
1718
+
1719
+ type TextareaValue = string | undefined;
1720
+ type BaseProps$1 = VariantBaseProps<TextareaValue>;
1721
+ /**
1722
+ * Full props for the Shadcn-based textarea variant.
1723
+ *
1724
+ * - Reuses all UI-level behaviour from `Textarea` (autoResize, upperControl,
1725
+ * leading/trailing controls, icons, size/density, padding knobs, etc.).
1726
+ * - Takes over `value` / `onChange` so it can emit through `onValue` with
1727
+ * a `ChangeDetail`.
1728
+ */
1729
+ interface ShadcnTextareaVariantProps extends Omit<TextareaProps, "value" | "defaultValue" | "onChange">, Pick<BaseProps$1, "value" | "onValue" | "error"> {
1730
+ }
1731
+
1732
+ declare function Switch({ className, thumbClassName, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root> & {
1733
+ thumbClassName?: string;
1734
+ }): react_jsx_runtime.JSX.Element;
1735
+
1736
+ type ToggleValue = boolean | undefined;
1737
+ type BaseProps = VariantBaseProps<ToggleValue>;
1738
+ type Size = "sm" | "md" | "lg";
1739
+ type Density = "default" | "dense";
1740
+ /**
1741
+ * UI props specific to the Shadcn-based toggle.
1742
+ *
1743
+ * This uses Switch as the underlying control, but we keep
1744
+ * the API surface small and focused.
1745
+ */
1746
+ interface ShadcnToggleUiProps extends Omit<React.ComponentProps<typeof Switch>, "checked" | "onCheckedChange" | "className"> {
1747
+ /**
1748
+ * Visual size of the switch / text.
1749
+ * Default: "md".
1750
+ */
1751
+ size?: Size;
1752
+ /**
1753
+ * Row density (vertical padding & gap).
1754
+ * Default: "default".
1755
+ */
1756
+ density?: Density;
1757
+ /**
1758
+ * Place the switch on the left or right of the state text.
1759
+ * Default: "left".
1760
+ */
1761
+ controlPlacement?: "left" | "right";
1762
+ /**
1763
+ * Optional state text shown next to the control when ON.
1764
+ */
1765
+ onText?: React.ReactNode;
1766
+ /**
1767
+ * Optional state text shown next to the control when OFF.
1768
+ */
1769
+ offText?: React.ReactNode;
1770
+ /**
1771
+ * Wrapper class for the whole toggle row.
1772
+ */
1773
+ className?: string;
1774
+ /**
1775
+ * Extra classes for the Switch root.
1776
+ */
1777
+ switchClassName?: string;
1778
+ /**
1779
+ * Extra classes for the Switch thumb.
1780
+ * (Your patched Switch should support thumbClassName.)
1781
+ */
1782
+ switchThumbClassName?: string;
1783
+ }
1784
+ /**
1785
+ * Full props for the Shadcn-based toggle variant.
1786
+ *
1787
+ * We only pick value/onValue/error from the variant base props;
1788
+ * everything else (id, disabled, aria-*) flows via Switch props.
1789
+ */
1790
+ type ShadcnToggleVariantProps = ShadcnToggleUiProps & Pick<BaseProps, "value" | "onValue" | "error">;
1791
+
1792
+ declare function RadioGroup({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Root>): react_jsx_runtime.JSX.Element;
1793
+
1794
+ /**
1795
+ * Visual size of the radio UI.
1796
+ */
1797
+ type RadioSize = "sm" | "md" | "lg";
1798
+ /**
1799
+ * Vertical density of each radio row.
1800
+ *
1801
+ * Names aligned with your FieldDensity, but local to this variant.
1802
+ */
1803
+ type RadioDensity = "compact" | "comfortable" | "loose";
1804
+ /**
1805
+ * Layout mode for the group.
1806
+ *
1807
+ * - "list" → stacked rows
1808
+ * - "grid" → CSS grid with `columns`
1809
+ */
1810
+ type RadioLayoutMode = "list" | "grid";
1811
+ /**
1812
+ * Base radio item shape.
1813
+ */
1814
+ interface RadioItem<TValue> {
1815
+ value: TValue;
1816
+ label: React.ReactNode;
1817
+ description?: React.ReactNode;
1818
+ disabled?: boolean;
1819
+ key?: React.Key;
1820
+ }
1821
+ /**
1822
+ * Mapping functions used when TItem is not `RadioItem<TValue>`.
1823
+ */
1824
+ interface RadioMappers<TItem, TValue> {
1825
+ getValue: (item: TItem, index: number) => TValue;
1826
+ getLabel: (item: TItem, index: number) => React.ReactNode;
1827
+ getDescription?: (item: TItem, index: number) => React.ReactNode;
1828
+ isDisabled?: (item: TItem, index: number) => boolean;
1829
+ getKey?: (item: TItem, index: number) => React.Key;
1830
+ }
1831
+ /**
1832
+ * Context passed to a custom renderOption callback.
1833
+ */
1834
+ interface RadioRenderOptionContext<TValue> {
1835
+ item: RadioItem<TValue>;
1836
+ index: number;
1837
+ selected: boolean;
1838
+ disabled: boolean;
1839
+ size: RadioSize;
1840
+ density: RadioDensity;
1841
+ /**
1842
+ * DOM id of this option (tied to the underlying RadioGroupItem).
1843
+ */
1844
+ optionId?: string;
1845
+ /**
1846
+ * Prebuilt radio control for convenience.
1847
+ * You can ignore this and render your own if you want.
1848
+ */
1849
+ radio: React.ReactNode;
1850
+ }
1851
+ /**
1852
+ * UI-specific radio props (independent of VariantBaseProps).
1853
+ */
1854
+ interface ShadcnRadioUiProps<TItem, TValue> {
1855
+ /**
1856
+ * Items to render as choices.
1857
+ *
1858
+ * Can be:
1859
+ * - `RadioItem<TValue>[]`, or
1860
+ * - any custom TItem[] when used with mapping functions
1861
+ * or optionValue/optionLabel keys.
1862
+ */
1863
+ items: readonly TItem[];
1864
+ /**
1865
+ * Mapping functions for TItem → value/label/etc.
1866
+ *
1867
+ * Takes precedence over optionValue/optionLabel if provided.
1868
+ */
1869
+ mappers?: RadioMappers<TItem, TValue>;
1870
+ /**
1871
+ * Property name on TItem that holds the **value**.
1872
+ *
1873
+ * Example:
1874
+ * items = [{ id: "free", title: "Free" }]
1875
+ * optionValue = "id"
1876
+ */
1877
+ optionValue?: keyof TItem;
1878
+ /**
1879
+ * Property name on TItem that holds the **label**.
1880
+ *
1881
+ * Example:
1882
+ * items = [{ id: "free", title: "Free" }]
1883
+ * optionLabel = "title"
1884
+ */
1885
+ optionLabel?: keyof TItem;
1886
+ /**
1887
+ * Optional custom renderer for each option.
1888
+ *
1889
+ * If provided, the default label/description layout is skipped and
1890
+ * this function is responsible for rendering the row.
1891
+ */
1892
+ renderOption?: (ctx: RadioRenderOptionContext<TValue>) => React.ReactNode;
1893
+ /**
1894
+ * Layout mode for the group.
1895
+ * Default: "list".
1896
+ */
1897
+ layout?: RadioLayoutMode;
1898
+ /**
1899
+ * Number of columns in grid mode.
1900
+ * Default: 2.
1901
+ */
1902
+ columns?: number;
1903
+ /**
1904
+ * Gap between items (list rows or grid cells) in px.
1905
+ * If omitted, Tailwind gaps/classes can handle spacing.
1906
+ */
1907
+ itemGapPx?: number;
1908
+ /**
1909
+ * Visual size of the radios.
1910
+ * Default: "md".
1911
+ */
1912
+ size?: RadioSize;
1913
+ /**
1914
+ * Vertical density (padding) of each row.
1915
+ * Default: "comfortable".
1916
+ */
1917
+ density?: RadioDensity;
1918
+ /**
1919
+ * ARIA overrides for the group.
1920
+ */
1921
+ "aria-label"?: string;
1922
+ "aria-labelledby"?: string;
1923
+ /**
1924
+ * Wrapper class for the whole radio group.
1925
+ */
1926
+ groupClassName?: string;
1927
+ /**
1928
+ * Extra classes for each radio option row.
1929
+ */
1930
+ optionClassName?: string;
1931
+ /**
1932
+ * Extra classes for the option label node.
1933
+ */
1934
+ labelClassName?: string;
1935
+ /**
1936
+ * Extra classes for the description text under the label.
1937
+ */
1938
+ descriptionClassName?: string;
1939
+ }
1940
+ /**
1941
+ * Full props for the Shadcn-based radio variant.
1942
+ */
1943
+ type ShadcnRadioVariantProps<TValue, TItem = RadioItem<TValue>> = ShadcnRadioUiProps<TItem, TValue> & Pick<VariantBaseProps<TValue | undefined>, "value" | "onValue" | "error" | "disabled" | "required"> & Pick<React.ComponentProps<typeof RadioGroup>, "name"> & {
1944
+ id?: string;
1945
+ className?: string;
1946
+ "aria-describedby"?: string;
1947
+ };
1948
+
1949
+ type CheckboxSize = "sm" | "md" | "lg";
1950
+ type CheckboxDensity = "compact" | "comfortable" | "loose";
1951
+ type CheckboxLayoutMode = "list" | "grid";
1952
+ /**
1953
+ * Internal state we store in the value list.
1954
+ * "none" never goes into the external value.
1955
+ */
1956
+ type CheckboxTriStateValue = true | false;
1957
+ /**
1958
+ * Internal state we pass to the Shadcn checkbox.
1959
+ * "none" is used to represent "no stance yet".
1960
+ */
1961
+ type CheckboxInternalState = true | false | "none";
1962
+ interface CheckboxGroupEntry<TValue> {
1963
+ value: TValue;
1964
+ state: CheckboxTriStateValue;
1965
+ }
1966
+ type CheckboxGroupValue<TValue> = readonly CheckboxGroupEntry<TValue>[] | undefined;
1967
+ /**
1968
+ * Single checkbox value.
1969
+ * undefined → "none"
1970
+ */
1971
+ type CheckboxSingleValue = boolean | undefined;
1972
+ /**
1973
+ * Public union type for the variant's value.
1974
+ *
1975
+ * - In single mode: we expect CheckboxSingleValue
1976
+ * - In group mode: we expect CheckboxGroupValue<TValue>
1977
+ *
1978
+ * At the type level this is a union; at runtime we branch using `single`.
1979
+ */
1980
+ type CheckboxVariantValue<TValue> = CheckboxSingleValue | CheckboxGroupValue<TValue>;
1981
+ interface CheckboxItem<TValue> {
1982
+ value: TValue;
1983
+ label: React.ReactNode;
1984
+ description?: React.ReactNode;
1985
+ disabled?: boolean;
1986
+ key?: React.Key;
1987
+ /**
1988
+ * Override tri-state behaviour for this item.
1989
+ * If undefined, variant-level `tristate` is used.
1990
+ */
1991
+ tristate?: boolean;
1992
+ }
1993
+ interface CheckboxMappers<TItem, TValue> {
1994
+ getValue: (item: TItem, index: number) => TValue;
1995
+ getLabel: (item: TItem, index: number) => React.ReactNode;
1996
+ getDescription?: (item: TItem, index: number) => React.ReactNode;
1997
+ isDisabled?: (item: TItem, index: number) => boolean;
1998
+ getKey?: (item: TItem, index: number) => React.Key;
1999
+ getTristate?: (item: TItem, index: number) => boolean | undefined;
2000
+ }
2001
+ interface CheckboxRenderOptionContext<TValue> {
2002
+ item: CheckboxItem<TValue>;
2003
+ index: number;
2004
+ state: CheckboxInternalState;
2005
+ effectiveTristate: boolean;
2006
+ disabled: boolean;
2007
+ size: CheckboxSize;
2008
+ density: CheckboxDensity;
2009
+ checkboxId?: string;
2010
+ /**
2011
+ * Prebuilt Shadcn checkbox node.
2012
+ */
2013
+ checkbox: React.ReactNode;
2014
+ }
2015
+ /**
2016
+ * UI props for both single and group modes.
2017
+ */
2018
+ interface ShadcnCheckboxUiProps<TItem, TValue> {
2019
+ /**
2020
+ * Group mode:
2021
+ * - Required when `single` is not true.
2022
+ *
2023
+ * Single mode:
2024
+ * - Optional; if provided, `items[0]` can supply label/description.
2025
+ */
2026
+ items?: readonly TItem[];
2027
+ /**
2028
+ * Mapping functions for arbitrary item shapes.
2029
+ * Takes precedence over optionValue/optionLabel.
2030
+ */
2031
+ mappers?: CheckboxMappers<TItem, TValue>;
2032
+ /**
2033
+ * Property name that holds the value on each item.
2034
+ *
2035
+ * Example:
2036
+ * items = [{ id: "read", label: "Read" }]
2037
+ * optionValue = "id"
2038
+ */
2039
+ optionValue?: keyof TItem;
2040
+ /**
2041
+ * Property name that holds the label on each item.
2042
+ *
2043
+ * Example:
2044
+ * items = [{ id: "read", title: "Read" }]
2045
+ * optionLabel = "title"
2046
+ */
2047
+ optionLabel?: keyof TItem;
2048
+ /**
2049
+ * Custom renderer for each option row.
2050
+ */
2051
+ renderOption?: (ctx: CheckboxRenderOptionContext<TValue>) => React.ReactNode;
2052
+ /**
2053
+ * If true, treat this variant as a single checkbox instead of a group.
2054
+ *
2055
+ * Value is then CheckboxSingleValue (boolean | undefined).
2056
+ */
2057
+ single?: boolean;
2058
+ /**
2059
+ * Variant-level default tri-state behaviour.
2060
+ *
2061
+ * - In single mode: directly controls tri-state for the single checkbox.
2062
+ * - In group mode: default for all items, unless item.tristate overrides.
2063
+ */
2064
+ tristate?: boolean;
2065
+ /**
2066
+ * Layout mode in group mode: vertical list or CSS grid.
2067
+ */
2068
+ layout?: CheckboxLayoutMode;
2069
+ /**
2070
+ * Number of columns in grid mode.
2071
+ * Default: 2.
2072
+ */
2073
+ columns?: number;
2074
+ /**
2075
+ * Gap between items in px.
2076
+ */
2077
+ itemGapPx?: number;
2078
+ /**
2079
+ * Visual size of the checkbox / text.
2080
+ * Default: "md".
2081
+ */
2082
+ size?: CheckboxSize;
2083
+ /**
2084
+ * Vertical density of each row.
2085
+ * Default: "comfortable".
2086
+ */
2087
+ density?: CheckboxDensity;
2088
+ /**
2089
+ * ARIA attributes for the group wrapper.
2090
+ */
2091
+ "aria-label"?: string;
2092
+ "aria-labelledby"?: string;
2093
+ /**
2094
+ * Wrapper class for the entire group (or single field).
2095
+ */
2096
+ groupClassName?: string;
2097
+ /**
2098
+ * Extra classes for each option row (group mode).
2099
+ */
2100
+ optionClassName?: string;
2101
+ /**
2102
+ * Extra classes for the option label text.
2103
+ */
2104
+ labelClassName?: string;
2105
+ /**
2106
+ * Extra classes for the option description text.
2107
+ */
2108
+ descriptionClassName?: string;
2109
+ /**
2110
+ * Single-mode inline label (if you want variant-level text).
2111
+ * Usually you'll rely on InputField's label instead.
2112
+ */
2113
+ singleLabel?: React.ReactNode;
2114
+ /**
2115
+ * Single-mode description text under the label.
2116
+ */
2117
+ singleDescription?: React.ReactNode;
2118
+ }
2119
+ /**
2120
+ * Full props for the Shadcn-based checkbox variant.
2121
+ *
2122
+ * TValue: primitive or object key
2123
+ * TItem: item shape used to build checkbox items
2124
+ */
2125
+ type ShadcnCheckboxVariantProps<TValue, TItem = CheckboxItem<TValue>> = ShadcnCheckboxUiProps<TItem, TValue> & Pick<VariantBaseProps<CheckboxVariantValue<TValue>>, "value" | "onValue" | "error" | "disabled" | "required"> & {
2126
+ id?: string;
2127
+ className?: string;
2128
+ name?: string;
2129
+ "aria-describedby"?: string;
2130
+ };
2131
+ /**
2132
+ * Default item value type for the checkbox variant.
2133
+ *
2134
+ * You can still use the generic ShadcnCheckboxVariantProps<TValue, TItem>
2135
+ * directly if you need a different TValue; the registry uses this alias.
2136
+ */
2137
+ type DefaultCheckboxItemValue = string | number;
2138
+ /**
2139
+ * Public "value" type for the checkbox variant used by the registry:
2140
+ *
2141
+ * - Single mode: boolean | undefined
2142
+ * - Group mode: CheckboxGroupEntry<DefaultCheckboxItemValue>[] | undefined
2143
+ *
2144
+ * In tri-state group mode, both `true` and `false` entries are present;
2145
+ * `"none"` never appears in this type.
2146
+ */
2147
+ type CheckboxVariantPublicValue = CheckboxVariantValue<DefaultCheckboxItemValue>;
2148
+ /**
2149
+ * Public props type for the checkbox variant used by the registry.
2150
+ *
2151
+ * This is ShadcnCheckboxVariantProps with TValue fixed to DefaultCheckboxItemValue.
2152
+ */
2153
+ type ShadcnCheckboxVariantPublicProps = ShadcnCheckboxVariantProps<DefaultCheckboxItemValue>;
2154
+
2155
+ type SelectPrimitive$1 = string | number;
2156
+ type MultiSelectOption = SelectPrimitive$1 | {
2157
+ label?: React.ReactNode;
2158
+ value?: SelectPrimitive$1;
2159
+ description?: React.ReactNode;
2160
+ disabled?: boolean;
2161
+ icon?: React.ReactNode;
2162
+ [key: string]: any;
2163
+ };
2164
+ type NormalizedMultiItem = {
2165
+ key: string;
2166
+ value: SelectPrimitive$1;
2167
+ labelNode: React.ReactNode;
2168
+ labelText: string;
2169
+ description?: React.ReactNode;
2170
+ disabled?: boolean;
2171
+ icon?: React.ReactNode;
2172
+ raw: MultiSelectOption;
2173
+ };
2174
+ interface ShadcnMultiSelectVariantProps extends Pick<VariantBaseProps<SelectPrimitive$1[] | undefined>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2175
+ /**
2176
+ * Options for the multi-select.
2177
+ *
2178
+ * You can pass:
2179
+ * - primitives: ["ng", "gh", "ke"]
2180
+ * - objects: [{ label, value, ...extra }]
2181
+ */
2182
+ options?: MultiSelectOption[];
2183
+ /**
2184
+ * Automatically capitalise the first letter of the label
2185
+ * (when the resolved label is a string).
2186
+ */
2187
+ autoCap?: boolean;
2188
+ /**
2189
+ * How to read the label from each option.
2190
+ *
2191
+ * - string → key on the option object
2192
+ * - function → custom mapper
2193
+ * - omitted → tries `label`, else String(value)
2194
+ */
2195
+ optionLabel?: string | ((item: MultiSelectOption) => React.ReactNode);
2196
+ /**
2197
+ * How to read the value from each option.
2198
+ *
2199
+ * - string → key on the option object
2200
+ * - function → custom mapper
2201
+ * - omitted → uses `value`, or `id`, or `key`, or index
2202
+ */
2203
+ optionValue?: string | ((item: MultiSelectOption) => SelectPrimitive$1);
2204
+ /**
2205
+ * Optional description line under the label.
2206
+ */
2207
+ optionDescription?: string | ((item: MultiSelectOption) => React.ReactNode);
2208
+ /**
2209
+ * How to determine if an option is disabled.
2210
+ */
2211
+ optionDisabled?: string | ((item: MultiSelectOption) => boolean);
2212
+ /**
2213
+ * How to extract an icon for each option.
2214
+ *
2215
+ * - string → key on the option object (default "icon")
2216
+ * - function → custom mapper
2217
+ */
2218
+ optionIcon?: string | ((item: MultiSelectOption) => React.ReactNode);
2219
+ /**
2220
+ * How to compute the React key for each option.
2221
+ */
2222
+ optionKey?: string | ((item: MultiSelectOption, index: number) => React.Key);
2223
+ /**
2224
+ * Enable inline search inside the dropdown.
2225
+ */
2226
+ searchable?: boolean;
2227
+ /**
2228
+ * Placeholder for the search input.
2229
+ */
2230
+ searchPlaceholder?: string;
2231
+ /**
2232
+ * Text to show when search yields no results.
2233
+ */
2234
+ emptySearchText?: React.ReactNode;
2235
+ /**
2236
+ * Placeholder when nothing is selected.
2237
+ */
2238
+ placeholder?: React.ReactNode;
2239
+ /**
2240
+ * Show a small clear button in the trigger when any value is selected.
2241
+ */
2242
+ clearable?: boolean;
2243
+ /**
2244
+ * Whether to show a "Select all" row.
2245
+ */
2246
+ showSelectAll?: boolean;
2247
+ /**
2248
+ * Label for the "Select all" row.
2249
+ * Default: "Select all".
2250
+ */
2251
+ selectAllLabel?: React.ReactNode;
2252
+ /**
2253
+ * Where to place the "Select all" row.
2254
+ * Default: "top".
2255
+ */
2256
+ selectAllPosition?: "top" | "bottom";
2257
+ /**
2258
+ * Custom renderer for each option row (checkbox + label).
2259
+ */
2260
+ renderOption?: (ctx: {
2261
+ item: NormalizedMultiItem;
2262
+ selected: boolean;
2263
+ index: number;
2264
+ option: React.ReactNode;
2265
+ }) => React.ReactNode;
2266
+ /**
2267
+ * Custom renderer for the trigger summary.
2268
+ */
2269
+ renderValue?: (ctx: {
2270
+ selectedItems: NormalizedMultiItem[];
2271
+ placeholder?: React.ReactNode;
2272
+ }) => React.ReactNode;
2273
+ /**
2274
+ * Custom renderer for the checkbox.
2275
+ *
2276
+ * - item: the option item (or null for "select all")
2277
+ * - selected: whether this row is currently fully selected
2278
+ * - indeterminate: partially selected (used for "select all")
2279
+ * - isSelectAll: true for the "select all" row
2280
+ */
2281
+ renderCheckbox?: (ctx: {
2282
+ item: NormalizedMultiItem | null;
2283
+ selected: boolean;
2284
+ indeterminate: boolean;
2285
+ isSelectAll: boolean;
2286
+ }) => React.ReactNode;
2287
+ /**
2288
+ * Max height (in px) for the dropdown list before scrolling.
2289
+ * Default: 260.
2290
+ */
2291
+ maxListHeight?: number;
2292
+ /**
2293
+ * Wrapper class for the whole variant.
2294
+ */
2295
+ className?: string;
2296
+ /**
2297
+ * Extra classes for the trigger button.
2298
+ */
2299
+ triggerClassName?: string;
2300
+ /**
2301
+ * Extra classes for the popover content.
2302
+ */
2303
+ contentClassName?: string;
2304
+ /**
2305
+ * One or more icons displayed inside the trigger, on the left.
2306
+ *
2307
+ * If not provided and `icon` is set, that single icon
2308
+ * is treated as `leadingIcons[0]`.
2309
+ */
2310
+ leadingIcons?: React.ReactNode[];
2311
+ /**
2312
+ * Icons displayed on the right side of the trigger,
2313
+ * near the clear button / chevron area.
2314
+ */
2315
+ trailingIcons?: React.ReactNode[];
2316
+ /**
2317
+ * Convenience single-icon prop for the left side.
2318
+ */
2319
+ icon?: React.ReactNode;
2320
+ /**
2321
+ * Base gap between icons and text.
2322
+ * Defaults to 4px-ish via `gap-1`.
2323
+ */
2324
+ iconGap?: number;
2325
+ /**
2326
+ * Extra spacing to apply between leading icons and the text.
2327
+ */
2328
+ leadingIconSpacing?: number;
2329
+ /**
2330
+ * Extra spacing to apply between trailing icons and the clear button.
2331
+ */
2332
+ trailingIconSpacing?: number;
2333
+ /**
2334
+ * Arbitrary React node rendered before the select (e.g. a button).
2335
+ */
2336
+ leadingControl?: React.ReactNode;
2337
+ /**
2338
+ * Arbitrary React node rendered after the select (e.g. a button).
2339
+ */
2340
+ trailingControl?: React.ReactNode;
2341
+ /**
2342
+ * Extra classes for the leading control wrapper.
2343
+ */
2344
+ leadingControlClassName?: string;
2345
+ /**
2346
+ * Extra classes for the trailing control wrapper.
2347
+ */
2348
+ trailingControlClassName?: string;
2349
+ /**
2350
+ * If true and there are controls, the select trigger + controls share
2351
+ * a single visual box (borders, radius, focus states).
2352
+ */
2353
+ joinControls?: boolean;
2354
+ /**
2355
+ * When joinControls is true, whether the box styling extends over controls
2356
+ * (true) or controls are visually separate (false).
2357
+ */
2358
+ extendBoxToControls?: boolean;
2359
+ }
2360
+
2361
+ type SliderValue$1 = number | undefined;
2362
+ interface ShadcnSliderVariantProps extends Pick<VariantBaseProps<SliderValue$1>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2363
+ /**
2364
+ * Minimum value for the slider.
2365
+ * Default: 0
2366
+ */
2367
+ min?: number;
2368
+ /**
2369
+ * Maximum value for the slider.
2370
+ * Default: 100
2371
+ */
2372
+ max?: number;
2373
+ /**
2374
+ * Step between values.
2375
+ * Default: 1
2376
+ */
2377
+ step?: number;
2378
+ /**
2379
+ * Show the current value as text next to the slider.
2380
+ * Default: true
2381
+ */
2382
+ showValue?: boolean;
2383
+ /**
2384
+ * Where to place the value label, relative to the slider.
2385
+ * - "end" → right of the slider (horizontal)
2386
+ * - "start" → left of the slider
2387
+ *
2388
+ * Default: "end"
2389
+ */
2390
+ valuePlacement?: "start" | "end";
2391
+ /**
2392
+ * Custom formatter for the numeric value.
2393
+ * If omitted, uses the raw number.
2394
+ */
2395
+ formatValue?: (value: SliderValue$1) => React.ReactNode;
2396
+ /**
2397
+ * Wrapper class for the entire slider field.
2398
+ */
2399
+ className?: string;
2400
+ /**
2401
+ * Extra classes for the Slider root.
2402
+ */
2403
+ sliderClassName?: string;
2404
+ /**
2405
+ * Extra classes for the value label.
2406
+ */
2407
+ valueClassName?: string;
2408
+ /**
2409
+ * One or more icons displayed inside the slider region, on the left.
2410
+ *
2411
+ * If not provided and `icon` is set, that single icon
2412
+ * is treated as `leadingIcons[0]`.
2413
+ */
2414
+ leadingIcons?: React.ReactNode[];
2415
+ /**
2416
+ * Icons displayed on the right side of the slider region
2417
+ * (before/after the value label depending on placement).
2418
+ */
2419
+ trailingIcons?: React.ReactNode[];
2420
+ /**
2421
+ * Convenience single-icon prop for the left side.
2422
+ */
2423
+ icon?: React.ReactNode;
2424
+ /**
2425
+ * Base gap between icons and slider/value.
2426
+ * Defaults to 4px-ish via `gap-1`.
2427
+ */
2428
+ iconGap?: number;
2429
+ /**
2430
+ * Extra spacing to apply between leading icons and the slider track.
2431
+ */
2432
+ leadingIconSpacing?: number;
2433
+ /**
2434
+ * Extra spacing to apply between trailing icons and the value label.
2435
+ */
2436
+ trailingIconSpacing?: number;
2437
+ /**
2438
+ * Arbitrary React node rendered before the slider (e.g. a button).
2439
+ */
2440
+ leadingControl?: React.ReactNode;
2441
+ /**
2442
+ * Arbitrary React node rendered after the slider (e.g. a button).
2443
+ */
2444
+ trailingControl?: React.ReactNode;
2445
+ /**
2446
+ * Extra classes for the leading control wrapper.
2447
+ */
2448
+ leadingControlClassName?: string;
2449
+ /**
2450
+ * Extra classes for the trailing control wrapper.
2451
+ */
2452
+ trailingControlClassName?: string;
2453
+ /**
2454
+ * If true and there are controls, the slider + controls share
2455
+ * a single visual box (borders, radius, focus states).
2456
+ * Default: true (to match text/select behaviour).
2457
+ */
2458
+ joinControls?: boolean;
2459
+ /**
2460
+ * When joinControls is true, whether the box styling extends over controls
2461
+ * (true) or controls are visually separate (false).
2462
+ * Default: true.
2463
+ */
2464
+ extendBoxToControls?: boolean;
2465
+ /**
2466
+ * Built-in +/- controls around the slider.
2467
+ *
2468
+ * - "none" → no built-in step buttons (default)
2469
+ * - "boxed" → +/- inside the same frame as the slider
2470
+ * - "edge" → loose layout: "- [ slider ] +"
2471
+ */
2472
+ controlVariant?: "none" | "boxed" | "edge";
2473
+ /**
2474
+ * Step used when clicking the +/- controls.
2475
+ * Defaults to `step`.
2476
+ */
2477
+ controlStep?: number;
2478
+ /**
2479
+ * Custom node for the decrement control. Default: "−".
2480
+ */
2481
+ controlDecrementIcon?: React.ReactNode;
2482
+ /**
2483
+ * Custom node for the increment control. Default: "+".
2484
+ */
2485
+ controlIncrementIcon?: React.ReactNode;
2486
+ }
2487
+
2488
+ /**
2489
+ * Slider value type:
2490
+ * - `number | undefined` for now (single-value slider).
2491
+ * If/when you add range support, this can be widened to [number, number].
2492
+ */
2493
+ type SliderValue = number | undefined;
2494
+
2495
+ type KeyValueMap = Record<string, string>;
2496
+ interface KV {
2497
+ key: string;
2498
+ value: string;
2499
+ }
2500
+ interface ShadcnKeyValueVariantProps extends Pick<VariantBaseProps<KeyValueMap | undefined>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2501
+ min?: number;
2502
+ max?: number;
2503
+ minVisible?: number;
2504
+ maxVisible?: number;
2505
+ showAddButton?: boolean;
2506
+ showMenuButton?: boolean;
2507
+ placeholder?: React.ReactNode;
2508
+ dialogTitle?: React.ReactNode;
2509
+ keyLabel?: React.ReactNode;
2510
+ valueLabel?: React.ReactNode;
2511
+ submitLabel?: React.ReactNode;
2512
+ moreLabel?: (count: number) => React.ReactNode;
2513
+ emptyLabel?: React.ReactNode;
2514
+ className?: string;
2515
+ chipsClassName?: string;
2516
+ chipClassName?: string;
2517
+ renderChip?: (ctx: {
2518
+ pair: KV;
2519
+ index: number;
2520
+ onEdit: () => void;
2521
+ onRemove: () => void;
2522
+ defaultChip: React.ReactNode;
2523
+ }) => React.ReactNode;
2524
+ }
2525
+
2526
+ /**
2527
+ * Props for the generic "custom" variant.
2528
+ *
2529
+ * - The only special props we define are:
2530
+ * - component: the React component to render
2531
+ * - valueProp / changeProp / disabledProp / readOnlyProp / errorProp
2532
+ * - idProp / nameProp / placeholderProp
2533
+ * - mapValue / mapDetail (optional hooks)
2534
+ *
2535
+ * - All other props are treated as "component props" and forwarded
2536
+ * directly to the underlying component.
2537
+ *
2538
+ * The underlying component is expected to:
2539
+ * - accept the mapped `valueProp`
2540
+ * - call the mapped `changeProp` with the next value (first argument)
2541
+ * - optionally use disabled/readOnly/error/id/name/placeholder via the mapped names
2542
+ */
2543
+ interface ShadcnCustomVariantProps<TValue = unknown> extends VariantBaseProps<TValue> {
2544
+ /**
2545
+ * The actual React component to render.
2546
+ *
2547
+ * Example:
2548
+ * component={MyToggle}
2549
+ */
2550
+ component: React.ComponentType<any>;
2551
+ /**
2552
+ * Prop name that carries the current value for the component.
2553
+ * Default: "value".
2554
+ */
2555
+ valueProp?: string;
2556
+ /**
2557
+ * Prop name for the change handler that the component will call.
2558
+ * Default: "onChange".
2559
+ *
2560
+ * The component is expected to call:
2561
+ * props[changeProp](nextValue, ...otherArgs?)
2562
+ *
2563
+ * The first argument is taken as the new value.
2564
+ */
2565
+ changeProp?: string;
2566
+ /**
2567
+ * Prop name for disabled state.
2568
+ * Default: "disabled".
2569
+ */
2570
+ disabledProp?: string;
2571
+ /**
2572
+ * Prop name for read-only state.
2573
+ * Default: "readOnly".
2574
+ */
2575
+ readOnlyProp?: string;
2576
+ /**
2577
+ * Prop name for passing error to the component (if it cares).
2578
+ * If provided, we pass the `error` field as-is.
2579
+ * Example values: "error", "isInvalid", "status".
2580
+ */
2581
+ errorProp?: string;
2582
+ /**
2583
+ * Prop name for the id attribute.
2584
+ * Default: "id".
2585
+ */
2586
+ idProp?: string;
2587
+ /**
2588
+ * Prop name for the name attribute.
2589
+ * Default: "name".
2590
+ */
2591
+ nameProp?: string;
2592
+ /**
2593
+ * Prop name for the placeholder attribute.
2594
+ * Default: "placeholder".
2595
+ */
2596
+ placeholderProp?: string;
2597
+ /**
2598
+ * Optional transform for the raw next value before it hits the field.
2599
+ *
2600
+ * Receives the first argument that the component passes to the change
2601
+ * handler, plus the full argument list for flexibility.
2602
+ */
2603
+ mapValue?: (raw: any, ...args: any[]) => TValue;
2604
+ /**
2605
+ * Optional builder for ChangeDetail, given the raw next value.
2606
+ *
2607
+ * If omitted, a default { source: "variant", raw } detail is used.
2608
+ */
2609
+ mapDetail?: (raw: any, ...args: any[]) => ChangeDetail;
2610
+ /**
2611
+ * Any other props are assumed to belong to the custom component.
2612
+ */
2613
+ [key: string]: unknown;
2614
+ }
2615
+
2616
+ type TreeKey = string | number;
2617
+ type TreeValue = TreeKey | TreeKey[] | undefined;
2618
+ type TreeSelectOption = TreeKey | {
2619
+ label?: React.ReactNode;
2620
+ value?: TreeKey;
2621
+ description?: React.ReactNode;
2622
+ disabled?: boolean;
2623
+ icon?: React.ReactNode;
2624
+ children?: TreeSelectOption[];
2625
+ [key: string]: any;
2626
+ };
2627
+ type NormalizedTreeItem = {
2628
+ key: string;
2629
+ value: TreeKey;
2630
+ labelNode: React.ReactNode;
2631
+ labelText: string;
2632
+ description?: React.ReactNode;
2633
+ disabled?: boolean;
2634
+ icon?: React.ReactNode;
2635
+ level: number;
2636
+ parentValue?: TreeKey;
2637
+ path: TreeKey[];
2638
+ hasChildren: boolean;
2639
+ children: NormalizedTreeItem[];
2640
+ raw: TreeSelectOption;
2641
+ };
2642
+ interface ShadcnTreeSelectVariantProps extends Pick<VariantBaseProps<TreeValue>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2643
+ options?: TreeSelectOption[];
2644
+ /**
2645
+ * If true, allows multiple selection (checkboxes).
2646
+ * If false, allows single selection (no checkboxes, closes on select).
2647
+ * Default: true
2648
+ */
2649
+ multiple?: boolean;
2650
+ autoCap?: boolean;
2651
+ optionLabel?: string | ((item: TreeSelectOption) => React.ReactNode);
2652
+ optionValue?: string | ((item: TreeSelectOption) => TreeKey);
2653
+ optionDescription?: string | ((item: TreeSelectOption) => React.ReactNode);
2654
+ optionDisabled?: string | ((item: TreeSelectOption) => boolean);
2655
+ optionIcon?: string | ((item: TreeSelectOption) => React.ReactNode);
2656
+ optionKey?: string | ((item: TreeSelectOption, index: number) => React.Key);
2657
+ searchable?: boolean;
2658
+ searchPlaceholder?: string;
2659
+ emptyLabel?: React.ReactNode;
2660
+ emptySearchText?: React.ReactNode;
2661
+ clearable?: boolean;
2662
+ placeholder?: React.ReactNode;
2663
+ className?: string;
2664
+ triggerClassName?: string;
2665
+ contentClassName?: string;
2666
+ renderOption?: (ctx: {
2667
+ item: NormalizedTreeItem;
2668
+ selected: boolean;
2669
+ index: number;
2670
+ option: React.ReactNode;
2671
+ }) => React.ReactNode;
2672
+ renderValue?: (ctx: {
2673
+ selectedItems: NormalizedTreeItem[];
2674
+ placeholder?: React.ReactNode;
2675
+ }) => React.ReactNode;
2676
+ expandAll?: boolean;
2677
+ defaultExpandedValues?: TreeKey[];
2678
+ leafOnly?: boolean;
2679
+ leadingIcons?: React.ReactNode[];
2680
+ trailingIcons?: React.ReactNode[];
2681
+ icon?: React.ReactNode;
2682
+ iconGap?: number;
2683
+ leadingIconSpacing?: number;
2684
+ trailingIconSpacing?: number;
2685
+ leadingControl?: React.ReactNode;
2686
+ trailingControl?: React.ReactNode;
2687
+ leadingControlClassName?: string;
2688
+ trailingControlClassName?: string;
2689
+ joinControls?: boolean;
2690
+ extendBoxToControls?: boolean;
2691
+ }
2692
+
2693
+ type FileSourceKind = "native" | "path" | "url" | "custom";
2694
+ interface FileItem {
2695
+ id: string;
2696
+ kind: FileSourceKind;
2697
+ file?: File;
2698
+ path?: string;
2699
+ url?: string;
2700
+ name: string;
2701
+ size?: number;
2702
+ type?: string;
2703
+ status?: "idle" | "loading" | "done" | "failed";
2704
+ error?: string | null;
2705
+ meta?: any;
2706
+ }
2707
+ type FileLike = File | string | {
2708
+ id?: string;
2709
+ file?: File;
2710
+ path?: string;
2711
+ url?: string;
2712
+ name?: string;
2713
+ size?: number;
2714
+ type?: string;
2715
+ status?: FileItem["status"];
2716
+ error?: string | null;
2717
+ meta?: any;
2718
+ [key: string]: unknown;
2719
+ };
2720
+ type CustomFileLoaderResult = FileLike | FileLike[] | null | undefined;
2721
+ type CustomFileLoader = (ctx: {
2722
+ multiple: boolean;
2723
+ current: FileItem[];
2724
+ }) => Promise<CustomFileLoaderResult> | CustomFileLoaderResult;
2725
+ interface ShadcnFileVariantProps extends Pick<VariantBaseProps<FileItem[]>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2726
+ multiple?: boolean;
2727
+ accept?: string | string[];
2728
+ maxFiles?: number;
2729
+ maxTotalSize?: number;
2730
+ showDropArea?: boolean;
2731
+ dropIcon?: React.ReactNode;
2732
+ dropTitle?: React.ReactNode;
2733
+ dropDescription?: React.ReactNode;
2734
+ renderDropArea?: (ctx: {
2735
+ openPicker: () => void;
2736
+ isDragging: boolean;
2737
+ }) => React.ReactNode;
2738
+ renderFileItem?: (ctx: {
2739
+ item: FileItem;
2740
+ index: number;
2741
+ selected: boolean;
2742
+ toggleSelected: () => void;
2743
+ remove: () => void;
2744
+ }) => React.ReactNode;
2745
+ showCheckboxes?: boolean;
2746
+ onFilesAdded?: (added: FileItem[], detail: ChangeDetail<{
2747
+ from: "input" | "drop" | "custom-loader";
2748
+ }>) => void;
2749
+ customLoader?: CustomFileLoader;
2750
+ mergeMode?: "append" | "replace";
2751
+ formatFileName?: (item: FileItem) => React.ReactNode;
2752
+ formatFileSize?: (size?: number) => React.ReactNode;
2753
+ placeholder?: string;
2754
+ className?: string;
2755
+ dropAreaClassName?: string;
2756
+ listClassName?: string;
2757
+ leadingIcons?: React.ReactNode[];
2758
+ trailingIcons?: React.ReactNode[];
2759
+ icon?: React.ReactNode;
2760
+ leadingControl?: React.ReactNode;
2761
+ trailingControl?: React.ReactNode;
2762
+ leadingControlClassName?: string;
2763
+ trailingControlClassName?: string;
2764
+ joinControls?: boolean;
2765
+ extendBoxToControls?: boolean;
2766
+ }
2767
+
2768
+ type SelectPrimitive = string | number;
2769
+ type SelectOption = SelectPrimitive | {
2770
+ label?: React.ReactNode;
2771
+ value?: SelectPrimitive;
2772
+ description?: React.ReactNode;
2773
+ disabled?: boolean;
2774
+ [key: string]: any;
2775
+ };
2776
+ type NormalizedSelectItem = {
2777
+ key: string;
2778
+ value: SelectPrimitive;
2779
+ labelNode: React.ReactNode;
2780
+ labelText: string;
2781
+ description?: React.ReactNode;
2782
+ disabled?: boolean;
2783
+ icon?: React.ReactNode;
2784
+ raw: SelectOption;
2785
+ };
2786
+ /**
2787
+ * Shadcn-based Select variant.
2788
+ */
2789
+ interface ShadcnSelectVariantProps extends Pick<VariantBaseProps<SelectPrimitive | undefined>, "value" | "onValue" | "error" | "disabled" | "readOnly" | "size" | "density"> {
2790
+ /**
2791
+ * Options for the select.
2792
+ *
2793
+ * You can pass:
2794
+ * - primitives: ["ng", "gh", "ke"]
2795
+ * - objects: [{ label, value, ...extra }]
2796
+ */
2797
+ options?: SelectOption[];
2798
+ /**
2799
+ * Automatically capitalise the first letter of the label
2800
+ * (when the resolved label is a string).
2801
+ */
2802
+ autoCap?: boolean;
2803
+ /**
2804
+ * How to read the label from each option.
2805
+ *
2806
+ * - string → key on the option object
2807
+ * - function → custom mapper
2808
+ * - omitted → tries `label`, else String(value)
2809
+ */
2810
+ optionLabel?: string | ((item: SelectOption) => React.ReactNode);
2811
+ /**
2812
+ * How to read the value from each option.
2813
+ *
2814
+ * - string → key on the option object
2815
+ * - function → custom mapper
2816
+ * - omitted → uses `value`, or `id`, or `key`, or index
2817
+ */
2818
+ optionValue?: string | ((item: SelectOption) => SelectPrimitive);
2819
+ /**
2820
+ * Optional description line under the label.
2821
+ */
2822
+ optionDescription?: string | ((item: SelectOption) => React.ReactNode);
2823
+ /**
2824
+ * How to determine if an option is disabled.
2825
+ */
2826
+ optionDisabled?: string | ((item: SelectOption) => boolean);
2827
+ /**
2828
+ * How to extract an icon for each option.
2829
+ *
2830
+ * - string → key on the option object (default "icon")
2831
+ * - function → custom mapper
2832
+ */
2833
+ optionIcon?: string | ((item: SelectOption) => React.ReactNode);
2834
+ /**
2835
+ * How to compute the React key for each option.
2836
+ */
2837
+ optionKey?: string | ((item: SelectOption, index: number) => React.Key);
2838
+ /**
2839
+ * Enable inline search inside the dropdown.
2840
+ */
2841
+ searchable?: boolean;
2842
+ /**
2843
+ * Placeholder for the search input.
2844
+ */
2845
+ searchPlaceholder?: string;
2846
+ /**
2847
+ * Label shown when there are no options available at all.
2848
+ *
2849
+ * If omitted, falls back to `emptySearchText` or a default message.
2850
+ */
2851
+ emptyLabel?: React.ReactNode;
2852
+ /**
2853
+ * Text to show when search yields no results
2854
+ * (but there *are* options in general).
2855
+ */
2856
+ emptySearchText?: React.ReactNode;
2857
+ /**
2858
+ * Show a small clear button in the trigger when a value is selected.
2859
+ */
2860
+ clearable?: boolean;
2861
+ /**
2862
+ * Placeholder when nothing is selected.
2863
+ */
2864
+ placeholder?: React.ReactNode;
2865
+ /**
2866
+ * Wrapper class for the whole variant.
2867
+ */
2868
+ className?: string;
2869
+ /**
2870
+ * Extra classes for the SelectTrigger.
2871
+ */
2872
+ triggerClassName?: string;
2873
+ /**
2874
+ * Extra classes for the SelectContent popover.
2875
+ */
2876
+ contentClassName?: string;
2877
+ /**
2878
+ * Custom renderer for each option row.
2879
+ */
2880
+ renderOption?: (ctx: {
2881
+ item: NormalizedSelectItem;
2882
+ selected: boolean;
2883
+ index: number;
2884
+ option: React.ReactNode;
2885
+ }) => React.ReactNode;
2886
+ /**
2887
+ * Custom renderer for the trigger value.
2888
+ */
2889
+ renderValue?: (ctx: {
2890
+ selectedItem: NormalizedSelectItem | null;
2891
+ placeholder?: React.ReactNode;
2892
+ }) => React.ReactNode;
2893
+ /**
2894
+ * One or more icons displayed inside the trigger, on the left.
2895
+ *
2896
+ * If not provided and `icon` is set, that single icon
2897
+ * is treated as `leadingIcons[0]`.
2898
+ */
2899
+ leadingIcons?: React.ReactNode[];
2900
+ /**
2901
+ * Icons displayed on the right side of the trigger,
2902
+ * near the clear button / chevron area.
2903
+ */
2904
+ trailingIcons?: React.ReactNode[];
2905
+ /**
2906
+ * Convenience single-icon prop for the left side.
2907
+ */
2908
+ icon?: React.ReactNode;
2909
+ /**
2910
+ * Base gap between icons and text.
2911
+ * Defaults to 4px-ish via `gap-1`.
2912
+ */
2913
+ iconGap?: number;
2914
+ /**
2915
+ * Extra spacing to apply between leading icons and the text.
2916
+ */
2917
+ leadingIconSpacing?: number;
2918
+ /**
2919
+ * Extra spacing to apply between trailing icons and the clear button.
2920
+ */
2921
+ trailingIconSpacing?: number;
2922
+ /**
2923
+ * Arbitrary React node rendered before the select (e.g. a button).
2924
+ */
2925
+ leadingControl?: React.ReactNode;
2926
+ /**
2927
+ * Arbitrary React node rendered after the select (e.g. a button).
2928
+ */
2929
+ trailingControl?: React.ReactNode;
2930
+ /**
2931
+ * Extra classes for the leading control wrapper.
2932
+ */
2933
+ leadingControlClassName?: string;
2934
+ /**
2935
+ * Extra classes for the trailing control wrapper.
2936
+ */
2937
+ trailingControlClassName?: string;
2938
+ /**
2939
+ * If true and there are controls, the select trigger + controls share
2940
+ * a single visual box (borders, radius, focus states).
2941
+ */
2942
+ joinControls?: boolean;
2943
+ /**
2944
+ * When joinControls is true, whether the box styling extends over controls
2945
+ * (true) or controls are visually separate (false).
2946
+ */
2947
+ extendBoxToControls?: boolean;
2948
+ /**
2949
+ * Enable incremental rendering for large option lists.
2950
+ *
2951
+ * When true, only a page of options is rendered initially,
2952
+ * and more are revealed as the user scrolls down.
2953
+ */
2954
+ virtualScroll?: boolean;
2955
+ /**
2956
+ * Number of options to render per "page" when virtualScroll is enabled.
2957
+ * Default: 50.
2958
+ */
2959
+ virtualScrollPageSize?: number;
2960
+ /**
2961
+ * Distance from the bottom (in px) at which the next page loads.
2962
+ * Default: 48px.
2963
+ */
2964
+ virtualScrollThreshold?: number;
2965
+ }
2966
+
2967
+ type SelectVariantProps = ShadcnSelectVariantProps;
2968
+
2969
+ /**
2970
+ * Helper type for a single variant registry entry.
2971
+ *
2972
+ * Keeps the shape consistent and easy to extend via declaration merging.
2973
+ */
2974
+ interface VariantEntry<TValue, TProps> {
2975
+ value: TValue;
2976
+ props: TProps;
2977
+ }
2978
+ /**
2979
+ * Base type-level variant registry.
2980
+ *
2981
+ * This is the **canonical mapping** used by:
2982
+ * - InputFieldProps<K>
2983
+ * - VariantModule<K>
2984
+ *
2985
+ * Hosts & presets extend it via declaration merging:
2986
+ *
2987
+ * declare module "@/schema/variant" {
2988
+ * interface Variants {
2989
+ * select: VariantEntry<SelectValuePublic, SelectPropsPublic>;
2990
+ * }
2991
+ * }
2992
+ */
2993
+ interface Variants<H = unknown> {
2994
+ /**
2995
+ * Built-in "text" variant.
2996
+ *
2997
+ * Shadcn-based implementation lives in presets/shadcn-variants/text.tsx
2998
+ */
2999
+ text: VariantEntry<string | undefined, ShadcnTextVariantProps>;
3000
+ /**
3001
+ * Example scalar variant.
3002
+ *
3003
+ * You can repurpose this for "custom" or drop it later.
3004
+ */
3005
+ number: VariantEntry<number | undefined, ShadcnNumberVariantProps>;
3006
+ phone: VariantEntry<string | number | undefined, ShadcnPhoneVariantProps>;
3007
+ color: VariantEntry<string | undefined, ShadcnColorVariantProps>;
3008
+ password: VariantEntry<string | undefined, ShadcnPasswordVariantProps>;
3009
+ date: VariantEntry<string | undefined, ShadcnDateVariantProps>;
3010
+ chips: VariantEntry<string[] | undefined, ShadcnChipsVariantProps>;
3011
+ textarea: VariantEntry<string | undefined, ShadcnTextareaVariantProps>;
3012
+ toggle: VariantEntry<boolean | undefined, ShadcnToggleVariantProps>;
3013
+ radio: VariantEntry<unknown | undefined, ShadcnRadioVariantProps<unknown, RadioItem<unknown>>>;
3014
+ checkbox: VariantEntry<CheckboxVariantPublicValue, ShadcnCheckboxVariantPublicProps>;
3015
+ select: VariantEntry<string | number | undefined, SelectVariantProps>;
3016
+ 'multi-select': VariantEntry<Array<string | number> | undefined, ShadcnMultiSelectVariantProps>;
3017
+ slider: VariantEntry<SliderValue, ShadcnSliderVariantProps>;
3018
+ keyvalue: VariantEntry<KeyValueMap | undefined, ShadcnKeyValueVariantProps>;
3019
+ custom: VariantEntry<unknown | undefined, ShadcnCustomVariantProps>;
3020
+ treeselect: VariantEntry<string | number | undefined, ShadcnTreeSelectVariantProps>;
3021
+ file: VariantEntry<FileLike, ShadcnFileVariantProps>;
3022
+ }
3023
+ /**
3024
+ * Union of all variant keys.
3025
+ */
3026
+ type VariantKey = keyof Variants;
3027
+ /**
3028
+ * Value type for a given variant key.
3029
+ *
3030
+ * Strongly drives autocomplete:
3031
+ * - InputFieldProps<"text"> → TValue = string | undefined
3032
+ */
3033
+ type VariantValueFor<K extends VariantKey, H = unknown> = Variants<H>[K]["value"];
3034
+ /**
3035
+ * Props type for a given variant key.
3036
+ *
3037
+ * Strongly drives autocomplete:
3038
+ * - InputFieldProps<"text"> → props = TextVariantProps
3039
+ */
3040
+ type VariantPropsFor<K extends VariantKey, H = unknown> = Variants<H>[K]["props"];
3041
+ /**
3042
+ * Signature for variant-level validation functions.
3043
+ */
3044
+ type VariantValidateFn<TValue, TProps> = (value: TValue | undefined, ctx: {
3045
+ required?: boolean;
3046
+ props: TProps;
3047
+ field: Field;
3048
+ form: CoreContext<Dict>;
3049
+ }) => ValidateResult;
3050
+ /**
3051
+ * Layout defaults for a variant.
3052
+ *
3053
+ * This extends FieldLayoutConfig, so it automatically includes:
3054
+ * - placement props (labelPlacement, descriptionPlacement, etc.)
3055
+ * - layout hints (inline, fullWidth, defaultSize/density)
3056
+ * - layout graph (relativeRoots, ordering)
3057
+ */
3058
+ interface VariantLayoutDefaults extends FieldLayoutConfig {
3059
+ }
3060
+ /**
3061
+ * Runtime module definition for a variant.
3062
+ *
3063
+ * IMPORTANT:
3064
+ * - This is **tied directly** to the registry:
3065
+ * TValue = VariantValueFor<K>
3066
+ * TProps = VariantPropsFor<K>
3067
+ *
3068
+ * So if you change the entry in `Variants`, both:
3069
+ * - <InputField variant="..." /> props
3070
+ * - The Variant component in the module
3071
+ * will see the updated types and IntelliSense matches everywhere.
3072
+ *
3073
+ * - For complex variants (select/multiselect):
3074
+ * you model the relationship via unions in `Variants["select"]`.
3075
+ */
3076
+ interface VariantModule<K extends VariantKey = VariantKey> {
3077
+ /**
3078
+ * Unique key for this variant, e.g. "text", "number", "select".
3079
+ */
3080
+ variant: K;
3081
+ /**
3082
+ * React component that renders the control.
3083
+ *
3084
+ * It receives:
3085
+ * - VariantBaseProps<VariantValueFor<K>>
3086
+ * - VariantPropsFor<K>
3087
+ */
3088
+ Variant: ComponentType<VariantBaseProps<VariantValueFor<K>> & VariantPropsFor<K>>;
3089
+ /**
3090
+ * Optional validation logic specific to this variant.
3091
+ */
3092
+ validate?: VariantValidateFn<VariantValueFor<K>, VariantPropsFor<K>>;
3093
+ /**
3094
+ * Optional default layout hints for this variant.
3095
+ */
3096
+ defaults?: {
3097
+ layout?: VariantLayoutDefaults;
3098
+ };
3099
+ /**
3100
+ * Optional smart layout resolver.
3101
+ *
3102
+ * Must respect host overrides.
3103
+ */
3104
+ resolveLayout?: LayoutResolver<VariantPropsFor<K>>;
3105
+ /**
3106
+ * Optional metadata, useful for docs/inspectors.
3107
+ */
3108
+ meta?: {
3109
+ label?: string;
3110
+ description?: string;
3111
+ tags?: string[];
3112
+ };
3113
+ }
3114
+ /**
3115
+ * Convenience alias when you want to be explicit:
3116
+ *
3117
+ * const textModule: VariantModuleFor<"text"> = { ... }
3118
+ */
3119
+ type VariantModuleFor<K extends VariantKey> = VariantModule<K>;
3120
+
3121
+ type Props<V extends Dict, S extends z.ZodType | undefined, K extends AdapterKey> = CoreProps<V, S, K> & {
3122
+ children?: React.ReactNode;
3123
+ };
3124
+ /**
3125
+ * CoreProvider: owns the form/core runtime state and implements CoreContext.
3126
+ *
3127
+ * - Tracks all inputs in a single store (inputsRef)
3128
+ * - Supports:
3129
+ * - named inputs via `name`
3130
+ * - bound inputs via `bindId`
3131
+ * - grouped inputs via `groupId`
3132
+ * - Manages errors + uncaught messages
3133
+ * - Builds values snapshots (including bucket values)
3134
+ * - Orchestrates submission via the adapter registry
3135
+ */
3136
+ declare function CoreProvider<V extends Dict, S extends z.ZodType | undefined, K extends AdapterKey = "local">(props: Props<V, S, K>): react_jsx_runtime.JSX.Element;
3137
+
3138
+ interface CoreRootProps extends React.FormHTMLAttributes<HTMLFormElement> {
3139
+ /**
3140
+ * If true, the global ErrorStrip will not be rendered automatically.
3141
+ */
3142
+ noErrorStrip?: boolean;
3143
+ /**
3144
+ * Optional hook invoked after CoreRoot orchestrates the submit.
3145
+ *
3146
+ * - The native event is already `preventDefault()`-ed.
3147
+ * - The adapter flow is triggered via `form.go(...)`.
3148
+ * - Use this to tap into submit without breaking the core.
3149
+ */
3150
+ onSubmitForm?(event: React.FormEvent<HTMLFormElement>, form: CoreContext<Dict>): void | Promise<void>;
3151
+ }
3152
+ /**
3153
+ * CoreRoot: actual <form> element wired to the core runtime.
3154
+ *
3155
+ * Responsibilities:
3156
+ * - Own the native submit event and prevent full-page navigation.
3157
+ * - Delegate submit orchestration to form.go().
3158
+ * - Optionally render the global ErrorStrip at the top.
3159
+ */
3160
+ declare function CoreRoot(props: CoreRootProps): react_jsx_runtime.JSX.Element;
3161
+
3162
+ /**
3163
+ * Combined provider + form-root wrapper.
3164
+ *
3165
+ * Usage:
3166
+ * <CoreShell adapter="local" schema={schema} formProps={{ className: "space-y-4" }}>
3167
+ * {...fields + buttons...}
3168
+ * </CoreShell>
3169
+ */
3170
+ interface CoreShellProps<V extends Dict = Dict, S extends z.ZodType | undefined = z.ZodType | undefined, K extends AdapterKey = "local"> extends CoreProps<V, S, K> {
3171
+ /**
3172
+ * Props passed directly to the underlying <form> element via CoreRoot.
3173
+ */
3174
+ formProps?: CoreRootProps;
3175
+ children?: React.ReactNode;
3176
+ }
3177
+ declare function CoreShell<V extends Dict, S extends z.ZodType | undefined, K extends AdapterKey = "local">(props: CoreShellProps<V, S, K>): react_jsx_runtime.JSX.Element;
3178
+
3179
+ interface UseButtonOptions {
3180
+ /**
3181
+ * Logical name of the button.
3182
+ *
3183
+ * Used by the core to:
3184
+ * - mark this as the "active" button before submit
3185
+ * - toggle loading/disabled specifically for this button
3186
+ */
3187
+ name: string;
3188
+ /**
3189
+ * If true, clicking this button should trigger a submit:
3190
+ *
3191
+ * - form.setActiveButton(name)
3192
+ * - form.go()
3193
+ */
3194
+ submit?: boolean;
3195
+ /**
3196
+ * Initial disabled state.
3197
+ */
3198
+ disabled?: boolean;
3199
+ /**
3200
+ * Optional click handler.
3201
+ *
3202
+ * This runs *in addition to* the submit behavior (if `submit` is true).
3203
+ * You can call `event.preventDefault()` to prevent the auto-submit.
3204
+ */
3205
+ onClick?(event: React.MouseEvent<HTMLButtonElement>, form: CoreContext<Dict>): void | Promise<void>;
3206
+ }
3207
+ interface UseButtonReturn {
3208
+ /**
3209
+ * Current loading state, controlled by the core (via adapters) and
3210
+ * optionally by the host via setLoading.
3211
+ */
3212
+ loading: boolean;
3213
+ setLoading(loading: boolean): void;
3214
+ /**
3215
+ * Current disabled state.
3216
+ */
3217
+ disabled: boolean;
3218
+ setDisabled(disabled: boolean): void;
3219
+ /**
3220
+ * Ref for the underlying <button>.
3221
+ */
3222
+ ref: React.RefObject<HTMLButtonElement>;
3223
+ /**
3224
+ * Click handler wired to the core.
3225
+ */
3226
+ onClick(event: React.MouseEvent<HTMLButtonElement>): void;
3227
+ /**
3228
+ * Convenience bundle for spreading onto a <button>.
3229
+ *
3230
+ * Example:
3231
+ * const btn = useButton({ name: "save", submit: true });
3232
+ * return <button {...btn.buttonProps}>Save</button>;
3233
+ */
3234
+ buttonProps: {
3235
+ ref: React.RefObject<HTMLButtonElement>;
3236
+ disabled: boolean;
3237
+ "data-loading"?: "true" | "false";
3238
+ onClick(event: React.MouseEvent<HTMLButtonElement>): void;
3239
+ };
3240
+ }
3241
+ /**
3242
+ * useButton
3243
+ *
3244
+ * - Registers a ButtonRef with the core.
3245
+ * - Cooperates with setActiveButton + adapter-based submit.
3246
+ * - Handles loading/disabled toggling via the core's callbacks.
3247
+ */
3248
+ declare function useButton(options: UseButtonOptions): UseButtonReturn;
3249
+
3250
+ /**
3251
+ * Convenience alias for useCoreContext.
3252
+ *
3253
+ * This mirrors the legacy useForm hook: you get the full CoreContext,
3254
+ * and can call core.values(), core.submit(), core.go(), etc.
3255
+ */
3256
+ declare function useCore<V extends Dict = Dict>(): CoreContext<V>;
3257
+
3258
+ /**
3259
+ * Typed hook to access the current core/form context.
3260
+ *
3261
+ * Must be used inside a <CoreProvider>. If no provider is found,
3262
+ * this will throw to make misuse obvious.
3263
+ */
3264
+ declare function useCoreContext<V extends Dict = Dict>(): CoreContext<V>;
3265
+
3266
+ type UseFieldValidate<T> = (value: T, report: boolean) => boolean | string;
3267
+ interface UseFieldOptions<T = unknown> {
3268
+ /**
3269
+ * Primary field name.
3270
+ *
3271
+ * This is the key that will show up in the values snapshot and
3272
+ * error bags (unless mapped via `shared` or `alias`).
3273
+ */
3274
+ name?: string;
3275
+ /**
3276
+ * Optional internal binding identifier.
3277
+ *
3278
+ * Used by the bound helpers (observeBoundField, waitForBoundField)
3279
+ * and the binder registry.
3280
+ */
3281
+ bindId?: string;
3282
+ /**
3283
+ * Optional external binding key – a semantic identifier for this
3284
+ * field’s binding group.
3285
+ *
3286
+ * Example:
3287
+ * bind="shipping"
3288
+ */
3289
+ bind?: string;
3290
+ /**
3291
+ * Shared key for nested grouping, e.g:
3292
+ *
3293
+ * shared="profile", name="first_name"
3294
+ * → values.profile.first_name
3295
+ */
3296
+ shared?: string;
3297
+ /**
3298
+ * Optional grouping identifier used to group related controls
3299
+ * (e.g. radio groups, segmented inputs).
3300
+ */
3301
+ groupId?: string;
3302
+ /**
3303
+ * Optional alias for error / mapping purposes.
3304
+ *
3305
+ * Example:
3306
+ * alias="email" but name="contact.email"
3307
+ */
3308
+ alias?: string;
3309
+ /**
3310
+ * Marks this field as the "main" one in a group.
3311
+ */
3312
+ main?: boolean;
3313
+ /**
3314
+ * If true, this field is ignored by snapshot / some validation
3315
+ * flows, but may still exist in the registry.
3316
+ */
3317
+ ignore?: boolean;
3318
+ /**
3319
+ * Whether the field is required.
3320
+ */
3321
+ required?: boolean;
3322
+ /**
3323
+ * Initial/default value for this field.
3324
+ */
3325
+ defaultValue?: T;
3326
+ /**
3327
+ * Initial disabled flag.
3328
+ */
3329
+ disabled?: boolean;
3330
+ /**
3331
+ * Initial readOnly flag.
3332
+ */
3333
+ readOnly?: boolean;
3334
+ /**
3335
+ * Custom validation hook.
3336
+ *
3337
+ * Return:
3338
+ * - `true` → valid
3339
+ * - `false` → invalid (no message)
3340
+ * - `"message"` → invalid with explicit message
3341
+ */
3342
+ validate?: UseFieldValidate<T>;
3343
+ /**
3344
+ * Optional projector to derive an "original" value from the
3345
+ * initial default.
3346
+ */
3347
+ getOriginalValue?(value: T | undefined): unknown;
3348
+ /**
3349
+ * Local change hook for the field.
3350
+ *
3351
+ * This is in addition to the form-level `onChange`.
3352
+ */
3353
+ onValueChange?(next: T, prev: T, variant: string): void;
3354
+ }
3355
+ interface UseFieldReturn<T = unknown> {
3356
+ /** Ref to the underlying DOM element */
3357
+ ref: React.RefObject<HTMLElement>;
3358
+ key: string;
3359
+ /** Current value */
3360
+ value: T | undefined;
3361
+ setValue(next: T | undefined, variant?: string): void;
3362
+ /** Current error message */
3363
+ error: string;
3364
+ setError(message: string): void;
3365
+ /** Async-loading flag (e.g. remote validation) */
3366
+ loading: boolean;
3367
+ setLoading(loading: boolean): void;
3368
+ /** Required flag */
3369
+ required: boolean;
3370
+ setRequired(required: boolean): void;
3371
+ /** Disabled flag */
3372
+ disabled: boolean;
3373
+ setDisabled(disabled: boolean): void;
3374
+ /** Readonly flag */
3375
+ readOnly: boolean;
3376
+ setReadOnly(readOnly: boolean): void;
3377
+ /** Metadata / wiring */
3378
+ name: string;
3379
+ bindId: string;
3380
+ bind?: string;
3381
+ shared?: string;
3382
+ groupId?: string;
3383
+ alias?: string;
3384
+ main?: boolean;
3385
+ ignore?: boolean;
3386
+ /** Snapshots */
3387
+ readonly defaultValue: T | undefined;
3388
+ readonly originalValue: unknown;
3389
+ /** Owning core context */
3390
+ form: CoreContext<Dict>;
3391
+ /** Run validation (optionally reporting errors) */
3392
+ validate(report?: boolean): boolean | undefined;
3393
+ }
3394
+ /**
3395
+ * Strict field hook.
3396
+ *
3397
+ * - Registers the field with the core provider / registry.
3398
+ * - Exposes value/error/loading and lifecycle helpers.
3399
+ * - Wires into:
3400
+ * - core-level `onChange`
3401
+ * - `controlButton()` dirty logic
3402
+ */
3403
+ declare function useField<T = unknown>(options: UseFieldOptions<T>): UseFieldReturn<T>;
3404
+
3405
+ /**
3406
+ * Optional variant of `useField`.
3407
+ *
3408
+ * - If there is a CoreProvider, behaves like `useField`.
3409
+ * - If not, it becomes a self-managed field (value/error/loading/etc).
3410
+ */
3411
+ declare function useOptionalField<T = unknown>(options: UseFieldOptions<T>): UseFieldReturn<T>;
3412
+
3413
+ type ErrorBag = Record<string, string | string[] | undefined | null>;
3414
+ type ErrorBagMapResult = {
3415
+ /** Field-specific errors keyed by field name. */
3416
+ fieldErrors: Record<string, string>;
3417
+ /** Errors that could not be mapped to a specific field. */
3418
+ uncaught: string[];
3419
+ };
3420
+ /**
3421
+ * Map a generic "error bag" object into field errors + uncaught messages.
3422
+ *
3423
+ * Typical input:
3424
+ * {
3425
+ * name: "Name is required",
3426
+ * email: ["Email is invalid"],
3427
+ * message: "Something went wrong" // global
3428
+ * }
3429
+ *
3430
+ * Heuristics:
3431
+ * - Keys like "message", "error", "_", "global" → treated as global/uncaught.
3432
+ * - Everything else → treated as a field error.
3433
+ * - Array values are joined with "\n".
3434
+ */
3435
+ declare function mapErrorBag(bag: ErrorBag): ErrorBagMapResult;
3436
+
3437
+ type ZodErrorMapResult = {
3438
+ /** Field-specific errors keyed by field name. */
3439
+ fieldErrors: Record<string, string>;
3440
+ /** Errors that could not be mapped to a specific field. */
3441
+ uncaught: string[];
3442
+ };
3443
+ /**
3444
+ * Map a ZodError into field-specific errors + uncaught messages.
3445
+ *
3446
+ * Heuristics:
3447
+ * - If issue.path[0] is a string → treated as a field name.
3448
+ * - Otherwise → message is pushed into `uncaught`.
3449
+ *
3450
+ * If a field has multiple issues, messages are joined with `\n`.
3451
+ */
3452
+ declare function mapZodError(error: $ZodError): ZodErrorMapResult;
3453
+
3454
+ interface ErrorStripProps extends React.HTMLAttributes<HTMLElement> {
3455
+ /**
3456
+ * Optional explicit form context. If omitted, the strip will use
3457
+ * the nearest CoreProvider via useCore().
3458
+ */
3459
+ form?: CoreContext<Dict>;
3460
+ /**
3461
+ * Optional explicit messages. If provided, these are used instead of
3462
+ * form.getUncaught().
3463
+ */
3464
+ messages?: readonly string[];
3465
+ /**
3466
+ * Custom renderer for each message.
3467
+ */
3468
+ renderMessage?: (message: string, index: number) => React.ReactNode;
3469
+ /**
3470
+ * Wrapper element type. Defaults to "div".
3471
+ */
3472
+ as?: React.ElementType;
3473
+ /**
3474
+ * Props forwarded to the inner <ul> element.
3475
+ */
3476
+ listProps?: React.HTMLAttributes<HTMLUListElement>;
3477
+ }
3478
+ /**
3479
+ * Simple global/uncaught error renderer.
3480
+ *
3481
+ * Reads messages from `form.getUncaught()` (unless `messages` is provided)
3482
+ * and renders them as a list.
3483
+ */
3484
+ declare function ErrorStrip(props: ErrorStripProps): react_jsx_runtime.JSX.Element | null;
3485
+
3486
+ /**
3487
+ * Core, variant-agnostic props for InputField.
3488
+ *
3489
+ * @template TValue Logical value type for this field. Will be refined by
3490
+ * variant typing (VariantValueFor<K>).
3491
+ */
3492
+ interface InputFieldBaseProps<TValue = unknown> {
3493
+ name?: string;
3494
+ bind?: string;
3495
+ groupId?: string;
3496
+ shared?: string;
3497
+ ignore?: boolean;
3498
+ alias?: string;
3499
+ main?: boolean;
3500
+ tags?: FieldTag[];
3501
+ contain?: boolean;
3502
+ label?: React.ReactNode;
3503
+ sublabel?: React.ReactNode;
3504
+ description?: React.ReactNode;
3505
+ helpText?: React.ReactNode;
3506
+ /**
3507
+ * Optional explicit error text to display.
3508
+ *
3509
+ * This is *visual* error copy. The actual validation state still
3510
+ * lives in field.error / schema / onValidate.
3511
+ */
3512
+ errorText?: React.ReactNode;
3513
+ /**
3514
+ * Placement hints for label / sublabel / description / helpText / errorText.
3515
+ *
3516
+ * These are purely layout hints; actual behaviour is implemented
3517
+ * by the preset / host component.
3518
+ */
3519
+ labelPlacement?: LabelPlacement;
3520
+ sublabelPlacement?: SublabelPlacement;
3521
+ descriptionPlacement?: DescriptionPlacement;
3522
+ helpTextPlacement?: HelpTextPlacement;
3523
+ errorTextPlacement?: ErrorTextPlacement;
3524
+ tagPlacement?: SlotPlacement;
3525
+ required?: boolean;
3526
+ disabled?: boolean;
3527
+ readOnly?: boolean;
3528
+ size?: FieldSize;
3529
+ density?: FieldDensity;
3530
+ inline?: boolean;
3531
+ fullWidth?: boolean;
3532
+ onValidate?(value: TValue | undefined, field: Field, form: CoreContext<Dict>): ValidateResult;
3533
+ /**
3534
+ * Per-field change hook at the InputField level.
3535
+ *
3536
+ * - `value` is what the variant is trying to set.
3537
+ * - `detail` comes from the variant (`ChangeDetail`).
3538
+ * - If you return `undefined`, the original value is used.
3539
+ * - If you return *anything else*, that is what will be stored
3540
+ * in the core (and emitted to the form).
3541
+ */
3542
+ onChange?(e: {
3543
+ value: TValue | undefined;
3544
+ preventDefault(): void;
3545
+ event?: React.SyntheticEvent;
3546
+ readonly isDefaultPrevented?: boolean;
3547
+ readonly detail: ChangeDetail;
3548
+ }): void;
3549
+ }
3550
+ /**
3551
+ * Public props for <InputField />.
3552
+ *
3553
+ * - `variant` selects the variant module.
3554
+ * - All variant-specific props are merged directly into the field props
3555
+ * via `VariantPropsFor<K>`.
3556
+ *
3557
+ * NOTE: this is a type alias (not an interface) so we can safely intersect
3558
+ * unions coming from VariantPropsFor<K> / VariantValueFor<K>.
3559
+ */
3560
+ type InputFieldProps<K extends VariantKey = VariantKey, H = unknown> = InputFieldBaseProps<VariantValueFor<K, H>> & VariantPropsFor<K, H> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {
3561
+ variant: K;
3562
+ classes?: Partial<InputFieldClassNames>;
3563
+ };
3564
+ interface InputFieldClassNames {
3565
+ root?: string;
3566
+ labelRow?: string;
3567
+ inlineRow?: string;
3568
+ label?: string;
3569
+ sublabel?: string;
3570
+ description?: string;
3571
+ helpText?: string;
3572
+ error?: string;
3573
+ group?: string;
3574
+ content?: string;
3575
+ variant?: string;
3576
+ inlineInputColumn?: string;
3577
+ inlineLabelColumn?: string;
3578
+ required?: string;
3579
+ tag?: string;
3580
+ }
3581
+ interface FieldTag {
3582
+ label: React.ReactNode;
3583
+ icon?: React.ReactNode;
3584
+ className?: string;
3585
+ color?: string;
3586
+ bgColor?: string;
3587
+ }
3588
+
3589
+ /**
3590
+ * Public InputField component.
3591
+ *
3592
+ * - Uses `useField` to register a Field and manage value/error/loading.
3593
+ * - Delegates rendering to the chosen variant's `Variant` component.
3594
+ * - Uses Shadcn's Field primitives for structure.
3595
+ * - Lets variants influence layout via defaults + optional resolveLayout().
3596
+ * - Uses a layout graph (buildLayoutGraph) + getSlotsFor().render(...) to
3597
+ * position helpers (sublabel, description, helpText, error, tags) relative to
3598
+ * "label" vs "input" roots without empty wrapper divs.
3599
+ */
3600
+ declare function InputField<K extends VariantKey = VariantKey>(props: InputFieldProps<K>): react_jsx_runtime.JSX.Element | null;
3601
+
3602
+ /**
3603
+ * Register (or overwrite) a variant module.
3604
+ *
3605
+ * Typically called from presets, e.g.:
3606
+ *
3607
+ * registerVariant(textVariant);
3608
+ * registerVariant(numberVariant);
3609
+ */
3610
+ declare function registerVariant<K extends VariantKey>(module: VariantModule<K>): void;
3611
+ /**
3612
+ * Look up a variant module by key.
3613
+ */
3614
+ declare function getVariant<K extends VariantKey>(key: K): VariantModule<K> | undefined;
3615
+ /**
3616
+ * List all registered variant modules.
3617
+ */
3618
+ declare function listVariants(): VariantModule<VariantKey>[];
3619
+
3620
+ /**
3621
+ * Register all core/built-in variants.
3622
+ *
3623
+ * Hosts can call this once at bootstrap:
3624
+ *
3625
+ * import { registerCoreVariants } from "@timeax/form-palette/variants";
3626
+ * registerCoreVariants();
3627
+ */
3628
+ declare function registerCoreVariants(): void;
3629
+
3630
+ interface InputMaskChangeEvent {
3631
+ originalEvent: React.SyntheticEvent<HTMLInputElement> | Event | undefined;
3632
+ value: string;
3633
+ stopPropagation(): void;
3634
+ preventDefault(): void;
3635
+ target: {
3636
+ name?: string;
3637
+ id?: string;
3638
+ value: string;
3639
+ };
3640
+ }
3641
+ interface InputMaskCompleteEvent {
3642
+ originalEvent: React.SyntheticEvent<HTMLInputElement> | Event;
3643
+ value: string;
3644
+ }
3645
+ interface InputMaskRef {
3646
+ focus(): void;
3647
+ getElement(): HTMLInputElement | null;
3648
+ }
3649
+ interface InputMaskProps$1 extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "defaultValue"> {
3650
+ mask: string | null;
3651
+ autoClear?: boolean;
3652
+ autoFocus?: boolean;
3653
+ invalid?: boolean;
3654
+ unmask?: boolean;
3655
+ slotChar?: string;
3656
+ 'data-slot'?: string;
3657
+ value?: string | null;
3658
+ onChange?: (e: InputMaskChangeEvent) => void;
3659
+ onComplete?: (e: InputMaskCompleteEvent) => void;
3660
+ }
3661
+ declare const InputMask: React.MemoExoticComponent<React.ForwardRefExoticComponent<InputMaskProps$1 & React.RefAttributes<InputMaskRef>>>;
3662
+
3663
+ type MaskMode = "raw" | "masked";
3664
+ interface InputMaskProps {
3665
+ mask?: string;
3666
+ maskDefinitions?: Record<string, RegExp>;
3667
+ slotChar?: string;
3668
+ autoClear?: boolean;
3669
+ unmask?: MaskMode | boolean;
3670
+ maskInsertMode?: "stream" | "caret";
3671
+ }
3672
+ interface InputAffixProps {
3673
+ prefix?: string;
3674
+ suffix?: string;
3675
+ /**
3676
+ * If true (default), we assume the model value does NOT contain the prefix
3677
+ * and we only add it visually at render time.
3678
+ */
3679
+ stripPrefix?: boolean;
3680
+ /**
3681
+ * If true (default), we assume the model value does NOT contain the suffix
3682
+ * and we only add it visually at render time.
3683
+ */
3684
+ stripSuffix?: boolean;
3685
+ }
3686
+ interface InputIconControlProps {
3687
+ leadingIcons?: React.ReactNode[];
3688
+ trailingIcons?: React.ReactNode[];
3689
+ icon?: React.ReactNode;
3690
+ iconGap?: number;
3691
+ leadingIconSpacing?: number;
3692
+ trailingIconSpacing?: number;
3693
+ leadingControl?: React.ReactNode;
3694
+ trailingControl?: React.ReactNode;
3695
+ leadingControlClassName?: string;
3696
+ trailingControlClassName?: string;
3697
+ joinControls?: boolean;
3698
+ extendBoxToControls?: boolean;
3699
+ px?: number;
3700
+ py?: number;
3701
+ ps?: number;
3702
+ pe?: number;
3703
+ pb?: number;
3704
+ inputClassName?: string;
3705
+ }
3706
+ interface InputSizeProps {
3707
+ size?: "sm" | "md" | "lg" | (string & {});
3708
+ density?: "compact" | "normal" | "relaxed" | "dense" | "loose" | (string & {});
3709
+ }
3710
+ type InputKeyFilter = string | RegExp | ((nextValue: string, ctx: {
3711
+ event: any;
3712
+ currentValue: string;
3713
+ input: HTMLInputElement;
3714
+ }) => boolean);
3715
+ interface InputKeyFilterProps {
3716
+ /**
3717
+ * Filter that constrains what can be typed / pasted.
3718
+ *
3719
+ * - string preset: "int" | "num" | "money" | "hex" | "alpha" | "alphanum" | "email"
3720
+ * - string pattern: converted to new RegExp(pattern)
3721
+ * - RegExp: used directly
3722
+ * - function: custom validator
3723
+ */
3724
+ keyFilter?: InputKeyFilter;
3725
+ /**
3726
+ * Which keyboard event to hook for filtering:
3727
+ * - "keydown"
3728
+ * - "keypress" (closest to PrimeReact default)
3729
+ * - "beforeinput"
3730
+ *
3731
+ * Default: "keypress"
3732
+ */
3733
+ keyFilterOn?: "keydown" | "keypress" | "beforeinput";
3734
+ /**
3735
+ * Whether to apply keyFilter to paste events.
3736
+ * Default: true
3737
+ */
3738
+ keyFilterOnPaste?: boolean;
3739
+ }
3740
+ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">, InputMaskProps, InputAffixProps, InputIconControlProps, InputSizeProps, InputKeyFilterProps {
3741
+ }
3742
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
3743
+
3744
+ export { AdapterKey, AdapterResult, AdapterSubmit, type BaseProps$7 as BaseProps, type ButtonRef, type CoreContext, type CoreProps, CoreProvider, type CoreShellProps, type DescriptionPlacement, type Dict, type EffectiveFieldLayout, type ErrorBag, type ErrorBagMapResult, ErrorStrip, type ErrorStripProps, type ErrorTextPlacement, type Field, type FieldLayoutConfig, type FieldOrdering, type FieldRootId, type FieldRoots, type FieldSlotId, type FieldSlots, CoreShell as Form, type FormProps, CoreRoot as FormRoot, type HelpTextPlacement, type InferFromSchema, Input, InputField, type InputFieldBaseProps, type InputFieldProps, InputMask, InputNumber, type InputStore, type LabelPlacement, type LayoutResolveContext, type LayoutResolver, Method, type RelativeRootsMap, type SlotPlacement, type SublabelPlacement, type SubmitEvent, Textarea, type UseButtonOptions, type UseButtonReturn, type UseFieldOptions, type UseFieldReturn, type UseFieldValidate, type ValidateResult, type ValuesResult, type VariantEntry, type VariantKey, type VariantLayoutDefaults, type VariantModule, type VariantModuleFor, type VariantPropsFor, type VariantValidateFn, type VariantValueFor, type Variants, type ZodErrorMapResult, getVariant, listVariants, mapErrorBag, mapZodError, registerCoreVariants, registerVariant, useButton, useCore, useCoreContext, useField, useOptionalField };