@fogpipe/forma-react 0.12.0-alpha.2 → 0.13.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/src/context.ts CHANGED
@@ -17,7 +17,9 @@ export const FormaContext = createContext<UseFormaReturn | null>(null);
17
17
  export function useFormaContext(): UseFormaReturn {
18
18
  const context = useContext(FormaContext);
19
19
  if (!context) {
20
- throw new Error("useFormaContext must be used within a FormaContext.Provider");
20
+ throw new Error(
21
+ "useFormaContext must be used within a FormaContext.Provider",
22
+ );
21
23
  }
22
24
  return context;
23
25
  }
package/src/index.ts CHANGED
@@ -20,7 +20,12 @@ export type {
20
20
 
21
21
  // Hook
22
22
  export { useForma } from "./useForma.js";
23
- export type { UseFormaOptions, UseFormaReturn, PageState, WizardHelpers } from "./useForma.js";
23
+ export type {
24
+ UseFormaOptions,
25
+ UseFormaReturn,
26
+ PageState,
27
+ WizardHelpers,
28
+ } from "./useForma.js";
24
29
 
25
30
  // Components
26
31
  export { FormRenderer } from "./FormRenderer.js";
package/src/types.ts CHANGED
@@ -2,7 +2,12 @@
2
2
  * Type definitions for forma-react components
3
3
  */
4
4
 
5
- import type { Forma, FieldDefinition, FieldError, SelectOption } from "@fogpipe/forma-core";
5
+ import type {
6
+ Forma,
7
+ FieldDefinition,
8
+ FieldError,
9
+ SelectOption,
10
+ } from "@fogpipe/forma-core";
6
11
 
7
12
  /**
8
13
  * Base props shared by all field components
@@ -52,7 +57,10 @@ export interface BaseFieldProps {
52
57
  /**
53
58
  * Props for text-based fields (text, email, password, url, textarea)
54
59
  */
55
- export interface TextFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
60
+ export interface TextFieldProps extends Omit<
61
+ BaseFieldProps,
62
+ "value" | "onChange"
63
+ > {
56
64
  fieldType: "text" | "email" | "password" | "url" | "textarea";
57
65
  value: string;
58
66
  onChange: (value: string) => void;
@@ -61,7 +69,10 @@ export interface TextFieldProps extends Omit<BaseFieldProps, "value" | "onChange
61
69
  /**
62
70
  * Props for number fields
63
71
  */
64
- export interface NumberFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
72
+ export interface NumberFieldProps extends Omit<
73
+ BaseFieldProps,
74
+ "value" | "onChange"
75
+ > {
65
76
  fieldType: "number";
66
77
  value: number | null;
67
78
  onChange: (value: number | null) => void;
@@ -73,7 +84,10 @@ export interface NumberFieldProps extends Omit<BaseFieldProps, "value" | "onChan
73
84
  /**
74
85
  * Props for integer fields
75
86
  */
76
- export interface IntegerFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
87
+ export interface IntegerFieldProps extends Omit<
88
+ BaseFieldProps,
89
+ "value" | "onChange"
90
+ > {
77
91
  fieldType: "integer";
78
92
  value: number | null;
79
93
  onChange: (value: number | null) => void;
@@ -85,7 +99,10 @@ export interface IntegerFieldProps extends Omit<BaseFieldProps, "value" | "onCha
85
99
  /**
86
100
  * Props for boolean fields
87
101
  */
88
- export interface BooleanFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
102
+ export interface BooleanFieldProps extends Omit<
103
+ BaseFieldProps,
104
+ "value" | "onChange"
105
+ > {
89
106
  fieldType: "boolean";
90
107
  value: boolean;
91
108
  onChange: (value: boolean) => void;
@@ -94,7 +111,10 @@ export interface BooleanFieldProps extends Omit<BaseFieldProps, "value" | "onCha
94
111
  /**
95
112
  * Props for date fields
96
113
  */
97
- export interface DateFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
114
+ export interface DateFieldProps extends Omit<
115
+ BaseFieldProps,
116
+ "value" | "onChange"
117
+ > {
98
118
  fieldType: "date";
99
119
  value: string | null;
100
120
  onChange: (value: string | null) => void;
@@ -103,7 +123,10 @@ export interface DateFieldProps extends Omit<BaseFieldProps, "value" | "onChange
103
123
  /**
104
124
  * Props for datetime fields
105
125
  */
106
- export interface DateTimeFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
126
+ export interface DateTimeFieldProps extends Omit<
127
+ BaseFieldProps,
128
+ "value" | "onChange"
129
+ > {
107
130
  fieldType: "datetime";
108
131
  value: string | null;
109
132
  onChange: (value: string | null) => void;
@@ -112,7 +135,10 @@ export interface DateTimeFieldProps extends Omit<BaseFieldProps, "value" | "onCh
112
135
  /**
113
136
  * Props for select fields (single selection)
114
137
  */
115
- export interface SelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
138
+ export interface SelectFieldProps extends Omit<
139
+ BaseFieldProps,
140
+ "value" | "onChange"
141
+ > {
116
142
  fieldType: "select";
117
143
  value: string | null;
118
144
  onChange: (value: string | null) => void;
@@ -122,7 +148,10 @@ export interface SelectFieldProps extends Omit<BaseFieldProps, "value" | "onChan
122
148
  /**
123
149
  * Props for multi-select fields
124
150
  */
125
- export interface MultiSelectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
151
+ export interface MultiSelectFieldProps extends Omit<
152
+ BaseFieldProps,
153
+ "value" | "onChange"
154
+ > {
126
155
  fieldType: "multiselect";
127
156
  value: string[];
128
157
  onChange: (value: string[]) => void;
@@ -189,7 +218,10 @@ export interface ArrayHelpers {
189
218
  /** Swap items at two indices */
190
219
  swap: (indexA: number, indexB: number) => void;
191
220
  /** Get field props for an item field */
192
- getItemFieldProps: (index: number, fieldName: string) => ArrayItemFieldPropsResult;
221
+ getItemFieldProps: (
222
+ index: number,
223
+ fieldName: string,
224
+ ) => ArrayItemFieldPropsResult;
193
225
  /** Minimum number of items allowed */
194
226
  minItems: number;
195
227
  /** Maximum number of items allowed */
@@ -203,7 +235,10 @@ export interface ArrayHelpers {
203
235
  /**
204
236
  * Props for array fields
205
237
  */
206
- export interface ArrayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
238
+ export interface ArrayFieldProps extends Omit<
239
+ BaseFieldProps,
240
+ "value" | "onChange"
241
+ > {
207
242
  fieldType: "array";
208
243
  value: unknown[];
209
244
  onChange: (value: unknown[]) => void;
@@ -217,7 +252,10 @@ export interface ArrayFieldProps extends Omit<BaseFieldProps, "value" | "onChang
217
252
  /**
218
253
  * Props for object fields
219
254
  */
220
- export interface ObjectFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
255
+ export interface ObjectFieldProps extends Omit<
256
+ BaseFieldProps,
257
+ "value" | "onChange"
258
+ > {
221
259
  fieldType: "object";
222
260
  value: Record<string, unknown>;
223
261
  onChange: (value: Record<string, unknown>) => void;
@@ -236,7 +274,10 @@ export interface ComputedFieldProps extends Omit<BaseFieldProps, "onChange"> {
236
274
  /**
237
275
  * Props for array item fields (within array context)
238
276
  */
239
- export interface ArrayItemFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
277
+ export interface ArrayItemFieldProps extends Omit<
278
+ BaseFieldProps,
279
+ "value" | "onChange"
280
+ > {
240
281
  /** The field type */
241
282
  fieldType: string;
242
283
  /** Current value */
@@ -252,7 +293,10 @@ export interface ArrayItemFieldProps extends Omit<BaseFieldProps, "value" | "onC
252
293
  /**
253
294
  * Props for display fields (read-only presentation content)
254
295
  */
255
- export interface DisplayFieldProps extends Omit<BaseFieldProps, "value" | "onChange"> {
296
+ export interface DisplayFieldProps extends Omit<
297
+ BaseFieldProps,
298
+ "value" | "onChange"
299
+ > {
256
300
  fieldType: "display";
257
301
  /** Static content (markdown/text) */
258
302
  content?: string;
package/src/useForma.ts CHANGED
@@ -237,6 +237,23 @@ function getDefaultBooleanValues(spec: Forma): Record<string, boolean> {
237
237
  return defaults;
238
238
  }
239
239
 
240
+ /**
241
+ * Get default values from field definitions.
242
+ * Collects `defaultValue` from each field that specifies one.
243
+ * These are applied after boolean defaults but before initialData,
244
+ * so explicit defaults override type-implicit defaults,
245
+ * and runtime initialData overrides everything.
246
+ */
247
+ function getFieldDefaults(spec: Forma): Record<string, unknown> {
248
+ const defaults: Record<string, unknown> = {};
249
+ for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
250
+ if (fieldDef.defaultValue !== undefined) {
251
+ defaults[fieldPath] = fieldDef.defaultValue;
252
+ }
253
+ }
254
+ return defaults;
255
+ }
256
+
240
257
  /**
241
258
  * Main Forma hook
242
259
  */
@@ -264,7 +281,11 @@ export function useForma(options: UseFormaOptions): UseFormaReturn {
264
281
  }, [inputSpec, referenceData]);
265
282
 
266
283
  const [state, dispatch] = useReducer(formReducer, {
267
- data: { ...getDefaultBooleanValues(spec), ...initialData }, // Boolean defaults merged UNDER initialData
284
+ data: {
285
+ ...getDefaultBooleanValues(spec),
286
+ ...getFieldDefaults(spec),
287
+ ...initialData,
288
+ },
268
289
  touched: {},
269
290
  isSubmitting: false,
270
291
  isSubmitted: false,
@@ -448,8 +469,15 @@ export function useForma(options: UseFormaOptions): UseFormaReturn {
448
469
  }, [immediateValidation, onSubmit, state.data]);
449
470
 
450
471
  const resetForm = useCallback(() => {
451
- dispatch({ type: "RESET", initialData });
452
- }, [initialData]);
472
+ dispatch({
473
+ type: "RESET",
474
+ initialData: {
475
+ ...getDefaultBooleanValues(spec),
476
+ ...getFieldDefaults(spec),
477
+ ...initialData,
478
+ },
479
+ });
480
+ }, [spec, initialData]);
453
481
 
454
482
  // Wizard helpers
455
483
  const wizard = useMemo((): WizardHelpers | null => {