@classytic/formkit 1.3.1 → 1.4.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/CHANGELOG.md +12 -0
- package/README.md +31 -12
- package/dist/index.d.mts +447 -161
- package/dist/index.mjs +665 -179
- package/dist/server.d.mts +393 -150
- package/dist/server.mjs +385 -92
- package/package.json +115 -113
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ import { ClassValue } from "clsx";
|
|
|
8
8
|
* Field type identifier.
|
|
9
9
|
* Can be built-in types or custom string identifiers.
|
|
10
10
|
*/
|
|
11
|
-
type FieldType = "text" | "email" | "password" | "number" | "tel" | "url" | "textarea" | "select" | "checkbox" | "radio" | "switch" | "date" | "time" | "datetime" | "file" | "hidden" | "group" | "array" | "custom" | (string & {});
|
|
11
|
+
type FieldType = "text" | "email" | "password" | "number" | "tel" | "phone" | "url" | "textarea" | "slug" | "select" | "combobox" | "multiselect" | "dependentSelect" | "checkbox" | "radio" | "switch" | "date" | "time" | "datetime" | "rich-text" | "color" | "rating" | "tags" | "json" | "file" | "hidden" | "group" | "array" | "custom" | (string & {});
|
|
12
12
|
/**
|
|
13
13
|
* Layout type identifier.
|
|
14
14
|
*/
|
|
@@ -70,12 +70,55 @@ interface FieldOptionGroup<TValue = string> {
|
|
|
70
70
|
/** Whether group is disabled */
|
|
71
71
|
disabled?: boolean;
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Object form for length/range validation rules with a custom message.
|
|
75
|
+
*/
|
|
76
|
+
interface ValidationRuleObject<TValue = number> {
|
|
77
|
+
value: TValue;
|
|
78
|
+
message: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Object form for pattern validation with a custom message.
|
|
82
|
+
*/
|
|
83
|
+
interface PatternRuleObject {
|
|
84
|
+
/** Regex string (will be compiled with `new RegExp(regex)`) */
|
|
85
|
+
regex: string;
|
|
86
|
+
/** Custom error message */
|
|
87
|
+
message: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* AI-friendly metadata attached to any field.
|
|
91
|
+
* Consumed by LLM coding assistants, documentation generators, and
|
|
92
|
+
* schema-introspection tools — never by the form renderer itself.
|
|
93
|
+
*/
|
|
94
|
+
interface FieldMeta {
|
|
95
|
+
/** Human-readable description of what this field collects */
|
|
96
|
+
description?: string;
|
|
97
|
+
/** Representative example value (for documentation / AI context) */
|
|
98
|
+
example?: unknown;
|
|
99
|
+
/** Logical category for grouping fields in documentation or tooling */
|
|
100
|
+
category?: string;
|
|
101
|
+
/** Arbitrary tags for filtering, search, or feature-flagging */
|
|
102
|
+
tags?: string[];
|
|
103
|
+
/** Whether this field is considered PII */
|
|
104
|
+
pii?: boolean;
|
|
105
|
+
/** Arbitrary extension point — anything extra you want to carry */
|
|
106
|
+
[key: string]: unknown;
|
|
107
|
+
}
|
|
73
108
|
/**
|
|
74
109
|
* Base field configuration shared by all field types.
|
|
75
110
|
* @template TFieldValues - Form field values type for type-safe field names
|
|
76
111
|
*/
|
|
77
112
|
interface BaseField<TFieldValues extends FieldValues = FieldValues> {
|
|
78
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Field name — a path into TFieldValues (e.g. `"email"`, `"address.street"`).
|
|
115
|
+
*
|
|
116
|
+
* Accepts any string so that:
|
|
117
|
+
* - Namespaced sections can use relative names (`"street"` → prefixed to `"address.street"`)
|
|
118
|
+
* - Group/array `itemFields` can use relative names (`"email"` → prefixed at render time)
|
|
119
|
+
*
|
|
120
|
+
* Use `field.for<T>()` builder for call-site enforcement that names are valid paths.
|
|
121
|
+
*/
|
|
79
122
|
name: Path<TFieldValues> | (string & {});
|
|
80
123
|
/** Field type identifier */
|
|
81
124
|
type: FieldType;
|
|
@@ -106,18 +149,41 @@ interface BaseField<TFieldValues extends FieldValues = FieldValues> {
|
|
|
106
149
|
defaultValue?: unknown;
|
|
107
150
|
/** Options for select/radio/checkbox fields */
|
|
108
151
|
options?: (FieldOption | FieldOptionGroup)[];
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Minimum value (for number/date fields).
|
|
154
|
+
* Pass an object `{ value, message }` to provide a custom error message.
|
|
155
|
+
*/
|
|
156
|
+
min?: number | string | ValidationRuleObject<number | string>;
|
|
157
|
+
/**
|
|
158
|
+
* Maximum value (for number/date fields).
|
|
159
|
+
* Pass an object `{ value, message }` to provide a custom error message.
|
|
160
|
+
*/
|
|
161
|
+
max?: number | string | ValidationRuleObject<number | string>;
|
|
113
162
|
/** Step value (for number fields) */
|
|
114
163
|
step?: number;
|
|
115
|
-
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Pattern for validation.
|
|
166
|
+
* Pass a regex string or `{ regex, message }` for a custom error message.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* // simple
|
|
171
|
+
* pattern: "^[a-z]+$"
|
|
172
|
+
* // with custom message
|
|
173
|
+
* pattern: { regex: "^[a-z]+$", message: "Only lowercase letters allowed" }
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
pattern?: string | PatternRuleObject;
|
|
177
|
+
/**
|
|
178
|
+
* Minimum length.
|
|
179
|
+
* Pass an object `{ value, message }` to provide a custom error message.
|
|
180
|
+
*/
|
|
181
|
+
minLength?: number | ValidationRuleObject<number>;
|
|
182
|
+
/**
|
|
183
|
+
* Maximum length.
|
|
184
|
+
* Pass an object `{ value, message }` to provide a custom error message.
|
|
185
|
+
*/
|
|
186
|
+
maxLength?: number | ValidationRuleObject<number>;
|
|
121
187
|
/** Number of rows (for textarea) */
|
|
122
188
|
rows?: number;
|
|
123
189
|
/** Multiple selection (for select/file) */
|
|
@@ -141,10 +207,13 @@ interface BaseField<TFieldValues extends FieldValues = FieldValues> {
|
|
|
141
207
|
*/
|
|
142
208
|
onLoadError?: (error: unknown) => void;
|
|
143
209
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
210
|
+
* Sub-fields for `group` and `array` field types.
|
|
211
|
+
*
|
|
212
|
+
* These fields use **relative** names (`"street"`, `"email"`) — FormGenerator
|
|
213
|
+
* prefixes them with the parent field name at render time (`"address.street"`).
|
|
214
|
+
* They are intentionally untyped to TFieldValues for this reason.
|
|
146
215
|
*/
|
|
147
|
-
itemFields?: BaseField
|
|
216
|
+
itemFields?: BaseField[];
|
|
148
217
|
/**
|
|
149
218
|
* Custom render function to override the component registry for this specific field.
|
|
150
219
|
* Completely bypasses the globally registered FieldComponent for this type.
|
|
@@ -153,15 +222,22 @@ interface BaseField<TFieldValues extends FieldValues = FieldValues> {
|
|
|
153
222
|
/**
|
|
154
223
|
* Cross-field validation function.
|
|
155
224
|
* Receives the field value and all form values for cross-field checks.
|
|
156
|
-
* Return `true` for valid,
|
|
225
|
+
* Return `true` for valid, a string error message for invalid, or a Promise of either
|
|
226
|
+
* for async validation (e.g., checking server-side uniqueness).
|
|
157
227
|
*
|
|
158
228
|
* @example
|
|
159
229
|
* ```ts
|
|
160
230
|
* validate: (value, formValues) =>
|
|
161
231
|
* value > formValues.minPrice || "Must be greater than min price"
|
|
232
|
+
*
|
|
233
|
+
* // Async example
|
|
234
|
+
* validate: async (value) => {
|
|
235
|
+
* const taken = await checkUsernameAvailability(value as string);
|
|
236
|
+
* return taken ? "Username already taken" : true;
|
|
237
|
+
* }
|
|
162
238
|
* ```
|
|
163
239
|
*/
|
|
164
|
-
validate?: (value: unknown, formValues: Partial<TFieldValues>) => string | true
|
|
240
|
+
validate?: (value: unknown, formValues: Partial<TFieldValues>) => string | true | Promise<string | true>;
|
|
165
241
|
/**
|
|
166
242
|
* Dependencies for optimizing conditionally rendered fields.
|
|
167
243
|
* Allows specifying specific field names to watch, preventing full form re-renders.
|
|
@@ -169,6 +245,32 @@ interface BaseField<TFieldValues extends FieldValues = FieldValues> {
|
|
|
169
245
|
watchNames?: Path<TFieldValues> | Path<TFieldValues>[];
|
|
170
246
|
/** Additional field-specific props for custom components */
|
|
171
247
|
customProps?: Record<string, unknown>;
|
|
248
|
+
/**
|
|
249
|
+
* AI / agent-friendly metadata for this field.
|
|
250
|
+
*
|
|
251
|
+
* Provides hints that help LLM coding assistants generate correct field
|
|
252
|
+
* configs without needing to inspect the schema at runtime.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* field.text("companyName", "Company", {
|
|
257
|
+
* meta: {
|
|
258
|
+
* description: "Legal entity name of the organization",
|
|
259
|
+
* example: "Acme Corp",
|
|
260
|
+
* category: "identity",
|
|
261
|
+
* tags: ["crm", "required-for-billing"],
|
|
262
|
+
* }
|
|
263
|
+
* })
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
meta?: FieldMeta;
|
|
267
|
+
/**
|
|
268
|
+
* Escape hatch for adapter-specific or custom props.
|
|
269
|
+
* Allows passing arbitrary props directly on the field object so they
|
|
270
|
+
* flow through the adapter spread (`{...field}`) without needing `customProps`.
|
|
271
|
+
* Intentionally broad to support diverse UI component libraries.
|
|
272
|
+
*/
|
|
273
|
+
[key: string]: unknown;
|
|
172
274
|
}
|
|
173
275
|
/**
|
|
174
276
|
* Props passed to field components.
|
|
@@ -214,13 +316,68 @@ interface FieldComponentProps<TFieldValues extends FieldValues = FieldValues> ex
|
|
|
214
316
|
invalid: boolean;
|
|
215
317
|
isDirty: boolean;
|
|
216
318
|
isTouched: boolean;
|
|
217
|
-
isValidating: boolean;
|
|
319
|
+
isValidating: boolean; /** True after the enclosing form's submit handler has been called at least once. */
|
|
320
|
+
isSubmitted: boolean;
|
|
218
321
|
error?: FieldError;
|
|
219
322
|
};
|
|
220
|
-
/**
|
|
323
|
+
/**
|
|
324
|
+
* Generated field ID for label-input association (e.g. `formkit-field-email`).
|
|
325
|
+
* Use as `id` on the input element and `htmlFor` on the `<label>`.
|
|
326
|
+
*/
|
|
221
327
|
fieldId: string;
|
|
328
|
+
/**
|
|
329
|
+
* Generated error container ID for ARIA association (e.g. `formkit-field-email-error`).
|
|
330
|
+
* Use as `id` on the error message element and as the value for `aria-errormessage`
|
|
331
|
+
* (preferred) or `aria-describedby` (broader support) on the input.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```tsx
|
|
335
|
+
* <input
|
|
336
|
+
* id={fieldId}
|
|
337
|
+
* aria-invalid={shouldShowError || undefined}
|
|
338
|
+
* aria-errormessage={shouldShowError ? errorId : undefined}
|
|
339
|
+
* />
|
|
340
|
+
* <p id={errorId} role="alert" aria-live="polite">
|
|
341
|
+
* {shouldShowError ? error?.message : null}
|
|
342
|
+
* </p>
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
errorId: string;
|
|
346
|
+
/**
|
|
347
|
+
* Whether to display the field error right now.
|
|
348
|
+
*
|
|
349
|
+
* Aligns with the CSS `:user-invalid` timing model: `true` only after the
|
|
350
|
+
* user has interacted with the field (blur) **or** the form has been
|
|
351
|
+
* submitted. This prevents premature "required" errors on untouched fields.
|
|
352
|
+
*
|
|
353
|
+
* Use this — not `!!error` — to drive `aria-invalid`, error message
|
|
354
|
+
* visibility, and destructive ring/border styles.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```tsx
|
|
358
|
+
* <input aria-invalid={shouldShowError || undefined} />
|
|
359
|
+
* {shouldShowError && <p id={errorId} role="alert">{error?.message}</p>}
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
shouldShowError: boolean;
|
|
222
363
|
/** Whether dynamic options are currently loading */
|
|
223
364
|
isLoading?: boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Pre-computed react-hook-form validation rules for this field.
|
|
367
|
+
* Equivalent to calling `buildValidationRules(field)` — provided here so
|
|
368
|
+
* adapter components can pass `rules={rules}` directly to `<Controller>`
|
|
369
|
+
* without importing or calling `buildValidationRules` themselves.
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```tsx
|
|
373
|
+
* function TextInput({ field, control, rules }: FieldComponentProps) {
|
|
374
|
+
* return (
|
|
375
|
+
* <Controller name={field.name} control={control} rules={rules} render={...} />
|
|
376
|
+
* );
|
|
377
|
+
* }
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
rules: ValidationRules;
|
|
224
381
|
}
|
|
225
382
|
/**
|
|
226
383
|
* Field component type.
|
|
@@ -271,6 +428,17 @@ interface Section<TFieldValues extends FieldValues = FieldValues> {
|
|
|
271
428
|
collapsible?: boolean;
|
|
272
429
|
/** Default collapsed state */
|
|
273
430
|
defaultCollapsed?: boolean;
|
|
431
|
+
/**
|
|
432
|
+
* Defer rendering of this section until it scrolls near the viewport.
|
|
433
|
+
* Applies `content-visibility: auto` + `contain-intrinsic-size` to the
|
|
434
|
+
* section container, skipping layout/paint work while off-screen.
|
|
435
|
+
*
|
|
436
|
+
* **Only use for sections that are below the initial fold.** Applying this
|
|
437
|
+
* to above-fold sections has no benefit and slightly increases overhead.
|
|
438
|
+
*
|
|
439
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility
|
|
440
|
+
*/
|
|
441
|
+
deferRender?: boolean;
|
|
274
442
|
}
|
|
275
443
|
/**
|
|
276
444
|
* Props passed to section render function.
|
|
@@ -298,6 +466,12 @@ interface SectionLayoutProps {
|
|
|
298
466
|
collapsible?: boolean;
|
|
299
467
|
/** Default collapsed state */
|
|
300
468
|
defaultCollapsed?: boolean;
|
|
469
|
+
/**
|
|
470
|
+
* When true the section is below the initial fold and should defer
|
|
471
|
+
* browser layout/paint work until it nears the viewport.
|
|
472
|
+
* Layout components may apply `content-visibility: auto` here.
|
|
473
|
+
*/
|
|
474
|
+
deferRender?: boolean;
|
|
301
475
|
/** Children content */
|
|
302
476
|
children: ReactNode;
|
|
303
477
|
}
|
|
@@ -336,6 +510,12 @@ type LayoutComponent<TProps extends LayoutComponentProps = LayoutComponentProps>
|
|
|
336
510
|
* @template TFieldValues - Form field values type for type-safe schemas
|
|
337
511
|
*/
|
|
338
512
|
interface FormSchema<TFieldValues extends FieldValues = FieldValues> {
|
|
513
|
+
/** Optional schema identifier — useful for serialization, analytics, and AI context */
|
|
514
|
+
id?: string;
|
|
515
|
+
/** Human-readable form title (AI / documentation use) */
|
|
516
|
+
title?: string;
|
|
517
|
+
/** Human-readable description of the form's purpose */
|
|
518
|
+
description?: string;
|
|
339
519
|
/** Form sections */
|
|
340
520
|
sections: Section<TFieldValues>[];
|
|
341
521
|
}
|
|
@@ -462,10 +642,12 @@ interface SectionRendererProps<TFieldValues extends FieldValues = FieldValues> {
|
|
|
462
642
|
disabled?: boolean;
|
|
463
643
|
variant?: Variant;
|
|
464
644
|
}
|
|
645
|
+
declare function SectionRendererImpl<TFieldValues extends FieldValues = FieldValues>(props: SectionRendererProps<TFieldValues>): FormElement;
|
|
465
646
|
/**
|
|
466
|
-
*
|
|
647
|
+
* Memoized section renderer. Re-renders only when section config or
|
|
648
|
+
* disabled/variant context changes — not on every form value change.
|
|
467
649
|
*/
|
|
468
|
-
declare
|
|
650
|
+
declare const SectionRenderer: typeof SectionRendererImpl;
|
|
469
651
|
interface GridRendererProps<TFieldValues extends FieldValues = FieldValues> {
|
|
470
652
|
fields?: BaseField<TFieldValues>[];
|
|
471
653
|
cols?: number;
|
|
@@ -474,10 +656,7 @@ interface GridRendererProps<TFieldValues extends FieldValues = FieldValues> {
|
|
|
474
656
|
disabled?: boolean;
|
|
475
657
|
variant?: Variant;
|
|
476
658
|
}
|
|
477
|
-
|
|
478
|
-
* Renders a grid of fields with specified column layout.
|
|
479
|
-
*/
|
|
480
|
-
declare function GridRenderer<TFieldValues extends FieldValues = FieldValues>({
|
|
659
|
+
declare function GridRendererImpl<TFieldValues extends FieldValues = FieldValues>({
|
|
481
660
|
fields,
|
|
482
661
|
cols,
|
|
483
662
|
gap,
|
|
@@ -485,18 +664,22 @@ declare function GridRenderer<TFieldValues extends FieldValues = FieldValues>({
|
|
|
485
664
|
disabled,
|
|
486
665
|
variant
|
|
487
666
|
}: GridRendererProps<TFieldValues>): FormElement;
|
|
667
|
+
/**
|
|
668
|
+
* Memoized grid renderer.
|
|
669
|
+
*/
|
|
670
|
+
declare const GridRenderer: typeof GridRendererImpl;
|
|
488
671
|
interface FieldWrapperProps<TFieldValues extends FieldValues = FieldValues> {
|
|
489
672
|
field: BaseField<TFieldValues>;
|
|
490
673
|
control?: Control<TFieldValues>;
|
|
491
674
|
disabled?: boolean;
|
|
492
675
|
variant?: Variant;
|
|
493
676
|
}
|
|
677
|
+
declare function FieldWrapperImpl<TFieldValues extends FieldValues = FieldValues>(props: FieldWrapperProps<TFieldValues>): FormElement;
|
|
494
678
|
/**
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
* Otherwise, it uses the Static wrapper, vastly improving performance by skipping `useWatch`.
|
|
679
|
+
* Memoized field wrapper — the dispatch layer between schema fields and
|
|
680
|
+
* their renderer. Re-renders only when the field config itself changes.
|
|
498
681
|
*/
|
|
499
|
-
declare
|
|
682
|
+
declare const FieldWrapper: typeof FieldWrapperImpl;
|
|
500
683
|
//#endregion
|
|
501
684
|
//#region src/FormSystemContext.d.ts
|
|
502
685
|
/**
|
|
@@ -645,6 +828,7 @@ declare function defineSection<TFieldValues extends FieldValues = FieldValues>(s
|
|
|
645
828
|
/**
|
|
646
829
|
* Extracts default values from a form schema.
|
|
647
830
|
* Walks all sections and fields, respecting nameSpace prefixes and group nesting.
|
|
831
|
+
* Array fields default to `[]` when no explicit `defaultValue` is provided.
|
|
648
832
|
*
|
|
649
833
|
* @example
|
|
650
834
|
* ```ts
|
|
@@ -653,11 +837,30 @@ declare function defineSection<TFieldValues extends FieldValues = FieldValues>(s
|
|
|
653
837
|
* ```
|
|
654
838
|
*/
|
|
655
839
|
declare function extractDefaultValues<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>): Partial<TFieldValues>;
|
|
840
|
+
/**
|
|
841
|
+
* Async version of `extractDefaultValues` for large schemas (50+ fields).
|
|
842
|
+
* Yields to the main thread after each section so that the browser can
|
|
843
|
+
* handle input events between chunks — keeping INP scores low.
|
|
844
|
+
*
|
|
845
|
+
* Use in `getDefaultValues` passed to `useForm` when the schema is known
|
|
846
|
+
* to be large:
|
|
847
|
+
*
|
|
848
|
+
* @example
|
|
849
|
+
* ```ts
|
|
850
|
+
* const form = useForm({
|
|
851
|
+
* defaultValues: async () => extractDefaultValuesAsync(schema),
|
|
852
|
+
* });
|
|
853
|
+
* ```
|
|
854
|
+
*/
|
|
855
|
+
declare function extractDefaultValuesAsync<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>): Promise<Partial<TFieldValues>>;
|
|
656
856
|
/**
|
|
657
857
|
* Generates react-hook-form `RegisterOptions`-compatible validation rules
|
|
658
858
|
* from a field's schema props. Maps `required`, `min`, `max`, `minLength`,
|
|
659
859
|
* `maxLength`, `pattern`, and `validate` to RHF rules.
|
|
660
860
|
*
|
|
861
|
+
* Supports both shorthand scalars and `{ value, message }` objects for all
|
|
862
|
+
* numeric/length rules, and `{ regex, message }` for pattern.
|
|
863
|
+
*
|
|
661
864
|
* @example
|
|
662
865
|
* ```tsx
|
|
663
866
|
* import { buildValidationRules } from '@classytic/formkit';
|
|
@@ -669,155 +872,171 @@ declare function extractDefaultValues<TFieldValues extends FieldValues = FieldVa
|
|
|
669
872
|
* ```
|
|
670
873
|
*/
|
|
671
874
|
declare function buildValidationRules<TFieldValues extends FieldValues = FieldValues>(field: BaseField<TFieldValues>): ValidationRules;
|
|
875
|
+
/** Returns true for fields that carry an `options` array (select, radio, etc.) */
|
|
876
|
+
declare function isChoiceField(field: BaseField): boolean;
|
|
877
|
+
/** Returns true for free-text input fields */
|
|
878
|
+
declare function isTextField(field: BaseField): boolean;
|
|
879
|
+
/** Returns true for numeric input fields */
|
|
880
|
+
declare function isNumericField(field: BaseField): boolean;
|
|
881
|
+
/** Returns true for date / time fields */
|
|
882
|
+
declare function isDateField(field: BaseField): boolean;
|
|
883
|
+
/** Returns true for structural fields that contain sub-fields (`itemFields`) */
|
|
884
|
+
declare function isContainerField(field: BaseField): boolean;
|
|
885
|
+
/** Returns true for array fields that render a repeatable list */
|
|
886
|
+
declare function isArrayField(field: BaseField): boolean;
|
|
887
|
+
/** Returns true for fields that load options asynchronously */
|
|
888
|
+
declare function isDynamicField(field: BaseField): boolean;
|
|
889
|
+
/** Returns true for fields with conditional rendering */
|
|
890
|
+
declare function isConditionalField(field: BaseField): boolean;
|
|
891
|
+
/**
|
|
892
|
+
* Merge two or more schemas into one, concatenating their sections.
|
|
893
|
+
*
|
|
894
|
+
* @example
|
|
895
|
+
* ```ts
|
|
896
|
+
* const full = mergeSchemas(personalSchema, addressSchema, billingSchema);
|
|
897
|
+
* ```
|
|
898
|
+
*/
|
|
899
|
+
declare function mergeSchemas<TFieldValues extends FieldValues = FieldValues>(...schemas: FormSchema<TFieldValues>[]): FormSchema<TFieldValues>;
|
|
900
|
+
/**
|
|
901
|
+
* Add fields to a section identified by `sectionId`.
|
|
902
|
+
* Returns a new schema — the original is not mutated.
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* ```ts
|
|
906
|
+
* const extended = extendSection(schema, "personal", [
|
|
907
|
+
* field.text("middleName", "Middle Name"),
|
|
908
|
+
* ]);
|
|
909
|
+
* ```
|
|
910
|
+
*/
|
|
911
|
+
declare function extendSection<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>, sectionId: string, fields: BaseField<TFieldValues>[], position?: "start" | "end"): FormSchema<TFieldValues>;
|
|
912
|
+
/**
|
|
913
|
+
* Create a new schema that includes only the named fields.
|
|
914
|
+
*
|
|
915
|
+
* @example
|
|
916
|
+
* ```ts
|
|
917
|
+
* const slim = pickFields(schema, ["email", "password"]);
|
|
918
|
+
* ```
|
|
919
|
+
*/
|
|
920
|
+
declare function pickFields<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>, names: string[]): FormSchema<TFieldValues>;
|
|
921
|
+
/**
|
|
922
|
+
* Create a new schema that excludes the named fields.
|
|
923
|
+
*
|
|
924
|
+
* @example
|
|
925
|
+
* ```ts
|
|
926
|
+
* const withoutInternal = omitFields(schema, ["__id", "__createdAt"]);
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
declare function omitFields<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>, names: string[]): FormSchema<TFieldValues>;
|
|
930
|
+
/**
|
|
931
|
+
* Collect every field from every section into a flat array.
|
|
932
|
+
* Useful for validation, documentation, and AI schema introspection.
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
* ```ts
|
|
936
|
+
* const allFields = flattenSchema(schema);
|
|
937
|
+
* const required = allFields.filter(f => f.required);
|
|
938
|
+
* ```
|
|
939
|
+
*/
|
|
940
|
+
declare function flattenSchema<TFieldValues extends FieldValues = FieldValues>(schema: FormSchema<TFieldValues>): BaseField<TFieldValues>[];
|
|
941
|
+
/**
|
|
942
|
+
* Maps a server error response to react-hook-form field errors.
|
|
943
|
+
*
|
|
944
|
+
* Call this in your `onError` / `catch` handler after a failed API submission
|
|
945
|
+
* to surface per-field server-side errors using the same UX as client validation.
|
|
946
|
+
*
|
|
947
|
+
* @param form - The `useForm` return value
|
|
948
|
+
* @param errors - Map of field path → error message (dot-notation paths supported)
|
|
949
|
+
*
|
|
950
|
+
* @example
|
|
951
|
+
* ```ts
|
|
952
|
+
* async function onSubmit(data: FormValues) {
|
|
953
|
+
* try {
|
|
954
|
+
* await api.save(data);
|
|
955
|
+
* } catch (err) {
|
|
956
|
+
* if (err.fieldErrors) {
|
|
957
|
+
* applyServerErrors(form, err.fieldErrors);
|
|
958
|
+
* // { email: "Already taken", "address.zip": "Invalid ZIP" }
|
|
959
|
+
* }
|
|
960
|
+
* }
|
|
961
|
+
* }
|
|
962
|
+
* ```
|
|
963
|
+
*/
|
|
964
|
+
declare function applyServerErrors<TFieldValues extends FieldValues = FieldValues>(form: UseFormReturn<TFieldValues>, errors: Record<string, string>): void;
|
|
672
965
|
//#endregion
|
|
673
966
|
//#region src/builders.d.ts
|
|
674
967
|
/**
|
|
675
|
-
* Additional field props
|
|
968
|
+
* Additional field props accepted by builder helpers.
|
|
676
969
|
* Accepts all BaseField properties except `name`, `type`, and `label`
|
|
677
|
-
* which are
|
|
970
|
+
* which are provided by the builder method directly.
|
|
678
971
|
*/
|
|
679
|
-
type FieldProps<TFieldValues extends FieldValues = FieldValues> = Omit<BaseField<TFieldValues>, "name" | "type" | "label"
|
|
680
|
-
/** Grid column class (e.g., "col-span-2") */gridColumn?: string; /** Icon for the left side of input */
|
|
681
|
-
iconLeft?: ReactNode; /** Icon for the right side of input */
|
|
682
|
-
iconRight?: ReactNode; /** Additional custom props */
|
|
683
|
-
[key: string]: unknown;
|
|
684
|
-
};
|
|
972
|
+
type FieldProps<TFieldValues extends FieldValues = FieldValues> = Omit<BaseField<TFieldValues>, "name" | "type" | "label">;
|
|
685
973
|
/**
|
|
686
974
|
* Section configuration props.
|
|
687
975
|
*/
|
|
688
976
|
interface SectionProps<TFieldValues extends FieldValues = FieldValues> extends Omit<Section<TFieldValues>, "id" | "title" | "fields" | "cols"> {
|
|
689
977
|
cols?: number;
|
|
690
978
|
}
|
|
691
|
-
/**
|
|
692
|
-
* Render function for custom field types.
|
|
693
|
-
*/
|
|
694
|
-
type CustomRenderFn = (props: {
|
|
695
|
-
control: Control<FieldValues>;
|
|
696
|
-
disabled?: boolean;
|
|
697
|
-
error?: FieldError;
|
|
698
|
-
}) => ReactNode;
|
|
699
979
|
/**
|
|
700
980
|
* Type-safe field builder helpers for schema-driven forms.
|
|
701
981
|
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
982
|
+
* All methods are generic over TFieldValues, defaulting to FieldValues (any string)
|
|
983
|
+
* when no type argument is provided. Specify the generic to enforce that field
|
|
984
|
+
* names are valid paths in your form values type.
|
|
985
|
+
*
|
|
986
|
+
* For fully-typed schemas where every field name is checked, prefer
|
|
987
|
+
* `field.for<MyForm>()` which fixes the generic once for the whole schema:
|
|
704
988
|
*
|
|
705
989
|
* @example
|
|
706
990
|
* ```ts
|
|
707
|
-
*
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
712
|
-
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
* ]),
|
|
718
|
-
* ], { cols: 2 }),
|
|
719
|
-
* ],
|
|
720
|
-
* };
|
|
991
|
+
* // Untyped — any string accepted (backwards compatible)
|
|
992
|
+
* field.text("email", "Email")
|
|
993
|
+
*
|
|
994
|
+
* // Per-call generic — name is checked against MyForm
|
|
995
|
+
* field.text<MyForm>("email", "Email")
|
|
996
|
+
*
|
|
997
|
+
* // Typed factory — name checked on every call without repeating the generic
|
|
998
|
+
* const f = field.for<MyForm>()
|
|
999
|
+
* f.text("email", "Email") // ✓
|
|
1000
|
+
* f.text("typo", "Email") // ✗ TypeScript error
|
|
721
1001
|
* ```
|
|
722
1002
|
*/
|
|
723
1003
|
declare const field: {
|
|
724
|
-
/**
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
/**
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
/**
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
/**
|
|
745
|
-
* Number input field with min: 0 default.
|
|
746
|
-
*/
|
|
747
|
-
number: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
748
|
-
/**
|
|
749
|
-
* Textarea field with default 3 rows.
|
|
750
|
-
*/
|
|
751
|
-
textarea: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
752
|
-
/**
|
|
753
|
-
* Select dropdown field.
|
|
754
|
-
*/
|
|
755
|
-
select: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
756
|
-
/**
|
|
757
|
-
* Searchable combobox field.
|
|
758
|
-
*/
|
|
759
|
-
combobox: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
760
|
-
/**
|
|
761
|
-
* Multi-select field (tag choice).
|
|
762
|
-
*/
|
|
763
|
-
multiselect: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
764
|
-
/**
|
|
765
|
-
* Dependent select field that reacts to parent field changes.
|
|
766
|
-
*/
|
|
767
|
-
dependentSelect: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
768
|
-
/**
|
|
769
|
-
* Switch/toggle field.
|
|
770
|
-
*/
|
|
771
|
-
switch: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
772
|
-
/**
|
|
773
|
-
* Boolean field (alias for switch).
|
|
774
|
-
*/
|
|
775
|
-
boolean: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
776
|
-
/**
|
|
777
|
-
* Checkbox field.
|
|
778
|
-
*/
|
|
779
|
-
checkbox: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
780
|
-
/**
|
|
781
|
-
* Radio button group field.
|
|
782
|
-
*/
|
|
783
|
-
radio: (name: string, label: string, options: FieldOption[], props?: FieldProps) => BaseField;
|
|
784
|
-
/**
|
|
785
|
-
* Date picker field.
|
|
786
|
-
*/
|
|
787
|
-
date: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
788
|
-
/**
|
|
789
|
-
* Tag input field with default placeholder.
|
|
790
|
-
*/
|
|
791
|
-
tags: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
792
|
-
/**
|
|
793
|
-
* Slug field with auto-generation from source value.
|
|
794
|
-
*/
|
|
795
|
-
slug: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
796
|
-
/**
|
|
797
|
-
* File upload field.
|
|
798
|
-
*/
|
|
799
|
-
file: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
800
|
-
/**
|
|
801
|
-
* Hidden field (no UI).
|
|
802
|
-
*/
|
|
803
|
-
hidden: (name: string, props?: FieldProps) => BaseField;
|
|
1004
|
+
/** Text input field. */text: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Email input field with default placeholder. */
|
|
1005
|
+
email: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** URL input field with default placeholder. */
|
|
1006
|
+
url: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Phone/tel input field with default placeholder. */
|
|
1007
|
+
tel: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Password input field. */
|
|
1008
|
+
password: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Number input field with min: 0 default (overrideable via props). */
|
|
1009
|
+
number: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Textarea field with default 3 rows. */
|
|
1010
|
+
textarea: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Select dropdown field. */
|
|
1011
|
+
select: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>; /** Searchable combobox field. */
|
|
1012
|
+
combobox: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>; /** Multi-select field. */
|
|
1013
|
+
multiselect: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>; /** Dependent select field that reacts to parent field changes. */
|
|
1014
|
+
dependentSelect: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Switch/toggle field. */
|
|
1015
|
+
switch: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Boolean field (alias for switch). */
|
|
1016
|
+
boolean: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Checkbox field. */
|
|
1017
|
+
checkbox: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Radio button group field. */
|
|
1018
|
+
radio: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, options: FieldOption[], props?: FieldProps<T>) => BaseField<T>; /** Date picker field. */
|
|
1019
|
+
date: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Tag input field. */
|
|
1020
|
+
tags: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Slug field. */
|
|
1021
|
+
slug: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** File upload field. */
|
|
1022
|
+
file: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>; /** Hidden field (no UI). */
|
|
1023
|
+
hidden: <T extends FieldValues = FieldValues>(name: Path<T>, props?: FieldProps<T>) => BaseField<T>;
|
|
804
1024
|
/**
|
|
805
1025
|
* Group field for nested objects.
|
|
806
|
-
* Renders itemFields as a sub-grid
|
|
1026
|
+
* Renders itemFields as a sub-grid. Child names are relative (e.g. "street"),
|
|
1027
|
+
* FormGenerator prefixes them with the group name at render time.
|
|
807
1028
|
*
|
|
808
1029
|
* @example
|
|
809
1030
|
* ```ts
|
|
810
1031
|
* field.group("address", "Address", [
|
|
811
1032
|
* field.text("street", "Street"),
|
|
812
1033
|
* field.text("city", "City"),
|
|
813
|
-
*
|
|
814
|
-
* ], { cols: 3 })
|
|
1034
|
+
* ], { cols: 2 })
|
|
815
1035
|
* ```
|
|
816
1036
|
*/
|
|
817
|
-
group: (name:
|
|
1037
|
+
group: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, itemFields: BaseField[], props?: FieldProps<T>) => BaseField<T>;
|
|
818
1038
|
/**
|
|
819
|
-
* Array/repeatable field.
|
|
820
|
-
* Renders a dynamic list of sub-forms using react-hook-form's useFieldArray.
|
|
1039
|
+
* Array/repeatable field backed by react-hook-form's useFieldArray.
|
|
821
1040
|
*
|
|
822
1041
|
* @example
|
|
823
1042
|
* ```ts
|
|
@@ -827,42 +1046,109 @@ declare const field: {
|
|
|
827
1046
|
* ])
|
|
828
1047
|
* ```
|
|
829
1048
|
*/
|
|
830
|
-
array: (name:
|
|
1049
|
+
array: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, itemFields: BaseField[], props?: FieldProps<T>) => BaseField<T>;
|
|
831
1050
|
/**
|
|
832
1051
|
* Custom field with a render function.
|
|
833
|
-
* Bypasses the component registry
|
|
1052
|
+
* Bypasses the component registry — full control over rendering.
|
|
1053
|
+
*
|
|
1054
|
+
* The render callback receives the complete `FieldComponentProps` including
|
|
1055
|
+
* `fieldId`, `errorId`, `shouldShowError`, `error`, `rules`, and `control`.
|
|
1056
|
+
*
|
|
1057
|
+
* Use `shouldShowError` (not `!!error`) to drive `aria-invalid` and error
|
|
1058
|
+
* visibility so timing mirrors the CSS `:user-invalid` pseudo-class.
|
|
834
1059
|
*
|
|
835
1060
|
* @example
|
|
836
|
-
* ```
|
|
837
|
-
* field.custom("skills", "Skills", ({ control,
|
|
838
|
-
* <
|
|
1061
|
+
* ```tsx
|
|
1062
|
+
* field.custom("skills", "Skills", ({ control, shouldShowError, errorId, error, fieldId }) => (
|
|
1063
|
+
* <div>
|
|
1064
|
+
* <SkillSelector
|
|
1065
|
+
* id={fieldId}
|
|
1066
|
+
* control={control}
|
|
1067
|
+
* aria-invalid={shouldShowError || undefined}
|
|
1068
|
+
* aria-errormessage={shouldShowError ? errorId : undefined}
|
|
1069
|
+
* />
|
|
1070
|
+
* {shouldShowError && (
|
|
1071
|
+
* <p id={errorId} role="alert" className="text-sm text-destructive">
|
|
1072
|
+
* {error?.message}
|
|
1073
|
+
* </p>
|
|
1074
|
+
* )}
|
|
1075
|
+
* </div>
|
|
839
1076
|
* ))
|
|
840
1077
|
* ```
|
|
841
1078
|
*/
|
|
842
|
-
custom: (name:
|
|
1079
|
+
custom: <T extends FieldValues = FieldValues>(name: Path<T>, label: string, render: (props: FieldComponentProps<T>) => ReactNode, props?: FieldProps<T>) => BaseField<T>;
|
|
1080
|
+
/**
|
|
1081
|
+
* Returns a typed field builder with `TFieldValues` fixed.
|
|
1082
|
+
* Every field name is validated against `Path<TFieldValues>` at the call site —
|
|
1083
|
+
* no need to repeat the generic on each individual builder call.
|
|
1084
|
+
*
|
|
1085
|
+
* @example
|
|
1086
|
+
* ```ts
|
|
1087
|
+
* interface ContactForm {
|
|
1088
|
+
* firstName: string;
|
|
1089
|
+
* email: string;
|
|
1090
|
+
* address: { street: string; city: string };
|
|
1091
|
+
* }
|
|
1092
|
+
*
|
|
1093
|
+
* const f = field.for<ContactForm>()
|
|
1094
|
+
*
|
|
1095
|
+
* const schema = defineSchema<ContactForm>({
|
|
1096
|
+
* sections: [{
|
|
1097
|
+
* fields: [
|
|
1098
|
+
* f.text("firstName", "First Name"), // ✓
|
|
1099
|
+
* f.email("email", "Email"), // ✓
|
|
1100
|
+
* f.text("typo", "Label"), // ✗ TypeScript error
|
|
1101
|
+
* ],
|
|
1102
|
+
* }],
|
|
1103
|
+
* })
|
|
1104
|
+
* ```
|
|
1105
|
+
*/
|
|
1106
|
+
for: <T extends FieldValues>() => {
|
|
1107
|
+
text: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1108
|
+
email: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1109
|
+
url: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1110
|
+
tel: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1111
|
+
password: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1112
|
+
number: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1113
|
+
textarea: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1114
|
+
select: (name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>;
|
|
1115
|
+
combobox: (name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>;
|
|
1116
|
+
multiselect: (name: Path<T>, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps<T>) => BaseField<T>;
|
|
1117
|
+
dependentSelect: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1118
|
+
switch: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1119
|
+
boolean: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1120
|
+
checkbox: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1121
|
+
radio: (name: Path<T>, label: string, options: FieldOption[], props?: FieldProps<T>) => BaseField<T>;
|
|
1122
|
+
date: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1123
|
+
tags: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1124
|
+
slug: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1125
|
+
file: (name: Path<T>, label: string, props?: FieldProps<T>) => BaseField<T>;
|
|
1126
|
+
hidden: (name: Path<T>, props?: FieldProps<T>) => BaseField<T>;
|
|
1127
|
+
group: (name: Path<T>, label: string, itemFields: BaseField[], props?: FieldProps<T>) => BaseField<T>;
|
|
1128
|
+
array: (name: Path<T>, label: string, itemFields: BaseField[], props?: FieldProps<T>) => BaseField<T>;
|
|
1129
|
+
custom: (name: Path<T>, label: string, render: (props: FieldComponentProps<T>) => ReactNode, builderProps?: FieldProps<T>) => BaseField<T>;
|
|
1130
|
+
};
|
|
843
1131
|
};
|
|
844
1132
|
/**
|
|
845
1133
|
* Create a section definition with sensible defaults.
|
|
846
1134
|
*
|
|
847
|
-
* @param id - Unique section identifier
|
|
848
|
-
* @param title - Section title
|
|
849
|
-
* @param fields - Array of field definitions
|
|
850
|
-
* @param props - Additional section configuration
|
|
851
|
-
*
|
|
852
1135
|
* @example
|
|
853
1136
|
* ```ts
|
|
854
1137
|
* section("personal", "Personal Info", [
|
|
855
1138
|
* field.text("name", "Name", { required: true }),
|
|
856
1139
|
* field.email("email", "Email"),
|
|
857
|
-
* ], { cols: 2
|
|
1140
|
+
* ], { cols: 2 })
|
|
858
1141
|
* ```
|
|
859
1142
|
*/
|
|
860
1143
|
declare function section<TFieldValues extends FieldValues = FieldValues>(id: string, title: string, fields: BaseField<TFieldValues>[], props?: SectionProps<TFieldValues>): Section<TFieldValues>;
|
|
861
1144
|
/**
|
|
862
1145
|
* Create a section without a title (transparent section).
|
|
863
1146
|
* Useful for grouping fields without visual separation.
|
|
1147
|
+
*
|
|
1148
|
+
* Accepts `BaseField[]` (no generic) so mixed-type field arrays don't trigger
|
|
1149
|
+
* conflicting type inference across different field name generics.
|
|
864
1150
|
*/
|
|
865
|
-
declare function sectionUntitled
|
|
1151
|
+
declare function sectionUntitled(fields: BaseField[], props?: Omit<SectionProps, "variant">): Section;
|
|
866
1152
|
//#endregion
|
|
867
1153
|
//#region src/useFormKit.d.ts
|
|
868
1154
|
/**
|
|
@@ -910,4 +1196,4 @@ interface UseFormKitReturn<TFieldValues extends FieldValues = FieldValues> exten
|
|
|
910
1196
|
*/
|
|
911
1197
|
declare function useFormKit<TFieldValues extends FieldValues = FieldValues>(options: UseFormKitOptions<TFieldValues>): UseFormKitReturn<TFieldValues>;
|
|
912
1198
|
//#endregion
|
|
913
|
-
export { type BaseField, type ClassValue, type ComponentRegistry, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldComponent, type FieldComponentProps, type FieldOption, type FieldOptionGroup, type FieldType, FieldWrapper, type FieldWrapperProps, type FormElement, FormGenerator, type FormGeneratorProps, type FormSchema, type FormSystemContextValue, FormSystemProvider, type FormSystemProviderProps, type GridLayoutProps, GridRenderer, type GridRendererProps, type InferSchemaValues, type LayoutComponent, type LayoutComponentProps, type LayoutRegistry, type LayoutType, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, SectionRenderer, type SectionRendererProps, type UseFormKitOptions, type UseFormKitReturn, type ValidationRules, type Variant, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
|
|
1199
|
+
export { type BaseField, type ClassValue, type ComponentRegistry, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldComponent, type FieldComponentProps, type FieldMeta, type FieldOption, type FieldOptionGroup, type FieldType, FieldWrapper, type FieldWrapperProps, type FormElement, FormGenerator, type FormGeneratorProps, type FormSchema, type FormSystemContextValue, FormSystemProvider, type FormSystemProviderProps, type GridLayoutProps, GridRenderer, type GridRendererProps, type InferSchemaValues, type LayoutComponent, type LayoutComponentProps, type LayoutRegistry, type LayoutType, type PatternRuleObject, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, SectionRenderer, type SectionRendererProps, type UseFormKitOptions, type UseFormKitReturn, type ValidationRuleObject, type ValidationRules, type Variant, applyServerErrors, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extendSection, extractDefaultValues, extractDefaultValuesAsync, extractWatchNames, field, flattenSchema, isArrayField, isChoiceField, isConditionalField, isContainerField, isDateField, isDynamicField, isNumericField, isTextField, mergeSchemas, omitFields, pickFields, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
|