@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/src/context.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Context for Forma
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createContext, useContext } from "react";
|
|
6
|
+
import type { UseFormaReturn } from "./useForma.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Context for sharing form state across components
|
|
10
|
+
*/
|
|
11
|
+
export const FormaContext = createContext<UseFormaReturn | null>(null);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Hook to access Forma context
|
|
15
|
+
* @throws Error if used outside of FormaContext.Provider
|
|
16
|
+
*/
|
|
17
|
+
export function useFormaContext(): UseFormaReturn {
|
|
18
|
+
const context = useContext(FormaContext);
|
|
19
|
+
if (!context) {
|
|
20
|
+
throw new Error("useFormaContext must be used within a FormaContext.Provider");
|
|
21
|
+
}
|
|
22
|
+
return context;
|
|
23
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fogpipe/forma-react
|
|
3
|
+
*
|
|
4
|
+
* Headless React form renderer for Forma specifications.
|
|
5
|
+
* Provides hooks and components for building dynamic forms.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Re-export core types
|
|
9
|
+
export type {
|
|
10
|
+
Forma,
|
|
11
|
+
FieldDefinition,
|
|
12
|
+
FieldType,
|
|
13
|
+
FieldError,
|
|
14
|
+
ValidationResult,
|
|
15
|
+
ComputedField,
|
|
16
|
+
PageDefinition,
|
|
17
|
+
SelectOption,
|
|
18
|
+
ValidationRule,
|
|
19
|
+
} from "@fogpipe/forma-core";
|
|
20
|
+
|
|
21
|
+
// Hook
|
|
22
|
+
export { useForma } from "./useForma.js";
|
|
23
|
+
export type { UseFormaOptions, UseFormaReturn, PageState, WizardHelpers } from "./useForma.js";
|
|
24
|
+
|
|
25
|
+
// Components
|
|
26
|
+
export { FormRenderer } from "./FormRenderer.js";
|
|
27
|
+
export type { FormRendererProps, FormRendererHandle } from "./FormRenderer.js";
|
|
28
|
+
export { FieldRenderer } from "./FieldRenderer.js";
|
|
29
|
+
export type { FieldRendererProps } from "./FieldRenderer.js";
|
|
30
|
+
export { FormaErrorBoundary } from "./ErrorBoundary.js";
|
|
31
|
+
export type { FormaErrorBoundaryProps } from "./ErrorBoundary.js";
|
|
32
|
+
|
|
33
|
+
// Context
|
|
34
|
+
export { FormaContext, useFormaContext } from "./context.js";
|
|
35
|
+
|
|
36
|
+
// Types
|
|
37
|
+
export type {
|
|
38
|
+
// Base field props
|
|
39
|
+
BaseFieldProps,
|
|
40
|
+
|
|
41
|
+
// Helper method return types
|
|
42
|
+
GetFieldPropsResult,
|
|
43
|
+
GetSelectFieldPropsResult,
|
|
44
|
+
GetArrayHelpersResult,
|
|
45
|
+
|
|
46
|
+
// Deprecated alias
|
|
47
|
+
LegacyFieldProps,
|
|
48
|
+
|
|
49
|
+
// Discriminated field props (for type narrowing)
|
|
50
|
+
FieldProps,
|
|
51
|
+
TextFieldProps,
|
|
52
|
+
NumberFieldProps,
|
|
53
|
+
IntegerFieldProps,
|
|
54
|
+
BooleanFieldProps,
|
|
55
|
+
DateFieldProps,
|
|
56
|
+
DateTimeFieldProps,
|
|
57
|
+
SelectFieldProps,
|
|
58
|
+
MultiSelectFieldProps,
|
|
59
|
+
SelectionFieldProps,
|
|
60
|
+
ObjectFieldProps,
|
|
61
|
+
ComputedFieldProps,
|
|
62
|
+
|
|
63
|
+
// Array types
|
|
64
|
+
ArrayFieldProps,
|
|
65
|
+
ArrayHelpers,
|
|
66
|
+
ArrayItemFieldProps,
|
|
67
|
+
ArrayItemFieldPropsResult,
|
|
68
|
+
|
|
69
|
+
// Component props (wrapper types with spec)
|
|
70
|
+
FieldComponentProps,
|
|
71
|
+
TextComponentProps,
|
|
72
|
+
NumberComponentProps,
|
|
73
|
+
IntegerComponentProps,
|
|
74
|
+
BooleanComponentProps,
|
|
75
|
+
DateComponentProps,
|
|
76
|
+
DateTimeComponentProps,
|
|
77
|
+
SelectComponentProps,
|
|
78
|
+
MultiSelectComponentProps,
|
|
79
|
+
ArrayComponentProps,
|
|
80
|
+
ObjectComponentProps,
|
|
81
|
+
ComputedComponentProps,
|
|
82
|
+
ComponentMap,
|
|
83
|
+
|
|
84
|
+
// Form state
|
|
85
|
+
FormState,
|
|
86
|
+
|
|
87
|
+
// Renderer props
|
|
88
|
+
LayoutProps,
|
|
89
|
+
FieldWrapperProps,
|
|
90
|
+
PageWrapperProps,
|
|
91
|
+
} from "./types.js";
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for forma-react components
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Forma, FieldDefinition, FieldError, SelectOption } from "@fogpipe/forma-core";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base props shared by all field components
|
|
9
|
+
*/
|
|
10
|
+
export interface BaseFieldProps {
|
|
11
|
+
/** Field path/name */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Field definition from the Forma spec */
|
|
14
|
+
field: FieldDefinition;
|
|
15
|
+
/** Current field value */
|
|
16
|
+
value: unknown;
|
|
17
|
+
/** Whether the field has been touched */
|
|
18
|
+
touched: boolean;
|
|
19
|
+
/** Whether the field is required */
|
|
20
|
+
required: boolean;
|
|
21
|
+
/** Whether the field is disabled */
|
|
22
|
+
disabled: boolean;
|
|
23
|
+
/** Validation errors for this field */
|
|
24
|
+
errors: FieldError[];
|
|
25
|
+
/** Handler for value changes */
|
|
26
|
+
onChange: (value: unknown) => void;
|
|
27
|
+
/** Handler for blur events */
|
|
28
|
+
onBlur: () => void;
|
|
29
|
+
// Convenience properties (derived from field definition)
|
|
30
|
+
/** Whether field is visible (always true since FormRenderer handles visibility) */
|
|
31
|
+
visible: boolean;
|
|
32
|
+
/** Whether field is enabled (inverse of disabled) */
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
/** Display label from field definition */
|
|
35
|
+
label: string;
|
|
36
|
+
/** Help text or description from field definition */
|
|
37
|
+
description?: string;
|
|
38
|
+
/** Placeholder text from field definition */
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Props for text-based fields (text, email, password, url, textarea)
|
|
44
|
+
*/
|
|
45
|
+
export interface TextFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
46
|
+
fieldType: "text" | "email" | "password" | "url" | "textarea";
|
|
47
|
+
value: string;
|
|
48
|
+
onChange: (value: string) => void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Props for number fields
|
|
53
|
+
*/
|
|
54
|
+
export interface NumberFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
55
|
+
fieldType: "number";
|
|
56
|
+
value: number | null;
|
|
57
|
+
onChange: (value: number | null) => void;
|
|
58
|
+
min?: number;
|
|
59
|
+
max?: number;
|
|
60
|
+
step?: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Props for integer fields
|
|
65
|
+
*/
|
|
66
|
+
export 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
|
+
/**
|
|
75
|
+
* Props for boolean fields
|
|
76
|
+
*/
|
|
77
|
+
export interface BooleanFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
78
|
+
fieldType: "boolean";
|
|
79
|
+
value: boolean;
|
|
80
|
+
onChange: (value: boolean) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Props for date fields
|
|
85
|
+
*/
|
|
86
|
+
export interface DateFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
87
|
+
fieldType: "date";
|
|
88
|
+
value: string | null;
|
|
89
|
+
onChange: (value: string | null) => void;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Props for datetime fields
|
|
94
|
+
*/
|
|
95
|
+
export interface DateTimeFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
96
|
+
fieldType: "datetime";
|
|
97
|
+
value: string | null;
|
|
98
|
+
onChange: (value: string | null) => void;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Props for select fields (single selection)
|
|
103
|
+
*/
|
|
104
|
+
export interface SelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
105
|
+
fieldType: "select";
|
|
106
|
+
value: string | null;
|
|
107
|
+
onChange: (value: string | null) => void;
|
|
108
|
+
options: SelectOption[];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Props for multi-select fields
|
|
113
|
+
*/
|
|
114
|
+
export interface MultiSelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
115
|
+
fieldType: "multiselect";
|
|
116
|
+
value: string[];
|
|
117
|
+
onChange: (value: string[]) => void;
|
|
118
|
+
options: SelectOption[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Union type for all selection-based field props
|
|
123
|
+
*/
|
|
124
|
+
export type SelectionFieldProps = SelectFieldProps | MultiSelectFieldProps;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Array item field props returned by getItemFieldProps
|
|
128
|
+
*/
|
|
129
|
+
export interface ArrayItemFieldPropsResult {
|
|
130
|
+
/** Field path/name */
|
|
131
|
+
name: string;
|
|
132
|
+
/** Current field value */
|
|
133
|
+
value: unknown;
|
|
134
|
+
/** Field type */
|
|
135
|
+
type: string;
|
|
136
|
+
/** Display label */
|
|
137
|
+
label: string;
|
|
138
|
+
/** Help text or description */
|
|
139
|
+
description?: string;
|
|
140
|
+
/** Placeholder text */
|
|
141
|
+
placeholder?: string;
|
|
142
|
+
/** Whether field is visible */
|
|
143
|
+
visible: boolean;
|
|
144
|
+
/** Whether field is enabled */
|
|
145
|
+
enabled: boolean;
|
|
146
|
+
/** Whether field is required */
|
|
147
|
+
required: boolean;
|
|
148
|
+
/** Whether field has been touched */
|
|
149
|
+
touched: boolean;
|
|
150
|
+
/** Validation errors for this field */
|
|
151
|
+
errors: FieldError[];
|
|
152
|
+
/** Handler for value changes */
|
|
153
|
+
onChange: (value: unknown) => void;
|
|
154
|
+
/** Handler for blur events */
|
|
155
|
+
onBlur: () => void;
|
|
156
|
+
/** Item index in the array */
|
|
157
|
+
itemIndex: number;
|
|
158
|
+
/** Field name within the item */
|
|
159
|
+
fieldName: string;
|
|
160
|
+
/** Options for select fields */
|
|
161
|
+
options?: SelectOption[];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Array manipulation helpers
|
|
166
|
+
*/
|
|
167
|
+
export interface ArrayHelpers {
|
|
168
|
+
/** Current array items */
|
|
169
|
+
items: unknown[];
|
|
170
|
+
/** Add item to end of array */
|
|
171
|
+
push: (item?: unknown) => void;
|
|
172
|
+
/** Insert item at specific index */
|
|
173
|
+
insert: (index: number, item: unknown) => void;
|
|
174
|
+
/** Remove item at index */
|
|
175
|
+
remove: (index: number) => void;
|
|
176
|
+
/** Move item from one index to another */
|
|
177
|
+
move: (from: number, to: number) => void;
|
|
178
|
+
/** Swap items at two indices */
|
|
179
|
+
swap: (indexA: number, indexB: number) => void;
|
|
180
|
+
/** Get field props for an item field */
|
|
181
|
+
getItemFieldProps: (index: number, fieldName: string) => ArrayItemFieldPropsResult;
|
|
182
|
+
/** Minimum number of items allowed */
|
|
183
|
+
minItems: number;
|
|
184
|
+
/** Maximum number of items allowed */
|
|
185
|
+
maxItems: number;
|
|
186
|
+
/** Whether more items can be added */
|
|
187
|
+
canAdd: boolean;
|
|
188
|
+
/** Whether items can be removed */
|
|
189
|
+
canRemove: boolean;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Props for array fields
|
|
194
|
+
*/
|
|
195
|
+
export interface ArrayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
196
|
+
fieldType: "array";
|
|
197
|
+
value: unknown[];
|
|
198
|
+
onChange: (value: unknown[]) => void;
|
|
199
|
+
helpers: ArrayHelpers;
|
|
200
|
+
/** Item field definitions keyed by field name */
|
|
201
|
+
itemFields: Record<string, FieldDefinition>;
|
|
202
|
+
minItems?: number;
|
|
203
|
+
maxItems?: number;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Props for object fields
|
|
208
|
+
*/
|
|
209
|
+
export interface ObjectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
210
|
+
fieldType: "object";
|
|
211
|
+
value: Record<string, unknown>;
|
|
212
|
+
onChange: (value: Record<string, unknown>) => void;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Props for computed fields (read-only)
|
|
217
|
+
*/
|
|
218
|
+
export interface ComputedFieldProps extends Omit<BaseFieldProps, "onChange"> {
|
|
219
|
+
fieldType: "computed";
|
|
220
|
+
value: unknown;
|
|
221
|
+
expression: string;
|
|
222
|
+
onChange?: never;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Props for array item fields (within array context)
|
|
227
|
+
*/
|
|
228
|
+
export interface ArrayItemFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
|
|
229
|
+
/** The field type */
|
|
230
|
+
fieldType: string;
|
|
231
|
+
/** Current value */
|
|
232
|
+
value: unknown;
|
|
233
|
+
/** Change handler */
|
|
234
|
+
onChange: (value: unknown) => void;
|
|
235
|
+
/** Item index in the array */
|
|
236
|
+
itemIndex: number;
|
|
237
|
+
/** Field name within the item */
|
|
238
|
+
fieldName: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Union of all field prop types
|
|
243
|
+
*/
|
|
244
|
+
export type FieldProps =
|
|
245
|
+
| TextFieldProps
|
|
246
|
+
| NumberFieldProps
|
|
247
|
+
| IntegerFieldProps
|
|
248
|
+
| BooleanFieldProps
|
|
249
|
+
| DateFieldProps
|
|
250
|
+
| DateTimeFieldProps
|
|
251
|
+
| SelectFieldProps
|
|
252
|
+
| MultiSelectFieldProps
|
|
253
|
+
| ArrayFieldProps
|
|
254
|
+
| ObjectFieldProps
|
|
255
|
+
| ComputedFieldProps;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Map of field types to React components
|
|
259
|
+
* Components receive wrapper props with { field, spec } structure
|
|
260
|
+
*/
|
|
261
|
+
export interface ComponentMap {
|
|
262
|
+
text?: React.ComponentType<TextComponentProps>;
|
|
263
|
+
email?: React.ComponentType<TextComponentProps>;
|
|
264
|
+
password?: React.ComponentType<TextComponentProps>;
|
|
265
|
+
url?: React.ComponentType<TextComponentProps>;
|
|
266
|
+
textarea?: React.ComponentType<TextComponentProps>;
|
|
267
|
+
number?: React.ComponentType<NumberComponentProps>;
|
|
268
|
+
integer?: React.ComponentType<IntegerComponentProps>;
|
|
269
|
+
boolean?: React.ComponentType<BooleanComponentProps>;
|
|
270
|
+
date?: React.ComponentType<DateComponentProps>;
|
|
271
|
+
datetime?: React.ComponentType<DateTimeComponentProps>;
|
|
272
|
+
select?: React.ComponentType<SelectComponentProps>;
|
|
273
|
+
multiselect?: React.ComponentType<MultiSelectComponentProps>;
|
|
274
|
+
array?: React.ComponentType<ArrayComponentProps>;
|
|
275
|
+
object?: React.ComponentType<ObjectComponentProps>;
|
|
276
|
+
computed?: React.ComponentType<ComputedComponentProps>;
|
|
277
|
+
fallback?: React.ComponentType<FieldComponentProps>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Props for custom layout components
|
|
282
|
+
*/
|
|
283
|
+
export interface LayoutProps {
|
|
284
|
+
children: React.ReactNode;
|
|
285
|
+
onSubmit: () => void;
|
|
286
|
+
isSubmitting: boolean;
|
|
287
|
+
isValid: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Props for custom field wrapper components
|
|
292
|
+
*/
|
|
293
|
+
export interface FieldWrapperProps {
|
|
294
|
+
/** Field path/identifier */
|
|
295
|
+
fieldPath: string;
|
|
296
|
+
/** Field definition from the Forma spec */
|
|
297
|
+
field: FieldDefinition;
|
|
298
|
+
children: React.ReactNode;
|
|
299
|
+
errors: FieldError[];
|
|
300
|
+
touched: boolean;
|
|
301
|
+
required: boolean;
|
|
302
|
+
visible: boolean;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Props for page wrapper components (multi-page forms)
|
|
307
|
+
*/
|
|
308
|
+
export interface PageWrapperProps {
|
|
309
|
+
title: string;
|
|
310
|
+
description?: string;
|
|
311
|
+
children: React.ReactNode;
|
|
312
|
+
pageIndex: number;
|
|
313
|
+
totalPages: number;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ============================================================================
|
|
317
|
+
// Component Props (wrapper types that include spec)
|
|
318
|
+
// ============================================================================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Wrapper type that includes spec alongside field props
|
|
322
|
+
* Components receive { field, spec } instead of just FieldProps
|
|
323
|
+
*/
|
|
324
|
+
export interface TextComponentProps {
|
|
325
|
+
field: TextFieldProps;
|
|
326
|
+
spec: Forma;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface NumberComponentProps {
|
|
330
|
+
field: NumberFieldProps;
|
|
331
|
+
spec: Forma;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface IntegerComponentProps {
|
|
335
|
+
field: IntegerFieldProps;
|
|
336
|
+
spec: Forma;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface BooleanComponentProps {
|
|
340
|
+
field: BooleanFieldProps;
|
|
341
|
+
spec: Forma;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export interface DateComponentProps {
|
|
345
|
+
field: DateFieldProps;
|
|
346
|
+
spec: Forma;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export interface DateTimeComponentProps {
|
|
350
|
+
field: DateTimeFieldProps;
|
|
351
|
+
spec: Forma;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export interface SelectComponentProps {
|
|
355
|
+
field: SelectFieldProps;
|
|
356
|
+
spec: Forma;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export interface MultiSelectComponentProps {
|
|
360
|
+
field: MultiSelectFieldProps;
|
|
361
|
+
spec: Forma;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export interface ArrayComponentProps {
|
|
365
|
+
field: ArrayFieldProps;
|
|
366
|
+
spec: Forma;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export interface ObjectComponentProps {
|
|
370
|
+
field: ObjectFieldProps;
|
|
371
|
+
spec: Forma;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export interface ComputedComponentProps {
|
|
375
|
+
field: ComputedFieldProps;
|
|
376
|
+
spec: Forma;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Generic field component props (for fallback/dynamic components)
|
|
381
|
+
*/
|
|
382
|
+
export interface FieldComponentProps {
|
|
383
|
+
field: FieldProps;
|
|
384
|
+
spec: Forma;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// ============================================================================
|
|
388
|
+
// Re-exported types from useForma
|
|
389
|
+
// ============================================================================
|
|
390
|
+
|
|
391
|
+
/** Form state exported from useForma */
|
|
392
|
+
export type { UseFormaReturn as FormState } from "./useForma.js";
|
|
393
|
+
export type { UseFormaOptions } from "./useForma.js";
|
|
394
|
+
export type { PageState, WizardHelpers } from "./useForma.js";
|
|
395
|
+
|
|
396
|
+
// Re-export ValidationResult for convenience
|
|
397
|
+
export type { ValidationResult } from "@fogpipe/forma-core";
|
|
398
|
+
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Helper Method Return Types
|
|
401
|
+
// ============================================================================
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Field props returned by getFieldProps()
|
|
405
|
+
* Contains all field information needed for rendering
|
|
406
|
+
*/
|
|
407
|
+
export interface GetFieldPropsResult {
|
|
408
|
+
/** Field path/name */
|
|
409
|
+
name: string;
|
|
410
|
+
/** Current field value */
|
|
411
|
+
value: unknown;
|
|
412
|
+
/** Field type */
|
|
413
|
+
type: string;
|
|
414
|
+
/** Display label */
|
|
415
|
+
label: string;
|
|
416
|
+
/** Help text or description */
|
|
417
|
+
description?: string;
|
|
418
|
+
/** Placeholder text */
|
|
419
|
+
placeholder?: string;
|
|
420
|
+
/** Whether field is visible */
|
|
421
|
+
visible: boolean;
|
|
422
|
+
/** Whether field is enabled (not disabled) */
|
|
423
|
+
enabled: boolean;
|
|
424
|
+
/** Whether field is required */
|
|
425
|
+
required: boolean;
|
|
426
|
+
/** Whether field has been touched */
|
|
427
|
+
touched: boolean;
|
|
428
|
+
/** Validation errors for this field */
|
|
429
|
+
errors: FieldError[];
|
|
430
|
+
/** Handler for value changes */
|
|
431
|
+
onChange: (value: unknown) => void;
|
|
432
|
+
/** Handler for blur events */
|
|
433
|
+
onBlur: () => void;
|
|
434
|
+
// ARIA accessibility attributes
|
|
435
|
+
/** ARIA: Indicates the field has validation errors */
|
|
436
|
+
"aria-invalid"?: boolean;
|
|
437
|
+
/** ARIA: ID of element(s) describing validation errors */
|
|
438
|
+
"aria-describedby"?: string;
|
|
439
|
+
/** ARIA: Indicates the field is required */
|
|
440
|
+
"aria-required"?: boolean;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Select field props returned by getSelectFieldProps()
|
|
445
|
+
*/
|
|
446
|
+
export interface GetSelectFieldPropsResult extends GetFieldPropsResult {
|
|
447
|
+
/** Available options for selection */
|
|
448
|
+
options: SelectOption[];
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Array helpers returned by getArrayHelpers()
|
|
453
|
+
*/
|
|
454
|
+
export interface GetArrayHelpersResult {
|
|
455
|
+
/** Current array items */
|
|
456
|
+
items: unknown[];
|
|
457
|
+
/** Add item to end of array */
|
|
458
|
+
push: (item: unknown) => void;
|
|
459
|
+
/** Remove item at index */
|
|
460
|
+
remove: (index: number) => void;
|
|
461
|
+
/** Move item from one index to another */
|
|
462
|
+
move: (from: number, to: number) => void;
|
|
463
|
+
/** Swap items at two indices */
|
|
464
|
+
swap: (indexA: number, indexB: number) => void;
|
|
465
|
+
/** Insert item at specific index */
|
|
466
|
+
insert: (index: number, item: unknown) => void;
|
|
467
|
+
/** Get field props for an item field */
|
|
468
|
+
getItemFieldProps: (index: number, fieldName: string) => GetFieldPropsResult;
|
|
469
|
+
/** Minimum number of items allowed */
|
|
470
|
+
minItems: number;
|
|
471
|
+
/** Maximum number of items allowed */
|
|
472
|
+
maxItems: number;
|
|
473
|
+
/** Whether more items can be added */
|
|
474
|
+
canAdd: boolean;
|
|
475
|
+
/** Whether items can be removed */
|
|
476
|
+
canRemove: boolean;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* @deprecated Use GetFieldPropsResult instead
|
|
481
|
+
*/
|
|
482
|
+
export type LegacyFieldProps = GetFieldPropsResult;
|