@uniform-ts/core 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1122 -0
- package/dist/index.d.mts +857 -0
- package/dist/index.d.ts +857 -0
- package/dist/index.js +1633 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1592 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,857 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { FieldValues, FieldPath, FieldPathValue, RefCallBack, Control } from 'react-hook-form';
|
|
3
|
+
import * as z from 'zod/v4/core';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extracts the element type of an array type.
|
|
8
|
+
* e.g. `ArrayItem<{ name: string }[]>` → `{ name: string }`
|
|
9
|
+
*/
|
|
10
|
+
type ArrayItem<T> = T extends (infer U)[] ? U : never;
|
|
11
|
+
/**
|
|
12
|
+
* Recursively produces all valid `fields` prop keys for a given schema shape:
|
|
13
|
+
*
|
|
14
|
+
* - Scalar fields → just their key (e.g. `"name"`)
|
|
15
|
+
* - Object fields → their key + all dot-notated child paths
|
|
16
|
+
* (e.g. `"address"` | `"address.street"`)
|
|
17
|
+
* - Array fields → their key + the unprefixed keys of the item object, so
|
|
18
|
+
* you can target every row's sub-field uniformly
|
|
19
|
+
* (e.g. `"items"` | `"items.name"` | `"items.qty"`)
|
|
20
|
+
* Index-based paths like `"items.0.name"` are intentionally
|
|
21
|
+
* excluded — row count is dynamic at runtime.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Given { name: string; address: { street: string }; items: { qty: number }[] }
|
|
25
|
+
* // DeepKeys produces:
|
|
26
|
+
* // "name" | "address" | "address.street" | "items" | "items.qty"
|
|
27
|
+
*/
|
|
28
|
+
type DeepKeys<T> = T extends object ? {
|
|
29
|
+
[K in keyof T & string]: T[K] extends unknown[] ? ArrayItem<T[K]> extends object ? K | `${K}.${DeepKeys<ArrayItem<T[K]>>}` : K : T[K] extends object ? K | `${K}.${DeepKeys<T[K]>}` : K;
|
|
30
|
+
}[keyof T & string] : never;
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the value type at a dot-notated path within a type `T`.
|
|
33
|
+
* Array fields use the unprefixed child path (matching `DeepKeys` convention).
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // DeepFieldValue<{ name: string; items: { qty: number }[] }, 'items.qty'> → number
|
|
37
|
+
*/
|
|
38
|
+
type DeepFieldValue<T, K extends string> = K extends keyof T ? T[K] : K extends `${infer Head}.${infer Tail}` ? Head extends keyof T ? T[Head] extends (infer Item)[] ? DeepFieldValue<NonNullable<Item>, Tail> : DeepFieldValue<NonNullable<T[Head]>, Tail> : unknown : unknown;
|
|
39
|
+
/**
|
|
40
|
+
* The resolved primitive or structural type of a schema field, as determined
|
|
41
|
+
* by introspecting the Zod schema. Used internally to decide which field
|
|
42
|
+
* component to render.
|
|
43
|
+
*/
|
|
44
|
+
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'select' | 'object' | 'array' | 'union' | 'unknown';
|
|
45
|
+
/**
|
|
46
|
+
* A single option entry used in `select` / enum fields.
|
|
47
|
+
*/
|
|
48
|
+
type SelectOption = {
|
|
49
|
+
/** Human-readable text displayed in the dropdown. */
|
|
50
|
+
label: string;
|
|
51
|
+
/** The underlying value submitted with the form. */
|
|
52
|
+
value: string | number;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* A predicate function that receives the current form values and returns
|
|
56
|
+
* `true` when the field should be visible, `false` when it should be hidden.
|
|
57
|
+
*
|
|
58
|
+
* @template TValues - The shape of the form values object.
|
|
59
|
+
*/
|
|
60
|
+
type FieldCondition<TValues = Record<string, unknown>> = (values: TValues) => boolean;
|
|
61
|
+
/**
|
|
62
|
+
* All programmatic form control methods, shared by both the field `onChange`
|
|
63
|
+
* callback and the imperative ref handle.
|
|
64
|
+
*
|
|
65
|
+
* @template TSchema - The Zod object schema that defines the form shape.
|
|
66
|
+
*/
|
|
67
|
+
type FormMethods<TValues extends FieldValues = FieldValues> = {
|
|
68
|
+
/** Set a single field value programmatically */
|
|
69
|
+
setValue: <K extends FieldPath<TValues>>(name: K, value: FieldPathValue<TValues, K>) => void;
|
|
70
|
+
/** Set multiple field values at once */
|
|
71
|
+
setValues: (values: Partial<TValues>) => void;
|
|
72
|
+
/** Get the current form values */
|
|
73
|
+
getValues: () => TValues;
|
|
74
|
+
/** Reset a single field to its default value */
|
|
75
|
+
resetField: (name: FieldPath<TValues>) => void;
|
|
76
|
+
/** Reset the entire form, optionally to new values */
|
|
77
|
+
reset: (values?: Partial<TValues>) => void;
|
|
78
|
+
/** Set a validation error on a specific field */
|
|
79
|
+
setError: (name: FieldPath<TValues>, message: string) => void;
|
|
80
|
+
/** Set validation errors on multiple fields at once */
|
|
81
|
+
setErrors: (errors: Partial<Record<FieldPath<TValues>, string>>) => void;
|
|
82
|
+
/** Clear validation errors (all fields, or specific ones) */
|
|
83
|
+
clearErrors: (names?: FieldPath<TValues> | FieldPath<TValues>[]) => void;
|
|
84
|
+
/** Programmatically trigger form submission */
|
|
85
|
+
submit: () => void;
|
|
86
|
+
/** Focus a specific field by name (dot-notated for nested fields) */
|
|
87
|
+
focus: (fieldName: FieldPath<TValues>) => void;
|
|
88
|
+
/** Get the current value of a field (or all values if no name provided) */
|
|
89
|
+
watch: {
|
|
90
|
+
(): TValues;
|
|
91
|
+
<K extends FieldPath<TValues>>(name: K): FieldPathValue<TValues, K>;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Dynamic field property overrides passed to `ctx.setFieldMeta()` inside a
|
|
96
|
+
* UniForm onChange handler. Each key is optional — only the properties you
|
|
97
|
+
* provide will be applied; omitted keys leave the current field state unchanged.
|
|
98
|
+
*/
|
|
99
|
+
type FieldDependencyResult = {
|
|
100
|
+
/** Override the available options for select fields */
|
|
101
|
+
options?: SelectOption[];
|
|
102
|
+
/** Dynamically show or hide the field */
|
|
103
|
+
hidden?: boolean;
|
|
104
|
+
/** Dynamically enable or disable the field */
|
|
105
|
+
disabled?: boolean;
|
|
106
|
+
/** Override the field label */
|
|
107
|
+
label?: string;
|
|
108
|
+
/** Override the placeholder text */
|
|
109
|
+
placeholder?: string;
|
|
110
|
+
/** Override the description text */
|
|
111
|
+
description?: string;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* The base set of per-field UI metadata that can be provided via the `fields`
|
|
115
|
+
* prop or through Zod schema extensions (`.meta()`).
|
|
116
|
+
*
|
|
117
|
+
* `FieldMeta` extends this type with an index signature to allow arbitrary
|
|
118
|
+
* extra keys for custom component use-cases.
|
|
119
|
+
*/
|
|
120
|
+
type FieldMetaBase = {
|
|
121
|
+
/** Human-readable label rendered above the field. Falls back to a derived label from the field name. */
|
|
122
|
+
label?: string;
|
|
123
|
+
/** Placeholder text rendered inside the input when it has no value. */
|
|
124
|
+
placeholder?: string;
|
|
125
|
+
/** Helper text rendered below the field to provide additional context. */
|
|
126
|
+
description?: string;
|
|
127
|
+
/** Static list of options for `select` / enum fields. */
|
|
128
|
+
options?: SelectOption[];
|
|
129
|
+
/** Group the field under a named section in the form layout. */
|
|
130
|
+
section?: string;
|
|
131
|
+
/** Explicit render order within the form or section (lower numbers render first). */
|
|
132
|
+
order?: number;
|
|
133
|
+
/** Grid column span for multi-column layouts (e.g. `1`–`12`). */
|
|
134
|
+
span?: number;
|
|
135
|
+
/** When `true`, the field is not rendered. */
|
|
136
|
+
hidden?: boolean;
|
|
137
|
+
/** When `true`, the field is rendered but not interactive. */
|
|
138
|
+
disabled?: boolean;
|
|
139
|
+
/** Conditionally show or hide the field based on the current form values. */
|
|
140
|
+
condition?: FieldCondition;
|
|
141
|
+
/**
|
|
142
|
+
* Override the component used to render this field.
|
|
143
|
+
*
|
|
144
|
+
* - **string** — a key registered in the `ComponentRegistry` (e.g. `'autocomplete'`
|
|
145
|
+
* registered via `createAutoForm({ components: { autocomplete: MyComp } })` or the
|
|
146
|
+
* `components` prop).
|
|
147
|
+
* - **React component** — a `FieldProps`-compatible component passed inline,
|
|
148
|
+
* bypassing the registry entirely (e.g. `component: MyCustomInput`).
|
|
149
|
+
*
|
|
150
|
+
* Note: typed as `React.ComponentType<any>` here to avoid a circular type
|
|
151
|
+
* reference through `FieldProps → FieldMeta → component → FieldProps`.
|
|
152
|
+
* The `ComponentRegistry` keeps the stricter `React.ComponentType<FieldProps>`.
|
|
153
|
+
*/
|
|
154
|
+
component?: string | React.ComponentType<any>;
|
|
155
|
+
/** Called when this field's value changes. Receives the new value and form control methods. May be async. */
|
|
156
|
+
onChange?: (value: unknown, form: FormMethods) => void | Promise<void>;
|
|
157
|
+
/** When `true`, rows in an array field can be reordered via move-up/move-down buttons. */
|
|
158
|
+
movable?: boolean;
|
|
159
|
+
/** When `true`, rows in an array field can be duplicated. */
|
|
160
|
+
duplicable?: boolean;
|
|
161
|
+
/** When `true`, rows in an array field can be individually collapsed. */
|
|
162
|
+
collapsible?: boolean;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Per-field UI metadata with an open index signature, allowing arbitrary
|
|
166
|
+
* extra keys for custom component use-cases. Extends `FieldMetaBase` with
|
|
167
|
+
* all the standard metadata properties.
|
|
168
|
+
*/
|
|
169
|
+
type FieldMeta = FieldMetaBase & {
|
|
170
|
+
[key: string]: unknown;
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Common properties shared by every field variant.
|
|
174
|
+
*/
|
|
175
|
+
type FieldConfigBase = {
|
|
176
|
+
/** Dot-notated field path (e.g. `"address.street"`). */
|
|
177
|
+
name: string;
|
|
178
|
+
/** Display label for the field. */
|
|
179
|
+
label: string;
|
|
180
|
+
/** Whether the field is required by the schema. */
|
|
181
|
+
required: boolean;
|
|
182
|
+
/** Merged UI metadata for the field. */
|
|
183
|
+
meta: FieldMeta;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The fully resolved configuration for a single form field, produced by
|
|
187
|
+
* introspecting the Zod schema and merging any `fields` prop overrides.
|
|
188
|
+
* Consumed internally by field renderer components.
|
|
189
|
+
*
|
|
190
|
+
* This is a discriminated union on the `type` field — narrow on `type` to
|
|
191
|
+
* access the fields that are only present for specific field kinds (e.g.
|
|
192
|
+
* `children` for `"object"`, `itemConfig` for `"array"`, etc.).
|
|
193
|
+
*/
|
|
194
|
+
type FieldConfig = FieldConfigBase & ({
|
|
195
|
+
type: 'string';
|
|
196
|
+
} | {
|
|
197
|
+
type: 'number';
|
|
198
|
+
} | {
|
|
199
|
+
type: 'boolean';
|
|
200
|
+
} | {
|
|
201
|
+
type: 'date';
|
|
202
|
+
} | {
|
|
203
|
+
type: 'select';
|
|
204
|
+
/** Resolved options for `select` / enum fields. */
|
|
205
|
+
options: SelectOption[];
|
|
206
|
+
} | {
|
|
207
|
+
type: 'object';
|
|
208
|
+
/** Child field configs for nested object fields. */
|
|
209
|
+
children: FieldConfig[];
|
|
210
|
+
} | {
|
|
211
|
+
type: 'array';
|
|
212
|
+
/** Item field config describing a single row's shape. */
|
|
213
|
+
itemConfig: FieldConfig;
|
|
214
|
+
/** Minimum number of items (from `z.array().min(...)`). */
|
|
215
|
+
minItems?: number;
|
|
216
|
+
/** Maximum number of items (from `z.array().max(...)`). */
|
|
217
|
+
maxItems?: number;
|
|
218
|
+
} | {
|
|
219
|
+
type: 'union';
|
|
220
|
+
/** Variant configs for each union member. */
|
|
221
|
+
unionVariants: FieldConfig[];
|
|
222
|
+
/** Discriminator key for discriminated unions. */
|
|
223
|
+
discriminatorKey?: string;
|
|
224
|
+
} | {
|
|
225
|
+
type: 'unknown';
|
|
226
|
+
});
|
|
227
|
+
/**
|
|
228
|
+
* The props passed to every field renderer component. Provides the current
|
|
229
|
+
* value, change/blur handlers, and all resolved UI metadata needed to render
|
|
230
|
+
* a single field.
|
|
231
|
+
*/
|
|
232
|
+
type FieldProps = {
|
|
233
|
+
/** Dot-notated field path (e.g. `"address.street"`). */
|
|
234
|
+
name: string;
|
|
235
|
+
/** The current field value. */
|
|
236
|
+
value: unknown;
|
|
237
|
+
/** Callback to update the field value. */
|
|
238
|
+
onChange: (value: unknown) => void;
|
|
239
|
+
/** Callback fired when the field loses focus. */
|
|
240
|
+
onBlur: () => void;
|
|
241
|
+
/** Ref callback for registering the DOM element with `react-hook-form`. */
|
|
242
|
+
ref: RefCallBack;
|
|
243
|
+
/** Resolved display label for the field. */
|
|
244
|
+
label: string;
|
|
245
|
+
/** Placeholder text for the input. */
|
|
246
|
+
placeholder?: string;
|
|
247
|
+
/** Helper text rendered below the field. */
|
|
248
|
+
description?: string;
|
|
249
|
+
/** Validation error message for the field. */
|
|
250
|
+
error?: string;
|
|
251
|
+
/** Whether the field is required by the schema. */
|
|
252
|
+
required: boolean;
|
|
253
|
+
/** When `true`, the field is rendered but not interactive. */
|
|
254
|
+
disabled?: boolean;
|
|
255
|
+
/** Resolved options for `select` / enum fields. */
|
|
256
|
+
options?: SelectOption[];
|
|
257
|
+
/** Full field metadata, including any custom keys. */
|
|
258
|
+
meta: FieldMeta;
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* A map of field type keys to React components used to render them.
|
|
262
|
+
* Built-in keys (`string`, `number`, `boolean`, `date`, `select`, `textarea`)
|
|
263
|
+
* are pre-typed. Additional custom keys can be added via the index signature
|
|
264
|
+
* and registered through `createAutoForm` or the `components` prop.
|
|
265
|
+
*/
|
|
266
|
+
type ComponentRegistry = {
|
|
267
|
+
string?: React.ComponentType<FieldProps>;
|
|
268
|
+
number?: React.ComponentType<FieldProps>;
|
|
269
|
+
boolean?: React.ComponentType<FieldProps>;
|
|
270
|
+
date?: React.ComponentType<FieldProps>;
|
|
271
|
+
select?: React.ComponentType<FieldProps>;
|
|
272
|
+
textarea?: React.ComponentType<FieldProps>;
|
|
273
|
+
[key: string]: React.ComponentType<FieldProps> | undefined;
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* Props passed to the field wrapper component that surrounds every rendered
|
|
277
|
+
* field. Used to render the label, description, error message, and grid span.
|
|
278
|
+
*/
|
|
279
|
+
type FieldWrapperProps = {
|
|
280
|
+
/** The field input component to wrap. */
|
|
281
|
+
children: React.ReactNode;
|
|
282
|
+
/** The fully resolved field configuration. */
|
|
283
|
+
field: FieldConfig;
|
|
284
|
+
/** Validation error message for the field. */
|
|
285
|
+
error?: string;
|
|
286
|
+
/** Grid column span override (takes precedence over `field.meta.span`). */
|
|
287
|
+
span?: number;
|
|
288
|
+
/**
|
|
289
|
+
* Zero-based render index of this field within its parent container
|
|
290
|
+
* (form root or section). Exposed as the `--field-index` CSS custom property.
|
|
291
|
+
*/
|
|
292
|
+
index?: number;
|
|
293
|
+
/**
|
|
294
|
+
* Nesting depth of this field (0 = top-level, 1 = inside object, etc.).
|
|
295
|
+
* Exposed as the `--field-depth` CSS custom property.
|
|
296
|
+
*/
|
|
297
|
+
depth?: number;
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* Props passed to the component that renders a single row inside an array field,
|
|
301
|
+
* including the row's content and action buttons (move, duplicate, remove, collapse).
|
|
302
|
+
*/
|
|
303
|
+
type ArrayRowLayoutProps = {
|
|
304
|
+
/** The rendered fields for this array item. */
|
|
305
|
+
children: React.ReactNode;
|
|
306
|
+
/** Action button nodes for the row. */
|
|
307
|
+
buttons: {
|
|
308
|
+
/** Button to move the row up, or `null` if already first. */
|
|
309
|
+
moveUp: React.ReactNode | null;
|
|
310
|
+
/** Button to move the row down, or `null` if already last. */
|
|
311
|
+
moveDown: React.ReactNode | null;
|
|
312
|
+
/** Button to duplicate the row, or `null` if at max items. */
|
|
313
|
+
duplicate: React.ReactNode | null;
|
|
314
|
+
/** Button to remove the row. */
|
|
315
|
+
remove: React.ReactNode;
|
|
316
|
+
/** Button to collapse/expand the row, or `null` if collapsing is disabled. */
|
|
317
|
+
collapse: React.ReactNode | null;
|
|
318
|
+
};
|
|
319
|
+
/** Zero-based index of this row within the array. */
|
|
320
|
+
index: number;
|
|
321
|
+
/** Total number of rows currently in the array. */
|
|
322
|
+
rowCount: number;
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* Optional layout slot overrides for top-level structural components of the
|
|
326
|
+
* form. Provide only the slots you want to replace; omitted slots fall back
|
|
327
|
+
* to the built-in defaults.
|
|
328
|
+
*/
|
|
329
|
+
type LayoutSlots = {
|
|
330
|
+
/** Wrapper rendered around the entire form. */
|
|
331
|
+
formWrapper?: React.ComponentType<{
|
|
332
|
+
children: React.ReactNode;
|
|
333
|
+
}>;
|
|
334
|
+
/** Wrapper rendered around each named field section. */
|
|
335
|
+
sectionWrapper?: React.ComponentType<{
|
|
336
|
+
children: React.ReactNode;
|
|
337
|
+
title: string;
|
|
338
|
+
}>;
|
|
339
|
+
/** Custom submit button component. */
|
|
340
|
+
submitButton?: React.ComponentType<{
|
|
341
|
+
isSubmitting: boolean;
|
|
342
|
+
label: string;
|
|
343
|
+
}>;
|
|
344
|
+
/** Custom layout component for individual rows in array fields. */
|
|
345
|
+
arrayRowLayout?: React.ComponentType<ArrayRowLayoutProps>;
|
|
346
|
+
/**
|
|
347
|
+
* Content rendered while async `defaultValues` are loading.
|
|
348
|
+
* Defaults to a simple `<p>Loading…</p>` when not provided.
|
|
349
|
+
*/
|
|
350
|
+
loadingFallback?: React.ReactNode;
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* The resolved version of `LayoutSlots` used internally, where all slots are
|
|
354
|
+
* guaranteed to be defined (falling back to built-in defaults).
|
|
355
|
+
*/
|
|
356
|
+
type ResolvedLayoutSlots = {
|
|
357
|
+
formWrapper: React.ComponentType<{
|
|
358
|
+
children: React.ReactNode;
|
|
359
|
+
}>;
|
|
360
|
+
sectionWrapper: React.ComponentType<{
|
|
361
|
+
children: React.ReactNode;
|
|
362
|
+
title: string;
|
|
363
|
+
}>;
|
|
364
|
+
submitButton: React.ComponentType<{
|
|
365
|
+
isSubmitting: boolean;
|
|
366
|
+
label: string;
|
|
367
|
+
}>;
|
|
368
|
+
arrayRowLayout: React.ComponentType<ArrayRowLayoutProps>;
|
|
369
|
+
loadingFallback: React.ReactNode;
|
|
370
|
+
};
|
|
371
|
+
/**
|
|
372
|
+
* CSS class name overrides for the various structural elements of the form.
|
|
373
|
+
* Only the keys you provide will be applied; omitted keys use the built-in
|
|
374
|
+
* default class names (or none, if the default components don't apply any).
|
|
375
|
+
*/
|
|
376
|
+
type FormClassNames = {
|
|
377
|
+
/** Class applied to the `<form>` element. */
|
|
378
|
+
form?: string;
|
|
379
|
+
/** Class applied to each field wrapper. */
|
|
380
|
+
fieldWrapper?: string;
|
|
381
|
+
/** Class applied to each field label. */
|
|
382
|
+
label?: string;
|
|
383
|
+
/** Class applied to each field description. */
|
|
384
|
+
description?: string;
|
|
385
|
+
/** Class applied to each field error message. */
|
|
386
|
+
error?: string;
|
|
387
|
+
/** Class applied to the "add item" button in array fields. */
|
|
388
|
+
arrayAdd?: string;
|
|
389
|
+
/** Class applied to the "remove item" button in array fields. */
|
|
390
|
+
arrayRemove?: string;
|
|
391
|
+
/** Class applied to the "move item" buttons in array fields. */
|
|
392
|
+
arrayMove?: string;
|
|
393
|
+
/** Class applied to the "duplicate item" button in array fields. */
|
|
394
|
+
arrayDuplicate?: string;
|
|
395
|
+
/** Class applied to the "collapse item" button in array fields. */
|
|
396
|
+
arrayCollapse?: string;
|
|
397
|
+
};
|
|
398
|
+
/**
|
|
399
|
+
* A per-field override entry used in the AutoFormProps `fields` prop.
|
|
400
|
+
* The `onChange` callback is typed to the specific schema's inferred value
|
|
401
|
+
* type, providing full IDE autocomplete.
|
|
402
|
+
*/
|
|
403
|
+
type FieldOverride<TSchema extends z.$ZodObject = z.$ZodObject, TValue = unknown> = Partial<FieldMetaBase> & {
|
|
404
|
+
/** Conditionally show or hide the field based on the current form values. */
|
|
405
|
+
condition?: FieldCondition<z.infer<TSchema>>;
|
|
406
|
+
/** Called when this field's value changes. Receives the new value and form control methods. May be async. */
|
|
407
|
+
onChange?: (value: TValue, form: FormMethods<z.infer<TSchema>>) => void | Promise<void>;
|
|
408
|
+
[key: string]: unknown;
|
|
409
|
+
};
|
|
410
|
+
type FormLabels = {
|
|
411
|
+
/** Submit button text — default: "Submit" */
|
|
412
|
+
submit?: string;
|
|
413
|
+
/** Array "Add item" button — default: "Add" */
|
|
414
|
+
arrayAdd?: string;
|
|
415
|
+
/** Array "Remove row" button — default: "Remove" */
|
|
416
|
+
arrayRemove?: string;
|
|
417
|
+
/** Array "Move row up" button — default: "↑" */
|
|
418
|
+
arrayMoveUp?: string;
|
|
419
|
+
/** Array "Move row down" button — default: "↓" */
|
|
420
|
+
arrayMoveDown?: string;
|
|
421
|
+
/** Array "Duplicate row" button — default: "Duplicate" */
|
|
422
|
+
arrayDuplicate?: string;
|
|
423
|
+
/** Array row toggle shown when the row is expanded (clicking collapses it) — default: "▼" */
|
|
424
|
+
arrayCollapse?: string;
|
|
425
|
+
/** Array row toggle shown when the row is collapsed (clicking expands it) — default: "▶" */
|
|
426
|
+
arrayExpand?: string;
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* A map of field names to coercion functions. Each function receives the raw
|
|
430
|
+
* field value and returns the coerced value before Zod validation is applied.
|
|
431
|
+
* Useful for transforming string inputs (e.g. from native `<input>`) into the
|
|
432
|
+
* types expected by the schema (e.g. numbers, dates).
|
|
433
|
+
*/
|
|
434
|
+
type CoercionMap$1 = Record<string, (value: unknown) => unknown>;
|
|
435
|
+
/**
|
|
436
|
+
* Custom validation error message overrides. Use `required` to override the
|
|
437
|
+
* global "required field" message, or provide a field name key to override
|
|
438
|
+
* messages for a specific field (supports nested dot-notated paths).
|
|
439
|
+
*/
|
|
440
|
+
type ValidationMessages = {
|
|
441
|
+
required?: string;
|
|
442
|
+
[fieldName: string]: string | Record<string, string> | undefined;
|
|
443
|
+
};
|
|
444
|
+
/**
|
|
445
|
+
* A minimal storage adapter interface compatible with `localStorage` and
|
|
446
|
+
* `sessionStorage`. Provide a custom implementation to persist form values
|
|
447
|
+
* to any backing store (e.g. IndexedDB, AsyncStorage).
|
|
448
|
+
*/
|
|
449
|
+
type PersistStorage = {
|
|
450
|
+
getItem: (key: string) => string | null;
|
|
451
|
+
setItem: (key: string, value: string) => void;
|
|
452
|
+
removeItem: (key: string) => void;
|
|
453
|
+
};
|
|
454
|
+
/**
|
|
455
|
+
* The imperative handle exposed via `ref` on `<AutoForm>`. Provides methods
|
|
456
|
+
* to programmatically control the form from a parent component.
|
|
457
|
+
*
|
|
458
|
+
* @template TSchema - The Zod object schema that defines the form shape.
|
|
459
|
+
*/
|
|
460
|
+
type AutoFormHandle<TSchema extends z.$ZodObject = z.$ZodObject> = FormMethods<z.infer<TSchema>> & {
|
|
461
|
+
/** `true` while an async `onSubmit` handler is in flight. */
|
|
462
|
+
isSubmitting: boolean;
|
|
463
|
+
};
|
|
464
|
+
/**
|
|
465
|
+
* Static configuration provided to `createAutoForm`. These options become the
|
|
466
|
+
* default for every form instance created by the factory, and can be
|
|
467
|
+
* overridden per-instance via the corresponding `<AutoForm>` props.
|
|
468
|
+
*/
|
|
469
|
+
type AutoFormConfig = {
|
|
470
|
+
/** Default component registry for all form instances. */
|
|
471
|
+
components?: ComponentRegistry;
|
|
472
|
+
/** Default field wrapper component for all form instances. */
|
|
473
|
+
fieldWrapper?: React.ComponentType<FieldWrapperProps>;
|
|
474
|
+
/** Default layout slot overrides for all form instances. */
|
|
475
|
+
layout?: LayoutSlots;
|
|
476
|
+
/** Default CSS class name overrides for all form instances. */
|
|
477
|
+
classNames?: FormClassNames;
|
|
478
|
+
/** When `true`, all fields in every form instance are disabled by default. */
|
|
479
|
+
disabled?: boolean;
|
|
480
|
+
/** Default coercion map applied to all form instances. */
|
|
481
|
+
coercions?: CoercionMap$1;
|
|
482
|
+
/** Default validation message overrides for all form instances. */
|
|
483
|
+
messages?: ValidationMessages;
|
|
484
|
+
/** Default label strings; overridden per-instance by the `labels` prop */
|
|
485
|
+
labels?: FormLabels;
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* Props for the `<AutoForm>` component. Drives schema introspection, field
|
|
489
|
+
* rendering, validation, and submission.
|
|
490
|
+
*
|
|
491
|
+
* @template TSchema - The Zod object schema that defines the form shape.
|
|
492
|
+
*/
|
|
493
|
+
type AutoFormProps<TSchema extends z.$ZodObject> = {
|
|
494
|
+
/** A UniForm instance carrying the schema and typed onChange handlers. */
|
|
495
|
+
form: {
|
|
496
|
+
readonly schema: TSchema;
|
|
497
|
+
};
|
|
498
|
+
/** Called with the validated form values when the form is submitted successfully. */
|
|
499
|
+
onSubmit: (values: z.infer<TSchema>) => void | Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* Initial values to pre-populate the form with.
|
|
502
|
+
* When an async function is provided, the form shows `loadingFallback` until the
|
|
503
|
+
* promise resolves, then resets the form with the loaded values.
|
|
504
|
+
*/
|
|
505
|
+
defaultValues?: Partial<z.infer<TSchema>> | (() => Promise<Partial<z.infer<TSchema>>>);
|
|
506
|
+
/** Component registry overrides for this form instance. */
|
|
507
|
+
components?: ComponentRegistry;
|
|
508
|
+
/** Per-field UI metadata overrides (label, placeholder, options, etc.). */
|
|
509
|
+
fields?: {
|
|
510
|
+
[K in DeepKeys<z.infer<TSchema>>]?: FieldOverride<TSchema, DeepFieldValue<z.infer<TSchema>, K>>;
|
|
511
|
+
};
|
|
512
|
+
/** Field wrapper component override for this form instance. */
|
|
513
|
+
fieldWrapper?: React.ComponentType<FieldWrapperProps>;
|
|
514
|
+
/** Layout slot overrides for this form instance. */
|
|
515
|
+
layout?: LayoutSlots;
|
|
516
|
+
/** CSS class name overrides for this form instance. */
|
|
517
|
+
classNames?: FormClassNames;
|
|
518
|
+
/** When `true`, all fields are rendered in a disabled (non-interactive) state. */
|
|
519
|
+
disabled?: boolean;
|
|
520
|
+
/** Coercion map applied before Zod validation for this form instance. */
|
|
521
|
+
coercions?: CoercionMap$1;
|
|
522
|
+
/** Validation message overrides for this form instance. */
|
|
523
|
+
messages?: ValidationMessages;
|
|
524
|
+
/** When set, form values are auto-saved to storage under this key */
|
|
525
|
+
persistKey?: string;
|
|
526
|
+
/** Debounce interval in ms for persistence writes (default: 300) */
|
|
527
|
+
persistDebounce?: number;
|
|
528
|
+
/** Custom storage adapter (default: localStorage) */
|
|
529
|
+
persistStorage?: PersistStorage;
|
|
530
|
+
/** Called on every value change with the current form values */
|
|
531
|
+
onValuesChange?: (values: z.infer<TSchema>) => void;
|
|
532
|
+
/** Customize hard-coded UI text (submit button, array buttons, etc.) */
|
|
533
|
+
labels?: FormLabels;
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
// zod@3.25+ — import from 'zod/v4'
|
|
537
|
+
declare module 'zod/v4/core' {
|
|
538
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
539
|
+
interface GlobalMeta extends FieldMetaBase {}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// zod@4.x — import from 'zod'
|
|
543
|
+
declare module 'zod' {
|
|
544
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
545
|
+
interface GlobalMeta extends FieldMetaBase {}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Recursively introspects a Zod schema and returns a {@link FieldConfig}
|
|
550
|
+
* describing the field's type, label, validation constraints, and UI metadata.
|
|
551
|
+
*
|
|
552
|
+
* Transparent wrappers (`optional`, `nullable`, `default`, `pipe`) are
|
|
553
|
+
* unwrapped before inspection. Unknown/unsupported types fall back to
|
|
554
|
+
* `type: 'unknown'` rather than throwing.
|
|
555
|
+
*
|
|
556
|
+
* @param schema - The Zod schema to introspect.
|
|
557
|
+
* @param name - The field key within its parent object (used for label derivation).
|
|
558
|
+
* @param parentPath - The dot-notated path of the parent (used to build `field.name`).
|
|
559
|
+
*/
|
|
560
|
+
declare function introspectSchema(schema: z.$ZodType, name?: string, parentPath?: string): FieldConfig;
|
|
561
|
+
/**
|
|
562
|
+
* Introspects all fields of a top-level `ZodObject` schema and returns an
|
|
563
|
+
* ordered array of {@link FieldConfig} objects, one per key in `schema.shape`.
|
|
564
|
+
*
|
|
565
|
+
* This is the entry point used by `<AutoForm>` to derive the field list from
|
|
566
|
+
* the provided schema.
|
|
567
|
+
*
|
|
568
|
+
* @param schema - The top-level `ZodObject` schema to introspect.
|
|
569
|
+
*/
|
|
570
|
+
declare function introspectObjectSchema(schema: z.$ZodObject): FieldConfig[];
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* The core auto-form component. Introspects the provided Zod `schema`,
|
|
574
|
+
* renders the appropriate field components, validates on submit using
|
|
575
|
+
* `zodResolver`, and calls `onSubmit` with the fully-typed, validated values.
|
|
576
|
+
*
|
|
577
|
+
* Supports: conditional fields, dynamic field meta via UniForm onChange
|
|
578
|
+
* handlers, section grouping, form persistence, imperative handle via `ref`,
|
|
579
|
+
* and full layout/component customisation.
|
|
580
|
+
*
|
|
581
|
+
* @template TSchema - A `ZodObject` schema that defines the form shape.
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* const myForm = new UniForm(z.object({ name: z.string(), age: z.number() }))
|
|
585
|
+
*
|
|
586
|
+
* <AutoForm form={myForm} onSubmit={(values) => console.log(values)} />
|
|
587
|
+
*/
|
|
588
|
+
declare function AutoForm<TSchema extends z.$ZodObject>(props: AutoFormProps<TSchema> & {
|
|
589
|
+
ref?: React.Ref<AutoFormHandle<TSchema>>;
|
|
590
|
+
}): react_jsx_runtime.JSX.Element;
|
|
591
|
+
|
|
592
|
+
type FieldRendererProps = {
|
|
593
|
+
field: FieldConfig;
|
|
594
|
+
control: Control;
|
|
595
|
+
namePrefix?: string;
|
|
596
|
+
/** Zero-based render index within the parent container (form root / section / object). */
|
|
597
|
+
index?: number;
|
|
598
|
+
/** Nesting depth (0 = top-level, 1 = inside object, etc.). */
|
|
599
|
+
depth?: number;
|
|
600
|
+
/** When `true`, unregisters the field's value on unmount so it resets to its default when reshown.
|
|
601
|
+
* Auto-set for conditional fields; propagated to object children. */
|
|
602
|
+
shouldUnregister?: boolean;
|
|
603
|
+
};
|
|
604
|
+
/**
|
|
605
|
+
* Renders a single form field by delegating to the appropriate field component
|
|
606
|
+
* based on `field.type`. Object and array fields manage their own layout and
|
|
607
|
+
* skip the field wrapper; all other fields are wrapped in the configured
|
|
608
|
+
* `FieldWrapper` with their resolved error message.
|
|
609
|
+
*/
|
|
610
|
+
declare function FieldRenderer({ field, control, namePrefix, index, depth, shouldUnregister, }: FieldRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
611
|
+
|
|
612
|
+
declare function DefaultInput(props: FieldProps): react_jsx_runtime.JSX.Element;
|
|
613
|
+
|
|
614
|
+
declare function DefaultCheckbox(props: FieldProps): react_jsx_runtime.JSX.Element;
|
|
615
|
+
|
|
616
|
+
declare function DefaultSelect(props: FieldProps): react_jsx_runtime.JSX.Element;
|
|
617
|
+
|
|
618
|
+
declare function DefaultFieldWrapper({ children, field, error, span, index, depth, }: FieldWrapperProps): react_jsx_runtime.JSX.Element;
|
|
619
|
+
|
|
620
|
+
type DefaultSubmitButtonProps = {
|
|
621
|
+
isSubmitting: boolean;
|
|
622
|
+
};
|
|
623
|
+
declare function DefaultSubmitButton({ isSubmitting, }: DefaultSubmitButtonProps): react_jsx_runtime.JSX.Element;
|
|
624
|
+
|
|
625
|
+
declare const defaultRegistry: ComponentRegistry;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Merges two {@link ComponentRegistry} objects, with `overrides` taking
|
|
629
|
+
* precedence over `base` for any keys that appear in both.
|
|
630
|
+
*
|
|
631
|
+
* Returns `base` unchanged when `overrides` is `undefined`.
|
|
632
|
+
*
|
|
633
|
+
* @param base - The default registry (typically the factory-level registry).
|
|
634
|
+
* @param overrides - Optional per-instance registry to merge on top.
|
|
635
|
+
*/
|
|
636
|
+
declare function mergeRegistries(base: ComponentRegistry, overrides?: ComponentRegistry): ComponentRegistry;
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Factory that creates a pre-configured `<AutoForm>` component with a fixed
|
|
640
|
+
* set of defaults baked in.
|
|
641
|
+
*
|
|
642
|
+
* All options passed to `createAutoForm` become the baseline for every form
|
|
643
|
+
* instance produced by the returned component. Any prop passed directly to the
|
|
644
|
+
* returned component is **deep-merged** on top of those defaults (instance
|
|
645
|
+
* props win on conflicts).
|
|
646
|
+
*
|
|
647
|
+
* Merged items: `components`, `layout`, `classNames`, `coercions`, `messages`.
|
|
648
|
+
* Replaced items: `fieldWrapper`, `disabled` (OR-ed with the factory default).
|
|
649
|
+
*
|
|
650
|
+
* @param config - Factory-level defaults applied to every form instance.
|
|
651
|
+
* @returns A `<AutoForm>`-compatible component with the provided defaults applied.
|
|
652
|
+
*
|
|
653
|
+
* @example
|
|
654
|
+
* const AutoForm = createAutoForm({
|
|
655
|
+
* components: { string: MyTextInput },
|
|
656
|
+
* classNames: { form: 'my-form' },
|
|
657
|
+
* })
|
|
658
|
+
*
|
|
659
|
+
* // Later:
|
|
660
|
+
* <AutoForm form={myUniForm} onSubmit={handleSubmit} />
|
|
661
|
+
*/
|
|
662
|
+
declare function createAutoForm(config: AutoFormConfig): {
|
|
663
|
+
<TSchema extends z.$ZodObject>(props: AutoFormProps<TSchema> & {
|
|
664
|
+
ref?: React.Ref<AutoFormHandle<TSchema>>;
|
|
665
|
+
}): react_jsx_runtime.JSX.Element;
|
|
666
|
+
displayName: string;
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
type CoercionMap = Record<string, (value: unknown) => unknown>;
|
|
670
|
+
/**
|
|
671
|
+
* Built-in coercion functions for the primitive field types. Each function
|
|
672
|
+
* converts the raw string value that comes from an HTML `<input>` into the
|
|
673
|
+
* type expected by the Zod schema before validation is applied.
|
|
674
|
+
*
|
|
675
|
+
* - `number` — converts to `Number`; returns `undefined` for empty/null inputs.
|
|
676
|
+
* - `date` — converts to `Date`; returns `undefined` for empty/null inputs.
|
|
677
|
+
* - `boolean` — converts to `Boolean`.
|
|
678
|
+
* - `string` — converts `null` / `undefined` to `''`, otherwise `String(value)`.
|
|
679
|
+
*/
|
|
680
|
+
declare const defaultCoercionMap: CoercionMap;
|
|
681
|
+
/**
|
|
682
|
+
* Coerces `value` to the type expected by `type`, using `customCoercions` first
|
|
683
|
+
* and falling back to {@link defaultCoercionMap}.
|
|
684
|
+
*
|
|
685
|
+
* Returns the value unchanged when no coercion function is found for the given type.
|
|
686
|
+
*
|
|
687
|
+
* @param type - The field type string (e.g. `'number'`, `'date'`).
|
|
688
|
+
* @param value - The raw value to coerce.
|
|
689
|
+
* @param customCoercions - Optional per-instance overrides that take precedence
|
|
690
|
+
* over the built-in coercion map.
|
|
691
|
+
*/
|
|
692
|
+
declare function coerceValue(type: string, value: unknown, customCoercions?: CoercionMap): unknown;
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Context passed to UniForm `setOnChange` handlers. Extends `FormMethods` with
|
|
696
|
+
* `setFieldMeta`, which lets handlers dynamically override per-field UI
|
|
697
|
+
* properties (hidden, disabled, options, label, etc.).
|
|
698
|
+
*
|
|
699
|
+
* @template TSchema - The Zod object schema that defines the form shape.
|
|
700
|
+
*/
|
|
701
|
+
type UniFormContext<TSchema extends z.$ZodObject = z.$ZodObject> = FormMethods<z.infer<TSchema>> & {
|
|
702
|
+
/**
|
|
703
|
+
* Dynamically override per-field UI metadata from inside a setOnChange handler.
|
|
704
|
+
* Changes are applied synchronously and trigger a re-render.
|
|
705
|
+
*
|
|
706
|
+
* Meta keys are stored and merged into the rendered field config.
|
|
707
|
+
*/
|
|
708
|
+
setFieldMeta: <K extends DeepKeys<z.infer<TSchema>>>(field: K, meta: Partial<FieldDependencyResult>) => void;
|
|
709
|
+
};
|
|
710
|
+
type Handler<TSchema extends z.$ZodObject, TValue> = (value: TValue, ctx: UniFormContext<TSchema>) => void | Promise<void>;
|
|
711
|
+
type Condition<TSchema extends z.$ZodObject> = (values: z.infer<TSchema>) => boolean;
|
|
712
|
+
/**
|
|
713
|
+
* A type-safe form definition that lives outside React components.
|
|
714
|
+
* Wraps a Zod schema and lets you attach typed `setOnChange` callbacks that fire
|
|
715
|
+
* whenever a specific field's value changes.
|
|
716
|
+
*
|
|
717
|
+
* Callbacks receive the new field value (typed to the schema) and a
|
|
718
|
+
* `UniFormContext` that provides all standard form methods plus `setFieldMeta`
|
|
719
|
+
* for dynamic field overrides.
|
|
720
|
+
*
|
|
721
|
+
* @template TSchema - The Zod object schema that defines the form shape.
|
|
722
|
+
* @template TRegistered - Union of field keys that already have a `setOnChange`
|
|
723
|
+
* handler registered. Attempting to call `setOnChange` for a key in this set
|
|
724
|
+
* produces a compile-time error, preventing silent handler replacement.
|
|
725
|
+
*
|
|
726
|
+
* @example
|
|
727
|
+
* const addressForm = new UniForm(addressSchema)
|
|
728
|
+
* .setOnChange('country', (value, ctx) => {
|
|
729
|
+
* ctx.setFieldMeta('state', { hidden: value !== 'US' })
|
|
730
|
+
* })
|
|
731
|
+
*
|
|
732
|
+
* // In component:
|
|
733
|
+
* <AutoForm form={addressForm} onSubmit={handleSubmit} />
|
|
734
|
+
*/
|
|
735
|
+
declare class UniForm<TSchema extends z.$ZodObject, TRegistered extends string = never> {
|
|
736
|
+
readonly schema: TSchema;
|
|
737
|
+
private readonly _handlers;
|
|
738
|
+
private readonly _conditions;
|
|
739
|
+
constructor(schema: TSchema);
|
|
740
|
+
/**
|
|
741
|
+
* Set the typed onChange handler for a specific field.
|
|
742
|
+
* Replaces any previously registered handler for that field — only one
|
|
743
|
+
* handler per field is kept. This prevents accidental handler accumulation
|
|
744
|
+
* when called inside a React render cycle.
|
|
745
|
+
* Returns `this` for fluent chaining.
|
|
746
|
+
*/
|
|
747
|
+
setOnChange<K extends Exclude<DeepKeys<z.infer<TSchema>>, TRegistered>>(field: K, handler: Handler<TSchema, DeepFieldValue<z.infer<TSchema>, K>>): UniForm<TSchema, TRegistered | K>;
|
|
748
|
+
/**
|
|
749
|
+
* Attach a typed condition for a specific field.
|
|
750
|
+
* The field is shown when the predicate returns `true`, hidden when `false`.
|
|
751
|
+
* Composes with any `condition` set via the `fields` prop (UniForm takes precedence).
|
|
752
|
+
* Returns `this` for fluent chaining.
|
|
753
|
+
*/
|
|
754
|
+
setCondition<K extends DeepKeys<z.infer<TSchema>>>(field: K, predicate: Condition<TSchema>): this;
|
|
755
|
+
/** @internal Called by AutoForm to fire the handler registered for a field. */
|
|
756
|
+
_fireHandler(field: string, value: unknown, ctx: UniFormContext<TSchema>): void | Promise<void>;
|
|
757
|
+
/** @internal Returns all field names that have registered onChange handlers. */
|
|
758
|
+
_getWatchedFields(): string[];
|
|
759
|
+
/** @internal Returns a copy of the conditions map for AutoForm to inject into field meta. */
|
|
760
|
+
_getConditions(): Map<string, Condition<TSchema>>;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Creates a new `UniForm` instance for the given Zod object schema.
|
|
764
|
+
*/
|
|
765
|
+
declare function createForm<TSchema extends z.$ZodObject>(schema: TSchema): UniForm<TSchema>;
|
|
766
|
+
/**
|
|
767
|
+
* Creates a `UniForm` directly from a `z.discriminatedUnion` schema.
|
|
768
|
+
*
|
|
769
|
+
* `AutoForm` automatically flattens the variant fields and attaches show/hide
|
|
770
|
+
* conditions based on the discriminator value — no manual `.condition()` calls
|
|
771
|
+
* needed. The union schema is used by `zodResolver` for strict per-variant
|
|
772
|
+
* validation on submit.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* const notificationForm = createForm(
|
|
776
|
+
* z.discriminatedUnion('channel', [
|
|
777
|
+
* z.object({ channel: z.literal('email'), email: z.string().email() }),
|
|
778
|
+
* z.object({ channel: z.literal('sms'), phone: z.string() }),
|
|
779
|
+
* ])
|
|
780
|
+
* )
|
|
781
|
+
*/
|
|
782
|
+
declare function createForm(schema: z.$ZodDiscriminatedUnion): UniForm<z.$ZodObject>;
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Filters and sorts a list of field configs based on the current form values.
|
|
786
|
+
*
|
|
787
|
+
* - Fields with `meta.hidden === true` are always excluded.
|
|
788
|
+
* - Fields with a `meta.condition` function are included only when the
|
|
789
|
+
* function returns `true` for the current values.
|
|
790
|
+
* - Remaining fields are sorted ascending by `meta.order` (fields without an
|
|
791
|
+
* order appear last).
|
|
792
|
+
*
|
|
793
|
+
* Re-evaluates reactively whenever the watched form values change.
|
|
794
|
+
*
|
|
795
|
+
* @param fields - The full list of field configs to filter and sort.
|
|
796
|
+
* @param control - The RHF `control` object from the parent form.
|
|
797
|
+
* @returns The filtered and ordered subset of `fields`.
|
|
798
|
+
*/
|
|
799
|
+
declare function useConditionalFields(fields: FieldConfig[], control: Control): FieldConfig[];
|
|
800
|
+
|
|
801
|
+
type SectionGroup = {
|
|
802
|
+
title: string | null;
|
|
803
|
+
fields: FieldConfig[];
|
|
804
|
+
};
|
|
805
|
+
/**
|
|
806
|
+
* Groups a flat list of field configs into ordered section groups based on
|
|
807
|
+
* each field's `meta.section` value.
|
|
808
|
+
*
|
|
809
|
+
* - Fields without a `meta.section` (or with a non-string value) are placed
|
|
810
|
+
* in an "ungrouped" section with `title: null`, rendered first.
|
|
811
|
+
* - Named sections appear in the order their first member is encountered.
|
|
812
|
+
* - The returned array is memoized and only recomputed when `fields` changes.
|
|
813
|
+
*
|
|
814
|
+
* @param fields - The ordered list of (already filtered/sorted) field configs.
|
|
815
|
+
* @returns An array of {@link SectionGroup} objects ready to be rendered.
|
|
816
|
+
*/
|
|
817
|
+
declare function useSectionGrouping(fields: FieldConfig[]): SectionGroup[];
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* Persists form values to a storage adapter and restores them on mount.
|
|
821
|
+
*
|
|
822
|
+
* - On mount, reads `key` from `storage` and calls `reset` with the merged
|
|
823
|
+
* stored + default values, so the form starts with any previously saved data.
|
|
824
|
+
* - On every value change, writes the current form values to `storage` after a
|
|
825
|
+
* `debounceMs` delay to avoid thrashing the storage layer.
|
|
826
|
+
* - When `key` is `undefined`, persistence is entirely disabled.
|
|
827
|
+
* - Falls back to `sessionStorage` when no custom `storage` adapter is provided.
|
|
828
|
+
*
|
|
829
|
+
* @returns An object with `clearPersistedData` — call this after a successful
|
|
830
|
+
* submission to remove the persisted draft.
|
|
831
|
+
*/
|
|
832
|
+
declare function useFormPersistence(options: {
|
|
833
|
+
control: Control;
|
|
834
|
+
key: string | undefined;
|
|
835
|
+
debounceMs: number;
|
|
836
|
+
storage?: PersistStorage;
|
|
837
|
+
reset: (values: Record<string, unknown>) => void;
|
|
838
|
+
defaultValues: Record<string, unknown>;
|
|
839
|
+
}): {
|
|
840
|
+
clearPersistedData: () => void;
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
type AutoFormContextValue = {
|
|
844
|
+
registry: ComponentRegistry;
|
|
845
|
+
fieldOverrides: Record<string, unknown>;
|
|
846
|
+
fieldWrapper: React.ComponentType<FieldWrapperProps>;
|
|
847
|
+
layout: ResolvedLayoutSlots;
|
|
848
|
+
classNames: FormClassNames;
|
|
849
|
+
disabled: boolean;
|
|
850
|
+
coercions?: CoercionMap$1;
|
|
851
|
+
messages?: ValidationMessages;
|
|
852
|
+
labels: FormLabels;
|
|
853
|
+
formMethods: FormMethods;
|
|
854
|
+
};
|
|
855
|
+
declare function useAutoFormContext(): AutoFormContextValue;
|
|
856
|
+
|
|
857
|
+
export { type ArrayRowLayoutProps, AutoForm, type AutoFormConfig, type AutoFormContextValue, type AutoFormHandle, type AutoFormProps, type CoercionMap$1 as CoercionMap, type ComponentRegistry, DefaultCheckbox, DefaultFieldWrapper, DefaultInput, DefaultSelect, DefaultSubmitButton, type FieldCondition, type FieldConfig, type FieldDependencyResult, type FieldMeta, type FieldMetaBase, type FieldOverride, type FieldProps, FieldRenderer, type FieldType, type FieldWrapperProps, type FormClassNames, type FormLabels, type FormMethods, type LayoutSlots, type PersistStorage, type ResolvedLayoutSlots, type SectionGroup, type SelectOption, UniForm, type UniFormContext, type ValidationMessages, coerceValue, createAutoForm, createForm, defaultCoercionMap, defaultRegistry, introspectObjectSchema, introspectSchema, mergeRegistries, useAutoFormContext, useConditionalFields, useFormPersistence, useSectionGrouping };
|