rhf-dynamic-forms 1.1.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.
@@ -0,0 +1,1124 @@
1
+ import * as react0 from "react";
2
+ import React$1, { CSSProperties, ReactNode } from "react";
3
+ import { ControllerFieldState, ControllerRenderProps, FieldErrors, FieldPath, FieldValues, Resolver, UseFormReturn } from "react-hook-form";
4
+ import { ZodObject, ZodRawShape, ZodTypeAny, z } from "zod";
5
+
6
+ //#region src/types/validation.d.ts
7
+ /**
8
+ * JSON Logic rule type - a generic record for JSON Logic expressions.
9
+ * Used for visibility and validation conditions.
10
+ */
11
+ type JsonLogicRule = Record<string, unknown>;
12
+ /**
13
+ * Validation configuration for form fields.
14
+ * Phase 1 supports: required, minLength, maxLength, pattern
15
+ * Phase 3 will add: condition (JSON Logic)
16
+ */
17
+ interface ValidationConfig {
18
+ /** Field is required - must have a non-empty value */
19
+ required?: boolean;
20
+ /** Type-specific validation (for future use) */
21
+ type?: "number" | "email" | "date";
22
+ /** Minimum length for text fields */
23
+ minLength?: number;
24
+ /** Maximum length for text fields */
25
+ maxLength?: number;
26
+ /** Regular expression pattern for validation */
27
+ pattern?: string;
28
+ /** Custom error message for pattern/condition failure */
29
+ message?: string;
30
+ /** JSON Logic condition for complex validation (Phase 3) */
31
+ condition?: JsonLogicRule;
32
+ }
33
+ /**
34
+ * Controls validation behavior for invisible fields.
35
+ * - 'skip': Do not validate invisible fields (default)
36
+ * - 'validate': Validate all fields regardless of visibility
37
+ * - 'warn': Validate but treat errors as warnings (non-blocking)
38
+ */
39
+ type InvisibleFieldValidation = "skip" | "validate" | "warn";
40
+ //#endregion
41
+ //#region src/types/elements.d.ts
42
+ /**
43
+ * All supported element types in the form configuration.
44
+ * Phase 1: text, email, boolean, phone, date, custom
45
+ * Phase 2 adds: container, column
46
+ * Phase 3 adds: select, array
47
+ */
48
+ type ElementType = "text" | "email" | "boolean" | "phone" | "date" | "select" | "array" | "container" | "column" | "custom";
49
+ /**
50
+ * Field types that render input controls.
51
+ */
52
+ type FieldType = "text" | "email" | "boolean" | "phone" | "date" | "select" | "array";
53
+ /**
54
+ * Base interface for all field elements.
55
+ */
56
+ interface BaseFieldElement {
57
+ type: ElementType;
58
+ /** Unique identifier for form data binding (supports dot notation like 'source.name') */
59
+ name: string;
60
+ /** Display label for the field */
61
+ label?: string;
62
+ /** Placeholder text (for text-based inputs) */
63
+ placeholder?: string;
64
+ /** Default value for the field (arrays for multi-select, records for complex fields) */
65
+ defaultValue?: string | number | boolean | null | unknown[] | Record<string, unknown>;
66
+ /** Validation configuration */
67
+ validation?: ValidationConfig;
68
+ /** Conditional visibility rules using JSON Logic (Phase 4) */
69
+ visible?: JsonLogicRule;
70
+ /** Field path this field depends on (for cascading selects, etc.) */
71
+ dependsOn?: string;
72
+ /** Reset this field when parent changes (default: true) */
73
+ resetOnParentChange?: boolean;
74
+ }
75
+ /**
76
+ * Text input field element.
77
+ */
78
+ interface TextFieldElement extends BaseFieldElement {
79
+ type: "text";
80
+ }
81
+ /**
82
+ * Email input field element.
83
+ */
84
+ interface EmailFieldElement extends BaseFieldElement {
85
+ type: "email";
86
+ }
87
+ /**
88
+ * Boolean (checkbox/toggle) field element.
89
+ */
90
+ interface BooleanFieldElement extends BaseFieldElement {
91
+ type: "boolean";
92
+ }
93
+ /**
94
+ * Phone number input field element.
95
+ */
96
+ interface PhoneFieldElement extends BaseFieldElement {
97
+ type: "phone";
98
+ }
99
+ /**
100
+ * Date picker field element.
101
+ */
102
+ interface DateFieldElement extends BaseFieldElement {
103
+ type: "date";
104
+ }
105
+ /**
106
+ * Option for select field elements.
107
+ */
108
+ interface SelectOption {
109
+ /** Option value (stored in form data) */
110
+ value: string | number;
111
+ /** Display label */
112
+ label: string;
113
+ /** Disable this option */
114
+ disabled?: boolean;
115
+ }
116
+ /**
117
+ * Static options source - use config.options directly.
118
+ */
119
+ interface StaticOptionsSource {
120
+ type: "static";
121
+ }
122
+ /**
123
+ * Map options source - lookup from provided options map.
124
+ */
125
+ interface MapOptionsSource {
126
+ type: "map";
127
+ /** Key in the options map */
128
+ key: string;
129
+ }
130
+ /**
131
+ * API options source - fetch from endpoint.
132
+ */
133
+ interface ApiOptionsSource {
134
+ type: "api";
135
+ /** API endpoint URL */
136
+ endpoint: string;
137
+ }
138
+ /**
139
+ * Search options source - search as you type.
140
+ */
141
+ interface SearchOptionsSource {
142
+ type: "search";
143
+ /** API endpoint for search */
144
+ endpoint: string;
145
+ /** Minimum characters before searching (default: 2) */
146
+ minChars?: number;
147
+ }
148
+ /**
149
+ * Resolver options source - custom resolver function.
150
+ */
151
+ interface ResolverOptionsSource {
152
+ type: "resolver";
153
+ /** Name of the registered resolver */
154
+ name: string;
155
+ }
156
+ /**
157
+ * Describes how to resolve options for a select field.
158
+ * This is declarative - describes intent, not implementation.
159
+ * Actual data fetching is done by field component.
160
+ */
161
+ type OptionsSource = StaticOptionsSource | MapOptionsSource | ApiOptionsSource | SearchOptionsSource | ResolverOptionsSource;
162
+ /**
163
+ * Select field element for dropdowns and multi-selects.
164
+ */
165
+ interface SelectFieldElement extends BaseFieldElement {
166
+ type: "select";
167
+ /** Available options (required when optionsSource is not provided) */
168
+ options?: SelectOption[];
169
+ /** Describes how to resolve options (when provided, options become optional) */
170
+ optionsSource?: OptionsSource;
171
+ /** Allow selecting multiple values (default: false) */
172
+ multiple?: boolean;
173
+ /** Allow clearing selection (default: true) */
174
+ clearable?: boolean;
175
+ /** Allow searching/filtering options (default: false) */
176
+ searchable?: boolean;
177
+ /** Allow creating new options not in the list (default: false) */
178
+ creatable?: boolean;
179
+ }
180
+ /**
181
+ * Custom component field element.
182
+ * Allows rendering user-defined components.
183
+ */
184
+ interface CustomFieldElement extends BaseFieldElement {
185
+ type: "custom";
186
+ /** Name of the registered custom component */
187
+ component: string;
188
+ /** Props to pass to the custom component */
189
+ componentProps?: Record<string, unknown>;
190
+ }
191
+ /**
192
+ * Array/repeater field element.
193
+ * Contains repeatable group of fields.
194
+ */
195
+ interface ArrayFieldElement extends BaseFieldElement {
196
+ type: "array";
197
+ /** Fields template for each item (can contain any field type) */
198
+ itemFields: FieldElement[];
199
+ /** Minimum items required */
200
+ minItems?: number;
201
+ /** Maximum items allowed */
202
+ maxItems?: number;
203
+ /** Label for add button */
204
+ addButtonLabel?: string;
205
+ /** Allow reordering items */
206
+ sortable?: boolean;
207
+ }
208
+ /**
209
+ * Container element for grouping fields in columns (Phase 2).
210
+ */
211
+ interface ContainerElement {
212
+ type: "container";
213
+ /** Array of column elements */
214
+ columns: ColumnElement[];
215
+ /** Conditional visibility rules using JSON Logic */
216
+ visible?: JsonLogicRule;
217
+ }
218
+ /**
219
+ * Column element within a container (Phase 2).
220
+ */
221
+ interface ColumnElement {
222
+ type: "column";
223
+ /** Column width (e.g., '50%', '200px') */
224
+ width: string;
225
+ /** Nested elements within the column */
226
+ elements: FormElement[];
227
+ /** Conditional visibility rules using JSON Logic */
228
+ visible?: JsonLogicRule;
229
+ }
230
+ /**
231
+ * Union of all field element types.
232
+ */
233
+ type FieldElement = TextFieldElement | EmailFieldElement | BooleanFieldElement | PhoneFieldElement | DateFieldElement | SelectFieldElement | ArrayFieldElement | CustomFieldElement;
234
+ /**
235
+ * Union of all layout element types.
236
+ */
237
+ type LayoutElement = ContainerElement | ColumnElement;
238
+ /**
239
+ * Union of all form element types.
240
+ */
241
+ type FormElement = FieldElement | LayoutElement;
242
+ /**
243
+ * Type guard to check if an element is a field element.
244
+ */
245
+ declare const isFieldElement: (element: FormElement) => element is FieldElement;
246
+ /**
247
+ * Type guard to check if an element is an array field element.
248
+ */
249
+ declare const isArrayFieldElement: (element: FormElement) => element is ArrayFieldElement;
250
+ /**
251
+ * Type guard to check if an element is a container element.
252
+ */
253
+ declare const isContainerElement: (element: FormElement) => element is ContainerElement;
254
+ /**
255
+ * Type guard to check if an element is a column element.
256
+ */
257
+ declare const isColumnElement: (element: FormElement) => element is ColumnElement;
258
+ /**
259
+ * Type guard to check if an element is a custom field element.
260
+ */
261
+ declare const isCustomFieldElement: (element: FormElement) => element is CustomFieldElement;
262
+ //#endregion
263
+ //#region src/types/events.d.ts
264
+ /**
265
+ * Form data type - a generic record for form values.
266
+ * Values are nested according to dot-notation field names.
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * // For field name "source.name", data will be:
271
+ * { source: { name: "John" } }
272
+ * ```
273
+ */
274
+ type FormData = Record<string, unknown>;
275
+ /**
276
+ * Handler called when form is submitted with valid data.
277
+ */
278
+ type OnSubmitHandler = (data: FormData) => void | Promise<void>;
279
+ /**
280
+ * Handler called when form values change.
281
+ *
282
+ * @param data - Current form data
283
+ * @param changedField - The name of the field that changed
284
+ */
285
+ type OnChangeHandler = (data: FormData, changedField: string) => void;
286
+ /**
287
+ * Handler called when validation state changes.
288
+ *
289
+ * @param errors - Current validation errors
290
+ * @param isValid - Whether the form is currently valid
291
+ */
292
+ type OnValidationChangeHandler = (errors: FieldErrors, isValid: boolean) => void;
293
+ /**
294
+ * Handler called when form is reset.
295
+ */
296
+ type OnResetHandler = () => void;
297
+ /**
298
+ * Handler called on form submission errors.
299
+ *
300
+ * @param errors - Validation errors that prevented submission
301
+ */
302
+ type OnErrorHandler = (errors: FieldErrors) => void;
303
+ //#endregion
304
+ //#region src/customComponents/types.d.ts
305
+ interface CustomComponentRenderProps<TProps extends Record<string, unknown> = Record<string, unknown>> {
306
+ field: ControllerRenderProps;
307
+ fieldState: ControllerFieldState;
308
+ config: CustomFieldElement;
309
+ componentProps: TProps;
310
+ formValues: FormData;
311
+ setValue: (name: string, value: unknown) => void;
312
+ }
313
+ interface CustomComponentDefinition<TProps extends Record<string, unknown> = Record<string, unknown>> {
314
+ component: React.ComponentType<CustomComponentRenderProps<TProps>>;
315
+ propsSchema?: ZodObject<ZodRawShape>;
316
+ defaultProps?: Partial<TProps>;
317
+ description?: string;
318
+ displayName?: string;
319
+ }
320
+ type CustomComponentRegistry = Record<string, CustomComponentDefinition<any> | React.ComponentType<any>>;
321
+ //#endregion
322
+ //#region src/customComponents/defineCustomComponent.d.ts
323
+ /**
324
+ * Type-safe helper for defining custom components.
325
+ * Provides TypeScript inference for component props based on propsSchema.
326
+ *
327
+ * @example
328
+ * ```ts
329
+ * const RatingField = defineCustomComponent({
330
+ * component: RatingFieldComponent,
331
+ * propsSchema: z.object({ maxStars: z.number() }),
332
+ * defaultProps: { maxStars: 5 },
333
+ * });
334
+ * ```
335
+ */
336
+ declare function defineCustomComponent<TProps extends Record<string, unknown> = Record<string, unknown>>(definition: CustomComponentDefinition<TProps>): CustomComponentDefinition<TProps>;
337
+ //#endregion
338
+ //#region src/types/fields.d.ts
339
+ /**
340
+ * Base props passed to all field components.
341
+ * Field components receive react-hook-form controller props.
342
+ *
343
+ * @example
344
+ * ```tsx
345
+ * const MyTextField: TextFieldComponent = ({ field, fieldState, config, formValues }) => (
346
+ * <div>
347
+ * <label>{config.label}</label>
348
+ * <input {...field} />
349
+ * {fieldState.error && <span>{fieldState.error.message}</span>}
350
+ * </div>
351
+ * );
352
+ * ```
353
+ */
354
+ interface BaseFieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TConfig extends BaseFieldElement = BaseFieldElement> {
355
+ /** react-hook-form field props (value, onChange, onBlur, name, ref) */
356
+ field: ControllerRenderProps<TFieldValues, TName>;
357
+ /** react-hook-form field state (invalid, isTouched, isDirty, error) */
358
+ fieldState: ControllerFieldState;
359
+ /** Field configuration from form config */
360
+ config: TConfig;
361
+ /** All current form values (for reading other fields, dependent logic) */
362
+ formValues: FormData;
363
+ /** Set any field value (for dependent field logic, cascading updates) */
364
+ setValue: (name: string, value: unknown) => void;
365
+ }
366
+ /**
367
+ * Props for text input field component.
368
+ */
369
+ type TextFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, TextFieldElement>;
370
+ /**
371
+ * Props for email input field component.
372
+ */
373
+ type EmailFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, EmailFieldElement>;
374
+ /**
375
+ * Props for boolean (checkbox/toggle) field component.
376
+ */
377
+ type BooleanFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, BooleanFieldElement>;
378
+ /**
379
+ * Props for phone input field component.
380
+ */
381
+ type PhoneFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, PhoneFieldElement>;
382
+ /**
383
+ * Props for date input field component.
384
+ */
385
+ type DateFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, DateFieldElement>;
386
+ /**
387
+ * Props for select field component.
388
+ */
389
+ type SelectFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, SelectFieldElement>;
390
+ /**
391
+ * Props for array field component.
392
+ */
393
+ type ArrayFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, ArrayFieldElement>;
394
+ /**
395
+ * Props for custom field components.
396
+ * Custom components receive additional componentProps from configuration.
397
+ */
398
+ type CustomFieldProps = BaseFieldProps<FieldValues, FieldPath<FieldValues>, CustomFieldElement>;
399
+ /**
400
+ * Base component type that accepts any field configuration.
401
+ * Used internally for dynamic field rendering where the specific
402
+ * field type is determined at runtime.
403
+ */
404
+ type BaseFieldComponent<TProps extends BaseFieldProps = BaseFieldProps> = React.ComponentType<TProps>;
405
+ /**
406
+ * Component type for text fields.
407
+ */
408
+ type TextFieldComponent = BaseFieldComponent<TextFieldProps>;
409
+ /**
410
+ * Component type for email fields.
411
+ */
412
+ type EmailFieldComponent = BaseFieldComponent<EmailFieldProps>;
413
+ /**
414
+ * Component type for boolean fields.
415
+ */
416
+ type BooleanFieldComponent = BaseFieldComponent<BooleanFieldProps>;
417
+ /**
418
+ * Component type for phone fields.
419
+ */
420
+ type PhoneFieldComponent = BaseFieldComponent<PhoneFieldProps>;
421
+ /**
422
+ * Component type for date fields.
423
+ */
424
+ type DateFieldComponent = BaseFieldComponent<DateFieldProps>;
425
+ /**
426
+ * Component type for select fields.
427
+ */
428
+ type SelectFieldComponent = BaseFieldComponent<SelectFieldProps>;
429
+ /**
430
+ * Component type for array fields.
431
+ */
432
+ type ArrayFieldComponent = BaseFieldComponent<ArrayFieldProps>;
433
+ /**
434
+ * Component type for custom fields.
435
+ */
436
+ type CustomFieldComponent = BaseFieldComponent<CustomFieldProps>;
437
+ type StandardFieldComponent = TextFieldComponent | EmailFieldComponent | BooleanFieldComponent | PhoneFieldComponent | DateFieldComponent | SelectFieldComponent | ArrayFieldComponent;
438
+ type StandardFieldComponentType = Exclude<ElementType, "custom">;
439
+ interface FieldComponentRegistry extends Partial<Record<StandardFieldComponentType, StandardFieldComponent>> {
440
+ text: TextFieldComponent;
441
+ email: EmailFieldComponent;
442
+ boolean: BooleanFieldComponent;
443
+ phone: PhoneFieldComponent;
444
+ date: DateFieldComponent;
445
+ select: SelectFieldComponent;
446
+ array: ArrayFieldComponent;
447
+ }
448
+ /**
449
+ * Union type for all field props.
450
+ */
451
+ type FieldProps = TextFieldProps | EmailFieldProps | BooleanFieldProps | PhoneFieldProps | DateFieldProps | SelectFieldProps | ArrayFieldProps | CustomFieldProps;
452
+ /**
453
+ * Props for container components.
454
+ * Containers wrap columns and provide layout structure.
455
+ */
456
+ interface ContainerProps {
457
+ /** Container configuration from form config */
458
+ config: ContainerElement;
459
+ /** Column elements rendered as children */
460
+ children: React.ReactNode;
461
+ }
462
+ /**
463
+ * Props for column components.
464
+ * Columns wrap form elements and apply width styling.
465
+ */
466
+ interface ColumnProps {
467
+ /** Column configuration from form config */
468
+ config: ColumnElement;
469
+ /** Form elements rendered as children */
470
+ children: React.ReactNode;
471
+ }
472
+ /**
473
+ * Component type for container layouts.
474
+ */
475
+ type ContainerComponent = React.ComponentType<ContainerProps>;
476
+ /**
477
+ * Component type for column layouts.
478
+ */
479
+ type ColumnComponent = React.ComponentType<ColumnProps>;
480
+ /**
481
+ * Registry for custom container components referenced by name.
482
+ * Allows users to provide custom container implementations.
483
+ *
484
+ * @example
485
+ * ```tsx
486
+ * const customContainers: CustomContainerRegistry = {
487
+ * card: CardContainer,
488
+ * section: SectionContainer,
489
+ * };
490
+ * ```
491
+ */
492
+ type CustomContainerRegistry = Record<string, ContainerComponent>;
493
+ //#endregion
494
+ //#region src/types/config.d.ts
495
+ /**
496
+ * Props passed to the fieldWrapper function.
497
+ * Contains field metadata for custom wrapper implementations.
498
+ */
499
+ interface FieldWrapperProps {
500
+ /** Field path (e.g., "contact.email") */
501
+ name: string;
502
+ /** Raw field configuration from form config */
503
+ config: FieldElement;
504
+ /** react-hook-form field state (error, isDirty, isTouched, invalid) */
505
+ fieldState: ControllerFieldState;
506
+ /** Current field value */
507
+ value: unknown;
508
+ /** All current form values (for reading other fields) */
509
+ formValues: FormData;
510
+ /** Set any field value (for dependent field logic) */
511
+ setValue: (name: string, value: unknown) => void;
512
+ }
513
+ /**
514
+ * Function type for wrapping field components.
515
+ * Receives field metadata and the rendered field element.
516
+ *
517
+ * @example
518
+ * ```tsx
519
+ * const myFieldWrapper: FieldWrapperFunction = (props, children) => (
520
+ * <div className="field-wrapper">
521
+ * <Badge>{props.name}</Badge>
522
+ * {children}
523
+ * </div>
524
+ * );
525
+ * ```
526
+ */
527
+ type FieldWrapperFunction = (props: FieldWrapperProps, children: ReactNode) => ReactNode;
528
+ /**
529
+ * Root form configuration object.
530
+ * This is the JSON structure that defines the entire form.
531
+ *
532
+ * @example
533
+ * ```json
534
+ * {
535
+ * "name": "Contact Form",
536
+ * "elements": [
537
+ * { "type": "text", "name": "source.name", "label": "Name" },
538
+ * { "type": "email", "name": "source.email", "label": "Email" }
539
+ * ]
540
+ * }
541
+ * ```
542
+ */
543
+ interface FormConfiguration {
544
+ /** Optional name/identifier for the form */
545
+ name?: string;
546
+ /** Array of form elements (fields and layouts) */
547
+ elements: FormElement[];
548
+ /** Custom component definitions (for advanced use) */
549
+ customComponents?: Record<string, CustomComponentDefinition>;
550
+ }
551
+ /**
552
+ * Props for the DynamicForm component.
553
+ *
554
+ * @example
555
+ * ```tsx
556
+ * <DynamicForm
557
+ * config={formConfig}
558
+ * fieldComponents={myFieldComponents}
559
+ * onSubmit={(data) => console.log(data)}
560
+ * onChange={(data, field) => console.log(`${field} changed`)}
561
+ * />
562
+ * ```
563
+ */
564
+ interface DynamicFormProps {
565
+ /** Form configuration - defines structure, fields, and validation */
566
+ config: FormConfiguration;
567
+ /** Initial form data to populate fields */
568
+ initialData?: FormData;
569
+ /** Required: Field component implementations for each field type */
570
+ fieldComponents: FieldComponentRegistry;
571
+ /** Optional: Custom field components referenced by name in config */
572
+ customComponents?: CustomComponentRegistry;
573
+ /** Optional: Custom container components for layout customization (Phase 2) */
574
+ customContainers?: CustomContainerRegistry;
575
+ /** Called on successful form submission with valid data */
576
+ onSubmit: OnSubmitHandler;
577
+ /** Called when any field value changes */
578
+ onChange?: OnChangeHandler;
579
+ /** Called when validation state changes */
580
+ onValidationChange?: OnValidationChangeHandler;
581
+ /** Called when form is reset */
582
+ onReset?: OnResetHandler;
583
+ /** Called on submission errors (validation failures) */
584
+ onError?: OnErrorHandler;
585
+ /**
586
+ * Validation mode for react-hook-form.
587
+ * - 'onChange': Validate on every change (default)
588
+ * - 'onBlur': Validate on blur
589
+ * - 'onSubmit': Only validate on submit
590
+ * - 'onTouched': Validate on blur, then on every change
591
+ * - 'all': Validate on blur and change
592
+ */
593
+ mode?: "onChange" | "onBlur" | "onSubmit" | "onTouched" | "all";
594
+ /**
595
+ * Controls validation behavior for invisible fields.
596
+ * Only applies when using `schema` prop (not custom `resolver`).
597
+ * - 'skip': Do not validate invisible fields (default)
598
+ * - 'validate': Validate all fields regardless of visibility
599
+ * - 'warn': Validate but treat errors as warnings (non-blocking)
600
+ */
601
+ invisibleFieldValidation?: InvisibleFieldValidation;
602
+ /** CSS class name for the form element */
603
+ className?: string;
604
+ /** Inline styles for the form element */
605
+ style?: CSSProperties;
606
+ /** HTML id attribute for the form element */
607
+ id?: string;
608
+ /** Content to render after all form fields (e.g., submit button) */
609
+ children?: React.ReactNode;
610
+ /**
611
+ * Optional wrapper function for each field.
612
+ * Receives field metadata and children, returns wrapped element.
613
+ * Use this for adding confidence indicators, status badges, edit tracking, etc.
614
+ *
615
+ * @example
616
+ * ```tsx
617
+ * <DynamicForm
618
+ * fieldWrapper={(props, children) => (
619
+ * <div className="field-wrapper">
620
+ * <Badge>{props.config.label}</Badge>
621
+ * {children}
622
+ * </div>
623
+ * )}
624
+ * />
625
+ * ```
626
+ */
627
+ fieldWrapper?: FieldWrapperFunction;
628
+ }
629
+ /**
630
+ * Ref interface for external form control.
631
+ * Access form methods from outside the component.
632
+ *
633
+ * @example
634
+ * ```tsx
635
+ * const formRef = useRef<DynamicFormRef>(null);
636
+ *
637
+ * // Reset city when country changes externally
638
+ * const handleCountryChange = (country: string) => {
639
+ * formRef.current?.setValue('country', country);
640
+ * formRef.current?.setValue('city', null);
641
+ * };
642
+ *
643
+ * <DynamicForm ref={formRef} ... />
644
+ * ```
645
+ */
646
+ interface DynamicFormRef {
647
+ /** Get all form values */
648
+ getValues: () => FormData;
649
+ /** Set a specific field value */
650
+ setValue: (name: string, value: unknown) => void;
651
+ /** Watch all form values reactively */
652
+ watchAll: () => FormData;
653
+ /** Watch a specific field value reactively */
654
+ watchField: (name: string) => unknown;
655
+ /** Reset form to initial values or provided values */
656
+ reset: (values?: FormData) => void;
657
+ /** Trigger validation for a specific field or all fields */
658
+ trigger: (name?: string) => Promise<boolean>;
659
+ }
660
+ //#endregion
661
+ //#region src/context/DynamicFormContext.d.ts
662
+ /**
663
+ * Value provided by the DynamicFormContext.
664
+ * Contains everything needed by child components to render and interact with the form.
665
+ */
666
+ interface DynamicFormContextValue {
667
+ /**
668
+ * react-hook-form methods.
669
+ * Provides access to form state, validation, and control.
670
+ */
671
+ form: UseFormReturn<FormData>;
672
+ /**
673
+ * Parsed and validated form configuration.
674
+ */
675
+ config: FormConfiguration;
676
+ /**
677
+ * Registered field components for each field type.
678
+ * These are provided by the consuming application.
679
+ */
680
+ fieldComponents: FieldComponentRegistry;
681
+ /**
682
+ * Registered custom components.
683
+ * These are referenced by name in 'custom' type elements.
684
+ */
685
+ customComponents: CustomComponentRegistry;
686
+ /**
687
+ * Registered custom container components (Phase 2).
688
+ * These can be used to customize container layout rendering.
689
+ */
690
+ customContainers: CustomContainerRegistry;
691
+ /**
692
+ * Current visibility state for all fields (Phase 4).
693
+ * Maps field names to their visibility (true = visible).
694
+ * For Phase 1, all fields are always visible.
695
+ */
696
+ visibility: Record<string, boolean>;
697
+ /**
698
+ * Optional wrapper function for each field.
699
+ * When provided, every field is wrapped with this function.
700
+ */
701
+ fieldWrapper?: FieldWrapperFunction;
702
+ }
703
+ /**
704
+ * Context for sharing form state and configuration with child components.
705
+ *
706
+ * This context is set up by the DynamicForm component and consumed by
707
+ * field renderers and other internal components.
708
+ */
709
+ declare const DynamicFormContext: react0.Context<DynamicFormContextValue | null>;
710
+ //#endregion
711
+ //#region src/DynamicForm.d.ts
712
+ interface DynamicFormPropsWithRef extends DynamicFormProps {
713
+ ref?: React$1.Ref<DynamicFormRef>;
714
+ }
715
+ declare const DynamicForm: {
716
+ ({
717
+ config,
718
+ initialData,
719
+ fieldComponents,
720
+ customComponents,
721
+ customContainers,
722
+ onSubmit,
723
+ onChange,
724
+ onValidationChange,
725
+ onReset,
726
+ onError,
727
+ mode,
728
+ invisibleFieldValidation,
729
+ className,
730
+ style,
731
+ id,
732
+ children,
733
+ fieldWrapper,
734
+ ref
735
+ }: DynamicFormPropsWithRef): React$1.ReactElement;
736
+ displayName: string;
737
+ };
738
+ //#endregion
739
+ //#region src/hooks/useDynamicFormContext.d.ts
740
+ /**
741
+ * Hook to access the DynamicForm context.
742
+ *
743
+ * Must be used within a DynamicForm component.
744
+ * Throws an error if used outside of the form context.
745
+ *
746
+ * @returns The DynamicFormContext value
747
+ * @throws Error if used outside of DynamicForm
748
+ *
749
+ * @example
750
+ * ```tsx
751
+ * function MyCustomField({ config }) {
752
+ * const { form, fieldComponents } = useDynamicFormContext();
753
+ *
754
+ * const value = form.watch(config.name);
755
+ * // ... render field
756
+ * }
757
+ * ```
758
+ */
759
+ declare const useDynamicFormContext: () => DynamicFormContextValue;
760
+ /**
761
+ * Hook to safely access the DynamicForm context.
762
+ * Returns null if used outside of the form context instead of throwing.
763
+ *
764
+ * @returns The DynamicFormContext value or null
765
+ *
766
+ * @example
767
+ * ```tsx
768
+ * function MaybeInForm() {
769
+ * const context = useDynamicFormContextSafe();
770
+ *
771
+ * if (!context) {
772
+ * return <span>Not in a form</span>;
773
+ * }
774
+ *
775
+ * return <span>In a form!</span>;
776
+ * }
777
+ * ```
778
+ */
779
+ declare const useDynamicFormContextSafe: () => DynamicFormContextValue | null;
780
+ //#endregion
781
+ //#region src/parser/configParser.d.ts
782
+ /**
783
+ * Error thrown when configuration parsing fails.
784
+ */
785
+ declare class ConfigurationError extends Error {
786
+ /** The original validation errors */
787
+ readonly errors: unknown[];
788
+ constructor(message: string, errors: unknown[]);
789
+ }
790
+ /**
791
+ * Result of parsing a configuration.
792
+ */
793
+ interface ParseResult {
794
+ success: boolean;
795
+ config?: FormConfiguration;
796
+ errors?: string[];
797
+ }
798
+ /**
799
+ * Parses and validates a form configuration.
800
+ *
801
+ * @param config - Raw configuration object (typically from JSON)
802
+ * @returns Validated FormConfiguration
803
+ * @throws ConfigurationError if validation fails
804
+ *
805
+ * @example
806
+ * ```typescript
807
+ * try {
808
+ * const config = parseConfiguration({
809
+ * elements: [
810
+ * { type: 'text', name: 'name', label: 'Name' }
811
+ * ]
812
+ * });
813
+ * // config is now typed as FormConfiguration
814
+ * } catch (error) {
815
+ * if (error instanceof ConfigurationError) {
816
+ * console.error('Invalid configuration:', error.errors);
817
+ * }
818
+ * }
819
+ * ```
820
+ */
821
+ declare const parseConfiguration: (config: unknown) => FormConfiguration;
822
+ /**
823
+ * Safely parses and validates a form configuration without throwing.
824
+ *
825
+ * @param config - Raw configuration object
826
+ * @returns ParseResult with success status and config or errors
827
+ *
828
+ * @example
829
+ * ```typescript
830
+ * const result = safeParseConfiguration(rawConfig);
831
+ * if (result.success) {
832
+ * // result.config is available
833
+ * renderForm(result.config);
834
+ * } else {
835
+ * // result.errors contains validation messages
836
+ * showErrors(result.errors);
837
+ * }
838
+ * ```
839
+ */
840
+ declare const safeParseConfiguration: (config: unknown) => ParseResult;
841
+ //#endregion
842
+ //#region src/resolver/visibilityAwareResolver.d.ts
843
+ /**
844
+ * Options for creating a visibility-aware resolver.
845
+ */
846
+ interface VisibilityAwareResolverOptions<T extends ZodRawShape> {
847
+ /** Zod schema for validation */
848
+ schema: ZodObject<T>;
849
+ /** Function that returns current visibility state for all fields */
850
+ getVisibility: () => Record<string, boolean>;
851
+ /** How to handle validation for invisible fields */
852
+ invisibleFieldValidation: InvisibleFieldValidation;
853
+ }
854
+ /**
855
+ * Creates a resolver that respects field visibility.
856
+ *
857
+ * This resolver wraps the standard zodResolver and filters validation
858
+ * errors based on field visibility. This is useful when fields are
859
+ * conditionally shown/hidden and you want to skip validation for
860
+ * hidden fields.
861
+ *
862
+ * @param options - Configuration for the resolver
863
+ * @returns A react-hook-form resolver
864
+ *
865
+ * @example
866
+ * ```typescript
867
+ * const resolver = createVisibilityAwareResolver({
868
+ * schema: myZodSchema,
869
+ * getVisibility: () => ({ name: true, phone: false }),
870
+ * invisibleFieldValidation: "skip",
871
+ * });
872
+ *
873
+ * const form = useForm({ resolver });
874
+ * ```
875
+ */
876
+ declare const createVisibilityAwareResolver: <T extends ZodRawShape>(options: VisibilityAwareResolverOptions<T>) => Resolver<FieldValues>;
877
+ //#endregion
878
+ //#region src/schema/fieldSchemas.d.ts
879
+ /**
880
+ * Build a complete Zod schema for a single field.
881
+ *
882
+ * @param field - Field element configuration
883
+ * @returns Zod schema for the field
884
+ *
885
+ * @example
886
+ * ```typescript
887
+ * const textField = {
888
+ * type: 'text',
889
+ * name: 'name',
890
+ * validation: { required: true, minLength: 3 }
891
+ * };
892
+ *
893
+ * const schema = buildFieldSchema(textField);
894
+ * // schema is z.string().min(1, 'required').min(3, '...')
895
+ * ```
896
+ */
897
+ declare const buildFieldSchema: (field: FieldElement) => ZodTypeAny;
898
+ //#endregion
899
+ //#region src/schema/generateSchema.d.ts
900
+ /**
901
+ * Generated schema type - a Zod object schema.
902
+ */
903
+ type GeneratedSchema = ZodObject<Record<string, ZodTypeAny>>;
904
+ /**
905
+ * Generate a Zod schema from form configuration.
906
+ * Supports nested field paths via dot notation.
907
+ *
908
+ * This function is called once when the form initializes and the schema
909
+ * is memoized. Visibility changes are handled at validation time, not
910
+ * by regenerating the schema.
911
+ *
912
+ * @param config - Form configuration object
913
+ * @returns Zod object schema for validating form data
914
+ *
915
+ * @example
916
+ * ```typescript
917
+ * const config = {
918
+ * elements: [
919
+ * { type: 'text', name: 'source.name', validation: { required: true } },
920
+ * { type: 'email', name: 'source.email' },
921
+ * { type: 'boolean', name: 'active' }
922
+ * ]
923
+ * };
924
+ *
925
+ * const schema = generateZodSchema(config);
926
+ *
927
+ * // The generated schema is equivalent to:
928
+ * // z.object({
929
+ * // source: z.object({
930
+ * // name: z.string().min(1, 'required'),
931
+ * // email: z.string().email()
932
+ * // }),
933
+ * // active: z.boolean()
934
+ * // })
935
+ *
936
+ * schema.parse({
937
+ * source: { name: 'John', email: 'john@example.com' },
938
+ * active: true
939
+ * }); // Valid
940
+ * ```
941
+ */
942
+ declare const generateZodSchema: (config: FormConfiguration) => GeneratedSchema;
943
+ /**
944
+ * Infer the TypeScript type from a generated schema.
945
+ * Useful for typing form data in the consuming application.
946
+ *
947
+ * @example
948
+ * ```typescript
949
+ * const schema = generateZodSchema(config);
950
+ * type FormData = InferSchemaType<typeof schema>;
951
+ *
952
+ * const onSubmit = (data: FormData) => {
953
+ * // data is fully typed based on configuration
954
+ * };
955
+ * ```
956
+ */
957
+ type InferSchemaType<T extends GeneratedSchema> = z.infer<T>;
958
+ /**
959
+ * Extract field paths from a generated schema.
960
+ * Returns all top-level and nested paths.
961
+ *
962
+ * @param schema - Generated Zod schema
963
+ * @param prefix - Current path prefix (used in recursion)
964
+ * @returns Array of all field paths
965
+ */
966
+ declare const getSchemaFieldPaths: (schema: ZodObject<Record<string, ZodTypeAny>>, prefix?: string) => string[];
967
+ //#endregion
968
+ //#region src/utils/calculateVisibility.d.ts
969
+ /**
970
+ * Visibility state for all fields in the form.
971
+ * Maps field names to their visibility (true = visible).
972
+ */
973
+ type VisibilityState = Record<string, boolean>;
974
+ /**
975
+ * Calculate visibility state for all fields based on their visibility rules.
976
+ * Evaluates JSON Logic rules against current form data.
977
+ *
978
+ * @param elements - Array of form elements
979
+ * @param formData - Current form values
980
+ * @returns Visibility state for all fields
981
+ *
982
+ * @example
983
+ * ```typescript
984
+ * const elements = [
985
+ * { type: 'text', name: 'reason', visible: { "==": [{ "var": "type" }, "other"] } },
986
+ * { type: 'text', name: 'name' }
987
+ * ];
988
+ *
989
+ * const visibility = calculateVisibility(elements, { type: 'other' });
990
+ * // Returns: { reason: true, name: true }
991
+ *
992
+ * const visibility2 = calculateVisibility(elements, { type: 'standard' });
993
+ * // Returns: { reason: false, name: true }
994
+ * ```
995
+ */
996
+ declare const calculateVisibility: (elements: FormElement[], formData: Record<string, unknown>) => VisibilityState;
997
+ //#endregion
998
+ //#region src/utils/flattenFields.d.ts
999
+ /**
1000
+ * Recursively extracts all field elements from a form configuration.
1001
+ * Traverses containers and columns to find nested fields.
1002
+ *
1003
+ * @param elements - Array of form elements (may include containers/columns)
1004
+ * @returns Flat array of all field elements
1005
+ *
1006
+ * @example
1007
+ * ```typescript
1008
+ * const config = {
1009
+ * elements: [
1010
+ * { type: 'text', name: 'name' },
1011
+ * {
1012
+ * type: 'container',
1013
+ * columns: [{
1014
+ * type: 'column',
1015
+ * width: '50%',
1016
+ * elements: [{ type: 'email', name: 'email' }]
1017
+ * }]
1018
+ * }
1019
+ * ]
1020
+ * };
1021
+ *
1022
+ * const fields = flattenFields(config.elements);
1023
+ * // Returns: [{ type: 'text', name: 'name' }, { type: 'email', name: 'email' }]
1024
+ * ```
1025
+ */
1026
+ declare const flattenFields: (elements: FormElement[]) => FieldElement[];
1027
+ /**
1028
+ * Gets all field names from a form configuration.
1029
+ * Useful for initializing form state or visibility tracking.
1030
+ *
1031
+ * @param elements - Array of form elements
1032
+ * @returns Array of field names (including nested paths like 'source.name')
1033
+ */
1034
+ declare const getFieldNames: (elements: FormElement[]) => string[];
1035
+ //#endregion
1036
+ //#region src/utils/mergeDefaults.d.ts
1037
+ /**
1038
+ * Sets a value in a nested object using dot notation path.
1039
+ *
1040
+ * @param obj - Object to modify
1041
+ * @param path - Dot-notation path (e.g., 'source.name')
1042
+ * @param value - Value to set
1043
+ *
1044
+ * @example
1045
+ * ```typescript
1046
+ * const obj = {};
1047
+ * setNestedValue(obj, 'source.name', 'John');
1048
+ * // obj is now { source: { name: 'John' } }
1049
+ * ```
1050
+ */
1051
+ declare const setNestedValue: (obj: Record<string, unknown>, path: string, value: unknown) => void;
1052
+ /**
1053
+ * Gets a value from a nested object using dot notation path.
1054
+ *
1055
+ * @param obj - Object to read from
1056
+ * @param path - Dot-notation path (e.g., 'source.name')
1057
+ * @returns The value at the path, or undefined if not found
1058
+ *
1059
+ * @example
1060
+ * ```typescript
1061
+ * const obj = { source: { name: 'John' } };
1062
+ * getNestedValue(obj, 'source.name'); // 'John'
1063
+ * getNestedValue(obj, 'source.email'); // undefined
1064
+ * ```
1065
+ */
1066
+ declare const getNestedValue: (obj: Record<string, unknown>, path: string) => unknown;
1067
+ /**
1068
+ * Merges configuration default values with initial data.
1069
+ * Priority: initialData > config.defaultValue > type default
1070
+ *
1071
+ * @param config - Form configuration containing field definitions
1072
+ * @param initialData - Initial data provided by the user
1073
+ * @returns Merged default values for react-hook-form
1074
+ *
1075
+ * @example
1076
+ * ```typescript
1077
+ * const config = {
1078
+ * elements: [
1079
+ * { type: 'text', name: 'source.name', defaultValue: 'Default Name' },
1080
+ * { type: 'boolean', name: 'source.active' }
1081
+ * ]
1082
+ * };
1083
+ *
1084
+ * const initialData = { source: { name: 'Provided Name' } };
1085
+ * const defaults = mergeDefaults(config, initialData);
1086
+ * // Result: { source: { name: 'Provided Name', active: false } }
1087
+ * ```
1088
+ */
1089
+ declare const mergeDefaults: (config: FormConfiguration, initialData?: FormData) => FormData;
1090
+ //#endregion
1091
+ //#region src/validation/jsonLogic.d.ts
1092
+ /**
1093
+ * Evaluate a JSON Logic rule against form data.
1094
+ *
1095
+ * @param rule - JSON Logic rule to evaluate
1096
+ * @param data - Form data to evaluate against
1097
+ * @returns Result of the evaluation
1098
+ *
1099
+ * @example
1100
+ * ```typescript
1101
+ * const rule = { "==": [{ var: "status" }, "active"] };
1102
+ * const data = { status: "active" };
1103
+ * applyJsonLogic(rule, data); // true
1104
+ * ```
1105
+ */
1106
+ declare const applyJsonLogic: (rule: JsonLogicRule, data: Record<string, unknown>) => unknown;
1107
+ /**
1108
+ * Evaluate a JSON Logic rule and return boolean result.
1109
+ * Returns true if rule evaluates to a truthy value.
1110
+ *
1111
+ * @param rule - JSON Logic condition
1112
+ * @param data - Form data
1113
+ * @returns true if condition passes, false otherwise
1114
+ *
1115
+ * @example
1116
+ * ```typescript
1117
+ * const rule = { "and": [{ var: "active" }, { var: "confirmed" }] };
1118
+ * evaluateCondition(rule, { active: true, confirmed: true }); // true
1119
+ * evaluateCondition(rule, { active: true, confirmed: false }); // false
1120
+ * ```
1121
+ */
1122
+ declare const evaluateCondition: (rule: JsonLogicRule, data: Record<string, unknown>) => boolean;
1123
+ //#endregion
1124
+ export { type ApiOptionsSource, type ArrayFieldComponent, type ArrayFieldElement, type ArrayFieldProps, type BaseFieldProps, type BooleanFieldComponent, type BooleanFieldElement, type BooleanFieldProps, type ColumnComponent, type ColumnElement, type ColumnProps, ConfigurationError, type ContainerComponent, type ContainerElement, type ContainerProps, type CustomComponentDefinition, type CustomComponentRegistry, type CustomComponentRenderProps, type CustomContainerRegistry, type CustomFieldComponent, type CustomFieldElement, type CustomFieldProps, type DateFieldComponent, type DateFieldElement, type DateFieldProps, DynamicForm, DynamicForm as default, DynamicFormContext, type DynamicFormContextValue, type DynamicFormProps, type DynamicFormRef, type ElementType, type EmailFieldComponent, type EmailFieldElement, type EmailFieldProps, type FieldComponentRegistry, type FieldElement, type FieldProps, type FieldType, type FieldWrapperFunction, type FieldWrapperProps, type FormConfiguration, type FormData, type FormElement, type GeneratedSchema, type InferSchemaType, type InvisibleFieldValidation, type JsonLogicRule, type LayoutElement, type MapOptionsSource, type OnChangeHandler, type OnErrorHandler, type OnResetHandler, type OnSubmitHandler, type OnValidationChangeHandler, type OptionsSource, type ParseResult, type PhoneFieldComponent, type PhoneFieldElement, type PhoneFieldProps, type ResolverOptionsSource, type SearchOptionsSource, type SelectFieldComponent, type SelectFieldElement, type SelectFieldProps, type SelectOption, type StaticOptionsSource, type TextFieldComponent, type TextFieldElement, type TextFieldProps, type ValidationConfig, type VisibilityAwareResolverOptions, type VisibilityState, applyJsonLogic, buildFieldSchema, calculateVisibility, createVisibilityAwareResolver, defineCustomComponent, evaluateCondition, flattenFields, generateZodSchema, getFieldNames, getNestedValue, getSchemaFieldPaths, isArrayFieldElement, isColumnElement, isContainerElement, isCustomFieldElement, isFieldElement, mergeDefaults, parseConfiguration, safeParseConfiguration, setNestedValue, useDynamicFormContext, useDynamicFormContextSafe };