@fogpipe/forma-react 0.17.1 → 0.19.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 +82 -0
- package/dist/FormRenderer-B7qwG4to.d.ts +566 -0
- package/dist/chunk-CFX3T5WK.js +1298 -0
- package/dist/chunk-CFX3T5WK.js.map +1 -0
- package/dist/defaults/index.d.ts +56 -0
- package/dist/defaults/index.js +899 -0
- package/dist/defaults/index.js.map +1 -0
- package/dist/defaults/styles/forma-defaults.css +696 -0
- package/dist/index.d.ts +7 -559
- package/dist/index.js +53 -1293
- package/dist/index.js.map +1 -1
- package/package.json +17 -3
- package/src/FieldRenderer.tsx +33 -1
- package/src/FormRenderer.tsx +35 -1
- package/src/__tests__/defaults/components.test.tsx +1074 -0
- package/src/__tests__/defaults/integration.test.tsx +626 -0
- package/src/__tests__/defaults/layout.test.tsx +298 -0
- package/src/__tests__/test-utils.tsx +4 -2
- package/src/defaults/DefaultFormRenderer.tsx +43 -0
- package/src/defaults/componentMap.ts +45 -0
- package/src/defaults/components/ArrayField.tsx +183 -0
- package/src/defaults/components/BooleanInput.tsx +32 -0
- package/src/defaults/components/ComputedDisplay.tsx +27 -0
- package/src/defaults/components/DateInput.tsx +59 -0
- package/src/defaults/components/DisplayField.tsx +22 -0
- package/src/defaults/components/FallbackField.tsx +35 -0
- package/src/defaults/components/MatrixField.tsx +98 -0
- package/src/defaults/components/MultiSelectInput.tsx +51 -0
- package/src/defaults/components/NumberInput.tsx +73 -0
- package/src/defaults/components/ObjectField.tsx +22 -0
- package/src/defaults/components/SelectInput.tsx +44 -0
- package/src/defaults/components/TextInput.tsx +48 -0
- package/src/defaults/components/TextareaInput.tsx +46 -0
- package/src/defaults/index.ts +33 -0
- package/src/defaults/layout/FieldWrapper.tsx +83 -0
- package/src/defaults/layout/FormLayout.tsx +34 -0
- package/src/defaults/layout/PageWrapper.tsx +18 -0
- package/src/defaults/layout/WizardLayout.tsx +130 -0
- package/src/defaults/styles/forma-defaults.css +696 -0
- package/src/types.ts +7 -0
package/README.md
CHANGED
|
@@ -354,6 +354,88 @@ The error boundary supports:
|
|
|
354
354
|
- `onError` callback for logging
|
|
355
355
|
- `resetKey` prop to reset error state
|
|
356
356
|
|
|
357
|
+
## Default Components
|
|
358
|
+
|
|
359
|
+
Don't want to build every field component yourself? The default component library gives you a working form in 2 lines:
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
import { DefaultFormRenderer } from "@fogpipe/forma-react/defaults";
|
|
363
|
+
import "@fogpipe/forma-react/defaults/styles.css";
|
|
364
|
+
|
|
365
|
+
<DefaultFormRenderer spec={formaSpec} onSubmit={handleSubmit} />;
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
This renders a fully styled, accessible form with all 18 field types, error handling, and wizard support — zero configuration.
|
|
369
|
+
|
|
370
|
+
### Override Individual Components
|
|
371
|
+
|
|
372
|
+
Swap any component while keeping the rest:
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { FormRenderer } from "@fogpipe/forma-react";
|
|
376
|
+
import {
|
|
377
|
+
defaultComponentMap,
|
|
378
|
+
defaultFieldWrapper,
|
|
379
|
+
defaultLayout,
|
|
380
|
+
} from "@fogpipe/forma-react/defaults";
|
|
381
|
+
import "@fogpipe/forma-react/defaults/styles.css";
|
|
382
|
+
|
|
383
|
+
const components = { ...defaultComponentMap, select: MyFancySelect };
|
|
384
|
+
|
|
385
|
+
<FormRenderer
|
|
386
|
+
spec={formaSpec}
|
|
387
|
+
components={components}
|
|
388
|
+
fieldWrapper={defaultFieldWrapper}
|
|
389
|
+
layout={defaultLayout}
|
|
390
|
+
onSubmit={handleSubmit}
|
|
391
|
+
/>;
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Wizard Forms
|
|
395
|
+
|
|
396
|
+
Enable wizard layout for multi-page forms:
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
<DefaultFormRenderer spec={wizardSpec} onSubmit={handleSubmit} wizardLayout />
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Theming
|
|
403
|
+
|
|
404
|
+
Override CSS variables to customize the look:
|
|
405
|
+
|
|
406
|
+
```css
|
|
407
|
+
:root {
|
|
408
|
+
--forma-color-primary: #7c3aed;
|
|
409
|
+
--forma-color-error: #e11d48;
|
|
410
|
+
--forma-radius: 12px;
|
|
411
|
+
--forma-font-family: "Inter", sans-serif;
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Dark mode works via `[data-theme="dark"]` attribute or `prefers-color-scheme: dark` media query.
|
|
416
|
+
|
|
417
|
+
### Component Reference
|
|
418
|
+
|
|
419
|
+
| Field Type | Component | Renders |
|
|
420
|
+
|---|---|---|
|
|
421
|
+
| `text`, `email`, `phone`, `url`, `password` | TextInput | `<input>` with type mapping |
|
|
422
|
+
| `textarea` | TextareaInput | `<textarea>` |
|
|
423
|
+
| `number` | NumberInput | `<input type="number">` with parseFloat |
|
|
424
|
+
| `integer` | IntegerInput | `<input type="number">` with parseInt |
|
|
425
|
+
| `boolean` | BooleanInput | Custom styled checkbox |
|
|
426
|
+
| `date` | DateInput | `<input type="date">` |
|
|
427
|
+
| `datetime` | DateTimeInput | `<input type="datetime-local">` |
|
|
428
|
+
| `select` | SelectInput | Native `<select>` with custom arrow |
|
|
429
|
+
| `multiselect` | MultiSelectInput | Checkbox group |
|
|
430
|
+
| `array` | ArrayField | Item list with Add/Remove |
|
|
431
|
+
| `object` | ObjectField | `<fieldset>` container |
|
|
432
|
+
| `computed` | ComputedDisplay | Read-only `<output>` |
|
|
433
|
+
| `display` | DisplayField | Static content `<div>` |
|
|
434
|
+
| `matrix` | MatrixField | `<table>` with radio/checkbox cells |
|
|
435
|
+
| `fallback` | FallbackField | Text input + dev warning |
|
|
436
|
+
|
|
437
|
+
See the [full documentation](https://docs.formidable.fogpipe.com/forma-react/default-components) for theming details, all CSS variables, and advanced usage.
|
|
438
|
+
|
|
357
439
|
## License
|
|
358
440
|
|
|
359
441
|
MIT
|
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { FieldError, SelectOption, FieldDefinition, Forma, FormatOptions, MatrixColumn, ValidationResult } from '@fogpipe/forma-core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Type definitions for forma-react components
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base props shared by all field components
|
|
10
|
+
*/
|
|
11
|
+
interface BaseFieldProps {
|
|
12
|
+
/** Field path/name */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Field definition from the Forma spec */
|
|
15
|
+
field: FieldDefinition;
|
|
16
|
+
/** Current field value */
|
|
17
|
+
value: unknown;
|
|
18
|
+
/** Whether the field has been touched */
|
|
19
|
+
touched: boolean;
|
|
20
|
+
/** Whether the field is required */
|
|
21
|
+
required: boolean;
|
|
22
|
+
/** Whether the field is disabled */
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
/** Validation errors for this field (always populated — use visibleErrors for display) */
|
|
25
|
+
errors: FieldError[];
|
|
26
|
+
/**
|
|
27
|
+
* Errors filtered by interaction state (touched or submitted).
|
|
28
|
+
* Use this for displaying errors in the UI to avoid showing errors on untouched fields.
|
|
29
|
+
*/
|
|
30
|
+
visibleErrors: FieldError[];
|
|
31
|
+
/** Handler for value changes */
|
|
32
|
+
onChange: (value: unknown) => void;
|
|
33
|
+
/** Handler for blur events */
|
|
34
|
+
onBlur: () => void;
|
|
35
|
+
/** Whether field is visible (always true since FormRenderer handles visibility) */
|
|
36
|
+
visible: boolean;
|
|
37
|
+
/** Whether field is enabled (inverse of disabled) */
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
/** Whether field is readonly (visible, not editable, value still submitted) */
|
|
40
|
+
readonly: boolean;
|
|
41
|
+
/** Display label from field definition */
|
|
42
|
+
label: string;
|
|
43
|
+
/** Help text or description from field definition */
|
|
44
|
+
description?: string;
|
|
45
|
+
/** Placeholder text from field definition */
|
|
46
|
+
placeholder?: string;
|
|
47
|
+
/** Prefix adorner text (e.g., "$") - only for adornable field types */
|
|
48
|
+
prefix?: string;
|
|
49
|
+
/** Suffix adorner text (e.g., "kg") - only for adornable field types */
|
|
50
|
+
suffix?: string;
|
|
51
|
+
/** Presentation variant hint (e.g., "slider", "radio", "nps") */
|
|
52
|
+
variant?: string;
|
|
53
|
+
/** Variant-specific configuration */
|
|
54
|
+
variantConfig?: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Props for text-based fields (text, email, password, url, textarea)
|
|
58
|
+
*/
|
|
59
|
+
interface TextFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
60
|
+
fieldType: "text" | "phone" | "email" | "password" | "url" | "textarea";
|
|
61
|
+
value: string;
|
|
62
|
+
onChange: (value: string) => void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Props for number fields
|
|
66
|
+
*/
|
|
67
|
+
interface NumberFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
68
|
+
fieldType: "number";
|
|
69
|
+
value: number | null;
|
|
70
|
+
onChange: (value: number | null) => void;
|
|
71
|
+
min?: number;
|
|
72
|
+
max?: number;
|
|
73
|
+
step?: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Props for integer fields
|
|
77
|
+
*/
|
|
78
|
+
interface IntegerFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
79
|
+
fieldType: "integer";
|
|
80
|
+
value: number | null;
|
|
81
|
+
onChange: (value: number | null) => void;
|
|
82
|
+
min?: number;
|
|
83
|
+
max?: number;
|
|
84
|
+
step?: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Props for boolean fields
|
|
88
|
+
*/
|
|
89
|
+
interface BooleanFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
90
|
+
fieldType: "boolean";
|
|
91
|
+
value: boolean;
|
|
92
|
+
onChange: (value: boolean) => void;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Props for date fields
|
|
96
|
+
*/
|
|
97
|
+
interface DateFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
98
|
+
fieldType: "date";
|
|
99
|
+
value: string | null;
|
|
100
|
+
onChange: (value: string | null) => void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Props for datetime fields
|
|
104
|
+
*/
|
|
105
|
+
interface DateTimeFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
106
|
+
fieldType: "datetime";
|
|
107
|
+
value: string | null;
|
|
108
|
+
onChange: (value: string | null) => void;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Props for select fields (single selection)
|
|
112
|
+
*/
|
|
113
|
+
interface SelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
114
|
+
fieldType: "select";
|
|
115
|
+
value: string | null;
|
|
116
|
+
onChange: (value: string | null) => void;
|
|
117
|
+
options: SelectOption[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Props for multi-select fields
|
|
121
|
+
*/
|
|
122
|
+
interface MultiSelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
123
|
+
fieldType: "multiselect";
|
|
124
|
+
value: string[];
|
|
125
|
+
onChange: (value: string[]) => void;
|
|
126
|
+
options: SelectOption[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Union type for all selection-based field props
|
|
130
|
+
*/
|
|
131
|
+
type SelectionFieldProps = SelectFieldProps | MultiSelectFieldProps;
|
|
132
|
+
/**
|
|
133
|
+
* Array item field props returned by getItemFieldProps
|
|
134
|
+
*/
|
|
135
|
+
interface ArrayItemFieldPropsResult {
|
|
136
|
+
/** Field path/name */
|
|
137
|
+
name: string;
|
|
138
|
+
/** Current field value */
|
|
139
|
+
value: unknown;
|
|
140
|
+
/** Field type */
|
|
141
|
+
type: string;
|
|
142
|
+
/** Display label */
|
|
143
|
+
label: string;
|
|
144
|
+
/** Help text or description */
|
|
145
|
+
description?: string;
|
|
146
|
+
/** Placeholder text */
|
|
147
|
+
placeholder?: string;
|
|
148
|
+
/** Whether field is visible */
|
|
149
|
+
visible: boolean;
|
|
150
|
+
/** Whether field is enabled */
|
|
151
|
+
enabled: boolean;
|
|
152
|
+
/** Whether field is required */
|
|
153
|
+
required: boolean;
|
|
154
|
+
/** Whether field has been touched */
|
|
155
|
+
touched: boolean;
|
|
156
|
+
/** Validation errors for this field */
|
|
157
|
+
errors: FieldError[];
|
|
158
|
+
/** Handler for value changes */
|
|
159
|
+
onChange: (value: unknown) => void;
|
|
160
|
+
/** Handler for blur events */
|
|
161
|
+
onBlur: () => void;
|
|
162
|
+
/** Item index in the array */
|
|
163
|
+
itemIndex: number;
|
|
164
|
+
/** Field name within the item */
|
|
165
|
+
fieldName: string;
|
|
166
|
+
/** Options for select fields */
|
|
167
|
+
options?: SelectOption[];
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Array manipulation helpers
|
|
171
|
+
*/
|
|
172
|
+
interface ArrayHelpers {
|
|
173
|
+
/** Current array items */
|
|
174
|
+
items: unknown[];
|
|
175
|
+
/** Add item to end of array */
|
|
176
|
+
push: (item?: unknown) => void;
|
|
177
|
+
/** Insert item at specific index */
|
|
178
|
+
insert: (index: number, item: unknown) => void;
|
|
179
|
+
/** Remove item at index */
|
|
180
|
+
remove: (index: number) => void;
|
|
181
|
+
/** Move item from one index to another */
|
|
182
|
+
move: (from: number, to: number) => void;
|
|
183
|
+
/** Swap items at two indices */
|
|
184
|
+
swap: (indexA: number, indexB: number) => void;
|
|
185
|
+
/** Get field props for an item field */
|
|
186
|
+
getItemFieldProps: (index: number, fieldName: string) => ArrayItemFieldPropsResult;
|
|
187
|
+
/** Minimum number of items allowed */
|
|
188
|
+
minItems: number;
|
|
189
|
+
/** Maximum number of items allowed */
|
|
190
|
+
maxItems: number;
|
|
191
|
+
/** Whether more items can be added */
|
|
192
|
+
canAdd: boolean;
|
|
193
|
+
/** Whether items can be removed */
|
|
194
|
+
canRemove: boolean;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Props for array fields
|
|
198
|
+
*/
|
|
199
|
+
interface ArrayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
200
|
+
fieldType: "array";
|
|
201
|
+
value: unknown[];
|
|
202
|
+
onChange: (value: unknown[]) => void;
|
|
203
|
+
helpers: ArrayHelpers;
|
|
204
|
+
/** Item field definitions keyed by field name */
|
|
205
|
+
itemFields: Record<string, FieldDefinition>;
|
|
206
|
+
/** Explicit ordering for itemFields (jsonb does not preserve object key order) */
|
|
207
|
+
itemFieldOrder?: string[];
|
|
208
|
+
minItems?: number;
|
|
209
|
+
maxItems?: number;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Props for object fields
|
|
213
|
+
*/
|
|
214
|
+
interface ObjectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
215
|
+
fieldType: "object";
|
|
216
|
+
value: Record<string, unknown>;
|
|
217
|
+
onChange: (value: Record<string, unknown>) => void;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Props for computed fields (read-only)
|
|
221
|
+
*/
|
|
222
|
+
interface ComputedFieldProps extends Omit<BaseFieldProps, "onChange"> {
|
|
223
|
+
fieldType: "computed";
|
|
224
|
+
value: unknown;
|
|
225
|
+
expression: string;
|
|
226
|
+
/** Display format string (e.g., "currency", "percent", "decimal(2)") */
|
|
227
|
+
format?: string;
|
|
228
|
+
/** Resolved format options (locale, currency) for number/date formatting */
|
|
229
|
+
formatOptions?: FormatOptions;
|
|
230
|
+
onChange?: never;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Props for array item fields (within array context)
|
|
234
|
+
*/
|
|
235
|
+
interface ArrayItemFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
236
|
+
/** The field type */
|
|
237
|
+
fieldType: string;
|
|
238
|
+
/** Current value */
|
|
239
|
+
value: unknown;
|
|
240
|
+
/** Change handler */
|
|
241
|
+
onChange: (value: unknown) => void;
|
|
242
|
+
/** Item index in the array */
|
|
243
|
+
itemIndex: number;
|
|
244
|
+
/** Field name within the item */
|
|
245
|
+
fieldName: string;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Props for display fields (read-only presentation content)
|
|
249
|
+
*/
|
|
250
|
+
interface DisplayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
251
|
+
fieldType: "display";
|
|
252
|
+
/** Static content (markdown/text) */
|
|
253
|
+
content?: string;
|
|
254
|
+
/** Computed source value (resolved by useForma from display field's source property) */
|
|
255
|
+
sourceValue?: unknown;
|
|
256
|
+
/** Display format string */
|
|
257
|
+
format?: string;
|
|
258
|
+
/** Resolved format options (locale, currency) for number/date formatting */
|
|
259
|
+
formatOptions?: FormatOptions;
|
|
260
|
+
/** No onChange - display fields are read-only */
|
|
261
|
+
onChange?: never;
|
|
262
|
+
value?: never;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Props for matrix/grid fields
|
|
266
|
+
*/
|
|
267
|
+
interface MatrixFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
268
|
+
fieldType: "matrix";
|
|
269
|
+
/** Current matrix value: row ID → selected column value(s) */
|
|
270
|
+
value: Record<string, string | number | string[] | number[]> | null;
|
|
271
|
+
onChange: (value: Record<string, string | number | string[] | number[]>) => void;
|
|
272
|
+
/** Row definitions with visibility state */
|
|
273
|
+
rows: Array<{
|
|
274
|
+
id: string;
|
|
275
|
+
label: string;
|
|
276
|
+
visible: boolean;
|
|
277
|
+
}>;
|
|
278
|
+
/** Column definitions (shared options for all rows) */
|
|
279
|
+
columns: MatrixColumn[];
|
|
280
|
+
/** Whether multiple selections per row are allowed */
|
|
281
|
+
multiSelect: boolean;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Union of all field prop types
|
|
285
|
+
*/
|
|
286
|
+
type FieldProps = TextFieldProps | NumberFieldProps | IntegerFieldProps | BooleanFieldProps | DateFieldProps | DateTimeFieldProps | SelectFieldProps | MultiSelectFieldProps | ArrayFieldProps | ObjectFieldProps | ComputedFieldProps | DisplayFieldProps | MatrixFieldProps;
|
|
287
|
+
/**
|
|
288
|
+
* Map of field types to React components
|
|
289
|
+
* Components receive wrapper props with { field, spec } structure
|
|
290
|
+
*/
|
|
291
|
+
interface ComponentMap {
|
|
292
|
+
text?: React.ComponentType<TextComponentProps>;
|
|
293
|
+
phone?: React.ComponentType<TextComponentProps>;
|
|
294
|
+
email?: React.ComponentType<TextComponentProps>;
|
|
295
|
+
password?: React.ComponentType<TextComponentProps>;
|
|
296
|
+
url?: React.ComponentType<TextComponentProps>;
|
|
297
|
+
textarea?: React.ComponentType<TextComponentProps>;
|
|
298
|
+
number?: React.ComponentType<NumberComponentProps>;
|
|
299
|
+
integer?: React.ComponentType<IntegerComponentProps>;
|
|
300
|
+
boolean?: React.ComponentType<BooleanComponentProps>;
|
|
301
|
+
date?: React.ComponentType<DateComponentProps>;
|
|
302
|
+
datetime?: React.ComponentType<DateTimeComponentProps>;
|
|
303
|
+
select?: React.ComponentType<SelectComponentProps>;
|
|
304
|
+
multiselect?: React.ComponentType<MultiSelectComponentProps>;
|
|
305
|
+
array?: React.ComponentType<ArrayComponentProps>;
|
|
306
|
+
object?: React.ComponentType<ObjectComponentProps>;
|
|
307
|
+
computed?: React.ComponentType<ComputedComponentProps>;
|
|
308
|
+
display?: React.ComponentType<DisplayComponentProps>;
|
|
309
|
+
matrix?: React.ComponentType<MatrixComponentProps>;
|
|
310
|
+
fallback?: React.ComponentType<FieldComponentProps>;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Props for custom layout components
|
|
314
|
+
*/
|
|
315
|
+
interface LayoutProps {
|
|
316
|
+
children: React.ReactNode;
|
|
317
|
+
onSubmit: (e?: React.FormEvent) => void;
|
|
318
|
+
isSubmitting: boolean;
|
|
319
|
+
isValid: boolean;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Props for custom field wrapper components
|
|
323
|
+
*/
|
|
324
|
+
interface FieldWrapperProps {
|
|
325
|
+
/** Field path/identifier */
|
|
326
|
+
fieldPath: string;
|
|
327
|
+
/** Field definition from the Forma spec */
|
|
328
|
+
field: FieldDefinition;
|
|
329
|
+
children: React.ReactNode;
|
|
330
|
+
errors: FieldError[];
|
|
331
|
+
touched: boolean;
|
|
332
|
+
required: boolean;
|
|
333
|
+
/**
|
|
334
|
+
* Whether to show the required indicator in the UI.
|
|
335
|
+
* False for boolean fields since false is a valid answer.
|
|
336
|
+
*/
|
|
337
|
+
showRequiredIndicator: boolean;
|
|
338
|
+
visible: boolean;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Props for page wrapper components (multi-page forms)
|
|
342
|
+
*/
|
|
343
|
+
interface PageWrapperProps {
|
|
344
|
+
title: string;
|
|
345
|
+
description?: string;
|
|
346
|
+
children: React.ReactNode;
|
|
347
|
+
pageIndex: number;
|
|
348
|
+
totalPages: number;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Wrapper type that includes spec alongside field props
|
|
352
|
+
* Components receive { field, spec } instead of just FieldProps
|
|
353
|
+
*/
|
|
354
|
+
interface TextComponentProps {
|
|
355
|
+
field: TextFieldProps;
|
|
356
|
+
spec: Forma;
|
|
357
|
+
}
|
|
358
|
+
interface NumberComponentProps {
|
|
359
|
+
field: NumberFieldProps;
|
|
360
|
+
spec: Forma;
|
|
361
|
+
}
|
|
362
|
+
interface IntegerComponentProps {
|
|
363
|
+
field: IntegerFieldProps;
|
|
364
|
+
spec: Forma;
|
|
365
|
+
}
|
|
366
|
+
interface BooleanComponentProps {
|
|
367
|
+
field: BooleanFieldProps;
|
|
368
|
+
spec: Forma;
|
|
369
|
+
}
|
|
370
|
+
interface DateComponentProps {
|
|
371
|
+
field: DateFieldProps;
|
|
372
|
+
spec: Forma;
|
|
373
|
+
}
|
|
374
|
+
interface DateTimeComponentProps {
|
|
375
|
+
field: DateTimeFieldProps;
|
|
376
|
+
spec: Forma;
|
|
377
|
+
}
|
|
378
|
+
interface SelectComponentProps {
|
|
379
|
+
field: SelectFieldProps;
|
|
380
|
+
spec: Forma;
|
|
381
|
+
}
|
|
382
|
+
interface MultiSelectComponentProps {
|
|
383
|
+
field: MultiSelectFieldProps;
|
|
384
|
+
spec: Forma;
|
|
385
|
+
}
|
|
386
|
+
interface ArrayComponentProps {
|
|
387
|
+
field: ArrayFieldProps;
|
|
388
|
+
spec: Forma;
|
|
389
|
+
}
|
|
390
|
+
interface ObjectComponentProps {
|
|
391
|
+
field: ObjectFieldProps;
|
|
392
|
+
spec: Forma;
|
|
393
|
+
}
|
|
394
|
+
interface ComputedComponentProps {
|
|
395
|
+
field: ComputedFieldProps;
|
|
396
|
+
spec: Forma;
|
|
397
|
+
}
|
|
398
|
+
interface DisplayComponentProps {
|
|
399
|
+
field: DisplayFieldProps;
|
|
400
|
+
spec: Forma;
|
|
401
|
+
}
|
|
402
|
+
interface MatrixComponentProps {
|
|
403
|
+
field: MatrixFieldProps;
|
|
404
|
+
spec: Forma;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Generic field component props (for fallback/dynamic components)
|
|
408
|
+
*/
|
|
409
|
+
interface FieldComponentProps {
|
|
410
|
+
field: FieldProps;
|
|
411
|
+
spec: Forma;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Field props returned by getFieldProps()
|
|
416
|
+
* Contains all field information needed for rendering
|
|
417
|
+
*/
|
|
418
|
+
interface GetFieldPropsResult {
|
|
419
|
+
/** Field path/name */
|
|
420
|
+
name: string;
|
|
421
|
+
/** Current field value */
|
|
422
|
+
value: unknown;
|
|
423
|
+
/** Field type */
|
|
424
|
+
type: string;
|
|
425
|
+
/** Display label */
|
|
426
|
+
label: string;
|
|
427
|
+
/** Help text or description */
|
|
428
|
+
description?: string;
|
|
429
|
+
/** Placeholder text */
|
|
430
|
+
placeholder?: string;
|
|
431
|
+
/** Whether field is visible */
|
|
432
|
+
visible: boolean;
|
|
433
|
+
/** Whether field is enabled (not disabled) */
|
|
434
|
+
enabled: boolean;
|
|
435
|
+
/** Whether field is readonly (visible, not editable, value still submitted) */
|
|
436
|
+
readonly: boolean;
|
|
437
|
+
/** Whether field is required (for validation) */
|
|
438
|
+
required: boolean;
|
|
439
|
+
/**
|
|
440
|
+
* Whether to show the required indicator in the UI.
|
|
441
|
+
* False for boolean fields since false is a valid answer.
|
|
442
|
+
*/
|
|
443
|
+
showRequiredIndicator: boolean;
|
|
444
|
+
/** Whether field has been touched */
|
|
445
|
+
touched: boolean;
|
|
446
|
+
/** Validation errors for this field (always populated — use visibleErrors for display) */
|
|
447
|
+
errors: FieldError[];
|
|
448
|
+
/**
|
|
449
|
+
* Errors filtered by interaction state (touched or submitted).
|
|
450
|
+
* Use this for displaying errors in the UI to avoid showing errors on untouched fields.
|
|
451
|
+
*/
|
|
452
|
+
visibleErrors: FieldError[];
|
|
453
|
+
/** Handler for value changes */
|
|
454
|
+
onChange: (value: unknown) => void;
|
|
455
|
+
/** Handler for blur events */
|
|
456
|
+
onBlur: () => void;
|
|
457
|
+
/** ARIA: Indicates the field has validation errors */
|
|
458
|
+
"aria-invalid"?: boolean;
|
|
459
|
+
/** ARIA: ID of element(s) describing validation errors */
|
|
460
|
+
"aria-describedby"?: string;
|
|
461
|
+
/** ARIA: Indicates the field is required */
|
|
462
|
+
"aria-required"?: boolean;
|
|
463
|
+
/** Options for select/multiselect fields (filtered by visibleWhen) */
|
|
464
|
+
options?: SelectOption[];
|
|
465
|
+
/** Prefix adorner text (e.g., "$") */
|
|
466
|
+
prefix?: string;
|
|
467
|
+
/** Suffix adorner text (e.g., "kg") */
|
|
468
|
+
suffix?: string;
|
|
469
|
+
/** Presentation variant hint */
|
|
470
|
+
variant?: string;
|
|
471
|
+
/** Variant-specific configuration */
|
|
472
|
+
variantConfig?: Record<string, unknown>;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Select field props returned by getSelectFieldProps()
|
|
476
|
+
*/
|
|
477
|
+
interface GetSelectFieldPropsResult extends GetFieldPropsResult {
|
|
478
|
+
/** Available options for selection */
|
|
479
|
+
options: SelectOption[];
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Array helpers returned by getArrayHelpers()
|
|
483
|
+
*/
|
|
484
|
+
interface GetArrayHelpersResult {
|
|
485
|
+
/** Current array items */
|
|
486
|
+
items: unknown[];
|
|
487
|
+
/** Add item to end of array */
|
|
488
|
+
push: (item: unknown) => void;
|
|
489
|
+
/** Remove item at index */
|
|
490
|
+
remove: (index: number) => void;
|
|
491
|
+
/** Move item from one index to another */
|
|
492
|
+
move: (from: number, to: number) => void;
|
|
493
|
+
/** Swap items at two indices */
|
|
494
|
+
swap: (indexA: number, indexB: number) => void;
|
|
495
|
+
/** Insert item at specific index */
|
|
496
|
+
insert: (index: number, item: unknown) => void;
|
|
497
|
+
/** Get field props for an item field */
|
|
498
|
+
getItemFieldProps: (index: number, fieldName: string) => GetFieldPropsResult;
|
|
499
|
+
/** Minimum number of items allowed */
|
|
500
|
+
minItems: number;
|
|
501
|
+
/** Maximum number of items allowed */
|
|
502
|
+
maxItems: number;
|
|
503
|
+
/** Whether more items can be added */
|
|
504
|
+
canAdd: boolean;
|
|
505
|
+
/** Whether items can be removed */
|
|
506
|
+
canRemove: boolean;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* @deprecated Use GetFieldPropsResult instead
|
|
510
|
+
*/
|
|
511
|
+
type LegacyFieldProps = GetFieldPropsResult;
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* FormRenderer Component
|
|
515
|
+
*
|
|
516
|
+
* Renders a complete form from a Forma specification.
|
|
517
|
+
* Supports single-page and multi-page (wizard) forms.
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Props for FormRenderer component
|
|
522
|
+
*/
|
|
523
|
+
interface FormRendererProps {
|
|
524
|
+
/** The Forma specification */
|
|
525
|
+
spec: Forma;
|
|
526
|
+
/** Initial form data */
|
|
527
|
+
initialData?: Record<string, unknown>;
|
|
528
|
+
/** Submit handler */
|
|
529
|
+
onSubmit?: (data: Record<string, unknown>) => void | Promise<void>;
|
|
530
|
+
/** Change handler */
|
|
531
|
+
onChange?: (data: Record<string, unknown>, computed?: Record<string, unknown>) => void;
|
|
532
|
+
/** Component map for rendering fields */
|
|
533
|
+
components: ComponentMap;
|
|
534
|
+
/** Custom layout component */
|
|
535
|
+
layout?: React__default.ComponentType<LayoutProps>;
|
|
536
|
+
/** Custom field wrapper component */
|
|
537
|
+
fieldWrapper?: React__default.ComponentType<FieldWrapperProps>;
|
|
538
|
+
/** Custom page wrapper component */
|
|
539
|
+
pageWrapper?: React__default.ComponentType<PageWrapperProps>;
|
|
540
|
+
/** When to validate */
|
|
541
|
+
validateOn?: "change" | "blur" | "submit";
|
|
542
|
+
/** Current page for controlled wizard */
|
|
543
|
+
page?: number;
|
|
544
|
+
/** Format options for number/currency/date display (overrides spec.meta.locale/currency) */
|
|
545
|
+
formatOptions?: FormatOptions;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Imperative handle for FormRenderer
|
|
549
|
+
*/
|
|
550
|
+
interface FormRendererHandle {
|
|
551
|
+
submitForm: () => Promise<void>;
|
|
552
|
+
resetForm: () => void;
|
|
553
|
+
validateForm: () => ValidationResult;
|
|
554
|
+
focusField: (path: string) => void;
|
|
555
|
+
focusFirstError: () => void;
|
|
556
|
+
getValues: () => Record<string, unknown>;
|
|
557
|
+
setValues: (values: Record<string, unknown>) => void;
|
|
558
|
+
isValid: boolean;
|
|
559
|
+
isDirty: boolean;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* FormRenderer component
|
|
563
|
+
*/
|
|
564
|
+
declare const FormRenderer: React__default.ForwardRefExoticComponent<FormRendererProps & React__default.RefAttributes<FormRendererHandle>>;
|
|
565
|
+
|
|
566
|
+
export { type ArrayFieldProps as A, type BaseFieldProps as B, type ComponentMap as C, type DateFieldProps as D, type MatrixFieldProps as E, FormRenderer as F, type GetFieldPropsResult as G, type MatrixComponentProps as H, type IntegerFieldProps as I, type LayoutProps as J, type FieldWrapperProps as K, type LegacyFieldProps as L, type MultiSelectFieldProps as M, type NumberFieldProps as N, type ObjectFieldProps as O, type PageWrapperProps as P, type SelectFieldProps as S, type TextFieldProps as T, type GetSelectFieldPropsResult as a, type GetArrayHelpersResult as b, type FormRendererProps as c, type FormRendererHandle as d, type FieldProps as e, type BooleanFieldProps as f, type DateTimeFieldProps as g, type SelectionFieldProps as h, type ComputedFieldProps as i, type ArrayHelpers as j, type ArrayItemFieldProps as k, type ArrayItemFieldPropsResult as l, type FieldComponentProps as m, type TextComponentProps as n, type NumberComponentProps as o, type IntegerComponentProps as p, type BooleanComponentProps as q, type DateComponentProps as r, type DateTimeComponentProps as s, type SelectComponentProps as t, type MultiSelectComponentProps as u, type ArrayComponentProps as v, type ObjectComponentProps as w, type ComputedComponentProps as x, type DisplayFieldProps as y, type DisplayComponentProps as z };
|