@overmap-ai/forms 1.0.32-react-flow-david-fixes.0 → 1.0.32-react-flow-david-fixes.2

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.
@@ -1,7 +1,7 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { SerializedFieldSection } from '../fields';
3
3
  import { FormBuilderSaveHandler } from './typings';
4
- interface FormBuilderRootProps extends PropsWithChildren {
4
+ export interface FormBuilderRootProps extends PropsWithChildren {
5
5
  initialTitle?: string;
6
6
  initialDescription?: string;
7
7
  initialFields?: SerializedFieldSection[];
@@ -11,4 +11,3 @@ interface FormBuilderRootProps extends PropsWithChildren {
11
11
  disableRequiredFields?: boolean;
12
12
  }
13
13
  export declare const FormBuilderRoot: import('react').NamedExoticComponent<FormBuilderRootProps>;
14
- export {};
@@ -1,4 +1 @@
1
- interface FormBuilderFlowBuilderProps {
2
- }
3
- export declare const FormBuilderFlowBuilder: import('react').NamedExoticComponent<FormBuilderFlowBuilderProps>;
4
- export {};
1
+ export declare const FormBuilderFlowBuilder: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -0,0 +1,9 @@
1
+ export type * from './typings';
2
+ export declare const FormBuilder: {
3
+ Root: import('react').NamedExoticComponent<import('./Root').FormBuilderRootProps>;
4
+ FlowBuilder: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
5
+ ListBuilder: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
6
+ Preview: import('react').NamedExoticComponent<import('./preview').FormBuilderPreviewProps>;
7
+ };
8
+ export { createCondition } from './utils';
9
+ export { createField } from './utils';
@@ -1,6 +1 @@
1
- interface FormBuilderListBuilderProps {
2
- showFormTitle?: boolean;
3
- showExplainerText?: boolean;
4
- }
5
- export declare const FormBuilderListBuilder: import('react').NamedExoticComponent<FormBuilderListBuilderProps>;
6
- export {};
1
+ export declare const FormBuilderListBuilder: import('react').MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
@@ -1,5 +1,4 @@
1
- interface FormBuilderPreviewProps {
1
+ export interface FormBuilderPreviewProps {
2
2
  showFormTitle?: boolean;
3
3
  }
4
4
  export declare const FormBuilderPreview: import('react').NamedExoticComponent<FormBuilderPreviewProps>;
5
- export {};
@@ -1,7 +1,4 @@
1
1
  import { BooleanFieldCondition, CheckboxListFieldCondition, DateFieldCondition, MultiSelectFieldCondition, MultiStringFieldCondition, NumberFieldCondition, RadioFieldCondition, ScanFieldCondition, SelectFieldCondition, StringFieldCondition, TextFieldCondition, UploadFieldCondition } from '../conditions';
2
- import { Field, FieldType, SerializedField, SerializedOnlyField } from '../fields';
3
- import { SerializedFieldSection } from '../fields/FieldSection/typings';
4
- export declare const emptySection: (id?: string, fields?: SerializedOnlyField[]) => SerializedFieldSection;
5
- export declare const wrapRootFieldsWithFieldSection: (fields: SerializedField[]) => SerializedFieldSection[];
2
+ import { Field, FieldType } from '../fields';
6
3
  export declare const createField: (type: Exclude<FieldType, "section">) => Field;
7
4
  export declare const createCondition: (field: Field) => BooleanFieldCondition | CheckboxListFieldCondition | DateFieldCondition | MultiSelectFieldCondition | MultiStringFieldCondition | NumberFieldCondition | RadioFieldCondition | ScanFieldCondition | SelectFieldCondition | StringFieldCondition | TextFieldCondition | UploadFieldCondition;
@@ -3,4 +3,4 @@ export * from './constants';
3
3
  export * from './fields';
4
4
  export * from './renderer';
5
5
  export type * from './typings';
6
- export { initializeFieldValues, validateFields } from './utils';
6
+ export { initializeFieldValues, separateFilesFromFields, separateFilesFromFieldValues, validateFields } from './utils';
@@ -1,8 +1,16 @@
1
1
  import { FormikErrors } from 'formik';
2
2
  import { FormBuilderValues } from './builder';
3
- import { AnyFormElement } from './fields';
3
+ import { AnyFormElement, SerializedField } from './fields';
4
4
  import { FieldValues } from './typings';
5
5
  export declare const hasKeys: (errors: object) => boolean;
6
6
  export declare const validateFields: (fields: AnyFormElement[], values: FieldValues | FormBuilderValues) => FormikErrors<FieldValues | FormBuilderValues> | undefined;
7
7
  export declare const initializeFieldValues: (fields: AnyFormElement[], values: FieldValues) => FieldValues;
8
8
  export declare const changedFieldValues: (fields: AnyFormElement[], values1: FieldValues, values2: FieldValues) => FieldValues;
9
+ export declare const separateFilesFromFieldValues: (values: FieldValues) => {
10
+ values: FieldValues;
11
+ files: Record<string, File[]>;
12
+ };
13
+ export declare const separateFilesFromFields: (fields: SerializedField[]) => Promise<{
14
+ fields: SerializedField[];
15
+ images: Record<string, File>;
16
+ }>;
package/dist/forms.js CHANGED
@@ -8,12 +8,12 @@ import * as React from "react";
8
8
  import { memo, forwardRef, useMemo, createContext, useContext, useState, useRef, useCallback, useEffect, Fragment as Fragment$1, use, useLayoutEffect, useId as useId$1 } from "react";
9
9
  import "@xyflow/react/dist/style.css";
10
10
  import { getBezierPath, BaseEdge, EdgeLabelRenderer, NodeToolbar, Position, Handle, MarkerType, useNodesState, useEdgesState, ReactFlow, Panel } from "@xyflow/react";
11
+ import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
11
12
  import { DirectedGraph } from "graphology";
12
13
  import { willCreateCycle } from "graphology-dag";
13
14
  import { v4 } from "uuid";
14
- import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
15
15
  import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
16
- import { Copy, Download, X, Plus, Check, ChevronDown, Minus, Circle, Maximize, FileWarning, File, Upload, Trash2, Settings } from "lucide-react";
16
+ import { Copy, Download, X, Plus, Check, ChevronDown, Minus, Circle, Maximize, FileWarning, File as File$1, Upload, Trash2, Settings } from "lucide-react";
17
17
  import * as ReactDOM from "react-dom";
18
18
  import ReactDOM__default from "react-dom";
19
19
  import { saveAs } from "file-saver";
@@ -32,6 +32,12 @@ const FileCard = memo(
32
32
  })
33
33
  );
34
34
  FileCard.displayName = "FileCard";
35
+ const SEVERITY_COLOR_MAPPING = {
36
+ danger: "danger",
37
+ warning: "warning",
38
+ info: "base",
39
+ success: "success"
40
+ };
35
41
  class Observable {
36
42
  constructor() {
37
43
  __publicField(this, "observers", /* @__PURE__ */ new Set());
@@ -189,12 +195,6 @@ const useFormikInput = (props) => {
189
195
  ];
190
196
  };
191
197
  const EMPTY_ARRAY = [];
192
- const SEVERITY_COLOR_MAPPING = {
193
- danger: "danger",
194
- warning: "warning",
195
- info: "base",
196
- success: "success"
197
- };
198
198
  const InputWithHelpText = (props) => {
199
199
  const { helpText, children, severity } = props;
200
200
  const color = severity ? SEVERITY_COLOR_MAPPING[severity] : "base";
@@ -31947,7 +31947,7 @@ const ImageCard = memo(
31947
31947
  "bg-transparent": !file
31948
31948
  }),
31949
31949
  children: [
31950
- error ? /* @__PURE__ */ jsx(FileWarning, { className: "h-4 w-4" }) : file && /* @__PURE__ */ jsx(File, { className: "h-4 w-4", style: { color: "var(--base-a11)" } }),
31950
+ error ? /* @__PURE__ */ jsx(FileWarning, { className: "h-4 w-4" }) : file && /* @__PURE__ */ jsx(File$1, { className: "h-4 w-4", style: { color: "var(--base-a11)" } }),
31951
31951
  /* @__PURE__ */ jsx(Text, { className: "truncate", size: "sm", children: error ?? (file == null ? void 0 : file.name) }),
31952
31952
  rightSlot
31953
31953
  ]
@@ -34529,6 +34529,52 @@ const changedFieldValues = (fields, values1, values2) => {
34529
34529
  return acc;
34530
34530
  }, {});
34531
34531
  };
34532
+ const isArrayOfFiles = (value) => {
34533
+ return Array.isArray(value) && value[0] instanceof File;
34534
+ };
34535
+ const separateFilesFromFieldValues = (values) => {
34536
+ const files = {};
34537
+ const newValues = {};
34538
+ for (const key in values) {
34539
+ const value = values[key];
34540
+ if (value instanceof File) {
34541
+ files[key] = [value];
34542
+ } else if (isArrayOfFiles(value)) {
34543
+ files[key] = value;
34544
+ } else if (value !== void 0) {
34545
+ newValues[key] = value;
34546
+ }
34547
+ }
34548
+ return { values: newValues, files };
34549
+ };
34550
+ const separateFilesFromFields = async (fields) => {
34551
+ const images = {};
34552
+ const newFields = [];
34553
+ for (const section of fields) {
34554
+ if (section.type !== "section") {
34555
+ throw new Error(`Expected ISerializedField type to be a section. Got ${section.type} instead.`);
34556
+ }
34557
+ const { fields: sectionFields } = section;
34558
+ const newSectionFields = [];
34559
+ for (const field of sectionFields) {
34560
+ if (field.image) {
34561
+ if (field.image instanceof Promise) {
34562
+ try {
34563
+ images[field.identifier] = await field.image;
34564
+ } catch (e) {
34565
+ console.error("Failed to get image from promise", e);
34566
+ }
34567
+ } else {
34568
+ images[field.identifier] = field.image;
34569
+ }
34570
+ delete field.image;
34571
+ }
34572
+ newSectionFields.push(field);
34573
+ }
34574
+ newFields.push({ ...section, fields: newSectionFields });
34575
+ }
34576
+ return { fields: newFields, images };
34577
+ };
34532
34578
  const FieldSettingsPopover = memo((props) => {
34533
34579
  const { popoverInputs, hasError, ...rest } = props;
34534
34580
  return /* @__PURE__ */ jsxs(Popover.Root, { children: [
@@ -35406,7 +35452,8 @@ const getLayoutedElements = (nodes, edges, direction) => {
35406
35452
  edges
35407
35453
  ];
35408
35454
  };
35409
- const FormBuilderFlowBuilder = memo((_props) => {
35455
+ const FormBuilderFlowBuilder = memo(() => {
35456
+ const { handleSubmit, errors } = useFormikContext();
35410
35457
  const { onCancel } = use(FormBuilderContext);
35411
35458
  const fieldSchema = use(FieldSchemaContext);
35412
35459
  const ref = useRef(null);
@@ -35495,61 +35542,98 @@ const FormBuilderFlowBuilder = memo((_props) => {
35495
35542
  },
35496
35543
  [fieldSchema.fields]
35497
35544
  );
35498
- return /* @__PURE__ */ jsxs(Card, { className: "size-full relative", variant: "outline", children: [
35545
+ const [titleFieldProps, titleMeta, titleHelpers] = useField("title");
35546
+ const [descriptionFieldProps, _descriptionMeta, descriptionHelpers] = useField("description");
35547
+ return /* @__PURE__ */ jsxs("form", { className: "size-full flex flex-col gap-4", id: formId, onSubmit: handleSubmit, children: [
35548
+ /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsx(
35549
+ Input.Root,
35550
+ {
35551
+ variant: "outline",
35552
+ size: "md",
35553
+ accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35554
+ children: /* @__PURE__ */ jsx(
35555
+ Input.Field,
35556
+ {
35557
+ placeholder: "Enter a title",
35558
+ value: titleFieldProps.value ?? "",
35559
+ onChange: (event) => {
35560
+ void titleHelpers.setValue(event.target.value);
35561
+ },
35562
+ maxLength: 100
35563
+ }
35564
+ )
35565
+ }
35566
+ ) }),
35499
35567
  /* @__PURE__ */ jsx(
35500
- ReactFlow,
35568
+ TextArea,
35501
35569
  {
35502
- ref,
35503
- onInit: setReactFlow,
35504
- nodes: layoutedNodes,
35505
- onNodesChange: handleNodesChange,
35506
- edges: layoutedEdges,
35507
- onEdgesChange: handleEdgesChange,
35508
- nodeTypes,
35509
- edgeTypes,
35510
- onConnect: handleConnect,
35511
- attributionPosition: "bottom-left",
35512
- fitView: true,
35513
- minZoom: 0,
35514
- isValidConnection: handleValidConnection
35570
+ className: "field-sizing-content",
35571
+ placeholder: "Explain a description",
35572
+ value: descriptionFieldProps.value ?? "",
35573
+ onChange: (event) => {
35574
+ void descriptionHelpers.setValue(event.target.value);
35575
+ },
35576
+ resize: "vertical",
35577
+ maxLength: 1e3,
35578
+ size: "md"
35515
35579
  }
35516
35580
  ),
35517
- /* @__PURE__ */ jsx(Panel, { position: "top-left", children: /* @__PURE__ */ jsx(ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: /* @__PURE__ */ jsxs(Button, { type: "submit", variant: "surface", onClick: handleAddSection, children: [
35518
- /* @__PURE__ */ jsx(LuIcon, { icon: "plus" }),
35519
- " Add section"
35520
- ] }) }) }),
35521
- /* @__PURE__ */ jsxs(Panel, { position: "top-right", className: "flex flex-col items-center gap-2", children: [
35522
- /* @__PURE__ */ jsxs(
35523
- ToggleGroup.Root,
35581
+ /* @__PURE__ */ jsxs(Card, { className: "size-full relative", variant: "outline", children: [
35582
+ /* @__PURE__ */ jsx(
35583
+ ReactFlow,
35524
35584
  {
35525
- className: "flex flex-col",
35526
- type: "single",
35527
- accentColor: "base",
35528
- size: "sm",
35529
- value: layoutDirection,
35530
- onValueChange: setLayoutDirection,
35531
- children: [
35532
- /* @__PURE__ */ jsx(ToggleGroup.IconItem, { className: "rounded-b-none", value: "LR", children: /* @__PURE__ */ jsx(LuIcon, { icon: "arrow-right-left" }) }),
35533
- /* @__PURE__ */ jsx(ToggleGroup.IconItem, { className: "rounded-t-none", value: "TB", children: /* @__PURE__ */ jsx(LuIcon, { icon: "arrow-down-up" }) })
35534
- ]
35585
+ ref,
35586
+ onInit: setReactFlow,
35587
+ nodes: layoutedNodes,
35588
+ onNodesChange: handleNodesChange,
35589
+ edges: layoutedEdges,
35590
+ onEdgesChange: handleEdgesChange,
35591
+ nodeTypes,
35592
+ edgeTypes,
35593
+ onConnect: handleConnect,
35594
+ attributionPosition: "bottom-left",
35595
+ fitView: true,
35596
+ minZoom: 0,
35597
+ isValidConnection: handleValidConnection
35535
35598
  }
35536
35599
  ),
35537
- /* @__PURE__ */ jsx(Separator, { size: "sm" }),
35538
- /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex flex-col ", size: "sm", accentColor: "base", variant: "soft", children: [
35539
- /* @__PURE__ */ jsx(IconButton, { className: "rounded-b-none", onClick: () => reactFlow == null ? void 0 : reactFlow.zoomIn(), children: /* @__PURE__ */ jsx(LuIcon, { icon: "plus" }) }),
35540
- /* @__PURE__ */ jsx(IconButton, { onClick: () => reactFlow == null ? void 0 : reactFlow.zoomOut(), radius: "none", children: /* @__PURE__ */ jsx(LuIcon, { icon: "minus" }) }),
35541
- /* @__PURE__ */ jsx(IconButton, { className: "rounded-t-none", onClick: () => reactFlow == null ? void 0 : reactFlow.fitView(), children: /* @__PURE__ */ jsx(LuIcon, { icon: "square-dashed" }) })
35542
- ] })
35600
+ /* @__PURE__ */ jsx(Panel, { position: "top-left", children: /* @__PURE__ */ jsx(ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "surface", onClick: handleAddSection, children: [
35601
+ /* @__PURE__ */ jsx(LuIcon, { icon: "plus" }),
35602
+ " Add section"
35603
+ ] }) }) }),
35604
+ /* @__PURE__ */ jsxs(Panel, { position: "top-right", className: "flex flex-col items-center gap-2", children: [
35605
+ /* @__PURE__ */ jsxs(
35606
+ ToggleGroup.Root,
35607
+ {
35608
+ className: "flex flex-col",
35609
+ type: "single",
35610
+ accentColor: "base",
35611
+ size: "sm",
35612
+ value: layoutDirection,
35613
+ onValueChange: setLayoutDirection,
35614
+ children: [
35615
+ /* @__PURE__ */ jsx(ToggleGroup.IconItem, { className: "rounded-b-none", value: "LR", type: "button", children: /* @__PURE__ */ jsx(LuIcon, { icon: "arrow-right-left" }) }),
35616
+ /* @__PURE__ */ jsx(ToggleGroup.IconItem, { className: "rounded-t-none", value: "TB", type: "button", children: /* @__PURE__ */ jsx(LuIcon, { icon: "arrow-down-up" }) })
35617
+ ]
35618
+ }
35619
+ ),
35620
+ /* @__PURE__ */ jsx(Separator, { size: "sm" }),
35621
+ /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex flex-col ", size: "sm", accentColor: "base", variant: "soft", children: [
35622
+ /* @__PURE__ */ jsx(IconButton, { className: "rounded-b-none", onClick: () => reactFlow == null ? void 0 : reactFlow.zoomIn(), type: "button", children: /* @__PURE__ */ jsx(LuIcon, { icon: "plus" }) }),
35623
+ /* @__PURE__ */ jsx(IconButton, { onClick: () => reactFlow == null ? void 0 : reactFlow.zoomOut(), radius: "none", type: "button", children: /* @__PURE__ */ jsx(LuIcon, { icon: "minus" }) }),
35624
+ /* @__PURE__ */ jsx(IconButton, { className: "rounded-t-none", onClick: () => reactFlow == null ? void 0 : reactFlow.fitView(), type: "button", children: /* @__PURE__ */ jsx(LuIcon, { icon: "square-dashed" }) })
35625
+ ] })
35626
+ ] }),
35627
+ /* @__PURE__ */ jsx(Panel, { position: "bottom-right", children: /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: [
35628
+ onCancel && /* @__PURE__ */ jsx(Button, { type: "button", variant: "soft", accentColor: "base", onClick: onCancel, children: "Cancel" }),
35629
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "surface", children: "Save" })
35630
+ ] }) })
35543
35631
  ] }),
35544
- /* @__PURE__ */ jsx(Panel, { position: "bottom-right", children: /* @__PURE__ */ jsxs(ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: [
35545
- onCancel && /* @__PURE__ */ jsx(Button, { type: "button", variant: "soft", accentColor: "base", onClick: onCancel, children: "Cancel" }),
35546
- /* @__PURE__ */ jsx(Button, { type: "submit", variant: "surface", children: "Save" })
35547
- ] }) })
35632
+ !!errors.fields && /* @__PURE__ */ jsx(Text, { size: "xs", accentColor: "danger", children: typeof errors.fields === "string" && errors.fields })
35548
35633
  ] });
35549
35634
  });
35550
35635
  FormBuilderFlowBuilder.displayName = "FormBuilderFlowBuilder";
35551
- const FormBuilderListBuilder = memo((props) => {
35552
- const { showFormTitle = true, showExplainerText = true } = props;
35636
+ const FormBuilderListBuilder = memo(() => {
35553
35637
  const { handleSubmit, errors } = useFormikContext();
35554
35638
  const { onCancel } = use(FormBuilderContext);
35555
35639
  const fieldSchema = use(FieldSchemaContext);
@@ -35559,43 +35643,41 @@ const FormBuilderListBuilder = memo((props) => {
35559
35643
  const [titleFieldProps, titleMeta, titleHelpers] = useField("title");
35560
35644
  const [descriptionFieldProps, _descriptionMeta, descriptionHelpers] = useField("description");
35561
35645
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
35562
- showExplainerText && /* @__PURE__ */ jsx(Text, { accentColor: "base", size: "sm", children: "Create your form using various field types. Sections can be conditionally rendered based on answers to fields in preceding sections." }),
35646
+ /* @__PURE__ */ jsx(Text, { accentColor: "base", size: "sm", children: "Create your form using various field types. Sections can be conditionally rendered based on answers to fields in preceding sections." }),
35563
35647
  /* @__PURE__ */ jsxs("form", { className: "flex flex-col gap-4", id: formId, onSubmit: handleSubmit, children: [
35564
- showFormTitle && /* @__PURE__ */ jsxs(Fragment, { children: [
35565
- /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsx(
35566
- Input.Root,
35567
- {
35568
- variant: "outline",
35569
- size: "md",
35570
- accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35571
- children: /* @__PURE__ */ jsx(
35572
- Input.Field,
35573
- {
35574
- placeholder: "Enter a title",
35575
- value: titleFieldProps.value ?? "",
35576
- onChange: (event) => {
35577
- void titleHelpers.setValue(event.target.value);
35578
- },
35579
- maxLength: 100
35580
- }
35581
- )
35582
- }
35583
- ) }),
35584
- /* @__PURE__ */ jsx(
35585
- TextArea,
35586
- {
35587
- className: "field-sizing-content",
35588
- placeholder: "Explain a description",
35589
- value: descriptionFieldProps.value ?? "",
35590
- onChange: (event) => {
35591
- void descriptionHelpers.setValue(event.target.value);
35592
- },
35593
- resize: "vertical",
35594
- maxLength: 1e3,
35595
- size: "md"
35596
- }
35597
- )
35598
- ] }),
35648
+ /* @__PURE__ */ jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsx(
35649
+ Input.Root,
35650
+ {
35651
+ variant: "outline",
35652
+ size: "md",
35653
+ accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35654
+ children: /* @__PURE__ */ jsx(
35655
+ Input.Field,
35656
+ {
35657
+ placeholder: "Enter a title",
35658
+ value: titleFieldProps.value ?? "",
35659
+ onChange: (event) => {
35660
+ void titleHelpers.setValue(event.target.value);
35661
+ },
35662
+ maxLength: 100
35663
+ }
35664
+ )
35665
+ }
35666
+ ) }),
35667
+ /* @__PURE__ */ jsx(
35668
+ TextArea,
35669
+ {
35670
+ className: "field-sizing-content",
35671
+ placeholder: "Explain a description",
35672
+ value: descriptionFieldProps.value ?? "",
35673
+ onChange: (event) => {
35674
+ void descriptionHelpers.setValue(event.target.value);
35675
+ },
35676
+ resize: "vertical",
35677
+ maxLength: 1e3,
35678
+ size: "md"
35679
+ }
35680
+ ),
35599
35681
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
35600
35682
  fieldSchema.fields.map((fieldSection, index) => /* @__PURE__ */ jsx(
35601
35683
  FieldSectionWithActions,
@@ -35786,45 +35868,53 @@ const FormBuilderRoot = memo((props) => {
35786
35868
  errors.fields = "At least one field is required.";
35787
35869
  }
35788
35870
  let fieldsToValidate = [];
35789
- for (const [sectionIndex, section] of form.fields.entries()) {
35871
+ for (const [sectionIndex, section] of form.fields.entries())
35790
35872
  for (const [fieldIndex, field] of section.fields.entries()) {
35791
35873
  let fieldSettings = [];
35792
- if (field instanceof CheckboxListField) {
35793
- fieldSettings = CheckboxListField.getFieldCreationSchema(
35794
- `fields.${sectionIndex}.fields.${fieldIndex}`
35795
- ).map((field2) => field2.field);
35796
- } else if (field instanceof MultiSelectField) {
35797
- fieldSettings = MultiSelectField.getFieldCreationSchema(
35798
- `fields.${sectionIndex}.fields.${fieldIndex}`
35799
- ).map((field2) => field2.field);
35800
- } else if (field instanceof NumberField) {
35801
- fieldSettings = NumberField.getFieldCreationSchema(
35802
- `fields.${sectionIndex}.fields.${fieldIndex}`
35803
- ).map((field2) => field2.field);
35804
- } else if (field instanceof RadioField) {
35805
- fieldSettings = RadioField.getFieldCreationSchema(
35806
- `fields.${sectionIndex}.fields.${fieldIndex}`
35807
- ).map((field2) => field2.field);
35808
- } else if (field instanceof SelectField) {
35809
- fieldSettings = SelectField.getFieldCreationSchema(
35810
- `fields.${sectionIndex}.fields.${fieldIndex}`
35811
- ).map((field2) => field2.field);
35812
- } else if (field instanceof StringField) {
35813
- fieldSettings = StringField.getFieldCreationSchema(
35814
- `fields.${sectionIndex}.fields.${fieldIndex}`
35815
- ).map((field2) => field2.field);
35816
- } else if (field instanceof TextField) {
35817
- fieldSettings = TextField.getFieldCreationSchema(
35818
- `fields.${sectionIndex}.fields.${fieldIndex}`
35819
- ).map((field2) => field2.field);
35820
- } else if (field instanceof UploadField) {
35821
- fieldSettings = UploadField.getFieldCreationSchema(
35822
- `fields.${sectionIndex}.fields.${fieldIndex}`
35823
- ).map((field2) => field2.field);
35874
+ switch (field.type) {
35875
+ case "text":
35876
+ fieldSettings = TextField.getFieldCreationSchema(
35877
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35878
+ ).map((field2) => field2.field);
35879
+ break;
35880
+ case "number":
35881
+ fieldSettings = NumberField.getFieldCreationSchema(
35882
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35883
+ ).map((field2) => field2.field);
35884
+ break;
35885
+ case "string":
35886
+ fieldSettings = StringField.getFieldCreationSchema(
35887
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35888
+ ).map((field2) => field2.field);
35889
+ break;
35890
+ case "select":
35891
+ fieldSettings = SelectField.getFieldCreationSchema(
35892
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35893
+ ).map((field2) => field2.field);
35894
+ break;
35895
+ case "multi-select":
35896
+ fieldSettings = MultiSelectField.getFieldCreationSchema(
35897
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35898
+ ).map((field2) => field2.field);
35899
+ break;
35900
+ case "upload":
35901
+ fieldSettings = UploadField.getFieldCreationSchema(
35902
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35903
+ ).map((field2) => field2.field);
35904
+ break;
35905
+ case "radio":
35906
+ fieldSettings = RadioField.getFieldCreationSchema(
35907
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35908
+ ).map((field2) => field2.field);
35909
+ break;
35910
+ case "checkbox-list":
35911
+ fieldSettings = fieldSettings = CheckboxListField.getFieldCreationSchema(
35912
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35913
+ ).map((field2) => field2.field);
35914
+ break;
35824
35915
  }
35825
35916
  fieldsToValidate = [...fieldsToValidate, ...fieldSettings];
35826
35917
  }
35827
- }
35828
35918
  const fieldErrors = validateFields(fieldsToValidate, form);
35829
35919
  if (fieldErrors) {
35830
35920
  errors.fields = fieldErrors.fields;
@@ -35855,16 +35945,17 @@ const FormBuilderRoot = memo((props) => {
35855
35945
  validateOnBlur: false,
35856
35946
  enableReinitialize
35857
35947
  });
35858
- const schema = useMemo(() => FieldSchema.deserialize(formik.values.fields), [formik.values.fields]);
35859
35948
  const observer = useCallback(
35860
35949
  (fieldSchema) => {
35861
35950
  formik.setFieldValue("fields", fieldSchema.serialize());
35862
35951
  },
35863
35952
  [formik]
35864
35953
  );
35865
- useLayoutEffect(() => {
35866
- return schema.observe(observer);
35867
- }, [observer, schema]);
35954
+ const schema = useMemo(() => {
35955
+ const schema2 = FieldSchema.deserialize(formik.values.fields);
35956
+ schema2.observe(observer);
35957
+ return schema2;
35958
+ }, [formik.values.fields, observer]);
35868
35959
  const contextValue = useMemo(() => {
35869
35960
  return {
35870
35961
  disableRequiredFields,
@@ -35939,6 +36030,8 @@ export {
35939
36030
  maxFileSizeB,
35940
36031
  maxFileSizeKB,
35941
36032
  maxFileSizeMB,
36033
+ separateFilesFromFieldValues,
36034
+ separateFilesFromFields,
35942
36035
  serializeFieldValues,
35943
36036
  useFieldInput,
35944
36037
  useFieldInputs,
@@ -1,6 +1,6 @@
1
1
  (function(global2, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("@overmap-ai/blocks"), require("class-variance-authority"), require("react"), require("@xyflow/react/dist/style.css"), require("@xyflow/react"), require("graphology"), require("graphology-dag"), require("uuid"), require("formik"), require("@hello-pangea/dnd"), require("lucide-react"), require("react-dom"), require("file-saver"), require("react-zxing"), require("lodash.get"), require("lodash.set"), require("@dagrejs/dagre")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "@overmap-ai/blocks", "class-variance-authority", "react", "@xyflow/react/dist/style.css", "@xyflow/react", "graphology", "graphology-dag", "uuid", "formik", "@hello-pangea/dnd", "lucide-react", "react-dom", "file-saver", "react-zxing", "lodash.get", "lodash.set", "@dagrejs/dagre"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.forms = {}, global2.jsxRuntime, global2.blocks, global2.classVarianceAuthority, global2.React, null, global2.react, global2.graphology, global2.graphologyDag, global2.uuid, global2.formik, global2.dnd, global2.lucideReact, global2.ReactDOM, global2.fileSaver, global2.reactZxing, global2.get, global2.set, global2.Dagre));
3
- })(this, function(exports2, jsxRuntime, blocks, classVarianceAuthority, React, style_css, react, graphology, graphologyDag, uuid, formik, dnd, lucideReact, ReactDOM, fileSaver, reactZxing, get, set, Dagre) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("@overmap-ai/blocks"), require("class-variance-authority"), require("react"), require("@xyflow/react/dist/style.css"), require("@xyflow/react"), require("formik"), require("graphology"), require("graphology-dag"), require("uuid"), require("@hello-pangea/dnd"), require("lucide-react"), require("react-dom"), require("file-saver"), require("react-zxing"), require("lodash.get"), require("lodash.set"), require("@dagrejs/dagre")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "@overmap-ai/blocks", "class-variance-authority", "react", "@xyflow/react/dist/style.css", "@xyflow/react", "formik", "graphology", "graphology-dag", "uuid", "@hello-pangea/dnd", "lucide-react", "react-dom", "file-saver", "react-zxing", "lodash.get", "lodash.set", "@dagrejs/dagre"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.forms = {}, global2.jsxRuntime, global2.blocks, global2.classVarianceAuthority, global2.React, null, global2.react, global2.formik, global2.graphology, global2.graphologyDag, global2.uuid, global2.dnd, global2.lucideReact, global2.ReactDOM, global2.fileSaver, global2.reactZxing, global2.get, global2.set, global2.Dagre));
3
+ })(this, function(exports2, jsxRuntime, blocks, classVarianceAuthority, React, style_css, react, formik, graphology, graphologyDag, uuid, dnd, lucideReact, ReactDOM, fileSaver, reactZxing, get, set, Dagre) {
4
4
  "use strict";var __defProp = Object.defineProperty;
5
5
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
6
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -34,6 +34,12 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
34
34
  })
35
35
  );
36
36
  FileCard.displayName = "FileCard";
37
+ const SEVERITY_COLOR_MAPPING = {
38
+ danger: "danger",
39
+ warning: "warning",
40
+ info: "base",
41
+ success: "success"
42
+ };
37
43
  class Observable {
38
44
  constructor() {
39
45
  __publicField(this, "observers", /* @__PURE__ */ new Set());
@@ -191,12 +197,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
191
197
  ];
192
198
  };
193
199
  const EMPTY_ARRAY = [];
194
- const SEVERITY_COLOR_MAPPING = {
195
- danger: "danger",
196
- warning: "warning",
197
- info: "base",
198
- success: "success"
199
- };
200
200
  const InputWithHelpText = (props) => {
201
201
  const { helpText, children, severity } = props;
202
202
  const color = severity ? SEVERITY_COLOR_MAPPING[severity] : "base";
@@ -34531,6 +34531,52 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
34531
34531
  return acc;
34532
34532
  }, {});
34533
34533
  };
34534
+ const isArrayOfFiles = (value) => {
34535
+ return Array.isArray(value) && value[0] instanceof File;
34536
+ };
34537
+ const separateFilesFromFieldValues = (values) => {
34538
+ const files = {};
34539
+ const newValues = {};
34540
+ for (const key in values) {
34541
+ const value = values[key];
34542
+ if (value instanceof File) {
34543
+ files[key] = [value];
34544
+ } else if (isArrayOfFiles(value)) {
34545
+ files[key] = value;
34546
+ } else if (value !== void 0) {
34547
+ newValues[key] = value;
34548
+ }
34549
+ }
34550
+ return { values: newValues, files };
34551
+ };
34552
+ const separateFilesFromFields = async (fields) => {
34553
+ const images = {};
34554
+ const newFields = [];
34555
+ for (const section of fields) {
34556
+ if (section.type !== "section") {
34557
+ throw new Error(`Expected ISerializedField type to be a section. Got ${section.type} instead.`);
34558
+ }
34559
+ const { fields: sectionFields } = section;
34560
+ const newSectionFields = [];
34561
+ for (const field of sectionFields) {
34562
+ if (field.image) {
34563
+ if (field.image instanceof Promise) {
34564
+ try {
34565
+ images[field.identifier] = await field.image;
34566
+ } catch (e) {
34567
+ console.error("Failed to get image from promise", e);
34568
+ }
34569
+ } else {
34570
+ images[field.identifier] = field.image;
34571
+ }
34572
+ delete field.image;
34573
+ }
34574
+ newSectionFields.push(field);
34575
+ }
34576
+ newFields.push({ ...section, fields: newSectionFields });
34577
+ }
34578
+ return { fields: newFields, images };
34579
+ };
34534
34580
  const FieldSettingsPopover = React.memo((props) => {
34535
34581
  const { popoverInputs, hasError, ...rest } = props;
34536
34582
  return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Popover.Root, { children: [
@@ -35408,7 +35454,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35408
35454
  edges
35409
35455
  ];
35410
35456
  };
35411
- const FormBuilderFlowBuilder = React.memo((_props) => {
35457
+ const FormBuilderFlowBuilder = React.memo(() => {
35458
+ const { handleSubmit, errors } = formik.useFormikContext();
35412
35459
  const { onCancel } = React.use(FormBuilderContext);
35413
35460
  const fieldSchema = React.use(FieldSchemaContext);
35414
35461
  const ref = React.useRef(null);
@@ -35497,61 +35544,98 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35497
35544
  },
35498
35545
  [fieldSchema.fields]
35499
35546
  );
35500
- return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Card, { className: "size-full relative", variant: "outline", children: [
35547
+ const [titleFieldProps, titleMeta, titleHelpers] = formik.useField("title");
35548
+ const [descriptionFieldProps, _descriptionMeta, descriptionHelpers] = formik.useField("description");
35549
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "size-full flex flex-col gap-4", id: formId, onSubmit: handleSubmit, children: [
35550
+ /* @__PURE__ */ jsxRuntime.jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsxRuntime.jsx(
35551
+ blocks.Input.Root,
35552
+ {
35553
+ variant: "outline",
35554
+ size: "md",
35555
+ accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35556
+ children: /* @__PURE__ */ jsxRuntime.jsx(
35557
+ blocks.Input.Field,
35558
+ {
35559
+ placeholder: "Enter a title",
35560
+ value: titleFieldProps.value ?? "",
35561
+ onChange: (event) => {
35562
+ void titleHelpers.setValue(event.target.value);
35563
+ },
35564
+ maxLength: 100
35565
+ }
35566
+ )
35567
+ }
35568
+ ) }),
35501
35569
  /* @__PURE__ */ jsxRuntime.jsx(
35502
- react.ReactFlow,
35570
+ blocks.TextArea,
35503
35571
  {
35504
- ref,
35505
- onInit: setReactFlow,
35506
- nodes: layoutedNodes,
35507
- onNodesChange: handleNodesChange,
35508
- edges: layoutedEdges,
35509
- onEdgesChange: handleEdgesChange,
35510
- nodeTypes,
35511
- edgeTypes,
35512
- onConnect: handleConnect,
35513
- attributionPosition: "bottom-left",
35514
- fitView: true,
35515
- minZoom: 0,
35516
- isValidConnection: handleValidConnection
35572
+ className: "field-sizing-content",
35573
+ placeholder: "Explain a description",
35574
+ value: descriptionFieldProps.value ?? "",
35575
+ onChange: (event) => {
35576
+ void descriptionHelpers.setValue(event.target.value);
35577
+ },
35578
+ resize: "vertical",
35579
+ maxLength: 1e3,
35580
+ size: "md"
35517
35581
  }
35518
35582
  ),
35519
- /* @__PURE__ */ jsxRuntime.jsx(react.Panel, { position: "top-left", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Button, { type: "submit", variant: "surface", onClick: handleAddSection, children: [
35520
- /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "plus" }),
35521
- " Add section"
35522
- ] }) }) }),
35523
- /* @__PURE__ */ jsxRuntime.jsxs(react.Panel, { position: "top-right", className: "flex flex-col items-center gap-2", children: [
35524
- /* @__PURE__ */ jsxRuntime.jsxs(
35525
- blocks.ToggleGroup.Root,
35583
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Card, { className: "size-full relative", variant: "outline", children: [
35584
+ /* @__PURE__ */ jsxRuntime.jsx(
35585
+ react.ReactFlow,
35526
35586
  {
35527
- className: "flex flex-col",
35528
- type: "single",
35529
- accentColor: "base",
35530
- size: "sm",
35531
- value: layoutDirection,
35532
- onValueChange: setLayoutDirection,
35533
- children: [
35534
- /* @__PURE__ */ jsxRuntime.jsx(blocks.ToggleGroup.IconItem, { className: "rounded-b-none", value: "LR", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "arrow-right-left" }) }),
35535
- /* @__PURE__ */ jsxRuntime.jsx(blocks.ToggleGroup.IconItem, { className: "rounded-t-none", value: "TB", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "arrow-down-up" }) })
35536
- ]
35587
+ ref,
35588
+ onInit: setReactFlow,
35589
+ nodes: layoutedNodes,
35590
+ onNodesChange: handleNodesChange,
35591
+ edges: layoutedEdges,
35592
+ onEdgesChange: handleEdgesChange,
35593
+ nodeTypes,
35594
+ edgeTypes,
35595
+ onConnect: handleConnect,
35596
+ attributionPosition: "bottom-left",
35597
+ fitView: true,
35598
+ minZoom: 0,
35599
+ isValidConnection: handleValidConnection
35537
35600
  }
35538
35601
  ),
35539
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Separator, { size: "sm" }),
35540
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex flex-col ", size: "sm", accentColor: "base", variant: "soft", children: [
35541
- /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { className: "rounded-b-none", onClick: () => reactFlow == null ? void 0 : reactFlow.zoomIn(), children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "plus" }) }),
35542
- /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { onClick: () => reactFlow == null ? void 0 : reactFlow.zoomOut(), radius: "none", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "minus" }) }),
35543
- /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { className: "rounded-t-none", onClick: () => reactFlow == null ? void 0 : reactFlow.fitView(), children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "square-dashed" }) })
35544
- ] })
35602
+ /* @__PURE__ */ jsxRuntime.jsx(react.Panel, { position: "top-left", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Button, { type: "button", variant: "surface", onClick: handleAddSection, children: [
35603
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "plus" }),
35604
+ " Add section"
35605
+ ] }) }) }),
35606
+ /* @__PURE__ */ jsxRuntime.jsxs(react.Panel, { position: "top-right", className: "flex flex-col items-center gap-2", children: [
35607
+ /* @__PURE__ */ jsxRuntime.jsxs(
35608
+ blocks.ToggleGroup.Root,
35609
+ {
35610
+ className: "flex flex-col",
35611
+ type: "single",
35612
+ accentColor: "base",
35613
+ size: "sm",
35614
+ value: layoutDirection,
35615
+ onValueChange: setLayoutDirection,
35616
+ children: [
35617
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.ToggleGroup.IconItem, { className: "rounded-b-none", value: "LR", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "arrow-right-left" }) }),
35618
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.ToggleGroup.IconItem, { className: "rounded-t-none", value: "TB", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "arrow-down-up" }) })
35619
+ ]
35620
+ }
35621
+ ),
35622
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Separator, { size: "sm" }),
35623
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex flex-col ", size: "sm", accentColor: "base", variant: "soft", children: [
35624
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { className: "rounded-b-none", onClick: () => reactFlow == null ? void 0 : reactFlow.zoomIn(), type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "plus" }) }),
35625
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { onClick: () => reactFlow == null ? void 0 : reactFlow.zoomOut(), radius: "none", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "minus" }) }),
35626
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { className: "rounded-t-none", onClick: () => reactFlow == null ? void 0 : reactFlow.fitView(), type: "button", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.LuIcon, { icon: "square-dashed" }) })
35627
+ ] })
35628
+ ] }),
35629
+ /* @__PURE__ */ jsxRuntime.jsx(react.Panel, { position: "bottom-right", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: [
35630
+ onCancel && /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "soft", accentColor: "base", onClick: onCancel, children: "Cancel" }),
35631
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", variant: "surface", children: "Save" })
35632
+ ] }) })
35545
35633
  ] }),
35546
- /* @__PURE__ */ jsxRuntime.jsx(react.Panel, { position: "bottom-right", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.ButtonGroup, { className: "flex items-center justify-end gap-2", size: "sm", children: [
35547
- onCancel && /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "soft", accentColor: "base", onClick: onCancel, children: "Cancel" }),
35548
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", variant: "surface", children: "Save" })
35549
- ] }) })
35634
+ !!errors.fields && /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "xs", accentColor: "danger", children: typeof errors.fields === "string" && errors.fields })
35550
35635
  ] });
35551
35636
  });
35552
35637
  FormBuilderFlowBuilder.displayName = "FormBuilderFlowBuilder";
35553
- const FormBuilderListBuilder = React.memo((props) => {
35554
- const { showFormTitle = true, showExplainerText = true } = props;
35638
+ const FormBuilderListBuilder = React.memo(() => {
35555
35639
  const { handleSubmit, errors } = formik.useFormikContext();
35556
35640
  const { onCancel } = React.use(FormBuilderContext);
35557
35641
  const fieldSchema = React.use(FieldSchemaContext);
@@ -35561,43 +35645,41 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35561
35645
  const [titleFieldProps, titleMeta, titleHelpers] = formik.useField("title");
35562
35646
  const [descriptionFieldProps, _descriptionMeta, descriptionHelpers] = formik.useField("description");
35563
35647
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
35564
- showExplainerText && /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { accentColor: "base", size: "sm", children: "Create your form using various field types. Sections can be conditionally rendered based on answers to fields in preceding sections." }),
35648
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { accentColor: "base", size: "sm", children: "Create your form using various field types. Sections can be conditionally rendered based on answers to fields in preceding sections." }),
35565
35649
  /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "flex flex-col gap-4", id: formId, onSubmit: handleSubmit, children: [
35566
- showFormTitle && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
35567
- /* @__PURE__ */ jsxRuntime.jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsxRuntime.jsx(
35568
- blocks.Input.Root,
35569
- {
35570
- variant: "outline",
35571
- size: "md",
35572
- accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35573
- children: /* @__PURE__ */ jsxRuntime.jsx(
35574
- blocks.Input.Field,
35575
- {
35576
- placeholder: "Enter a title",
35577
- value: titleFieldProps.value ?? "",
35578
- onChange: (event) => {
35579
- void titleHelpers.setValue(event.target.value);
35580
- },
35581
- maxLength: 100
35582
- }
35583
- )
35584
- }
35585
- ) }),
35586
- /* @__PURE__ */ jsxRuntime.jsx(
35587
- blocks.TextArea,
35588
- {
35589
- className: "field-sizing-content",
35590
- placeholder: "Explain a description",
35591
- value: descriptionFieldProps.value ?? "",
35592
- onChange: (event) => {
35593
- void descriptionHelpers.setValue(event.target.value);
35594
- },
35595
- resize: "vertical",
35596
- maxLength: 1e3,
35597
- size: "md"
35598
- }
35599
- )
35600
- ] }),
35650
+ /* @__PURE__ */ jsxRuntime.jsx(InputWithHelpText, { severity: "danger", helpText: titleMeta.error ?? null, children: /* @__PURE__ */ jsxRuntime.jsx(
35651
+ blocks.Input.Root,
35652
+ {
35653
+ variant: "outline",
35654
+ size: "md",
35655
+ accentColor: titleMeta.error ? SEVERITY_COLOR_MAPPING.danger : "primary",
35656
+ children: /* @__PURE__ */ jsxRuntime.jsx(
35657
+ blocks.Input.Field,
35658
+ {
35659
+ placeholder: "Enter a title",
35660
+ value: titleFieldProps.value ?? "",
35661
+ onChange: (event) => {
35662
+ void titleHelpers.setValue(event.target.value);
35663
+ },
35664
+ maxLength: 100
35665
+ }
35666
+ )
35667
+ }
35668
+ ) }),
35669
+ /* @__PURE__ */ jsxRuntime.jsx(
35670
+ blocks.TextArea,
35671
+ {
35672
+ className: "field-sizing-content",
35673
+ placeholder: "Explain a description",
35674
+ value: descriptionFieldProps.value ?? "",
35675
+ onChange: (event) => {
35676
+ void descriptionHelpers.setValue(event.target.value);
35677
+ },
35678
+ resize: "vertical",
35679
+ maxLength: 1e3,
35680
+ size: "md"
35681
+ }
35682
+ ),
35601
35683
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
35602
35684
  fieldSchema.fields.map((fieldSection, index) => /* @__PURE__ */ jsxRuntime.jsx(
35603
35685
  FieldSectionWithActions,
@@ -35788,45 +35870,53 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35788
35870
  errors.fields = "At least one field is required.";
35789
35871
  }
35790
35872
  let fieldsToValidate = [];
35791
- for (const [sectionIndex, section] of form.fields.entries()) {
35873
+ for (const [sectionIndex, section] of form.fields.entries())
35792
35874
  for (const [fieldIndex, field] of section.fields.entries()) {
35793
35875
  let fieldSettings = [];
35794
- if (field instanceof CheckboxListField) {
35795
- fieldSettings = CheckboxListField.getFieldCreationSchema(
35796
- `fields.${sectionIndex}.fields.${fieldIndex}`
35797
- ).map((field2) => field2.field);
35798
- } else if (field instanceof MultiSelectField) {
35799
- fieldSettings = MultiSelectField.getFieldCreationSchema(
35800
- `fields.${sectionIndex}.fields.${fieldIndex}`
35801
- ).map((field2) => field2.field);
35802
- } else if (field instanceof NumberField) {
35803
- fieldSettings = NumberField.getFieldCreationSchema(
35804
- `fields.${sectionIndex}.fields.${fieldIndex}`
35805
- ).map((field2) => field2.field);
35806
- } else if (field instanceof RadioField) {
35807
- fieldSettings = RadioField.getFieldCreationSchema(
35808
- `fields.${sectionIndex}.fields.${fieldIndex}`
35809
- ).map((field2) => field2.field);
35810
- } else if (field instanceof SelectField) {
35811
- fieldSettings = SelectField.getFieldCreationSchema(
35812
- `fields.${sectionIndex}.fields.${fieldIndex}`
35813
- ).map((field2) => field2.field);
35814
- } else if (field instanceof StringField) {
35815
- fieldSettings = StringField.getFieldCreationSchema(
35816
- `fields.${sectionIndex}.fields.${fieldIndex}`
35817
- ).map((field2) => field2.field);
35818
- } else if (field instanceof TextField) {
35819
- fieldSettings = TextField.getFieldCreationSchema(
35820
- `fields.${sectionIndex}.fields.${fieldIndex}`
35821
- ).map((field2) => field2.field);
35822
- } else if (field instanceof UploadField) {
35823
- fieldSettings = UploadField.getFieldCreationSchema(
35824
- `fields.${sectionIndex}.fields.${fieldIndex}`
35825
- ).map((field2) => field2.field);
35876
+ switch (field.type) {
35877
+ case "text":
35878
+ fieldSettings = TextField.getFieldCreationSchema(
35879
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35880
+ ).map((field2) => field2.field);
35881
+ break;
35882
+ case "number":
35883
+ fieldSettings = NumberField.getFieldCreationSchema(
35884
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35885
+ ).map((field2) => field2.field);
35886
+ break;
35887
+ case "string":
35888
+ fieldSettings = StringField.getFieldCreationSchema(
35889
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35890
+ ).map((field2) => field2.field);
35891
+ break;
35892
+ case "select":
35893
+ fieldSettings = SelectField.getFieldCreationSchema(
35894
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35895
+ ).map((field2) => field2.field);
35896
+ break;
35897
+ case "multi-select":
35898
+ fieldSettings = MultiSelectField.getFieldCreationSchema(
35899
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35900
+ ).map((field2) => field2.field);
35901
+ break;
35902
+ case "upload":
35903
+ fieldSettings = UploadField.getFieldCreationSchema(
35904
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35905
+ ).map((field2) => field2.field);
35906
+ break;
35907
+ case "radio":
35908
+ fieldSettings = RadioField.getFieldCreationSchema(
35909
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35910
+ ).map((field2) => field2.field);
35911
+ break;
35912
+ case "checkbox-list":
35913
+ fieldSettings = fieldSettings = CheckboxListField.getFieldCreationSchema(
35914
+ `fields.${sectionIndex}.fields.${fieldIndex}`
35915
+ ).map((field2) => field2.field);
35916
+ break;
35826
35917
  }
35827
35918
  fieldsToValidate = [...fieldsToValidate, ...fieldSettings];
35828
35919
  }
35829
- }
35830
35920
  const fieldErrors = validateFields(fieldsToValidate, form);
35831
35921
  if (fieldErrors) {
35832
35922
  errors.fields = fieldErrors.fields;
@@ -35857,16 +35947,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35857
35947
  validateOnBlur: false,
35858
35948
  enableReinitialize
35859
35949
  });
35860
- const schema = React.useMemo(() => FieldSchema.deserialize(formik$1.values.fields), [formik$1.values.fields]);
35861
35950
  const observer = React.useCallback(
35862
35951
  (fieldSchema) => {
35863
35952
  formik$1.setFieldValue("fields", fieldSchema.serialize());
35864
35953
  },
35865
35954
  [formik$1]
35866
35955
  );
35867
- React.useLayoutEffect(() => {
35868
- return schema.observe(observer);
35869
- }, [observer, schema]);
35956
+ const schema = React.useMemo(() => {
35957
+ const schema2 = FieldSchema.deserialize(formik$1.values.fields);
35958
+ schema2.observe(observer);
35959
+ return schema2;
35960
+ }, [formik$1.values.fields, observer]);
35870
35961
  const contextValue = React.useMemo(() => {
35871
35962
  return {
35872
35963
  disableRequiredFields,
@@ -35940,6 +36031,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
35940
36031
  exports2.maxFileSizeB = maxFileSizeB;
35941
36032
  exports2.maxFileSizeKB = maxFileSizeKB;
35942
36033
  exports2.maxFileSizeMB = maxFileSizeMB;
36034
+ exports2.separateFilesFromFieldValues = separateFilesFromFieldValues;
36035
+ exports2.separateFilesFromFields = separateFilesFromFields;
35943
36036
  exports2.serializeFieldValues = serializeFieldValues;
35944
36037
  exports2.useFieldInput = useFieldInput;
35945
36038
  exports2.useFieldInputs = useFieldInputs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overmap-ai/forms",
3
- "version": "1.0.32-react-flow-david-fixes.0",
3
+ "version": "1.0.32-react-flow-david-fixes.2",
4
4
  "license": "UNLICENSED",
5
5
  "main": "dist/forms.umd.cjs",
6
6
  "module": "dist/forms.js",