@fogpipe/forma-react 0.6.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 +277 -0
- package/dist/index.d.ts +668 -0
- package/dist/index.js +1039 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
- package/src/ErrorBoundary.tsx +115 -0
- package/src/FieldRenderer.tsx +258 -0
- package/src/FormRenderer.tsx +470 -0
- package/src/__tests__/FormRenderer.test.tsx +803 -0
- package/src/__tests__/test-utils.tsx +297 -0
- package/src/__tests__/useForma.test.ts +1103 -0
- package/src/context.ts +23 -0
- package/src/index.ts +91 -0
- package/src/types.ts +482 -0
- package/src/useForma.ts +681 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import { FieldError, SelectOption, FieldDefinition, Forma, ValidationResult } from '@fogpipe/forma-core';
|
|
2
|
+
export { ComputedField, FieldDefinition, FieldError, FieldType, Forma, PageDefinition, SelectOption, ValidationResult, ValidationRule } from '@fogpipe/forma-core';
|
|
3
|
+
import * as React$1 from 'react';
|
|
4
|
+
import React__default from 'react';
|
|
5
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Type definitions for forma-react components
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base props shared by all field components
|
|
13
|
+
*/
|
|
14
|
+
interface BaseFieldProps {
|
|
15
|
+
/** Field path/name */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Field definition from the Forma spec */
|
|
18
|
+
field: FieldDefinition;
|
|
19
|
+
/** Current field value */
|
|
20
|
+
value: unknown;
|
|
21
|
+
/** Whether the field has been touched */
|
|
22
|
+
touched: boolean;
|
|
23
|
+
/** Whether the field is required */
|
|
24
|
+
required: boolean;
|
|
25
|
+
/** Whether the field is disabled */
|
|
26
|
+
disabled: boolean;
|
|
27
|
+
/** Validation errors for this field */
|
|
28
|
+
errors: FieldError[];
|
|
29
|
+
/** Handler for value changes */
|
|
30
|
+
onChange: (value: unknown) => void;
|
|
31
|
+
/** Handler for blur events */
|
|
32
|
+
onBlur: () => void;
|
|
33
|
+
/** Whether field is visible (always true since FormRenderer handles visibility) */
|
|
34
|
+
visible: boolean;
|
|
35
|
+
/** Whether field is enabled (inverse of disabled) */
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
/** Display label from field definition */
|
|
38
|
+
label: string;
|
|
39
|
+
/** Help text or description from field definition */
|
|
40
|
+
description?: string;
|
|
41
|
+
/** Placeholder text from field definition */
|
|
42
|
+
placeholder?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Props for text-based fields (text, email, password, url, textarea)
|
|
46
|
+
*/
|
|
47
|
+
interface TextFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
48
|
+
fieldType: "text" | "email" | "password" | "url" | "textarea";
|
|
49
|
+
value: string;
|
|
50
|
+
onChange: (value: string) => void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Props for number fields
|
|
54
|
+
*/
|
|
55
|
+
interface NumberFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
56
|
+
fieldType: "number";
|
|
57
|
+
value: number | null;
|
|
58
|
+
onChange: (value: number | null) => void;
|
|
59
|
+
min?: number;
|
|
60
|
+
max?: number;
|
|
61
|
+
step?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Props for integer fields
|
|
65
|
+
*/
|
|
66
|
+
interface IntegerFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
67
|
+
fieldType: "integer";
|
|
68
|
+
value: number | null;
|
|
69
|
+
onChange: (value: number | null) => void;
|
|
70
|
+
min?: number;
|
|
71
|
+
max?: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Props for boolean fields
|
|
75
|
+
*/
|
|
76
|
+
interface BooleanFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
77
|
+
fieldType: "boolean";
|
|
78
|
+
value: boolean;
|
|
79
|
+
onChange: (value: boolean) => void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Props for date fields
|
|
83
|
+
*/
|
|
84
|
+
interface DateFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
85
|
+
fieldType: "date";
|
|
86
|
+
value: string | null;
|
|
87
|
+
onChange: (value: string | null) => void;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Props for datetime fields
|
|
91
|
+
*/
|
|
92
|
+
interface DateTimeFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
93
|
+
fieldType: "datetime";
|
|
94
|
+
value: string | null;
|
|
95
|
+
onChange: (value: string | null) => void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Props for select fields (single selection)
|
|
99
|
+
*/
|
|
100
|
+
interface SelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
101
|
+
fieldType: "select";
|
|
102
|
+
value: string | null;
|
|
103
|
+
onChange: (value: string | null) => void;
|
|
104
|
+
options: SelectOption[];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Props for multi-select fields
|
|
108
|
+
*/
|
|
109
|
+
interface MultiSelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
110
|
+
fieldType: "multiselect";
|
|
111
|
+
value: string[];
|
|
112
|
+
onChange: (value: string[]) => void;
|
|
113
|
+
options: SelectOption[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Union type for all selection-based field props
|
|
117
|
+
*/
|
|
118
|
+
type SelectionFieldProps = SelectFieldProps | MultiSelectFieldProps;
|
|
119
|
+
/**
|
|
120
|
+
* Array item field props returned by getItemFieldProps
|
|
121
|
+
*/
|
|
122
|
+
interface ArrayItemFieldPropsResult {
|
|
123
|
+
/** Field path/name */
|
|
124
|
+
name: string;
|
|
125
|
+
/** Current field value */
|
|
126
|
+
value: unknown;
|
|
127
|
+
/** Field type */
|
|
128
|
+
type: string;
|
|
129
|
+
/** Display label */
|
|
130
|
+
label: string;
|
|
131
|
+
/** Help text or description */
|
|
132
|
+
description?: string;
|
|
133
|
+
/** Placeholder text */
|
|
134
|
+
placeholder?: string;
|
|
135
|
+
/** Whether field is visible */
|
|
136
|
+
visible: boolean;
|
|
137
|
+
/** Whether field is enabled */
|
|
138
|
+
enabled: boolean;
|
|
139
|
+
/** Whether field is required */
|
|
140
|
+
required: boolean;
|
|
141
|
+
/** Whether field has been touched */
|
|
142
|
+
touched: boolean;
|
|
143
|
+
/** Validation errors for this field */
|
|
144
|
+
errors: FieldError[];
|
|
145
|
+
/** Handler for value changes */
|
|
146
|
+
onChange: (value: unknown) => void;
|
|
147
|
+
/** Handler for blur events */
|
|
148
|
+
onBlur: () => void;
|
|
149
|
+
/** Item index in the array */
|
|
150
|
+
itemIndex: number;
|
|
151
|
+
/** Field name within the item */
|
|
152
|
+
fieldName: string;
|
|
153
|
+
/** Options for select fields */
|
|
154
|
+
options?: SelectOption[];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Array manipulation helpers
|
|
158
|
+
*/
|
|
159
|
+
interface ArrayHelpers {
|
|
160
|
+
/** Current array items */
|
|
161
|
+
items: unknown[];
|
|
162
|
+
/** Add item to end of array */
|
|
163
|
+
push: (item?: unknown) => void;
|
|
164
|
+
/** Insert item at specific index */
|
|
165
|
+
insert: (index: number, item: unknown) => void;
|
|
166
|
+
/** Remove item at index */
|
|
167
|
+
remove: (index: number) => void;
|
|
168
|
+
/** Move item from one index to another */
|
|
169
|
+
move: (from: number, to: number) => void;
|
|
170
|
+
/** Swap items at two indices */
|
|
171
|
+
swap: (indexA: number, indexB: number) => void;
|
|
172
|
+
/** Get field props for an item field */
|
|
173
|
+
getItemFieldProps: (index: number, fieldName: string) => ArrayItemFieldPropsResult;
|
|
174
|
+
/** Minimum number of items allowed */
|
|
175
|
+
minItems: number;
|
|
176
|
+
/** Maximum number of items allowed */
|
|
177
|
+
maxItems: number;
|
|
178
|
+
/** Whether more items can be added */
|
|
179
|
+
canAdd: boolean;
|
|
180
|
+
/** Whether items can be removed */
|
|
181
|
+
canRemove: boolean;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Props for array fields
|
|
185
|
+
*/
|
|
186
|
+
interface ArrayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
187
|
+
fieldType: "array";
|
|
188
|
+
value: unknown[];
|
|
189
|
+
onChange: (value: unknown[]) => void;
|
|
190
|
+
helpers: ArrayHelpers;
|
|
191
|
+
/** Item field definitions keyed by field name */
|
|
192
|
+
itemFields: Record<string, FieldDefinition>;
|
|
193
|
+
minItems?: number;
|
|
194
|
+
maxItems?: number;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Props for object fields
|
|
198
|
+
*/
|
|
199
|
+
interface ObjectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
200
|
+
fieldType: "object";
|
|
201
|
+
value: Record<string, unknown>;
|
|
202
|
+
onChange: (value: Record<string, unknown>) => void;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Props for computed fields (read-only)
|
|
206
|
+
*/
|
|
207
|
+
interface ComputedFieldProps extends Omit<BaseFieldProps, "onChange"> {
|
|
208
|
+
fieldType: "computed";
|
|
209
|
+
value: unknown;
|
|
210
|
+
expression: string;
|
|
211
|
+
onChange?: never;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Props for array item fields (within array context)
|
|
215
|
+
*/
|
|
216
|
+
interface ArrayItemFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
217
|
+
/** The field type */
|
|
218
|
+
fieldType: string;
|
|
219
|
+
/** Current value */
|
|
220
|
+
value: unknown;
|
|
221
|
+
/** Change handler */
|
|
222
|
+
onChange: (value: unknown) => void;
|
|
223
|
+
/** Item index in the array */
|
|
224
|
+
itemIndex: number;
|
|
225
|
+
/** Field name within the item */
|
|
226
|
+
fieldName: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Union of all field prop types
|
|
230
|
+
*/
|
|
231
|
+
type FieldProps = TextFieldProps | NumberFieldProps | IntegerFieldProps | BooleanFieldProps | DateFieldProps | DateTimeFieldProps | SelectFieldProps | MultiSelectFieldProps | ArrayFieldProps | ObjectFieldProps | ComputedFieldProps;
|
|
232
|
+
/**
|
|
233
|
+
* Map of field types to React components
|
|
234
|
+
* Components receive wrapper props with { field, spec } structure
|
|
235
|
+
*/
|
|
236
|
+
interface ComponentMap {
|
|
237
|
+
text?: React.ComponentType<TextComponentProps>;
|
|
238
|
+
email?: React.ComponentType<TextComponentProps>;
|
|
239
|
+
password?: React.ComponentType<TextComponentProps>;
|
|
240
|
+
url?: React.ComponentType<TextComponentProps>;
|
|
241
|
+
textarea?: React.ComponentType<TextComponentProps>;
|
|
242
|
+
number?: React.ComponentType<NumberComponentProps>;
|
|
243
|
+
integer?: React.ComponentType<IntegerComponentProps>;
|
|
244
|
+
boolean?: React.ComponentType<BooleanComponentProps>;
|
|
245
|
+
date?: React.ComponentType<DateComponentProps>;
|
|
246
|
+
datetime?: React.ComponentType<DateTimeComponentProps>;
|
|
247
|
+
select?: React.ComponentType<SelectComponentProps>;
|
|
248
|
+
multiselect?: React.ComponentType<MultiSelectComponentProps>;
|
|
249
|
+
array?: React.ComponentType<ArrayComponentProps>;
|
|
250
|
+
object?: React.ComponentType<ObjectComponentProps>;
|
|
251
|
+
computed?: React.ComponentType<ComputedComponentProps>;
|
|
252
|
+
fallback?: React.ComponentType<FieldComponentProps>;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Props for custom layout components
|
|
256
|
+
*/
|
|
257
|
+
interface LayoutProps {
|
|
258
|
+
children: React.ReactNode;
|
|
259
|
+
onSubmit: () => void;
|
|
260
|
+
isSubmitting: boolean;
|
|
261
|
+
isValid: boolean;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Props for custom field wrapper components
|
|
265
|
+
*/
|
|
266
|
+
interface FieldWrapperProps {
|
|
267
|
+
/** Field path/identifier */
|
|
268
|
+
fieldPath: string;
|
|
269
|
+
/** Field definition from the Forma spec */
|
|
270
|
+
field: FieldDefinition;
|
|
271
|
+
children: React.ReactNode;
|
|
272
|
+
errors: FieldError[];
|
|
273
|
+
touched: boolean;
|
|
274
|
+
required: boolean;
|
|
275
|
+
visible: boolean;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Props for page wrapper components (multi-page forms)
|
|
279
|
+
*/
|
|
280
|
+
interface PageWrapperProps {
|
|
281
|
+
title: string;
|
|
282
|
+
description?: string;
|
|
283
|
+
children: React.ReactNode;
|
|
284
|
+
pageIndex: number;
|
|
285
|
+
totalPages: number;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Wrapper type that includes spec alongside field props
|
|
289
|
+
* Components receive { field, spec } instead of just FieldProps
|
|
290
|
+
*/
|
|
291
|
+
interface TextComponentProps {
|
|
292
|
+
field: TextFieldProps;
|
|
293
|
+
spec: Forma;
|
|
294
|
+
}
|
|
295
|
+
interface NumberComponentProps {
|
|
296
|
+
field: NumberFieldProps;
|
|
297
|
+
spec: Forma;
|
|
298
|
+
}
|
|
299
|
+
interface IntegerComponentProps {
|
|
300
|
+
field: IntegerFieldProps;
|
|
301
|
+
spec: Forma;
|
|
302
|
+
}
|
|
303
|
+
interface BooleanComponentProps {
|
|
304
|
+
field: BooleanFieldProps;
|
|
305
|
+
spec: Forma;
|
|
306
|
+
}
|
|
307
|
+
interface DateComponentProps {
|
|
308
|
+
field: DateFieldProps;
|
|
309
|
+
spec: Forma;
|
|
310
|
+
}
|
|
311
|
+
interface DateTimeComponentProps {
|
|
312
|
+
field: DateTimeFieldProps;
|
|
313
|
+
spec: Forma;
|
|
314
|
+
}
|
|
315
|
+
interface SelectComponentProps {
|
|
316
|
+
field: SelectFieldProps;
|
|
317
|
+
spec: Forma;
|
|
318
|
+
}
|
|
319
|
+
interface MultiSelectComponentProps {
|
|
320
|
+
field: MultiSelectFieldProps;
|
|
321
|
+
spec: Forma;
|
|
322
|
+
}
|
|
323
|
+
interface ArrayComponentProps {
|
|
324
|
+
field: ArrayFieldProps;
|
|
325
|
+
spec: Forma;
|
|
326
|
+
}
|
|
327
|
+
interface ObjectComponentProps {
|
|
328
|
+
field: ObjectFieldProps;
|
|
329
|
+
spec: Forma;
|
|
330
|
+
}
|
|
331
|
+
interface ComputedComponentProps {
|
|
332
|
+
field: ComputedFieldProps;
|
|
333
|
+
spec: Forma;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Generic field component props (for fallback/dynamic components)
|
|
337
|
+
*/
|
|
338
|
+
interface FieldComponentProps {
|
|
339
|
+
field: FieldProps;
|
|
340
|
+
spec: Forma;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Field props returned by getFieldProps()
|
|
345
|
+
* Contains all field information needed for rendering
|
|
346
|
+
*/
|
|
347
|
+
interface GetFieldPropsResult {
|
|
348
|
+
/** Field path/name */
|
|
349
|
+
name: string;
|
|
350
|
+
/** Current field value */
|
|
351
|
+
value: unknown;
|
|
352
|
+
/** Field type */
|
|
353
|
+
type: string;
|
|
354
|
+
/** Display label */
|
|
355
|
+
label: string;
|
|
356
|
+
/** Help text or description */
|
|
357
|
+
description?: string;
|
|
358
|
+
/** Placeholder text */
|
|
359
|
+
placeholder?: string;
|
|
360
|
+
/** Whether field is visible */
|
|
361
|
+
visible: boolean;
|
|
362
|
+
/** Whether field is enabled (not disabled) */
|
|
363
|
+
enabled: boolean;
|
|
364
|
+
/** Whether field is required */
|
|
365
|
+
required: boolean;
|
|
366
|
+
/** Whether field has been touched */
|
|
367
|
+
touched: boolean;
|
|
368
|
+
/** Validation errors for this field */
|
|
369
|
+
errors: FieldError[];
|
|
370
|
+
/** Handler for value changes */
|
|
371
|
+
onChange: (value: unknown) => void;
|
|
372
|
+
/** Handler for blur events */
|
|
373
|
+
onBlur: () => void;
|
|
374
|
+
/** ARIA: Indicates the field has validation errors */
|
|
375
|
+
"aria-invalid"?: boolean;
|
|
376
|
+
/** ARIA: ID of element(s) describing validation errors */
|
|
377
|
+
"aria-describedby"?: string;
|
|
378
|
+
/** ARIA: Indicates the field is required */
|
|
379
|
+
"aria-required"?: boolean;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Select field props returned by getSelectFieldProps()
|
|
383
|
+
*/
|
|
384
|
+
interface GetSelectFieldPropsResult extends GetFieldPropsResult {
|
|
385
|
+
/** Available options for selection */
|
|
386
|
+
options: SelectOption[];
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Array helpers returned by getArrayHelpers()
|
|
390
|
+
*/
|
|
391
|
+
interface GetArrayHelpersResult {
|
|
392
|
+
/** Current array items */
|
|
393
|
+
items: unknown[];
|
|
394
|
+
/** Add item to end of array */
|
|
395
|
+
push: (item: unknown) => void;
|
|
396
|
+
/** Remove item at index */
|
|
397
|
+
remove: (index: number) => void;
|
|
398
|
+
/** Move item from one index to another */
|
|
399
|
+
move: (from: number, to: number) => void;
|
|
400
|
+
/** Swap items at two indices */
|
|
401
|
+
swap: (indexA: number, indexB: number) => void;
|
|
402
|
+
/** Insert item at specific index */
|
|
403
|
+
insert: (index: number, item: unknown) => void;
|
|
404
|
+
/** Get field props for an item field */
|
|
405
|
+
getItemFieldProps: (index: number, fieldName: string) => GetFieldPropsResult;
|
|
406
|
+
/** Minimum number of items allowed */
|
|
407
|
+
minItems: number;
|
|
408
|
+
/** Maximum number of items allowed */
|
|
409
|
+
maxItems: number;
|
|
410
|
+
/** Whether more items can be added */
|
|
411
|
+
canAdd: boolean;
|
|
412
|
+
/** Whether items can be removed */
|
|
413
|
+
canRemove: boolean;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* @deprecated Use GetFieldPropsResult instead
|
|
417
|
+
*/
|
|
418
|
+
type LegacyFieldProps = GetFieldPropsResult;
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* useForma Hook
|
|
422
|
+
*
|
|
423
|
+
* Main hook for managing Forma form state.
|
|
424
|
+
* This is a placeholder - the full implementation will be migrated from formidable.
|
|
425
|
+
*/
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Options for useForma hook
|
|
429
|
+
*/
|
|
430
|
+
interface UseFormaOptions {
|
|
431
|
+
/** The Forma specification */
|
|
432
|
+
spec: Forma;
|
|
433
|
+
/** Initial form data */
|
|
434
|
+
initialData?: Record<string, unknown>;
|
|
435
|
+
/** Submit handler */
|
|
436
|
+
onSubmit?: (data: Record<string, unknown>) => void | Promise<void>;
|
|
437
|
+
/** Change handler */
|
|
438
|
+
onChange?: (data: Record<string, unknown>, computed?: Record<string, unknown>) => void;
|
|
439
|
+
/** When to validate: on change, blur, or submit only */
|
|
440
|
+
validateOn?: "change" | "blur" | "submit";
|
|
441
|
+
/** Additional reference data to merge with spec.referenceData */
|
|
442
|
+
referenceData?: Record<string, unknown>;
|
|
443
|
+
/**
|
|
444
|
+
* Debounce validation by this many milliseconds.
|
|
445
|
+
* Useful for large forms to improve performance.
|
|
446
|
+
* Set to 0 (default) for immediate validation.
|
|
447
|
+
*/
|
|
448
|
+
validationDebounceMs?: number;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Page state for multi-page forms
|
|
452
|
+
*/
|
|
453
|
+
interface PageState {
|
|
454
|
+
id: string;
|
|
455
|
+
title: string;
|
|
456
|
+
description?: string;
|
|
457
|
+
visible: boolean;
|
|
458
|
+
fields: string[];
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Wizard navigation helpers
|
|
462
|
+
*/
|
|
463
|
+
interface WizardHelpers {
|
|
464
|
+
pages: PageState[];
|
|
465
|
+
currentPageIndex: number;
|
|
466
|
+
currentPage: PageState | null;
|
|
467
|
+
goToPage: (index: number) => void;
|
|
468
|
+
nextPage: () => void;
|
|
469
|
+
previousPage: () => void;
|
|
470
|
+
hasNextPage: boolean;
|
|
471
|
+
hasPreviousPage: boolean;
|
|
472
|
+
canProceed: boolean;
|
|
473
|
+
isLastPage: boolean;
|
|
474
|
+
touchCurrentPageFields: () => void;
|
|
475
|
+
validateCurrentPage: () => boolean;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Return type of useForma hook
|
|
479
|
+
*/
|
|
480
|
+
interface UseFormaReturn {
|
|
481
|
+
/** Current form data */
|
|
482
|
+
data: Record<string, unknown>;
|
|
483
|
+
/** Computed field values */
|
|
484
|
+
computed: Record<string, unknown>;
|
|
485
|
+
/** Field visibility map */
|
|
486
|
+
visibility: Record<string, boolean>;
|
|
487
|
+
/** Field required state map */
|
|
488
|
+
required: Record<string, boolean>;
|
|
489
|
+
/** Field enabled state map */
|
|
490
|
+
enabled: Record<string, boolean>;
|
|
491
|
+
/** Field touched state map */
|
|
492
|
+
touched: Record<string, boolean>;
|
|
493
|
+
/** Validation errors */
|
|
494
|
+
errors: FieldError[];
|
|
495
|
+
/** Whether form is valid */
|
|
496
|
+
isValid: boolean;
|
|
497
|
+
/** Whether form is submitting */
|
|
498
|
+
isSubmitting: boolean;
|
|
499
|
+
/** Whether form has been submitted */
|
|
500
|
+
isSubmitted: boolean;
|
|
501
|
+
/** Whether any field has been modified */
|
|
502
|
+
isDirty: boolean;
|
|
503
|
+
/** The Forma spec */
|
|
504
|
+
spec: Forma;
|
|
505
|
+
/** Wizard helpers (if multi-page) */
|
|
506
|
+
wizard: WizardHelpers | null;
|
|
507
|
+
/** Set a field value */
|
|
508
|
+
setFieldValue: (path: string, value: unknown) => void;
|
|
509
|
+
/** Set a field as touched */
|
|
510
|
+
setFieldTouched: (path: string, touched?: boolean) => void;
|
|
511
|
+
/** Set multiple values */
|
|
512
|
+
setValues: (values: Record<string, unknown>) => void;
|
|
513
|
+
/** Validate a single field */
|
|
514
|
+
validateField: (path: string) => FieldError[];
|
|
515
|
+
/** Validate entire form */
|
|
516
|
+
validateForm: () => ValidationResult;
|
|
517
|
+
/** Submit the form */
|
|
518
|
+
submitForm: () => Promise<void>;
|
|
519
|
+
/** Reset the form */
|
|
520
|
+
resetForm: () => void;
|
|
521
|
+
/** Get props for any field */
|
|
522
|
+
getFieldProps: (path: string) => GetFieldPropsResult;
|
|
523
|
+
/** Get props for select field (includes options) */
|
|
524
|
+
getSelectFieldProps: (path: string) => GetSelectFieldPropsResult;
|
|
525
|
+
/** Get array helpers for array field */
|
|
526
|
+
getArrayHelpers: (path: string) => GetArrayHelpersResult;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Main Forma hook
|
|
530
|
+
*/
|
|
531
|
+
declare function useForma(options: UseFormaOptions): UseFormaReturn;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* FormRenderer Component
|
|
535
|
+
*
|
|
536
|
+
* Renders a complete form from a Forma specification.
|
|
537
|
+
* Supports single-page and multi-page (wizard) forms.
|
|
538
|
+
*/
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Props for FormRenderer component
|
|
542
|
+
*/
|
|
543
|
+
interface FormRendererProps {
|
|
544
|
+
/** The Forma specification */
|
|
545
|
+
spec: Forma;
|
|
546
|
+
/** Initial form data */
|
|
547
|
+
initialData?: Record<string, unknown>;
|
|
548
|
+
/** Submit handler */
|
|
549
|
+
onSubmit?: (data: Record<string, unknown>) => void | Promise<void>;
|
|
550
|
+
/** Change handler */
|
|
551
|
+
onChange?: (data: Record<string, unknown>, computed?: Record<string, unknown>) => void;
|
|
552
|
+
/** Component map for rendering fields */
|
|
553
|
+
components: ComponentMap;
|
|
554
|
+
/** Custom layout component */
|
|
555
|
+
layout?: React__default.ComponentType<LayoutProps>;
|
|
556
|
+
/** Custom field wrapper component */
|
|
557
|
+
fieldWrapper?: React__default.ComponentType<FieldWrapperProps>;
|
|
558
|
+
/** Custom page wrapper component */
|
|
559
|
+
pageWrapper?: React__default.ComponentType<PageWrapperProps>;
|
|
560
|
+
/** When to validate */
|
|
561
|
+
validateOn?: "change" | "blur" | "submit";
|
|
562
|
+
/** Current page for controlled wizard */
|
|
563
|
+
page?: number;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Imperative handle for FormRenderer
|
|
567
|
+
*/
|
|
568
|
+
interface FormRendererHandle {
|
|
569
|
+
submitForm: () => Promise<void>;
|
|
570
|
+
resetForm: () => void;
|
|
571
|
+
validateForm: () => ValidationResult;
|
|
572
|
+
focusField: (path: string) => void;
|
|
573
|
+
focusFirstError: () => void;
|
|
574
|
+
getValues: () => Record<string, unknown>;
|
|
575
|
+
setValues: (values: Record<string, unknown>) => void;
|
|
576
|
+
isValid: boolean;
|
|
577
|
+
isDirty: boolean;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* FormRenderer component
|
|
581
|
+
*/
|
|
582
|
+
declare const FormRenderer: React__default.ForwardRefExoticComponent<FormRendererProps & React__default.RefAttributes<FormRendererHandle>>;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Props for FieldRenderer component
|
|
586
|
+
*/
|
|
587
|
+
interface FieldRendererProps {
|
|
588
|
+
/** Field path (e.g., "firstName" or "address.city") */
|
|
589
|
+
fieldPath: string;
|
|
590
|
+
/** Component map for rendering fields */
|
|
591
|
+
components: ComponentMap;
|
|
592
|
+
/** Optional class name for the wrapper */
|
|
593
|
+
className?: string;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* FieldRenderer component
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```tsx
|
|
600
|
+
* // Render a specific field with custom components
|
|
601
|
+
* <FieldRenderer fieldPath="email" components={componentMap} />
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
declare function FieldRenderer({ fieldPath, components, className }: FieldRendererProps): react_jsx_runtime.JSX.Element | null;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* FormaErrorBoundary Component
|
|
608
|
+
*
|
|
609
|
+
* Error boundary for catching render errors in form components.
|
|
610
|
+
* Provides graceful error handling and recovery options.
|
|
611
|
+
*/
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Props for FormaErrorBoundary component
|
|
615
|
+
*/
|
|
616
|
+
interface FormaErrorBoundaryProps {
|
|
617
|
+
/** Child components to render */
|
|
618
|
+
children: React__default.ReactNode;
|
|
619
|
+
/** Custom fallback UI to show when an error occurs */
|
|
620
|
+
fallback?: React__default.ReactNode | ((error: Error, reset: () => void) => React__default.ReactNode);
|
|
621
|
+
/** Callback when an error is caught */
|
|
622
|
+
onError?: (error: Error, errorInfo: React__default.ErrorInfo) => void;
|
|
623
|
+
/** Key to reset the error boundary (change this to reset) */
|
|
624
|
+
resetKey?: string | number;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* State for FormaErrorBoundary component
|
|
628
|
+
*/
|
|
629
|
+
interface FormaErrorBoundaryState {
|
|
630
|
+
hasError: boolean;
|
|
631
|
+
error: Error | null;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Error boundary component for Forma forms
|
|
635
|
+
*
|
|
636
|
+
* Catches JavaScript errors in child component tree and displays
|
|
637
|
+
* a fallback UI instead of crashing the entire application.
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```tsx
|
|
641
|
+
* <FormaErrorBoundary
|
|
642
|
+
* fallback={<div>Form error occurred</div>}
|
|
643
|
+
* onError={(error) => logError(error)}
|
|
644
|
+
* >
|
|
645
|
+
* <FormRenderer spec={spec} components={components} />
|
|
646
|
+
* </FormaErrorBoundary>
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
declare class FormaErrorBoundary extends React__default.Component<FormaErrorBoundaryProps, FormaErrorBoundaryState> {
|
|
650
|
+
constructor(props: FormaErrorBoundaryProps);
|
|
651
|
+
static getDerivedStateFromError(error: Error): FormaErrorBoundaryState;
|
|
652
|
+
componentDidCatch(error: Error, errorInfo: React__default.ErrorInfo): void;
|
|
653
|
+
componentDidUpdate(prevProps: FormaErrorBoundaryProps): void;
|
|
654
|
+
reset: () => void;
|
|
655
|
+
render(): React__default.ReactNode;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Context for sharing form state across components
|
|
660
|
+
*/
|
|
661
|
+
declare const FormaContext: React$1.Context<UseFormaReturn | null>;
|
|
662
|
+
/**
|
|
663
|
+
* Hook to access Forma context
|
|
664
|
+
* @throws Error if used outside of FormaContext.Provider
|
|
665
|
+
*/
|
|
666
|
+
declare function useFormaContext(): UseFormaReturn;
|
|
667
|
+
|
|
668
|
+
export { type ArrayComponentProps, type ArrayFieldProps, type ArrayHelpers, type ArrayItemFieldProps, type ArrayItemFieldPropsResult, type BaseFieldProps, type BooleanComponentProps, type BooleanFieldProps, type ComponentMap, type ComputedComponentProps, type ComputedFieldProps, type DateComponentProps, type DateFieldProps, type DateTimeComponentProps, type DateTimeFieldProps, type FieldComponentProps, type FieldProps, FieldRenderer, type FieldRendererProps, type FieldWrapperProps, FormRenderer, type FormRendererHandle, type FormRendererProps, type UseFormaReturn as FormState, FormaContext, FormaErrorBoundary, type FormaErrorBoundaryProps, type GetArrayHelpersResult, type GetFieldPropsResult, type GetSelectFieldPropsResult, type IntegerComponentProps, type IntegerFieldProps, type LayoutProps, type LegacyFieldProps, type MultiSelectComponentProps, type MultiSelectFieldProps, type NumberComponentProps, type NumberFieldProps, type ObjectComponentProps, type ObjectFieldProps, type PageState, type PageWrapperProps, type SelectComponentProps, type SelectFieldProps, type SelectionFieldProps, type TextComponentProps, type TextFieldProps, type UseFormaOptions, type UseFormaReturn, type WizardHelpers, useForma, useFormaContext };
|