@bluprynt/forms-viewer 4.0.1 → 4.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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { DocumentError, DocumentError as DocumentError$1, FormEngine, FormValuesEditor } from "@bluprynt/forms-core";
1
+ import { DocumentError, DocumentError as DocumentError$1, FormEngine, FormValuesEditor, applySuggestion, removeSuggestion } from "@bluprynt/forms-core";
2
2
  import { Fragment, createContext, useCallback, useContext, useMemo, useRef } from "react";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/constants.ts
@@ -97,12 +97,15 @@ const getFieldErrors = (fieldErrors, fieldId, itemIndex) => {
97
97
  * Array fields store their per-item schema in `arrayField.item` ({@link ArrayItemDef}).
98
98
  * Components that render individual array items need a standard `FieldContentItem` shape,
99
99
  * so this helper projects the item definition into one, preserving the parent field's `id`
100
- * while adopting the item's `type`, `label`, `description`, `validation`, and `options`.
100
+ * while adopting the item's `type`, `label`, authoring metadata, `validation`, and `options`.
101
+ *
102
+ * A `static` item projects to a `StaticFieldContentItem`, so the return type is
103
+ * the wider {@link AnyFieldContentItem}.
101
104
  *
102
105
  * @param arrayField - The array field definition whose `.item` property describes the item schema.
103
106
  * @param _index - The zero-based position of the item in the array (reserved for future use,
104
107
  * e.g. per-item overrides).
105
- * @returns A `FieldContentItem` that can be passed directly to a typed field component.
108
+ * @returns An `AnyFieldContentItem` that can be passed directly to a typed field component.
106
109
  *
107
110
  * @example
108
111
  * ```ts
@@ -117,16 +120,79 @@ const getFieldErrors = (fieldErrors, fieldId, itemIndex) => {
117
120
  */
118
121
  const getArrayField = (arrayField, _index) => {
119
122
  const itemDef = arrayField.item;
123
+ const metadata = {
124
+ description: itemDef.description,
125
+ placeholder: itemDef.placeholder,
126
+ answer_guidelines: itemDef.answer_guidelines,
127
+ reference_id: itemDef.reference_id
128
+ };
129
+ if (itemDef.type === "static") return {
130
+ id: arrayField.id,
131
+ type: "static",
132
+ text: itemDef.text,
133
+ label: itemDef.label,
134
+ ...metadata
135
+ };
120
136
  return {
121
137
  id: arrayField.id,
122
138
  type: itemDef.type,
123
139
  label: itemDef.label,
124
- description: itemDef.description,
140
+ ...metadata,
125
141
  validation: itemDef.validation,
126
142
  options: itemDef.options
127
143
  };
128
144
  };
129
145
  /**
146
+ * Creates a {@link AnyFieldContentItem} representing one sub-field of an `array_obj` field.
147
+ *
148
+ * Unlike an `array` item, a sub-field carries its own id, so the projection keeps it:
149
+ * it is both the key its value is stored under inside each row and a stable React key.
150
+ *
151
+ * @param subField - The sub-field definition taken from the field's `items` list.
152
+ * @returns An `AnyFieldContentItem` that can be passed directly to a typed field component.
153
+ */
154
+ const getArrayObjField = (subField) => {
155
+ const metadata = {
156
+ description: subField.description,
157
+ placeholder: subField.placeholder,
158
+ answer_guidelines: subField.answer_guidelines,
159
+ reference_id: subField.reference_id
160
+ };
161
+ if (subField.type === "static") return {
162
+ id: subField.id,
163
+ type: "static",
164
+ text: subField.text,
165
+ label: subField.label,
166
+ ...metadata
167
+ };
168
+ return {
169
+ id: subField.id,
170
+ type: subField.type,
171
+ label: subField.label,
172
+ ...metadata,
173
+ validation: subField.validation,
174
+ options: subField.options
175
+ };
176
+ };
177
+ /**
178
+ * Retrieves the validation errors for one sub-field of one row of an `array_obj` field.
179
+ *
180
+ * Errors for an `array_obj` are all stored under the container's id; the row is
181
+ * identified by `itemIndex` and the sub-field by `itemFieldId`.
182
+ *
183
+ * @param fieldErrors - Map from field id to its validation errors.
184
+ * @param fieldId - The numeric id of the `array_obj` field.
185
+ * @param index - Zero-based row index.
186
+ * @param subFieldId - The numeric id of the sub-field.
187
+ * @returns Errors for that cell. Empty array if none.
188
+ */
189
+ const getArrayObjItemErrors = (fieldErrors, fieldId, index, subFieldId) => (fieldErrors.get(fieldId) ?? []).filter((e) => e.itemIndex === index && e.itemFieldId === subFieldId);
190
+ /**
191
+ * Retrieves the row-level validation errors for one row of an `array_obj` field --
192
+ * those carrying an `itemIndex` but no `itemFieldId`, such as a row that is not an object.
193
+ */
194
+ const getArrayObjRowErrors = (fieldErrors, fieldId, index) => (fieldErrors.get(fieldId) ?? []).filter((e) => e.itemIndex === index && e.itemFieldId == null);
195
+ /**
130
196
  * Recursively searches content items for a section with the given id.
131
197
  *
132
198
  * Walks the content tree depth-first, checking sections and their nested
@@ -154,7 +220,13 @@ const findSection = (items, sectionId) => {
154
220
  };
155
221
  //#endregion
156
222
  //#region src/form/form-items.tsx
157
- const FormItems = ({ items, visibilityMap, values, fieldErrors, components, showInlineValidation, renderFieldProps, renderArrayItemProps }) => {
223
+ /** Looks up the component for a value field type. Optional map keys may be absent. */
224
+ const componentFor = (components, type) => components[type];
225
+ /** `select` and `multiselect` components are the only ones that receive injected options. */
226
+ const withOptions = (props, def) => {
227
+ if (def.type === "select" || def.type === "multiselect") props.options = def.options ?? [];
228
+ };
229
+ const FormItems = ({ items, visibilityMap, values, suggestions, fieldErrors, components, showInlineValidation, renderFieldProps, renderArrayItemProps, renderArrayObjItemProps }) => {
158
230
  const SectionComponent = components.section;
159
231
  const ErrorComponent = showInlineValidation ? components.error : void 0;
160
232
  const elements = [];
@@ -166,11 +238,13 @@ const FormItems = ({ items, visibilityMap, values, fieldErrors, components, show
166
238
  items: item.content,
167
239
  visibilityMap,
168
240
  values,
241
+ suggestions,
169
242
  fieldErrors,
170
243
  components,
171
244
  showInlineValidation,
172
245
  renderFieldProps,
173
- renderArrayItemProps
246
+ renderArrayItemProps,
247
+ renderArrayObjItemProps
174
248
  })
175
249
  }, item.id));
176
250
  else if (item.type === "array") {
@@ -179,23 +253,29 @@ const FormItems = ({ items, visibilityMap, values, fieldErrors, components, show
179
253
  const ArrayComponent = components.array;
180
254
  const arrayValue = values[String(item.id)] ?? [];
181
255
  const itemDef = item.item;
182
- const ItemComponent = components[itemDef.type];
183
- elements.push(/* @__PURE__ */ jsx(ArrayComponent, {
256
+ const ItemComponent = componentFor(components, itemDef.type);
257
+ const arrayProps = {
184
258
  field: item,
185
259
  value: values[String(item.id)],
186
260
  itemDef: item.item,
187
261
  errors,
188
- ...modeProps,
262
+ ...modeProps
263
+ };
264
+ const arraySuggestion = suggestions?.[String(item.id)];
265
+ if (arraySuggestion) arrayProps.suggestion = arraySuggestion;
266
+ elements.push(/* @__PURE__ */ jsx(ArrayComponent, {
267
+ ...arrayProps,
189
268
  children: ItemComponent ? arrayValue.map((itemValue, index) => {
190
- const itemErrors = getFieldErrors(fieldErrors, item.id, index);
191
269
  const synthetic = getArrayField(item, index);
270
+ if (synthetic.type === "static") return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ItemComponent, { field: synthetic }) }, `${item.id}-${index}`);
271
+ const itemErrors = getFieldErrors(fieldErrors, item.id, index);
192
272
  const baseProps = {
193
273
  field: synthetic,
194
274
  value: itemValue,
195
275
  errors: itemErrors,
196
276
  ...renderArrayItemProps?.(item, index) ?? {}
197
277
  };
198
- if (itemDef.type === "select") baseProps.options = itemDef.options ?? [];
278
+ withOptions(baseProps, itemDef);
199
279
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ItemComponent, { ...baseProps }), ErrorComponent && itemErrors.length > 0 && /* @__PURE__ */ jsx(ErrorComponent, {
200
280
  errors: itemErrors,
201
281
  field: synthetic
@@ -206,6 +286,55 @@ const FormItems = ({ items, visibilityMap, values, fieldErrors, components, show
206
286
  errors,
207
287
  field: item
208
288
  }, `${item.id}-error`));
289
+ } else if (item.type === "array_obj") {
290
+ const ArrayObjComponent = components.array_obj;
291
+ if (!ArrayObjComponent) continue;
292
+ const itemsDef = item.items ?? [];
293
+ const rows = values[String(item.id)] ?? [];
294
+ const errors = [...getFieldErrors(fieldErrors, item.id), ...rows.flatMap((_row, index) => getArrayObjRowErrors(fieldErrors, item.id, index))];
295
+ const modeProps = renderFieldProps?.(item) ?? {};
296
+ const arrayProps = {
297
+ field: item,
298
+ value: values[String(item.id)],
299
+ itemsDef,
300
+ kind: item.kind ?? "list",
301
+ errors,
302
+ ...modeProps
303
+ };
304
+ const arraySuggestion = suggestions?.[String(item.id)];
305
+ if (arraySuggestion) arrayProps.suggestion = arraySuggestion;
306
+ const children = rows.map((row, index) => itemsDef.map((subField) => {
307
+ const key = `${item.id}-${index}-${subField.id}`;
308
+ const SubComponent = componentFor(components, subField.type);
309
+ if (!SubComponent) return /* @__PURE__ */ jsx(Fragment, {}, key);
310
+ const synthetic = getArrayObjField(subField);
311
+ if (subField.type === "static") return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(SubComponent, { field: synthetic }) }, key);
312
+ const cellErrors = getArrayObjItemErrors(fieldErrors, item.id, index, subField.id);
313
+ const cellModeProps = renderArrayObjItemProps?.(item, index, subField.id) ?? {};
314
+ const cellProps = {
315
+ field: synthetic,
316
+ value: row?.[String(subField.id)],
317
+ errors: cellErrors,
318
+ ...cellModeProps
319
+ };
320
+ withOptions(cellProps, subField);
321
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SubComponent, { ...cellProps }), ErrorComponent && cellErrors.length > 0 && /* @__PURE__ */ jsx(ErrorComponent, {
322
+ errors: cellErrors,
323
+ field: synthetic
324
+ })] }, key);
325
+ }));
326
+ elements.push(/* @__PURE__ */ jsx(ArrayObjComponent, {
327
+ ...arrayProps,
328
+ children
329
+ }, item.id));
330
+ if (ErrorComponent && errors.length > 0) elements.push(/* @__PURE__ */ jsx(ErrorComponent, {
331
+ errors,
332
+ field: item
333
+ }, `${item.id}-error`));
334
+ } else if (item.type === "static") {
335
+ const StaticComponent = components.static;
336
+ if (!StaticComponent) continue;
337
+ elements.push(/* @__PURE__ */ jsx(StaticComponent, { field: item }, item.id));
209
338
  } else {
210
339
  const errors = getFieldErrors(fieldErrors, item.id);
211
340
  const modeProps = renderFieldProps?.(item) ?? {};
@@ -215,8 +344,11 @@ const FormItems = ({ items, visibilityMap, values, fieldErrors, components, show
215
344
  errors,
216
345
  ...modeProps
217
346
  };
218
- if (item.type === "select") fieldProps.options = item.options ?? [];
219
- const FieldComponent = components[item.type];
347
+ const suggestion = suggestions?.[String(item.id)];
348
+ if (suggestion) fieldProps.suggestion = suggestion;
349
+ withOptions(fieldProps, item);
350
+ const FieldComponent = componentFor(components, item.type);
351
+ if (!FieldComponent) continue;
220
352
  elements.push(/* @__PURE__ */ jsx(FieldComponent, { ...fieldProps }, item.id));
221
353
  if (ErrorComponent && errors.length > 0) elements.push(/* @__PURE__ */ jsx(ErrorComponent, {
222
354
  errors,
@@ -230,18 +362,21 @@ const FormItems = ({ items, visibilityMap, values, fieldErrors, components, show
230
362
  //#endregion
231
363
  //#region src/form/form-content.tsx
232
364
  const FormContent = (props) => {
233
- const { items, visibilityMap, values, fieldErrors, section, showInlineValidation } = props;
365
+ const { items, visibilityMap, values, suggestions, fieldErrors, section, showInlineValidation } = props;
234
366
  const sharedProps = props.mode === "editor" ? {
235
367
  visibilityMap,
236
368
  values,
369
+ suggestions,
237
370
  fieldErrors,
238
371
  components: props.components,
239
372
  showInlineValidation,
240
373
  renderFieldProps: props.renderFieldProps,
241
- renderArrayItemProps: props.renderArrayItemProps
374
+ renderArrayItemProps: props.renderArrayItemProps,
375
+ renderArrayObjItemProps: props.renderArrayObjItemProps
242
376
  } : {
243
377
  visibilityMap,
244
378
  values,
379
+ suggestions,
245
380
  fieldErrors,
246
381
  components: props.components,
247
382
  showInlineValidation
@@ -274,19 +409,21 @@ const resolveDefaultSection = (items, visibilityMap) => {
274
409
  //#region src/form-editor.tsx
275
410
  const FormEditor = ({ components, onChange }) => {
276
411
  const { definition, data, visibilityMap, fieldErrors, section, engine, showInlineValidation, documentErrors } = useFormContext();
277
- const { renderFieldProps, renderArrayItemProps } = useEditorHandlers(engine, data, onChange);
412
+ const { renderFieldProps, renderArrayItemProps, renderArrayObjItemProps } = useEditorHandlers(engine, data, onChange);
278
413
  if (!definition || !data || documentErrors && documentErrors.length > 0) return null;
279
414
  return /* @__PURE__ */ jsx(FormContent, {
280
415
  mode: "editor",
281
416
  items: definition.content,
282
417
  visibilityMap,
283
418
  values: data.values,
419
+ suggestions: data.suggestions,
284
420
  fieldErrors,
285
421
  components,
286
422
  section,
287
423
  showInlineValidation,
288
424
  renderFieldProps,
289
- renderArrayItemProps
425
+ renderArrayItemProps,
426
+ renderArrayObjItemProps
290
427
  });
291
428
  };
292
429
  const useEditorHandlers = (engine, data, onChange) => {
@@ -322,7 +459,7 @@ const useEditorHandlers = (engine, data, onChange) => {
322
459
  return handler;
323
460
  }, []);
324
461
  const arrayHandlersMap = useRef(/* @__PURE__ */ new Map());
325
- const getArrayHandlers = useCallback((fieldId) => {
462
+ const getArrayHandlers = useCallback((fieldId, newItem) => {
326
463
  const key = String(fieldId);
327
464
  let handlers = arrayHandlersMap.current.get(key);
328
465
  if (!handlers) {
@@ -341,7 +478,7 @@ const useEditorHandlers = (engine, data, onChange) => {
341
478
  };
342
479
  handlers = {
343
480
  onAddItem: () => fire((values) => {
344
- values.push(void 0);
481
+ values.push(newItem());
345
482
  return values;
346
483
  }),
347
484
  onRemoveItem: (index) => fire((values) => {
@@ -358,6 +495,26 @@ const useEditorHandlers = (engine, data, onChange) => {
358
495
  }
359
496
  return handlers;
360
497
  }, []);
498
+ const suggestionHandlersMap = useRef(/* @__PURE__ */ new Map());
499
+ const getSuggestionHandlers = useCallback((fieldId) => {
500
+ const key = String(fieldId);
501
+ let handlers = suggestionHandlersMap.current.get(key);
502
+ if (!handlers) {
503
+ const fire = (next) => {
504
+ const { data, onChange, engine } = stateRef.current;
505
+ if (!data || !engine) return;
506
+ const document = next(data);
507
+ if (document === data) return;
508
+ onChange(document, engine.validate(document));
509
+ };
510
+ handlers = {
511
+ onAcceptSuggestion: () => fire((document) => applySuggestion(document, fieldId)),
512
+ onRejectSuggestion: () => fire((document) => removeSuggestion(document, fieldId))
513
+ };
514
+ suggestionHandlersMap.current.set(key, handlers);
515
+ }
516
+ return handlers;
517
+ }, []);
361
518
  const arrayItemOnChangeMap = useRef(/* @__PURE__ */ new Map());
362
519
  const getArrayItemOnChange = useCallback((fieldId, index) => {
363
520
  const mapKey = `${fieldId}-${index}`;
@@ -382,15 +539,51 @@ const useEditorHandlers = (engine, data, onChange) => {
382
539
  }
383
540
  return handler;
384
541
  }, []);
542
+ const arrayObjItemOnChangeMap = useRef(/* @__PURE__ */ new Map());
543
+ const getArrayObjItemOnChange = useCallback((fieldId, index, subFieldId) => {
544
+ const mapKey = `${fieldId}-${index}-${subFieldId}`;
545
+ let handler = arrayObjItemOnChangeMap.current.get(mapKey);
546
+ if (!handler) {
547
+ handler = (newValue) => {
548
+ const fieldKey = String(fieldId);
549
+ const { data, onChange, engine } = stateRef.current;
550
+ if (!data || !engine) return;
551
+ const rows = [...data.values[fieldKey] ?? []];
552
+ const current = rows[index];
553
+ rows[index] = {
554
+ ...typeof current === "object" && current !== null && !Array.isArray(current) ? current : {},
555
+ [String(subFieldId)]: newValue
556
+ };
557
+ const document = {
558
+ ...data,
559
+ values: {
560
+ ...data.values,
561
+ [fieldKey]: rows
562
+ }
563
+ };
564
+ onChange(document, engine.validate(document));
565
+ };
566
+ arrayObjItemOnChangeMap.current.set(mapKey, handler);
567
+ }
568
+ return handler;
569
+ }, []);
385
570
  return {
386
571
  renderFieldProps: (field) => {
387
- if (field.type === "array") return {
572
+ if (field.type === "array" || field.type === "array_obj") {
573
+ const newItem = field.type === "array_obj" ? () => ({}) : () => void 0;
574
+ return {
575
+ onChange: getFieldOnChange(field.id),
576
+ ...getArrayHandlers(field.id, newItem),
577
+ ...getSuggestionHandlers(field.id)
578
+ };
579
+ }
580
+ return {
388
581
  onChange: getFieldOnChange(field.id),
389
- ...getArrayHandlers(field.id)
582
+ ...getSuggestionHandlers(field.id)
390
583
  };
391
- return { onChange: getFieldOnChange(field.id) };
392
584
  },
393
- renderArrayItemProps: (field, index) => ({ onChange: getArrayItemOnChange(field.id, index) })
585
+ renderArrayItemProps: (field, index) => ({ onChange: getArrayItemOnChange(field.id, index) }),
586
+ renderArrayObjItemProps: (field, index, subFieldId) => ({ onChange: getArrayObjItemOnChange(field.id, index, subFieldId) })
394
587
  };
395
588
  };
396
589
  //#endregion
@@ -417,7 +610,7 @@ const FormFieldsValidation = ({ container: ContainerComponent, field: FieldCompo
417
610
  if (groups.length === 0) return null;
418
611
  return /* @__PURE__ */ jsx(ContainerComponent, { children: groups.map((group) => /* @__PURE__ */ jsx(FieldComponent, {
419
612
  ...group,
420
- children: group.errors.map((error) => /* @__PURE__ */ jsx(ErrorComponent, { ...error }, `${error.fieldId}-${error.rule}-${error.itemIndex ?? ""}`))
613
+ children: group.errors.map((error) => /* @__PURE__ */ jsx(ErrorComponent, { ...error }, `${error.fieldId}-${error.rule}-${error.itemIndex ?? ""}-${error.itemFieldId ?? ""}`))
421
614
  }, group.field?.id)) });
422
615
  };
423
616
  //#endregion
@@ -471,6 +664,7 @@ const FormViewer = ({ components }) => {
471
664
  items: definition.content,
472
665
  visibilityMap,
473
666
  values: data.values,
667
+ suggestions: data.suggestions,
474
668
  fieldErrors,
475
669
  components,
476
670
  section,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["DocumentError"],"sources":["../src/constants.ts","../src/form-context.tsx","../src/form-document-validation.tsx","../src/form/utils.ts","../src/form/form-items.tsx","../src/form/form-content.tsx","../src/form-editor.tsx","../src/form-fields-validation.tsx","../src/use-form-sections.ts","../src/form-sections.tsx","../src/form-viewer.tsx"],"sourcesContent":["export const ROOT: unique symbol = Symbol('ROOT')\nexport type ROOT = typeof ROOT\n\nexport const DEFAULT: unique symbol = Symbol('DEFAULT')\nexport type DEFAULT = typeof DEFAULT\n","import { createContext, type FC, type ReactNode, useContext, useMemo } from 'react'\n\nimport {\n DocumentError,\n DocumentValidationError,\n FieldValidationError,\n FormDefinition,\n FormDocument,\n FormEngine,\n FormValidationResult,\n} from '@bluprynt/forms-core'\n\nimport type { DEFAULT, ROOT } from './constants'\n\ntype FormContextValue = {\n definition: FormDefinition | undefined\n data: FormDocument | undefined\n engine: FormEngine | undefined\n visibilityMap: Map<number, boolean>\n validation: FormValidationResult | undefined\n documentErrors: readonly DocumentValidationError[] | undefined\n fieldErrors: Map<number, FieldValidationError[]>\n section: typeof ROOT | typeof DEFAULT | number | undefined\n showInlineValidation: boolean\n}\n\nconst FormContext = createContext<FormContextValue | undefined>(undefined)\n\nexport const useFormContext = (): FormContextValue => {\n const context = useContext(FormContext)\n if (!context) throw new Error('useFormContext must be used within a <Form> provider')\n\n return context\n}\n\ntype FormProps = {\n definition?: FormDefinition\n data?: FormDocument\n section?: typeof ROOT | typeof DEFAULT | number\n showInlineValidation?: boolean\n children: ReactNode\n}\n\nexport const Form: FC<FormProps> = ({ definition, data, section, showInlineValidation = true, children }) => {\n const { engine, documentErrors: definitionErrors } = useMemo(() => {\n if (!definition) return {}\n\n try {\n return { engine: new FormEngine(definition) }\n } catch (error) {\n if (error instanceof DocumentError) return { documentErrors: error.errors }\n throw error\n }\n }, [definition])\n\n const { visibilityMap, validation, documentErrors, fieldErrors } = useMemo(() => {\n const visibilityMap = engine && data ? engine.getVisibilityMap(data) : new Map<number, boolean>()\n const validation =\n engine && data\n ? engine.validate(data)\n : ({\n valid: true,\n fieldErrors: new Map<number, FieldValidationError[]>(),\n } satisfies FormValidationResult)\n\n return {\n visibilityMap,\n validation,\n documentErrors: [...(definitionErrors ?? []), ...(validation?.documentErrors ?? [])],\n fieldErrors: validation?.fieldErrors ?? new Map<number, FieldValidationError[]>(),\n } as const\n }, [engine, data, definitionErrors])\n\n const value: FormContextValue = {\n definition,\n data,\n engine,\n visibilityMap,\n validation,\n documentErrors,\n fieldErrors,\n section,\n showInlineValidation,\n } as const\n\n return <FormContext.Provider value={value}>{children}</FormContext.Provider>\n}\n","import type { ComponentType, FC, PropsWithChildren } from 'react'\n\nimport type { DocumentValidationError } from '@bluprynt/forms-core'\n\nimport { useFormContext } from './form-context'\n\ntype FormDocumentValidationProps = {\n container: ComponentType<PropsWithChildren>\n error: ComponentType<DocumentValidationError>\n}\n\nexport const FormDocumentValidation: FC<FormDocumentValidationProps> = ({\n container: ContainerComponent,\n error: ErrorComponent,\n}) => {\n const { documentErrors } = useFormContext()\n\n if (!documentErrors?.length) return null\n\n return (\n <ContainerComponent>\n {documentErrors.map((error, index) => (\n <ErrorComponent\n // biome-ignore lint/suspicious/noArrayIndexKey: index is unique in array\n key={`error-${error.code}-${error.itemId ?? ''}-${index}`}\n {...error}\n />\n ))}\n </ContainerComponent>\n )\n}\n","import type {\n ArrayItemDef,\n ContentItem,\n FieldContentItem,\n FieldType,\n FieldValidationError,\n SectionContentItem,\n} from '@bluprynt/forms-core'\n\n/**\n * Retrieves validation errors for a specific field from the pre-indexed error map.\n *\n * Uses O(1) map lookup by `fieldId`. When `itemIndex` is omitted, returns only\n * **field-level** errors (those without an `itemIndex`). When `itemIndex` is\n * provided, returns only **item-level** errors matching the given array item index.\n *\n * @param fieldErrors - Map from field id to its validation errors.\n * @param fieldId - The numeric ID of the field to retrieve errors for.\n * @param itemIndex - Optional zero-based index of the array item. When omitted, only\n * field-level errors (where `itemIndex` is `null` / `undefined`) are returned.\n * @returns Errors for the given field (and optionally item index). Empty array if none.\n *\n * @example\n * ```ts\n * // Field-level errors only (no itemIndex on the error)\n * getFieldErrors(fieldErrors, 5)\n *\n * // Errors for the third item of array field 5\n * getFieldErrors(fieldErrors, 5, 2)\n * ```\n */\nexport const getFieldErrors = (\n fieldErrors: Map<number, FieldValidationError[]>,\n fieldId: number,\n itemIndex?: number,\n): FieldValidationError[] => {\n const errors = fieldErrors.get(fieldId) ?? []\n if (itemIndex === undefined) return errors.filter((e) => e.itemIndex == null)\n return errors.filter((e) => e.itemIndex === itemIndex)\n}\n\n/**\n * Creates a synthetic {@link FieldContentItem} that represents a single item inside an array field.\n *\n * Array fields store their per-item schema in `arrayField.item` ({@link ArrayItemDef}).\n * Components that render individual array items need a standard `FieldContentItem` shape,\n * so this helper projects the item definition into one, preserving the parent field's `id`\n * while adopting the item's `type`, `label`, `description`, `validation`, and `options`.\n *\n * @param arrayField - The array field definition whose `.item` property describes the item schema.\n * @param _index - The zero-based position of the item in the array (reserved for future use,\n * e.g. per-item overrides).\n * @returns A `FieldContentItem` that can be passed directly to a typed field component.\n *\n * @example\n * ```ts\n * const arrayField: FieldContentItem = {\n * id: 10, type: 'array', label: 'Tags',\n * item: { type: 'string', label: 'Tag' },\n * }\n *\n * const itemDef = getArrayField(arrayField, 0)\n * // → { id: 10, type: 'string', label: 'Tag', ... }\n * ```\n */\nexport const getArrayField = (arrayField: FieldContentItem, _index: number): FieldContentItem => {\n const itemDef = arrayField.item as ArrayItemDef\n return {\n id: arrayField.id,\n type: itemDef.type as FieldType,\n label: itemDef.label,\n description: itemDef.description,\n validation: itemDef.validation as FieldContentItem['validation'],\n options: itemDef.options,\n }\n}\n\n/**\n * Recursively searches content items for a section with the given id.\n *\n * Walks the content tree depth-first, checking sections and their nested\n * content. Returns the first matching {@link SectionContentItem}, or\n * `undefined` if no section with that id exists.\n *\n * @param items - The content items to search through.\n * @param sectionId - The numeric id of the section to find.\n * @returns The matching section, or `undefined` if not found.\n *\n * @example\n * ```ts\n * const section = findSection(definition.content, 42)\n * if (section) {\n * // render section.content\n * }\n * ```\n */\nexport const findSection = (items: ContentItem[], sectionId: number): SectionContentItem | undefined => {\n for (const item of items) {\n if (item.type === 'section') {\n if (item.id === sectionId) return item\n const found = findSection(item.content, sectionId)\n if (found) return found\n }\n }\n return undefined\n}\n","import { type FC, Fragment } from 'react'\n\nimport type {\n ArrayItemDef,\n ContentItem,\n FieldContentItem,\n FieldValidationError,\n FormValues,\n} from '@bluprynt/forms-core'\n\nimport type { EditorArrayItemProps, EditorComponentMap, EditorFieldProps, ViewerComponentMap } from '../types'\nimport { getArrayField, getFieldErrors } from './utils'\n\ntype FormItemsProps = {\n items: ContentItem[]\n visibilityMap: Map<number, boolean>\n values: FormValues\n fieldErrors: Map<number, FieldValidationError[]>\n components: ViewerComponentMap | EditorComponentMap\n showInlineValidation: boolean\n renderFieldProps?: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps?: (arrayField: FieldContentItem, index: number) => EditorArrayItemProps\n}\n\nexport const FormItems: FC<FormItemsProps> = ({\n items,\n visibilityMap,\n values,\n fieldErrors,\n components,\n showInlineValidation,\n renderFieldProps,\n renderArrayItemProps,\n}) => {\n const SectionComponent = components.section\n const ErrorComponent = showInlineValidation ? components.error : undefined\n\n const elements: React.ReactNode[] = []\n\n for (const item of items) {\n if (!visibilityMap.get(item.id)) continue\n\n if (item.type === 'section') {\n elements.push(\n <SectionComponent key={item.id} section={item}>\n <FormItems\n items={item.content}\n visibilityMap={visibilityMap}\n values={values}\n fieldErrors={fieldErrors}\n components={components}\n showInlineValidation={showInlineValidation}\n renderFieldProps={renderFieldProps}\n renderArrayItemProps={renderArrayItemProps}\n />\n </SectionComponent>,\n )\n } else if (item.type === 'array') {\n const errors = getFieldErrors(fieldErrors, item.id)\n const modeProps = renderFieldProps?.(item) ?? {}\n\n const ArrayComponent = components.array as React.ComponentType<Record<string, unknown>>\n const arrayValue = (values[String(item.id)] as unknown[] | undefined) ?? []\n const itemDef = item.item as ArrayItemDef\n const ItemComponent = components[\n itemDef.type as keyof Omit<ViewerComponentMap, 'array' | 'section' | 'error'>\n ] as React.ComponentType<Record<string, unknown>> | undefined\n\n elements.push(\n <ArrayComponent\n key={item.id}\n field={item}\n value={values[String(item.id)]}\n itemDef={item.item}\n errors={errors}\n {...modeProps}>\n {ItemComponent\n ? arrayValue.map((itemValue, index) => {\n const itemErrors = getFieldErrors(fieldErrors, item.id, index)\n const synthetic = getArrayField(item, index)\n const itemModeProps = renderArrayItemProps?.(item, index) ?? {}\n\n const baseProps: Record<string, unknown> = {\n field: synthetic,\n value: itemValue,\n errors: itemErrors,\n ...itemModeProps,\n }\n\n if (itemDef.type === 'select') {\n baseProps.options = itemDef.options ?? []\n }\n\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: index is unique in array\n <Fragment key={`${item.id}-${index}`}>\n <ItemComponent {...baseProps} />\n {ErrorComponent && itemErrors.length > 0 && (\n <ErrorComponent errors={itemErrors} field={synthetic} />\n )}\n </Fragment>\n )\n })\n : null}\n </ArrayComponent>,\n )\n\n if (ErrorComponent && errors.length > 0) {\n elements.push(<ErrorComponent key={`${item.id}-error`} errors={errors} field={item} />)\n }\n } else {\n const errors = getFieldErrors(fieldErrors, item.id)\n const modeProps = renderFieldProps?.(item) ?? {}\n\n const fieldProps: Record<string, unknown> = {\n field: item,\n value: values[String(item.id)],\n errors,\n ...modeProps,\n }\n\n if (item.type === 'select') fieldProps.options = (item as FieldContentItem).options ?? []\n\n const fieldType = item.type as keyof Omit<ViewerComponentMap, 'array' | 'section' | 'error'>\n const FieldComponent = components[fieldType] as React.ComponentType<Record<string, unknown>>\n\n elements.push(<FieldComponent key={item.id} {...fieldProps} />)\n\n if (ErrorComponent && errors.length > 0)\n elements.push(<ErrorComponent key={`${item.id}-error`} errors={errors} field={item} />)\n }\n }\n\n if (elements.length === 0) return null\n\n return elements\n}\n","import type { FC } from 'react'\n\nimport type { ContentItem, FieldContentItem, FieldValidationError, FormValues } from '@bluprynt/forms-core'\n\nimport { DEFAULT, ROOT } from '../constants'\nimport type { EditorArrayItemProps, EditorComponentMap, EditorFieldProps, ViewerComponentMap } from '../types'\nimport { FormItems } from './form-items'\nimport { findSection } from './utils'\n\ntype FormContentBaseProps = {\n items: ContentItem[]\n visibilityMap: Map<number, boolean>\n values: FormValues\n fieldErrors: Map<number, FieldValidationError[]>\n section?: typeof ROOT | typeof DEFAULT | number\n showInlineValidation: boolean\n}\n\ntype FormContentViewerProps = FormContentBaseProps & {\n mode: 'viewer'\n components: ViewerComponentMap\n}\n\ntype FormContentEditorProps = FormContentBaseProps & {\n mode: 'editor'\n components: EditorComponentMap\n renderFieldProps: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps: (arrayField: FieldContentItem, index: number) => EditorArrayItemProps\n}\n\nexport type FormContentProps = FormContentViewerProps | FormContentEditorProps\n\nexport const FormContent: FC<FormContentProps> = (props) => {\n const { items, visibilityMap, values, fieldErrors, section, showInlineValidation } = props\n\n const sharedProps =\n props.mode === 'editor'\n ? {\n visibilityMap,\n values,\n fieldErrors,\n components: props.components,\n showInlineValidation,\n renderFieldProps: props.renderFieldProps,\n renderArrayItemProps: props.renderArrayItemProps,\n }\n : {\n visibilityMap,\n values,\n fieldErrors,\n components: props.components,\n showInlineValidation,\n }\n\n const selectedSection = section === DEFAULT ? resolveDefaultSection(items, visibilityMap) : section\n\n if (selectedSection === undefined) return <FormItems items={items} {...sharedProps} />\n\n if (selectedSection === ROOT) {\n const nonSectionItems = items.filter((item) => item.type !== 'section')\n return <FormItems items={nonSectionItems} {...sharedProps} />\n }\n\n const foundSection = findSection(items, selectedSection)\n if (!foundSection || !visibilityMap.get(foundSection.id)) return null\n\n const Section = props.components.section\n return (\n <Section key={foundSection.id} section={foundSection}>\n <FormItems items={foundSection.content} {...sharedProps} />\n </Section>\n )\n}\n\nconst resolveDefaultSection = (\n items: ContentItem[],\n visibilityMap: Map<number, boolean>,\n): typeof ROOT | number | undefined => {\n const rootFields = items.filter((item) => item.type !== 'section')\n if (rootFields.some((item) => visibilityMap.get(item.id))) return ROOT\n\n const firstVisibleSection = items.find((item) => item.type === 'section' && visibilityMap.get(item.id) !== false)\n\n return firstVisibleSection?.id\n}\n","import { type FC, useCallback, useRef } from 'react'\n\nimport { FieldContentItem, FormDocument, FormEngine, FormValidationResult } from '@bluprynt/forms-core'\n\nimport { FormContent } from './form'\nimport { useFormContext } from './form-context'\nimport type { EditorArrayItemProps, EditorComponentMap, EditorFieldProps } from './types'\n\ntype FormEditorProps = {\n components: EditorComponentMap\n onChange: (data: FormDocument, validation: FormValidationResult) => void\n}\n\nexport const FormEditor: FC<FormEditorProps> = ({ components, onChange }) => {\n const { definition, data, visibilityMap, fieldErrors, section, engine, showInlineValidation, documentErrors } =\n useFormContext()\n\n const { renderFieldProps, renderArrayItemProps } = useEditorHandlers(engine, data, onChange)\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <FormContent\n mode=\"editor\"\n items={definition.content}\n visibilityMap={visibilityMap}\n values={data.values}\n fieldErrors={fieldErrors}\n components={components}\n section={section}\n showInlineValidation={showInlineValidation}\n renderFieldProps={renderFieldProps}\n renderArrayItemProps={renderArrayItemProps}\n />\n )\n}\n\nexport const useEditorHandlers = (\n engine: FormEngine | undefined,\n data: FormDocument | undefined,\n onChange: (data: FormDocument, validation: FormValidationResult) => void,\n): {\n renderFieldProps: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps: (field: FieldContentItem, index: number) => EditorArrayItemProps\n} => {\n // Latest ref pattern\n const stateRef = useRef({ data, onChange, engine })\n stateRef.current = { data, onChange, engine }\n\n // Per-field onChange handler\n\n const fieldOnChangeMap = useRef(new Map<string, (value: unknown) => void>())\n const getFieldOnChange = useCallback((fieldId: number): ((value: unknown) => void) => {\n const key = String(fieldId)\n\n let handler = fieldOnChangeMap.current.get(key)\n if (!handler) {\n handler = (newValue: unknown) => {\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const document: FormDocument = { ...data, values: { ...data.values, [key]: newValue } }\n\n onChange(document, engine.validate(document))\n }\n fieldOnChangeMap.current.set(key, handler)\n }\n return handler\n }, [])\n\n // Array mutation handlers\n\n const arrayHandlersMap = useRef(\n new Map<\n string,\n {\n onAddItem: () => void\n onRemoveItem: (index: number) => void\n onMoveItem: (fromIndex: number, toIndex: number) => void\n }\n >(),\n )\n const getArrayHandlers = useCallback((fieldId: number) => {\n const key = String(fieldId)\n\n let handlers = arrayHandlersMap.current.get(key)\n if (!handlers) {\n const fire = (mutate: (arr: unknown[]) => unknown[]) => {\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const items = (data.values[key] as unknown[] | undefined) ?? []\n const document: FormDocument = { ...data, values: { ...data.values, [key]: mutate([...items]) } }\n\n onChange(document, engine.validate(document))\n }\n\n handlers = {\n onAddItem: () =>\n fire((values) => {\n values.push(undefined)\n return values\n }),\n onRemoveItem: (index: number) =>\n fire((values) => {\n values.splice(index, 1)\n return values\n }),\n onMoveItem: (fromIndex: number, toIndex: number) =>\n fire((values) => {\n const [moved] = values.splice(fromIndex, 1)\n values.splice(toIndex, 0, moved)\n return values\n }),\n }\n arrayHandlersMap.current.set(key, handlers)\n }\n return handlers\n }, [])\n\n // Array item onChange handler\n\n const arrayItemOnChangeMap = useRef(new Map<string, (value: unknown) => void>())\n const getArrayItemOnChange = useCallback((fieldId: number, index: number): ((value: unknown) => void) => {\n const mapKey = `${fieldId}-${index}`\n\n let handler = arrayItemOnChangeMap.current.get(mapKey)\n if (!handler) {\n handler = (newValue: unknown) => {\n const fieldKey = String(fieldId)\n\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const items = [...((data.values[fieldKey] as unknown[] | undefined) ?? [])]\n items[index] = newValue\n\n const document: FormDocument = { ...data, values: { ...data.values, [fieldKey]: items } }\n onChange(document, engine.validate(document))\n }\n arrayItemOnChangeMap.current.set(mapKey, handler)\n }\n return handler\n }, [])\n\n return {\n renderFieldProps: (field: FieldContentItem): EditorFieldProps => {\n if (field.type === 'array') {\n return {\n onChange: getFieldOnChange(field.id),\n ...getArrayHandlers(field.id),\n }\n }\n return { onChange: getFieldOnChange(field.id) }\n },\n renderArrayItemProps: (field: FieldContentItem, index: number): EditorArrayItemProps => ({\n onChange: getArrayItemOnChange(field.id, index),\n }),\n } as const\n}\n","import { type ComponentType, type FC, type PropsWithChildren, useMemo } from 'react'\n\nimport type { FieldEntry, FieldValidationError } from '@bluprynt/forms-core'\n\nimport { useFormContext } from './form-context'\n\nexport type FieldValidationFieldEntry = {\n field: FieldEntry | undefined\n errors: FieldValidationError[]\n}\n\ntype FormFieldsValidationProps = {\n container: ComponentType<PropsWithChildren>\n field: ComponentType<PropsWithChildren<FieldValidationFieldEntry>>\n error: ComponentType<FieldValidationError>\n}\n\nexport const FormFieldsValidation: FC<FormFieldsValidationProps> = ({\n container: ContainerComponent,\n field: FieldComponent,\n error: ErrorComponent,\n}) => {\n const { engine, data, fieldErrors, visibilityMap } = useFormContext()\n\n const groups = useMemo(() => {\n if (!engine || !data || fieldErrors.size === 0) return []\n\n const result: FieldValidationFieldEntry[] = []\n\n for (const [fieldId, errors] of fieldErrors) {\n if (visibilityMap.get(fieldId) === false) continue\n\n result.push({\n field: engine.getFieldDef(fieldId),\n errors,\n })\n }\n\n return result\n }, [engine, data, fieldErrors, visibilityMap])\n\n if (groups.length === 0) return null\n\n return (\n <ContainerComponent>\n {groups.map((group) => (\n <FieldComponent key={group.field?.id} {...group}>\n {group.errors.map((error) => (\n <ErrorComponent key={`${error.fieldId}-${error.rule}-${error.itemIndex ?? ''}`} {...error} />\n ))}\n </FieldComponent>\n ))}\n </ContainerComponent>\n )\n}\n","import { useMemo } from 'react'\n\nimport type { SectionContentItem } from '@bluprynt/forms-core'\n\nimport { ROOT } from './constants'\nimport { useFormContext } from './form-context'\n\nexport type FormSectionEntry = Omit<SectionContentItem, 'id' | 'type'> & {\n id: typeof ROOT | number\n}\n\nexport const useFormSections = (\n defaultSectionTitle = 'General',\n defaultSectionDescription?: string,\n): FormSectionEntry[] => {\n const { definition, visibilityMap, data } = useFormContext()\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: invalidate section list when data changes\n return useMemo(() => {\n if (!definition) return []\n\n const result: FormSectionEntry[] = []\n\n const rootFields = definition.content.filter((item) => item.type !== 'section')\n if (rootFields.some((item) => visibilityMap.get(item.id)))\n result.push({\n id: ROOT,\n title: defaultSectionTitle,\n description: defaultSectionDescription,\n content: rootFields,\n condition: undefined,\n })\n\n for (const item of definition.content) {\n if (item.type === 'section') {\n if (visibilityMap.get(item.id) === false) continue\n\n result.push(item)\n }\n }\n\n return result\n }, [definition?.content, visibilityMap, data, defaultSectionTitle, defaultSectionDescription])\n}\n","import { type ComponentType, type FC, type PropsWithChildren } from 'react'\n\nimport { DEFAULT, ROOT } from './constants'\nimport { useFormContext } from './form-context'\nimport { type FormSectionEntry, useFormSections } from './use-form-sections'\n\nexport type { FormSectionEntry }\n\nexport type FormSectionItemProps = {\n index: number\n section: FormSectionEntry\n active: boolean\n select: () => void\n}\n\ntype FormSectionsProps = {\n container: ComponentType<PropsWithChildren>\n item: ComponentType<FormSectionItemProps>\n defaultSectionTitle?: string\n defaultSectionDescription?: string\n onSelect?: (id: typeof ROOT | typeof DEFAULT | number) => void\n}\n\nexport const FormSections: FC<FormSectionsProps> = ({\n container: Container,\n item: Item,\n defaultSectionTitle,\n defaultSectionDescription,\n onSelect,\n}) => {\n const { definition, data, documentErrors, section } = useFormContext()\n const entries = useFormSections(defaultSectionTitle, defaultSectionDescription)\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <Container>\n {entries.map((entry, index) => (\n <Item\n key={entry.id === ROOT ? 'root' : String(entry.id)}\n index={index}\n section={entry}\n active={section === DEFAULT ? index === 0 : entry.id === section}\n select={() => onSelect?.(entry.id)}\n />\n ))}\n </Container>\n )\n}\n","import type { FC } from 'react'\n\nimport { FormContent } from './form'\nimport { useFormContext } from './form-context'\nimport type { ViewerComponentMap } from './types'\n\ntype FormViewerProps = {\n components: ViewerComponentMap\n}\n\nexport const FormViewer: FC<FormViewerProps> = ({ components }) => {\n const { definition, data, visibilityMap, fieldErrors, section, showInlineValidation, documentErrors } =\n useFormContext()\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <FormContent\n mode=\"viewer\"\n items={definition.content}\n visibilityMap={visibilityMap}\n values={data.values}\n fieldErrors={fieldErrors}\n components={components}\n section={section}\n showInlineValidation={showInlineValidation}\n />\n )\n}\n"],"mappings":";;;;AAAA,MAAa,OAAsB,OAAO,OAAO;AAGjD,MAAa,UAAyB,OAAO,UAAU;;;ACuBvD,MAAM,cAAc,cAA4C,KAAA,EAAU;AAE1E,MAAa,uBAAyC;CAClD,MAAM,UAAU,WAAW,YAAY;AACvC,KAAI,CAAC,QAAS,OAAM,IAAI,MAAM,uDAAuD;AAErF,QAAO;;AAWX,MAAa,QAAuB,EAAE,YAAY,MAAM,SAAS,uBAAuB,MAAM,eAAe;CACzG,MAAM,EAAE,QAAQ,gBAAgB,qBAAqB,cAAc;AAC/D,MAAI,CAAC,WAAY,QAAO,EAAE;AAE1B,MAAI;AACA,UAAO,EAAE,QAAQ,IAAI,WAAW,WAAW,EAAE;WACxC,OAAO;AACZ,OAAI,iBAAiBA,gBAAe,QAAO,EAAE,gBAAgB,MAAM,QAAQ;AAC3E,SAAM;;IAEX,CAAC,WAAW,CAAC;CAEhB,MAAM,EAAE,eAAe,YAAY,gBAAgB,gBAAgB,cAAc;EAC7E,MAAM,gBAAgB,UAAU,OAAO,OAAO,iBAAiB,KAAK,mBAAG,IAAI,KAAsB;EACjG,MAAM,aACF,UAAU,OACJ,OAAO,SAAS,KAAK,GACpB;GACG,OAAO;GACP,6BAAa,IAAI,KAAqC;GACzD;AAEX,SAAO;GACH;GACA;GACA,gBAAgB,CAAC,GAAI,oBAAoB,EAAE,EAAG,GAAI,YAAY,kBAAkB,EAAE,CAAE;GACpF,aAAa,YAAY,+BAAe,IAAI,KAAqC;GACpF;IACF;EAAC;EAAQ;EAAM;EAAiB,CAAC;CAEpC,MAAM,QAA0B;EAC5B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACH;AAED,QAAO,oBAAC,YAAY,UAAb;EAA6B;EAAQ;EAAgC,CAAA;;;;AC1EhF,MAAa,0BAA2D,EACpE,WAAW,oBACX,OAAO,qBACL;CACF,MAAM,EAAE,mBAAmB,gBAAgB;AAE3C,KAAI,CAAC,gBAAgB,OAAQ,QAAO;AAEpC,QACI,oBAAC,oBAAD,EAAA,UACK,eAAe,KAAK,OAAO,UACxB,oBAAC,gBAAD,EAGI,GAAI,OACN,EAFO,SAAS,MAAM,KAAK,GAAG,MAAM,UAAU,GAAG,GAAG,QAEpD,CACJ,EACe,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACG7B,MAAa,kBACT,aACA,SACA,cACyB;CACzB,MAAM,SAAS,YAAY,IAAI,QAAQ,IAAI,EAAE;AAC7C,KAAI,cAAc,KAAA,EAAW,QAAO,OAAO,QAAQ,MAAM,EAAE,aAAa,KAAK;AAC7E,QAAO,OAAO,QAAQ,MAAM,EAAE,cAAc,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;AA2B1D,MAAa,iBAAiB,YAA8B,WAAqC;CAC7F,MAAM,UAAU,WAAW;AAC3B,QAAO;EACH,IAAI,WAAW;EACf,MAAM,QAAQ;EACd,OAAO,QAAQ;EACf,aAAa,QAAQ;EACrB,YAAY,QAAQ;EACpB,SAAS,QAAQ;EACpB;;;;;;;;;;;;;;;;;;;;;AAsBL,MAAa,eAAe,OAAsB,cAAsD;AACpG,MAAK,MAAM,QAAQ,MACf,KAAI,KAAK,SAAS,WAAW;AACzB,MAAI,KAAK,OAAO,UAAW,QAAO;EAClC,MAAM,QAAQ,YAAY,KAAK,SAAS,UAAU;AAClD,MAAI,MAAO,QAAO;;;;;AC7E9B,MAAa,aAAiC,EAC1C,OACA,eACA,QACA,aACA,YACA,sBACA,kBACA,2BACE;CACF,MAAM,mBAAmB,WAAW;CACpC,MAAM,iBAAiB,uBAAuB,WAAW,QAAQ,KAAA;CAEjE,MAAM,WAA8B,EAAE;AAEtC,MAAK,MAAM,QAAQ,OAAO;AACtB,MAAI,CAAC,cAAc,IAAI,KAAK,GAAG,CAAE;AAEjC,MAAI,KAAK,SAAS,UACd,UAAS,KACL,oBAAC,kBAAD;GAAgC,SAAS;aACrC,oBAAC,WAAD;IACI,OAAO,KAAK;IACG;IACP;IACK;IACD;IACU;IACJ;IACI;IACxB,CAAA;GACa,EAXI,KAAK,GAWT,CACtB;WACM,KAAK,SAAS,SAAS;GAC9B,MAAM,SAAS,eAAe,aAAa,KAAK,GAAG;GACnD,MAAM,YAAY,mBAAmB,KAAK,IAAI,EAAE;GAEhD,MAAM,iBAAiB,WAAW;GAClC,MAAM,aAAc,OAAO,OAAO,KAAK,GAAG,KAA+B,EAAE;GAC3E,MAAM,UAAU,KAAK;GACrB,MAAM,gBAAgB,WAClB,QAAQ;AAGZ,YAAS,KACL,oBAAC,gBAAD;IAEI,OAAO;IACP,OAAO,OAAO,OAAO,KAAK,GAAG;IAC7B,SAAS,KAAK;IACN;IACR,GAAI;cACH,gBACK,WAAW,KAAK,WAAW,UAAU;KACjC,MAAM,aAAa,eAAe,aAAa,KAAK,IAAI,MAAM;KAC9D,MAAM,YAAY,cAAc,MAAM,MAAM;KAG5C,MAAM,YAAqC;MACvC,OAAO;MACP,OAAO;MACP,QAAQ;MACR,GANkB,uBAAuB,MAAM,MAAM,IAAI,EAAE;MAO9D;AAED,SAAI,QAAQ,SAAS,SACjB,WAAU,UAAU,QAAQ,WAAW,EAAE;AAG7C,YAEI,qBAAC,UAAD,EAAA,UAAA,CACI,oBAAC,eAAD,EAAe,GAAI,WAAa,CAAA,EAC/B,kBAAkB,WAAW,SAAS,KACnC,oBAAC,gBAAD;MAAgB,QAAQ;MAAY,OAAO;MAAa,CAAA,CAErD,EAAA,EALI,GAAG,KAAK,GAAG,GAAG,QAKlB;MAEjB,GACF;IACO,EAlCR,KAAK,GAkCG,CACpB;AAED,OAAI,kBAAkB,OAAO,SAAS,EAClC,UAAS,KAAK,oBAAC,gBAAD;IAAiD;IAAQ,OAAO;IAAQ,EAAnD,GAAG,KAAK,GAAG,QAAwC,CAAC;SAExF;GACH,MAAM,SAAS,eAAe,aAAa,KAAK,GAAG;GACnD,MAAM,YAAY,mBAAmB,KAAK,IAAI,EAAE;GAEhD,MAAM,aAAsC;IACxC,OAAO;IACP,OAAO,OAAO,OAAO,KAAK,GAAG;IAC7B;IACA,GAAG;IACN;AAED,OAAI,KAAK,SAAS,SAAU,YAAW,UAAW,KAA0B,WAAW,EAAE;GAGzF,MAAM,iBAAiB,WADL,KAAK;AAGvB,YAAS,KAAK,oBAAC,gBAAD,EAA8B,GAAI,YAAc,EAA3B,KAAK,GAAsB,CAAC;AAE/D,OAAI,kBAAkB,OAAO,SAAS,EAClC,UAAS,KAAK,oBAAC,gBAAD;IAAiD;IAAQ,OAAO;IAAQ,EAAnD,GAAG,KAAK,GAAG,QAAwC,CAAC;;;AAInG,KAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAO;;;;ACvGX,MAAa,eAAqC,UAAU;CACxD,MAAM,EAAE,OAAO,eAAe,QAAQ,aAAa,SAAS,yBAAyB;CAErF,MAAM,cACF,MAAM,SAAS,WACT;EACI;EACA;EACA;EACA,YAAY,MAAM;EAClB;EACA,kBAAkB,MAAM;EACxB,sBAAsB,MAAM;EAC/B,GACD;EACI;EACA;EACA;EACA,YAAY,MAAM;EAClB;EACH;CAEX,MAAM,kBAAkB,YAAY,UAAU,sBAAsB,OAAO,cAAc,GAAG;AAE5F,KAAI,oBAAoB,KAAA,EAAW,QAAO,oBAAC,WAAD;EAAkB;EAAO,GAAI;EAAe,CAAA;AAEtF,KAAI,oBAAoB,KAEpB,QAAO,oBAAC,WAAD;EAAW,OADM,MAAM,QAAQ,SAAS,KAAK,SAAS,UAAU;EAC7B,GAAI;EAAe,CAAA;CAGjE,MAAM,eAAe,YAAY,OAAO,gBAAgB;AACxD,KAAI,CAAC,gBAAgB,CAAC,cAAc,IAAI,aAAa,GAAG,CAAE,QAAO;CAEjE,MAAM,UAAU,MAAM,WAAW;AACjC,QACI,oBAAC,SAAD;EAA+B,SAAS;YACpC,oBAAC,WAAD;GAAW,OAAO,aAAa;GAAS,GAAI;GAAe,CAAA;EACrD,EAFI,aAAa,GAEjB;;AAIlB,MAAM,yBACF,OACA,kBACmC;AAEnC,KADmB,MAAM,QAAQ,SAAS,KAAK,SAAS,UAAU,CACnD,MAAM,SAAS,cAAc,IAAI,KAAK,GAAG,CAAC,CAAE,QAAO;AAIlE,QAF4B,MAAM,MAAM,SAAS,KAAK,SAAS,aAAa,cAAc,IAAI,KAAK,GAAG,KAAK,MAAM,EAErF;;;;ACtEhC,MAAa,cAAmC,EAAE,YAAY,eAAe;CACzE,MAAM,EAAE,YAAY,MAAM,eAAe,aAAa,SAAS,QAAQ,sBAAsB,mBACzF,gBAAgB;CAEpB,MAAM,EAAE,kBAAkB,yBAAyB,kBAAkB,QAAQ,MAAM,SAAS;AAE5F,KAAI,CAAC,cAAc,CAAC,QAAS,kBAAkB,eAAe,SAAS,EAAI,QAAO;AAElF,QACI,oBAAC,aAAD;EACI,MAAK;EACL,OAAO,WAAW;EACH;EACf,QAAQ,KAAK;EACA;EACD;EACH;EACa;EACJ;EACI;EACxB,CAAA;;AAIV,MAAa,qBACT,QACA,MACA,aAIC;CAED,MAAM,WAAW,OAAO;EAAE;EAAM;EAAU;EAAQ,CAAC;AACnD,UAAS,UAAU;EAAE;EAAM;EAAU;EAAQ;CAI7C,MAAM,mBAAmB,uBAAO,IAAI,KAAuC,CAAC;CAC5E,MAAM,mBAAmB,aAAa,YAAgD;EAClF,MAAM,MAAM,OAAO,QAAQ;EAE3B,IAAI,UAAU,iBAAiB,QAAQ,IAAI,IAAI;AAC/C,MAAI,CAAC,SAAS;AACV,cAAW,aAAsB;IAC7B,MAAM,EAAE,MAAM,UAAU,WAAW,SAAS;AAC5C,QAAI,CAAC,QAAQ,CAAC,OAAQ;IAEtB,MAAM,WAAyB;KAAE,GAAG;KAAM,QAAQ;MAAE,GAAG,KAAK;OAAS,MAAM;MAAU;KAAE;AAEvF,aAAS,UAAU,OAAO,SAAS,SAAS,CAAC;;AAEjD,oBAAiB,QAAQ,IAAI,KAAK,QAAQ;;AAE9C,SAAO;IACR,EAAE,CAAC;CAIN,MAAM,mBAAmB,uBACrB,IAAI,KAOD,CACN;CACD,MAAM,mBAAmB,aAAa,YAAoB;EACtD,MAAM,MAAM,OAAO,QAAQ;EAE3B,IAAI,WAAW,iBAAiB,QAAQ,IAAI,IAAI;AAChD,MAAI,CAAC,UAAU;GACX,MAAM,QAAQ,WAA0C;IACpD,MAAM,EAAE,MAAM,UAAU,WAAW,SAAS;AAC5C,QAAI,CAAC,QAAQ,CAAC,OAAQ;IAEtB,MAAM,QAAS,KAAK,OAAO,QAAkC,EAAE;IAC/D,MAAM,WAAyB;KAAE,GAAG;KAAM,QAAQ;MAAE,GAAG,KAAK;OAAS,MAAM,OAAO,CAAC,GAAG,MAAM,CAAC;MAAE;KAAE;AAEjG,aAAS,UAAU,OAAO,SAAS,SAAS,CAAC;;AAGjD,cAAW;IACP,iBACI,MAAM,WAAW;AACb,YAAO,KAAK,KAAA,EAAU;AACtB,YAAO;MACT;IACN,eAAe,UACX,MAAM,WAAW;AACb,YAAO,OAAO,OAAO,EAAE;AACvB,YAAO;MACT;IACN,aAAa,WAAmB,YAC5B,MAAM,WAAW;KACb,MAAM,CAAC,SAAS,OAAO,OAAO,WAAW,EAAE;AAC3C,YAAO,OAAO,SAAS,GAAG,MAAM;AAChC,YAAO;MACT;IACT;AACD,oBAAiB,QAAQ,IAAI,KAAK,SAAS;;AAE/C,SAAO;IACR,EAAE,CAAC;CAIN,MAAM,uBAAuB,uBAAO,IAAI,KAAuC,CAAC;CAChF,MAAM,uBAAuB,aAAa,SAAiB,UAA8C;EACrG,MAAM,SAAS,GAAG,QAAQ,GAAG;EAE7B,IAAI,UAAU,qBAAqB,QAAQ,IAAI,OAAO;AACtD,MAAI,CAAC,SAAS;AACV,cAAW,aAAsB;IAC7B,MAAM,WAAW,OAAO,QAAQ;IAEhC,MAAM,EAAE,MAAM,UAAU,WAAW,SAAS;AAC5C,QAAI,CAAC,QAAQ,CAAC,OAAQ;IAEtB,MAAM,QAAQ,CAAC,GAAK,KAAK,OAAO,aAAuC,EAAE,CAAE;AAC3E,UAAM,SAAS;IAEf,MAAM,WAAyB;KAAE,GAAG;KAAM,QAAQ;MAAE,GAAG,KAAK;OAAS,WAAW;MAAO;KAAE;AACzF,aAAS,UAAU,OAAO,SAAS,SAAS,CAAC;;AAEjD,wBAAqB,QAAQ,IAAI,QAAQ,QAAQ;;AAErD,SAAO;IACR,EAAE,CAAC;AAEN,QAAO;EACH,mBAAmB,UAA8C;AAC7D,OAAI,MAAM,SAAS,QACf,QAAO;IACH,UAAU,iBAAiB,MAAM,GAAG;IACpC,GAAG,iBAAiB,MAAM,GAAG;IAChC;AAEL,UAAO,EAAE,UAAU,iBAAiB,MAAM,GAAG,EAAE;;EAEnD,uBAAuB,OAAyB,WAAyC,EACrF,UAAU,qBAAqB,MAAM,IAAI,MAAM,EAClD;EACJ;;;;AC7IL,MAAa,wBAAuD,EAChE,WAAW,oBACX,OAAO,gBACP,OAAO,qBACL;CACF,MAAM,EAAE,QAAQ,MAAM,aAAa,kBAAkB,gBAAgB;CAErE,MAAM,SAAS,cAAc;AACzB,MAAI,CAAC,UAAU,CAAC,QAAQ,YAAY,SAAS,EAAG,QAAO,EAAE;EAEzD,MAAM,SAAsC,EAAE;AAE9C,OAAK,MAAM,CAAC,SAAS,WAAW,aAAa;AACzC,OAAI,cAAc,IAAI,QAAQ,KAAK,MAAO;AAE1C,UAAO,KAAK;IACR,OAAO,OAAO,YAAY,QAAQ;IAClC;IACH,CAAC;;AAGN,SAAO;IACR;EAAC;EAAQ;EAAM;EAAa;EAAc,CAAC;AAE9C,KAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QACI,oBAAC,oBAAD,EAAA,UACK,OAAO,KAAK,UACT,oBAAC,gBAAD;EAAsC,GAAI;YACrC,MAAM,OAAO,KAAK,UACf,oBAAC,gBAAD,EAAgF,GAAI,OAAS,EAAxE,GAAG,MAAM,QAAQ,GAAG,MAAM,KAAK,GAAG,MAAM,aAAa,KAAmB,CAC/F;EACW,EAJI,MAAM,OAAO,GAIjB,CACnB,EACe,CAAA;;;;ACzC7B,MAAa,mBACT,sBAAsB,WACtB,8BACqB;CACrB,MAAM,EAAE,YAAY,eAAe,SAAS,gBAAgB;AAG5D,QAAO,cAAc;AACjB,MAAI,CAAC,WAAY,QAAO,EAAE;EAE1B,MAAM,SAA6B,EAAE;EAErC,MAAM,aAAa,WAAW,QAAQ,QAAQ,SAAS,KAAK,SAAS,UAAU;AAC/E,MAAI,WAAW,MAAM,SAAS,cAAc,IAAI,KAAK,GAAG,CAAC,CACrD,QAAO,KAAK;GACR,IAAI;GACJ,OAAO;GACP,aAAa;GACb,SAAS;GACT,WAAW,KAAA;GACd,CAAC;AAEN,OAAK,MAAM,QAAQ,WAAW,QAC1B,KAAI,KAAK,SAAS,WAAW;AACzB,OAAI,cAAc,IAAI,KAAK,GAAG,KAAK,MAAO;AAE1C,UAAO,KAAK,KAAK;;AAIzB,SAAO;IACR;EAAC,YAAY;EAAS;EAAe;EAAM;EAAqB;EAA0B,CAAC;;;;ACnBlG,MAAa,gBAAuC,EAChD,WAAW,WACX,MAAM,MACN,qBACA,2BACA,eACE;CACF,MAAM,EAAE,YAAY,MAAM,gBAAgB,YAAY,gBAAgB;CACtE,MAAM,UAAU,gBAAgB,qBAAqB,0BAA0B;AAE/E,KAAI,CAAC,cAAc,CAAC,QAAS,kBAAkB,eAAe,SAAS,EAAI,QAAO;AAElF,QACI,oBAAC,WAAD,EAAA,UACK,QAAQ,KAAK,OAAO,UACjB,oBAAC,MAAD;EAEW;EACP,SAAS;EACT,QAAQ,YAAY,UAAU,UAAU,IAAI,MAAM,OAAO;EACzD,cAAc,WAAW,MAAM,GAAG;EACpC,EALO,MAAM,OAAO,OAAO,SAAS,OAAO,MAAM,GAAG,CAKpD,CACJ,EACM,CAAA;;;;ACpCpB,MAAa,cAAmC,EAAE,iBAAiB;CAC/D,MAAM,EAAE,YAAY,MAAM,eAAe,aAAa,SAAS,sBAAsB,mBACjF,gBAAgB;AAEpB,KAAI,CAAC,cAAc,CAAC,QAAS,kBAAkB,eAAe,SAAS,EAAI,QAAO;AAElF,QACI,oBAAC,aAAD;EACI,MAAK;EACL,OAAO,WAAW;EACH;EACf,QAAQ,KAAK;EACA;EACD;EACH;EACa;EACxB,CAAA"}
1
+ {"version":3,"file":"index.mjs","names":["DocumentError"],"sources":["../src/constants.ts","../src/form-context.tsx","../src/form-document-validation.tsx","../src/form/utils.ts","../src/form/form-items.tsx","../src/form/form-content.tsx","../src/form-editor.tsx","../src/form-fields-validation.tsx","../src/use-form-sections.ts","../src/form-sections.tsx","../src/form-viewer.tsx"],"sourcesContent":["export const ROOT: unique symbol = Symbol('ROOT')\nexport type ROOT = typeof ROOT\n\nexport const DEFAULT: unique symbol = Symbol('DEFAULT')\nexport type DEFAULT = typeof DEFAULT\n","import { createContext, type FC, type ReactNode, useContext, useMemo } from 'react'\n\nimport {\n DocumentError,\n DocumentValidationError,\n FieldValidationError,\n FormDefinition,\n FormDocument,\n FormEngine,\n FormValidationResult,\n} from '@bluprynt/forms-core'\n\nimport type { DEFAULT, ROOT } from './constants'\n\ntype FormContextValue = {\n definition: FormDefinition | undefined\n data: FormDocument | undefined\n engine: FormEngine | undefined\n visibilityMap: Map<number, boolean>\n validation: FormValidationResult | undefined\n documentErrors: readonly DocumentValidationError[] | undefined\n fieldErrors: Map<number, FieldValidationError[]>\n section: typeof ROOT | typeof DEFAULT | number | undefined\n showInlineValidation: boolean\n}\n\nconst FormContext = createContext<FormContextValue | undefined>(undefined)\n\nexport const useFormContext = (): FormContextValue => {\n const context = useContext(FormContext)\n if (!context) throw new Error('useFormContext must be used within a <Form> provider')\n\n return context\n}\n\ntype FormProps = {\n definition?: FormDefinition\n data?: FormDocument\n section?: typeof ROOT | typeof DEFAULT | number\n showInlineValidation?: boolean\n children: ReactNode\n}\n\nexport const Form: FC<FormProps> = ({ definition, data, section, showInlineValidation = true, children }) => {\n const { engine, documentErrors: definitionErrors } = useMemo(() => {\n if (!definition) return {}\n\n try {\n return { engine: new FormEngine(definition) }\n } catch (error) {\n if (error instanceof DocumentError) return { documentErrors: error.errors }\n throw error\n }\n }, [definition])\n\n const { visibilityMap, validation, documentErrors, fieldErrors } = useMemo(() => {\n const visibilityMap = engine && data ? engine.getVisibilityMap(data) : new Map<number, boolean>()\n const validation =\n engine && data\n ? engine.validate(data)\n : ({\n valid: true,\n fieldErrors: new Map<number, FieldValidationError[]>(),\n } satisfies FormValidationResult)\n\n return {\n visibilityMap,\n validation,\n documentErrors: [...(definitionErrors ?? []), ...(validation?.documentErrors ?? [])],\n fieldErrors: validation?.fieldErrors ?? new Map<number, FieldValidationError[]>(),\n } as const\n }, [engine, data, definitionErrors])\n\n const value: FormContextValue = {\n definition,\n data,\n engine,\n visibilityMap,\n validation,\n documentErrors,\n fieldErrors,\n section,\n showInlineValidation,\n } as const\n\n return <FormContext.Provider value={value}>{children}</FormContext.Provider>\n}\n","import type { ComponentType, FC, PropsWithChildren } from 'react'\n\nimport type { DocumentValidationError } from '@bluprynt/forms-core'\n\nimport { useFormContext } from './form-context'\n\ntype FormDocumentValidationProps = {\n container: ComponentType<PropsWithChildren>\n error: ComponentType<DocumentValidationError>\n}\n\nexport const FormDocumentValidation: FC<FormDocumentValidationProps> = ({\n container: ContainerComponent,\n error: ErrorComponent,\n}) => {\n const { documentErrors } = useFormContext()\n\n if (!documentErrors?.length) return null\n\n return (\n <ContainerComponent>\n {documentErrors.map((error, index) => (\n <ErrorComponent\n // biome-ignore lint/suspicious/noArrayIndexKey: index is unique in array\n key={`error-${error.code}-${error.itemId ?? ''}-${index}`}\n {...error}\n />\n ))}\n </ContainerComponent>\n )\n}\n","import type {\n AnyFieldContentItem,\n ArrayItemDef,\n ArrayObjItemDef,\n ContentItem,\n FieldContentItem,\n FieldValidationError,\n SectionContentItem,\n} from '@bluprynt/forms-core'\n\n/**\n * Retrieves validation errors for a specific field from the pre-indexed error map.\n *\n * Uses O(1) map lookup by `fieldId`. When `itemIndex` is omitted, returns only\n * **field-level** errors (those without an `itemIndex`). When `itemIndex` is\n * provided, returns only **item-level** errors matching the given array item index.\n *\n * @param fieldErrors - Map from field id to its validation errors.\n * @param fieldId - The numeric ID of the field to retrieve errors for.\n * @param itemIndex - Optional zero-based index of the array item. When omitted, only\n * field-level errors (where `itemIndex` is `null` / `undefined`) are returned.\n * @returns Errors for the given field (and optionally item index). Empty array if none.\n *\n * @example\n * ```ts\n * // Field-level errors only (no itemIndex on the error)\n * getFieldErrors(fieldErrors, 5)\n *\n * // Errors for the third item of array field 5\n * getFieldErrors(fieldErrors, 5, 2)\n * ```\n */\nexport const getFieldErrors = (\n fieldErrors: Map<number, FieldValidationError[]>,\n fieldId: number,\n itemIndex?: number,\n): FieldValidationError[] => {\n const errors = fieldErrors.get(fieldId) ?? []\n if (itemIndex === undefined) return errors.filter((e) => e.itemIndex == null)\n return errors.filter((e) => e.itemIndex === itemIndex)\n}\n\n/**\n * Creates a synthetic {@link FieldContentItem} that represents a single item inside an array field.\n *\n * Array fields store their per-item schema in `arrayField.item` ({@link ArrayItemDef}).\n * Components that render individual array items need a standard `FieldContentItem` shape,\n * so this helper projects the item definition into one, preserving the parent field's `id`\n * while adopting the item's `type`, `label`, authoring metadata, `validation`, and `options`.\n *\n * A `static` item projects to a `StaticFieldContentItem`, so the return type is\n * the wider {@link AnyFieldContentItem}.\n *\n * @param arrayField - The array field definition whose `.item` property describes the item schema.\n * @param _index - The zero-based position of the item in the array (reserved for future use,\n * e.g. per-item overrides).\n * @returns An `AnyFieldContentItem` that can be passed directly to a typed field component.\n *\n * @example\n * ```ts\n * const arrayField: FieldContentItem = {\n * id: 10, type: 'array', label: 'Tags',\n * item: { type: 'string', label: 'Tag' },\n * }\n *\n * const itemDef = getArrayField(arrayField, 0)\n * // → { id: 10, type: 'string', label: 'Tag', ... }\n * ```\n */\nexport const getArrayField = (arrayField: FieldContentItem, _index: number): AnyFieldContentItem => {\n const itemDef = arrayField.item as ArrayItemDef\n const metadata = {\n description: itemDef.description,\n placeholder: itemDef.placeholder,\n answer_guidelines: itemDef.answer_guidelines,\n reference_id: itemDef.reference_id,\n }\n\n if (itemDef.type === 'static') {\n return { id: arrayField.id, type: 'static', text: itemDef.text, label: itemDef.label, ...metadata }\n }\n\n return {\n id: arrayField.id,\n type: itemDef.type,\n label: itemDef.label,\n ...metadata,\n validation: itemDef.validation as FieldContentItem['validation'],\n options: itemDef.options,\n }\n}\n\n/**\n * Creates a {@link AnyFieldContentItem} representing one sub-field of an `array_obj` field.\n *\n * Unlike an `array` item, a sub-field carries its own id, so the projection keeps it:\n * it is both the key its value is stored under inside each row and a stable React key.\n *\n * @param subField - The sub-field definition taken from the field's `items` list.\n * @returns An `AnyFieldContentItem` that can be passed directly to a typed field component.\n */\nexport const getArrayObjField = (subField: ArrayObjItemDef): AnyFieldContentItem => {\n const metadata = {\n description: subField.description,\n placeholder: subField.placeholder,\n answer_guidelines: subField.answer_guidelines,\n reference_id: subField.reference_id,\n }\n\n if (subField.type === 'static') {\n return { id: subField.id, type: 'static', text: subField.text, label: subField.label, ...metadata }\n }\n\n return {\n id: subField.id,\n type: subField.type,\n label: subField.label,\n ...metadata,\n validation: subField.validation as FieldContentItem['validation'],\n options: subField.options,\n }\n}\n\n/**\n * Retrieves the validation errors for one sub-field of one row of an `array_obj` field.\n *\n * Errors for an `array_obj` are all stored under the container's id; the row is\n * identified by `itemIndex` and the sub-field by `itemFieldId`.\n *\n * @param fieldErrors - Map from field id to its validation errors.\n * @param fieldId - The numeric id of the `array_obj` field.\n * @param index - Zero-based row index.\n * @param subFieldId - The numeric id of the sub-field.\n * @returns Errors for that cell. Empty array if none.\n */\nexport const getArrayObjItemErrors = (\n fieldErrors: Map<number, FieldValidationError[]>,\n fieldId: number,\n index: number,\n subFieldId: number,\n): FieldValidationError[] =>\n (fieldErrors.get(fieldId) ?? []).filter((e) => e.itemIndex === index && e.itemFieldId === subFieldId)\n\n/**\n * Retrieves the row-level validation errors for one row of an `array_obj` field --\n * those carrying an `itemIndex` but no `itemFieldId`, such as a row that is not an object.\n */\nexport const getArrayObjRowErrors = (\n fieldErrors: Map<number, FieldValidationError[]>,\n fieldId: number,\n index: number,\n): FieldValidationError[] =>\n (fieldErrors.get(fieldId) ?? []).filter((e) => e.itemIndex === index && e.itemFieldId == null)\n\n/**\n * Recursively searches content items for a section with the given id.\n *\n * Walks the content tree depth-first, checking sections and their nested\n * content. Returns the first matching {@link SectionContentItem}, or\n * `undefined` if no section with that id exists.\n *\n * @param items - The content items to search through.\n * @param sectionId - The numeric id of the section to find.\n * @returns The matching section, or `undefined` if not found.\n *\n * @example\n * ```ts\n * const section = findSection(definition.content, 42)\n * if (section) {\n * // render section.content\n * }\n * ```\n */\nexport const findSection = (items: ContentItem[], sectionId: number): SectionContentItem | undefined => {\n for (const item of items) {\n if (item.type === 'section') {\n if (item.id === sectionId) return item\n const found = findSection(item.content, sectionId)\n if (found) return found\n }\n }\n return undefined\n}\n","import { type FC, Fragment } from 'react'\n\nimport type {\n AnyFieldContentItem,\n ArrayItemDef,\n ArrayObjRow,\n ContentItem,\n FieldContentItem,\n FieldValidationError,\n FormSuggestions,\n FormValues,\n} from '@bluprynt/forms-core'\n\nimport type {\n EditorArrayItemProps,\n EditorArrayObjItemProps,\n EditorComponentMap,\n EditorFieldProps,\n ViewerComponentMap,\n} from '../types'\nimport { getArrayField, getArrayObjField, getArrayObjItemErrors, getArrayObjRowErrors, getFieldErrors } from './utils'\n\ntype AnyComponent = React.ComponentType<Record<string, unknown>> | undefined\n\ntype FormItemsProps = {\n items: ContentItem[]\n visibilityMap: Map<number, boolean>\n values: FormValues\n suggestions?: FormSuggestions\n fieldErrors: Map<number, FieldValidationError[]>\n components: ViewerComponentMap | EditorComponentMap\n showInlineValidation: boolean\n renderFieldProps?: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps?: (arrayField: FieldContentItem, index: number) => EditorArrayItemProps\n renderArrayObjItemProps?: (\n arrayField: FieldContentItem,\n index: number,\n subFieldId: number,\n ) => EditorArrayObjItemProps\n}\n\n/** Looks up the component for a value field type. Optional map keys may be absent. */\nconst componentFor = (components: ViewerComponentMap | EditorComponentMap, type: string): AnyComponent =>\n components[type as keyof Omit<ViewerComponentMap, 'array' | 'section' | 'error'>] as AnyComponent\n\n/** `select` and `multiselect` components are the only ones that receive injected options. */\nconst withOptions = (props: Record<string, unknown>, def: { type: string; options?: unknown }): void => {\n if (def.type === 'select' || def.type === 'multiselect') props.options = def.options ?? []\n}\n\nexport const FormItems: FC<FormItemsProps> = ({\n items,\n visibilityMap,\n values,\n suggestions,\n fieldErrors,\n components,\n showInlineValidation,\n renderFieldProps,\n renderArrayItemProps,\n renderArrayObjItemProps,\n}) => {\n const SectionComponent = components.section\n const ErrorComponent = showInlineValidation ? components.error : undefined\n\n const elements: React.ReactNode[] = []\n\n for (const item of items) {\n if (!visibilityMap.get(item.id)) continue\n\n if (item.type === 'section') {\n elements.push(\n <SectionComponent key={item.id} section={item}>\n <FormItems\n items={item.content}\n visibilityMap={visibilityMap}\n values={values}\n suggestions={suggestions}\n fieldErrors={fieldErrors}\n components={components}\n showInlineValidation={showInlineValidation}\n renderFieldProps={renderFieldProps}\n renderArrayItemProps={renderArrayItemProps}\n renderArrayObjItemProps={renderArrayObjItemProps}\n />\n </SectionComponent>,\n )\n } else if (item.type === 'array') {\n const errors = getFieldErrors(fieldErrors, item.id)\n const modeProps = renderFieldProps?.(item) ?? {}\n\n const ArrayComponent = components.array as React.ComponentType<Record<string, unknown>>\n const arrayValue = (values[String(item.id)] as unknown[] | undefined) ?? []\n const itemDef = item.item as ArrayItemDef\n const ItemComponent = componentFor(components, itemDef.type)\n\n const arrayProps: Record<string, unknown> = {\n field: item,\n value: values[String(item.id)],\n itemDef: item.item,\n errors,\n ...modeProps,\n }\n\n const arraySuggestion = suggestions?.[String(item.id)]\n if (arraySuggestion) arrayProps.suggestion = arraySuggestion\n\n elements.push(\n <ArrayComponent key={item.id} {...arrayProps}>\n {ItemComponent\n ? arrayValue.map((itemValue, index) => {\n const synthetic = getArrayField(item, index)\n\n // A static item holds no value: it gets the field and nothing else.\n if (synthetic.type === 'static') {\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: index is unique in array\n <Fragment key={`${item.id}-${index}`}>\n <ItemComponent field={synthetic} />\n </Fragment>\n )\n }\n\n const itemErrors = getFieldErrors(fieldErrors, item.id, index)\n const itemModeProps = renderArrayItemProps?.(item, index) ?? {}\n\n const baseProps: Record<string, unknown> = {\n field: synthetic,\n value: itemValue,\n errors: itemErrors,\n ...itemModeProps,\n }\n\n withOptions(baseProps, itemDef)\n\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: index is unique in array\n <Fragment key={`${item.id}-${index}`}>\n <ItemComponent {...baseProps} />\n {ErrorComponent && itemErrors.length > 0 && (\n <ErrorComponent errors={itemErrors} field={synthetic as FieldContentItem} />\n )}\n </Fragment>\n )\n })\n : null}\n </ArrayComponent>,\n )\n\n if (ErrorComponent && errors.length > 0) {\n elements.push(<ErrorComponent key={`${item.id}-error`} errors={errors} field={item} />)\n }\n } else if (item.type === 'array_obj') {\n // Optional map key, like the other late additions: render nothing rather than crash.\n const ArrayObjComponent = components.array_obj as AnyComponent\n if (!ArrayObjComponent) continue\n\n const itemsDef = item.items ?? []\n const rows = (values[String(item.id)] as ArrayObjRow[] | undefined) ?? []\n\n // Row-level errors (a row that is not an object) have no cell to land\n // on, so they join the field-level ones.\n const errors = [\n ...getFieldErrors(fieldErrors, item.id),\n ...rows.flatMap((_row, index) => getArrayObjRowErrors(fieldErrors, item.id, index)),\n ]\n const modeProps = renderFieldProps?.(item) ?? {}\n\n const arrayProps: Record<string, unknown> = {\n field: item,\n value: values[String(item.id)],\n itemsDef,\n // Resolved here so every component does not repeat the default.\n kind: item.kind ?? 'list',\n errors,\n ...modeProps,\n }\n\n const arraySuggestion = suggestions?.[String(item.id)]\n if (arraySuggestion) arrayProps.suggestion = arraySuggestion\n\n // children[rowIndex][subFieldIndex], aligned with itemsDef so a\n // component can lay the rows out as a table.\n const children = rows.map((row, index) =>\n itemsDef.map((subField) => {\n const key = `${item.id}-${index}-${subField.id}`\n const SubComponent = componentFor(components, subField.type)\n if (!SubComponent) return <Fragment key={key} />\n\n const synthetic = getArrayObjField(subField)\n\n if (subField.type === 'static') {\n return (\n <Fragment key={key}>\n <SubComponent field={synthetic} />\n </Fragment>\n )\n }\n\n const cellErrors = getArrayObjItemErrors(fieldErrors, item.id, index, subField.id)\n const cellModeProps = renderArrayObjItemProps?.(item, index, subField.id) ?? {}\n\n const cellProps: Record<string, unknown> = {\n field: synthetic,\n value: row?.[String(subField.id)],\n errors: cellErrors,\n ...cellModeProps,\n }\n\n withOptions(cellProps, subField)\n\n return (\n <Fragment key={key}>\n <SubComponent {...cellProps} />\n {ErrorComponent && cellErrors.length > 0 && (\n <ErrorComponent errors={cellErrors} field={synthetic as FieldContentItem} />\n )}\n </Fragment>\n )\n }),\n )\n\n elements.push(\n <ArrayObjComponent key={item.id} {...arrayProps}>\n {children}\n </ArrayObjComponent>,\n )\n\n if (ErrorComponent && errors.length > 0) {\n elements.push(<ErrorComponent key={`${item.id}-error`} errors={errors} field={item} />)\n }\n } else if (item.type === 'static') {\n // Static blocks hold no value: no errors, no suggestion, nothing to change.\n const StaticComponent = components.static as AnyComponent\n if (!StaticComponent) continue\n\n elements.push(<StaticComponent key={item.id} field={item} />)\n } else {\n const errors = getFieldErrors(fieldErrors, item.id)\n const modeProps = renderFieldProps?.(item) ?? {}\n\n const fieldProps: Record<string, unknown> = {\n field: item,\n value: values[String(item.id)],\n errors,\n ...modeProps,\n }\n\n const suggestion = suggestions?.[String(item.id)]\n if (suggestion) fieldProps.suggestion = suggestion\n\n withOptions(fieldProps, item as AnyFieldContentItem & { options?: unknown })\n\n const FieldComponent = componentFor(components, item.type)\n\n // Optional map keys (e.g. `multiselect`) may be absent; skip rather than crash.\n if (!FieldComponent) continue\n\n elements.push(<FieldComponent key={item.id} {...fieldProps} />)\n\n if (ErrorComponent && errors.length > 0)\n elements.push(<ErrorComponent key={`${item.id}-error`} errors={errors} field={item} />)\n }\n }\n\n if (elements.length === 0) return null\n\n return elements\n}\n","import type { FC } from 'react'\n\nimport type {\n ContentItem,\n FieldContentItem,\n FieldValidationError,\n FormSuggestions,\n FormValues,\n} from '@bluprynt/forms-core'\n\nimport { DEFAULT, ROOT } from '../constants'\nimport type {\n EditorArrayItemProps,\n EditorArrayObjItemProps,\n EditorComponentMap,\n EditorFieldProps,\n ViewerComponentMap,\n} from '../types'\nimport { FormItems } from './form-items'\nimport { findSection } from './utils'\n\ntype FormContentBaseProps = {\n items: ContentItem[]\n visibilityMap: Map<number, boolean>\n values: FormValues\n suggestions?: FormSuggestions\n fieldErrors: Map<number, FieldValidationError[]>\n section?: typeof ROOT | typeof DEFAULT | number\n showInlineValidation: boolean\n}\n\ntype FormContentViewerProps = FormContentBaseProps & {\n mode: 'viewer'\n components: ViewerComponentMap\n}\n\ntype FormContentEditorProps = FormContentBaseProps & {\n mode: 'editor'\n components: EditorComponentMap\n renderFieldProps: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps: (arrayField: FieldContentItem, index: number) => EditorArrayItemProps\n renderArrayObjItemProps: (\n arrayField: FieldContentItem,\n index: number,\n subFieldId: number,\n ) => EditorArrayObjItemProps\n}\n\nexport type FormContentProps = FormContentViewerProps | FormContentEditorProps\n\nexport const FormContent: FC<FormContentProps> = (props) => {\n const { items, visibilityMap, values, suggestions, fieldErrors, section, showInlineValidation } = props\n\n const sharedProps =\n props.mode === 'editor'\n ? {\n visibilityMap,\n values,\n suggestions,\n fieldErrors,\n components: props.components,\n showInlineValidation,\n renderFieldProps: props.renderFieldProps,\n renderArrayItemProps: props.renderArrayItemProps,\n renderArrayObjItemProps: props.renderArrayObjItemProps,\n }\n : {\n visibilityMap,\n values,\n suggestions,\n fieldErrors,\n components: props.components,\n showInlineValidation,\n }\n\n const selectedSection = section === DEFAULT ? resolveDefaultSection(items, visibilityMap) : section\n\n if (selectedSection === undefined) return <FormItems items={items} {...sharedProps} />\n\n if (selectedSection === ROOT) {\n const nonSectionItems = items.filter((item) => item.type !== 'section')\n return <FormItems items={nonSectionItems} {...sharedProps} />\n }\n\n const foundSection = findSection(items, selectedSection)\n if (!foundSection || !visibilityMap.get(foundSection.id)) return null\n\n const Section = props.components.section\n return (\n <Section key={foundSection.id} section={foundSection}>\n <FormItems items={foundSection.content} {...sharedProps} />\n </Section>\n )\n}\n\nconst resolveDefaultSection = (\n items: ContentItem[],\n visibilityMap: Map<number, boolean>,\n): typeof ROOT | number | undefined => {\n const rootFields = items.filter((item) => item.type !== 'section')\n if (rootFields.some((item) => visibilityMap.get(item.id))) return ROOT\n\n const firstVisibleSection = items.find((item) => item.type === 'section' && visibilityMap.get(item.id) !== false)\n\n return firstVisibleSection?.id\n}\n","import { type FC, useCallback, useRef } from 'react'\n\nimport {\n applySuggestion,\n FieldContentItem,\n FormDocument,\n FormEngine,\n FormValidationResult,\n removeSuggestion,\n} from '@bluprynt/forms-core'\n\nimport { FormContent } from './form'\nimport { useFormContext } from './form-context'\nimport type { EditorArrayItemProps, EditorArrayObjItemProps, EditorComponentMap, EditorFieldProps } from './types'\n\ntype FormEditorProps = {\n components: EditorComponentMap\n onChange: (data: FormDocument, validation: FormValidationResult) => void\n}\n\nexport const FormEditor: FC<FormEditorProps> = ({ components, onChange }) => {\n const { definition, data, visibilityMap, fieldErrors, section, engine, showInlineValidation, documentErrors } =\n useFormContext()\n\n const { renderFieldProps, renderArrayItemProps, renderArrayObjItemProps } = useEditorHandlers(\n engine,\n data,\n onChange,\n )\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <FormContent\n mode=\"editor\"\n items={definition.content}\n visibilityMap={visibilityMap}\n values={data.values}\n suggestions={data.suggestions}\n fieldErrors={fieldErrors}\n components={components}\n section={section}\n showInlineValidation={showInlineValidation}\n renderFieldProps={renderFieldProps}\n renderArrayItemProps={renderArrayItemProps}\n renderArrayObjItemProps={renderArrayObjItemProps}\n />\n )\n}\n\nexport const useEditorHandlers = (\n engine: FormEngine | undefined,\n data: FormDocument | undefined,\n onChange: (data: FormDocument, validation: FormValidationResult) => void,\n): {\n renderFieldProps: (field: FieldContentItem) => EditorFieldProps\n renderArrayItemProps: (field: FieldContentItem, index: number) => EditorArrayItemProps\n renderArrayObjItemProps: (field: FieldContentItem, index: number, subFieldId: number) => EditorArrayObjItemProps\n} => {\n // Latest ref pattern\n const stateRef = useRef({ data, onChange, engine })\n stateRef.current = { data, onChange, engine }\n\n // Per-field onChange handler\n\n const fieldOnChangeMap = useRef(new Map<string, (value: unknown) => void>())\n const getFieldOnChange = useCallback((fieldId: number): ((value: unknown) => void) => {\n const key = String(fieldId)\n\n let handler = fieldOnChangeMap.current.get(key)\n if (!handler) {\n handler = (newValue: unknown) => {\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const document: FormDocument = { ...data, values: { ...data.values, [key]: newValue } }\n\n onChange(document, engine.validate(document))\n }\n fieldOnChangeMap.current.set(key, handler)\n }\n return handler\n }, [])\n\n // Array mutation handlers\n\n const arrayHandlersMap = useRef(\n new Map<\n string,\n {\n onAddItem: () => void\n onRemoveItem: (index: number) => void\n onMoveItem: (fromIndex: number, toIndex: number) => void\n }\n >(),\n )\n const getArrayHandlers = useCallback((fieldId: number, newItem: () => unknown) => {\n const key = String(fieldId)\n\n let handlers = arrayHandlersMap.current.get(key)\n if (!handlers) {\n const fire = (mutate: (arr: unknown[]) => unknown[]) => {\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const items = (data.values[key] as unknown[] | undefined) ?? []\n const document: FormDocument = { ...data, values: { ...data.values, [key]: mutate([...items]) } }\n\n onChange(document, engine.validate(document))\n }\n\n handlers = {\n onAddItem: () =>\n fire((values) => {\n values.push(newItem())\n return values\n }),\n onRemoveItem: (index: number) =>\n fire((values) => {\n values.splice(index, 1)\n return values\n }),\n onMoveItem: (fromIndex: number, toIndex: number) =>\n fire((values) => {\n const [moved] = values.splice(fromIndex, 1)\n values.splice(toIndex, 0, moved)\n return values\n }),\n }\n arrayHandlersMap.current.set(key, handlers)\n }\n return handlers\n }, [])\n\n // Suggestion accept/reject handlers\n\n const suggestionHandlersMap = useRef(\n new Map<string, { onAcceptSuggestion: () => void; onRejectSuggestion: () => void }>(),\n )\n const getSuggestionHandlers = useCallback((fieldId: number) => {\n const key = String(fieldId)\n\n let handlers = suggestionHandlersMap.current.get(key)\n if (!handlers) {\n // Both helpers return the same document when the field has no\n // suggestion, which makes each handler a no-op in that case.\n const fire = (next: (document: FormDocument) => FormDocument) => {\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const document = next(data)\n if (document === data) return\n\n onChange(document, engine.validate(document))\n }\n\n handlers = {\n onAcceptSuggestion: () => fire((document) => applySuggestion(document, fieldId)),\n onRejectSuggestion: () => fire((document) => removeSuggestion(document, fieldId)),\n }\n suggestionHandlersMap.current.set(key, handlers)\n }\n return handlers\n }, [])\n\n // Array item onChange handler\n\n const arrayItemOnChangeMap = useRef(new Map<string, (value: unknown) => void>())\n const getArrayItemOnChange = useCallback((fieldId: number, index: number): ((value: unknown) => void) => {\n const mapKey = `${fieldId}-${index}`\n\n let handler = arrayItemOnChangeMap.current.get(mapKey)\n if (!handler) {\n handler = (newValue: unknown) => {\n const fieldKey = String(fieldId)\n\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const items = [...((data.values[fieldKey] as unknown[] | undefined) ?? [])]\n items[index] = newValue\n\n const document: FormDocument = { ...data, values: { ...data.values, [fieldKey]: items } }\n onChange(document, engine.validate(document))\n }\n arrayItemOnChangeMap.current.set(mapKey, handler)\n }\n return handler\n }, [])\n\n // `array_obj` cell onChange handler\n\n const arrayObjItemOnChangeMap = useRef(new Map<string, (value: unknown) => void>())\n const getArrayObjItemOnChange = useCallback(\n (fieldId: number, index: number, subFieldId: number): ((value: unknown) => void) => {\n const mapKey = `${fieldId}-${index}-${subFieldId}`\n\n let handler = arrayObjItemOnChangeMap.current.get(mapKey)\n if (!handler) {\n handler = (newValue: unknown) => {\n const fieldKey = String(fieldId)\n\n const { data, onChange, engine } = stateRef.current\n if (!data || !engine) return\n\n const rows = [...((data.values[fieldKey] as unknown[] | undefined) ?? [])]\n const current = rows[index]\n const row =\n typeof current === 'object' && current !== null && !Array.isArray(current)\n ? (current as Record<string, unknown>)\n : {}\n\n rows[index] = { ...row, [String(subFieldId)]: newValue }\n\n const document: FormDocument = { ...data, values: { ...data.values, [fieldKey]: rows } }\n onChange(document, engine.validate(document))\n }\n arrayObjItemOnChangeMap.current.set(mapKey, handler)\n }\n return handler\n },\n [],\n )\n\n return {\n renderFieldProps: (field: FieldContentItem): EditorFieldProps => {\n if (field.type === 'array' || field.type === 'array_obj') {\n const newItem = field.type === 'array_obj' ? () => ({}) : () => undefined\n return {\n onChange: getFieldOnChange(field.id),\n ...getArrayHandlers(field.id, newItem),\n ...getSuggestionHandlers(field.id),\n }\n }\n return { onChange: getFieldOnChange(field.id), ...getSuggestionHandlers(field.id) }\n },\n renderArrayItemProps: (field: FieldContentItem, index: number): EditorArrayItemProps => ({\n onChange: getArrayItemOnChange(field.id, index),\n }),\n renderArrayObjItemProps: (\n field: FieldContentItem,\n index: number,\n subFieldId: number,\n ): EditorArrayObjItemProps => ({\n onChange: getArrayObjItemOnChange(field.id, index, subFieldId),\n }),\n } as const\n}\n","import { type ComponentType, type FC, type PropsWithChildren, useMemo } from 'react'\n\nimport type { FieldEntry, FieldValidationError } from '@bluprynt/forms-core'\n\nimport { useFormContext } from './form-context'\n\nexport type FieldValidationFieldEntry = {\n field: FieldEntry | undefined\n errors: FieldValidationError[]\n}\n\ntype FormFieldsValidationProps = {\n container: ComponentType<PropsWithChildren>\n field: ComponentType<PropsWithChildren<FieldValidationFieldEntry>>\n error: ComponentType<FieldValidationError>\n}\n\nexport const FormFieldsValidation: FC<FormFieldsValidationProps> = ({\n container: ContainerComponent,\n field: FieldComponent,\n error: ErrorComponent,\n}) => {\n const { engine, data, fieldErrors, visibilityMap } = useFormContext()\n\n const groups = useMemo(() => {\n if (!engine || !data || fieldErrors.size === 0) return []\n\n const result: FieldValidationFieldEntry[] = []\n\n for (const [fieldId, errors] of fieldErrors) {\n if (visibilityMap.get(fieldId) === false) continue\n\n result.push({\n field: engine.getFieldDef(fieldId),\n errors,\n })\n }\n\n return result\n }, [engine, data, fieldErrors, visibilityMap])\n\n if (groups.length === 0) return null\n\n return (\n <ContainerComponent>\n {groups.map((group) => (\n <FieldComponent key={group.field?.id} {...group}>\n {group.errors.map((error) => (\n <ErrorComponent\n key={`${error.fieldId}-${error.rule}-${error.itemIndex ?? ''}-${error.itemFieldId ?? ''}`}\n {...error}\n />\n ))}\n </FieldComponent>\n ))}\n </ContainerComponent>\n )\n}\n","import { useMemo } from 'react'\n\nimport type { SectionContentItem } from '@bluprynt/forms-core'\n\nimport { ROOT } from './constants'\nimport { useFormContext } from './form-context'\n\nexport type FormSectionEntry = Omit<SectionContentItem, 'id' | 'type'> & {\n id: typeof ROOT | number\n}\n\nexport const useFormSections = (\n defaultSectionTitle = 'General',\n defaultSectionDescription?: string,\n): FormSectionEntry[] => {\n const { definition, visibilityMap, data } = useFormContext()\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: invalidate section list when data changes\n return useMemo(() => {\n if (!definition) return []\n\n const result: FormSectionEntry[] = []\n\n const rootFields = definition.content.filter((item) => item.type !== 'section')\n if (rootFields.some((item) => visibilityMap.get(item.id)))\n result.push({\n id: ROOT,\n title: defaultSectionTitle,\n description: defaultSectionDescription,\n content: rootFields,\n condition: undefined,\n })\n\n for (const item of definition.content) {\n if (item.type === 'section') {\n if (visibilityMap.get(item.id) === false) continue\n\n result.push(item)\n }\n }\n\n return result\n }, [definition?.content, visibilityMap, data, defaultSectionTitle, defaultSectionDescription])\n}\n","import { type ComponentType, type FC, type PropsWithChildren } from 'react'\n\nimport { DEFAULT, ROOT } from './constants'\nimport { useFormContext } from './form-context'\nimport { type FormSectionEntry, useFormSections } from './use-form-sections'\n\nexport type { FormSectionEntry }\n\nexport type FormSectionItemProps = {\n index: number\n section: FormSectionEntry\n active: boolean\n select: () => void\n}\n\ntype FormSectionsProps = {\n container: ComponentType<PropsWithChildren>\n item: ComponentType<FormSectionItemProps>\n defaultSectionTitle?: string\n defaultSectionDescription?: string\n onSelect?: (id: typeof ROOT | typeof DEFAULT | number) => void\n}\n\nexport const FormSections: FC<FormSectionsProps> = ({\n container: Container,\n item: Item,\n defaultSectionTitle,\n defaultSectionDescription,\n onSelect,\n}) => {\n const { definition, data, documentErrors, section } = useFormContext()\n const entries = useFormSections(defaultSectionTitle, defaultSectionDescription)\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <Container>\n {entries.map((entry, index) => (\n <Item\n key={entry.id === ROOT ? 'root' : String(entry.id)}\n index={index}\n section={entry}\n active={section === DEFAULT ? index === 0 : entry.id === section}\n select={() => onSelect?.(entry.id)}\n />\n ))}\n </Container>\n )\n}\n","import type { FC } from 'react'\n\nimport { FormContent } from './form'\nimport { useFormContext } from './form-context'\nimport type { ViewerComponentMap } from './types'\n\ntype FormViewerProps = {\n components: ViewerComponentMap\n}\n\nexport const FormViewer: FC<FormViewerProps> = ({ components }) => {\n const { definition, data, visibilityMap, fieldErrors, section, showInlineValidation, documentErrors } =\n useFormContext()\n\n if (!definition || !data || (documentErrors && documentErrors.length > 0)) return null\n\n return (\n <FormContent\n mode=\"viewer\"\n items={definition.content}\n visibilityMap={visibilityMap}\n values={data.values}\n suggestions={data.suggestions}\n fieldErrors={fieldErrors}\n components={components}\n section={section}\n showInlineValidation={showInlineValidation}\n />\n )\n}\n"],"mappings":"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"}