@overmap-ai/forms 1.0.10-conditional-arrows-2.5 → 1.0.10-conditional-arrows-2.7
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/builder/FieldActions.d.ts +2 -1
- package/dist/builder/FieldBuilder.d.ts +5 -4
- package/dist/fields/BaseField/hooks.d.ts +1 -1
- package/dist/fields/BooleanField/BooleanField.d.ts +1 -1
- package/dist/fields/DateField/DateField.d.ts +1 -1
- package/dist/fields/MultiStringField/MultiStringField.d.ts +1 -1
- package/dist/fields/NumberField/NumberField.d.ts +1 -1
- package/dist/fields/SelectField/MultiSelectField.d.ts +1 -1
- package/dist/fields/SelectField/SelectField.d.ts +1 -1
- package/dist/fields/StringOrTextFields/StringField/StringField.d.ts +1 -1
- package/dist/fields/StringOrTextFields/TextField/TextField.d.ts +1 -1
- package/dist/fields/UploadField/UploadField.d.ts +1 -1
- package/dist/fields/UploadField/utils.d.ts +1 -1
- package/dist/forms.js +180 -105
- package/dist/forms.js.map +1 -1
- package/dist/forms.umd.cjs +226 -153
- package/dist/forms.umd.cjs.map +1 -1
- package/dist/typings.d.ts +6 -0
- package/package.json +6 -4
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
import { DraggableProvidedDragHandleProps } from "@hello-pangea/dnd";
|
|
2
3
|
import { FieldBuilderArgs } from "./FieldBuilder";
|
|
3
4
|
interface FieldActionsProps {
|
|
4
5
|
remove: () => void;
|
|
6
|
+
dragHandleProps: DraggableProvidedDragHandleProps | null | undefined;
|
|
5
7
|
editProps: FieldBuilderArgs;
|
|
6
8
|
insertAfterProps: FieldBuilderArgs;
|
|
7
9
|
duplicateProps: FieldBuilderArgs;
|
|
8
|
-
type?: string;
|
|
9
10
|
}
|
|
10
11
|
export declare const FieldActions: import("react").NamedExoticComponent<FieldActionsProps>;
|
|
11
12
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NestedFieldPath } from "./typings";
|
|
2
|
-
import { FC,
|
|
2
|
+
import { FC, Dispatch, SetStateAction } from "react";
|
|
3
3
|
import { FieldTypeIdentifier, ISerializedField } from "@overmap-ai/core";
|
|
4
4
|
import { Form } from '../typings';
|
|
5
5
|
interface FieldOptionsFormProps {
|
|
@@ -11,13 +11,14 @@ interface FieldOptionsFormProps {
|
|
|
11
11
|
handleDirtyChange: (dirty: boolean) => void;
|
|
12
12
|
handleCreateField: (form: Form) => void;
|
|
13
13
|
}
|
|
14
|
-
interface FieldBuilderProps extends Pick<FieldOptionsFormProps, "conditionalSourceFields"> {
|
|
14
|
+
export interface FieldBuilderProps extends Pick<FieldOptionsFormProps, "conditionalSourceFields"> {
|
|
15
15
|
index: number;
|
|
16
16
|
parentPath: NestedFieldPath;
|
|
17
|
+
isOpen: boolean;
|
|
18
|
+
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
|
17
19
|
initial?: ISerializedField;
|
|
18
20
|
editing?: boolean;
|
|
19
|
-
children: ReactNode;
|
|
20
21
|
}
|
|
21
|
-
export type FieldBuilderArgs = Omit<FieldBuilderProps, "children">;
|
|
22
|
+
export type FieldBuilderArgs = Omit<FieldBuilderProps, "children" | "isOpen" | "setIsOpen">;
|
|
22
23
|
export declare const FieldBuilder: FC<FieldBuilderProps>;
|
|
23
24
|
export {};
|
|
@@ -116,7 +116,7 @@ export declare const useFormikInput: <TField extends AnyField>(props: ComponentP
|
|
|
116
116
|
readonly accessKey?: string | undefined;
|
|
117
117
|
readonly autoFocus?: boolean | undefined;
|
|
118
118
|
readonly className?: string | undefined;
|
|
119
|
-
readonly contentEditable?: (boolean | "true" | "false") | "inherit" | undefined;
|
|
119
|
+
readonly contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
|
|
120
120
|
readonly contextMenu?: string | undefined;
|
|
121
121
|
readonly draggable?: (boolean | "true" | "false") | undefined;
|
|
122
122
|
readonly hidden?: boolean | undefined;
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SerializedBooleanField } from "@overmap-ai/core";
|
|
|
2
2
|
import { BaseField, ChildFieldOptions } from "../BaseField";
|
|
3
3
|
import { ChangeEvent, ReactNode } from "react";
|
|
4
4
|
import { ComponentProps } from "../typings";
|
|
5
|
-
import { CheckCircledIcon } from "@
|
|
5
|
+
import { CheckCircledIcon } from "@radix-ui/react-icons";
|
|
6
6
|
export declare class BooleanField extends BaseField<boolean, "boolean"> {
|
|
7
7
|
static readonly fieldTypeName = "Checkbox";
|
|
8
8
|
static readonly fieldTypeDescription = "Perfect for both optional and required yes/no questions.";
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SerializedDateField } from "@overmap-ai/core";
|
|
|
2
2
|
import { BaseField, ChildFieldOptions } from "../BaseField";
|
|
3
3
|
import { GetInputProps } from "../typings";
|
|
4
4
|
import React from "react";
|
|
5
|
-
import { CalendarIcon } from "@
|
|
5
|
+
import { CalendarIcon } from "@radix-ui/react-icons";
|
|
6
6
|
export declare class DateField extends BaseField<string, "date"> {
|
|
7
7
|
static readonly fieldTypeName = "Date";
|
|
8
8
|
static readonly fieldTypeDescription = "Allows specifying a date.";
|
|
@@ -2,7 +2,7 @@ import { BaseField, ChildFieldOptions } from "../BaseField";
|
|
|
2
2
|
import { ISerializedField, SelectFieldOption, SerializedMultiStringField } from "@overmap-ai/core";
|
|
3
3
|
import { GetInputProps, InputFieldLevelValidator } from "../typings.ts";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
|
-
import { ListBulletIcon } from "@
|
|
5
|
+
import { ListBulletIcon } from "@radix-ui/react-icons";
|
|
6
6
|
type MultiStringFieldOptions = ChildFieldOptions<SelectFieldOption[]> & {
|
|
7
7
|
minimum_length?: number;
|
|
8
8
|
maximum_length?: number;
|
|
@@ -3,7 +3,7 @@ import { BooleanField } from "../BooleanField";
|
|
|
3
3
|
import { BaseField, ChildFieldOptions } from "../BaseField";
|
|
4
4
|
import { GetInputProps, InputFieldLevelValidator, InputValidator } from "../typings";
|
|
5
5
|
import { ChangeEvent, ReactNode } from "react";
|
|
6
|
-
import { FontFamilyIcon } from "@
|
|
6
|
+
import { FontFamilyIcon } from "@radix-ui/react-icons";
|
|
7
7
|
export type NumberFieldValue = number | "";
|
|
8
8
|
export interface NumberFieldOptions extends ChildFieldOptions<NumberFieldValue> {
|
|
9
9
|
maximum?: number;
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SelectFieldOptionValue, SerializedMultiSelectField }
|
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import { GetInputProps } from "../typings";
|
|
4
4
|
import { BaseSelectField, BaseSelectFieldOptions } from "./BaseSelectField";
|
|
5
|
-
import { CheckboxIcon } from "@
|
|
5
|
+
import { CheckboxIcon } from "@radix-ui/react-icons";
|
|
6
6
|
/**
|
|
7
7
|
* The options passed to the constructor of MultiSelectField.
|
|
8
8
|
*/
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SelectFieldOptionValue, SerializedSelectField } from
|
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import { GetInputProps } from "../typings";
|
|
4
4
|
import { BaseSelectField, BaseSelectFieldOptions } from "./BaseSelectField";
|
|
5
|
-
import { DropdownMenuIcon } from "@
|
|
5
|
+
import { DropdownMenuIcon } from "@radix-ui/react-icons";
|
|
6
6
|
/**
|
|
7
7
|
* The options passed to the constructor of SelectField.
|
|
8
8
|
*/
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SerializedStringField, StringInputType } from "@overm
|
|
|
2
2
|
import { StringOrTextField, StringOrTextFieldOptions } from "../StringOrTextField";
|
|
3
3
|
import { GetInputProps } from "../../typings";
|
|
4
4
|
import React from "react";
|
|
5
|
-
import { InputIcon } from "@
|
|
5
|
+
import { InputIcon } from "@radix-ui/react-icons";
|
|
6
6
|
interface StringFieldOptions extends Omit<StringOrTextFieldOptions, "type"> {
|
|
7
7
|
inputType?: StringInputType;
|
|
8
8
|
}
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SerializedTextField } from "@overmap-ai/core";
|
|
|
2
2
|
import { StringOrTextField, StringOrTextFieldOptions } from "../StringOrTextField";
|
|
3
3
|
import { GetInputProps } from "../../typings";
|
|
4
4
|
import React from "react";
|
|
5
|
-
import { RowsIcon } from "@
|
|
5
|
+
import { RowsIcon } from "@radix-ui/react-icons";
|
|
6
6
|
export interface TextFieldOptions extends Omit<StringOrTextFieldOptions, "type"> {
|
|
7
7
|
}
|
|
8
8
|
export declare class TextField extends StringOrTextField<"text"> {
|
|
@@ -2,7 +2,7 @@ import { ISerializedField, SerializedUploadField } from "@overmap-ai/core";
|
|
|
2
2
|
import { BaseField, ChildFieldOptions } from "../BaseField";
|
|
3
3
|
import { GetInputProps, InputFieldLevelValidator } from "../typings";
|
|
4
4
|
import { ChangeEvent, ReactNode } from "react";
|
|
5
|
-
import { UploadIcon } from "@
|
|
5
|
+
import { UploadIcon } from "@radix-ui/react-icons";
|
|
6
6
|
import { NumberField } from "../NumberField";
|
|
7
7
|
import { MultiSelectField } from "../SelectField";
|
|
8
8
|
export interface UploadFieldOptions extends ChildFieldOptions<File[]> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const convertKilobytesToLargestUnit: (kilobytes: number) => string;
|
package/dist/forms.js
CHANGED
|
@@ -5,9 +5,11 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
7
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
8
|
-
import { Flex, Text, useSeverityColor, Checkbox,
|
|
8
|
+
import { Flex, Text, useSeverityColor, Checkbox, TextArea, Select, IconButton, Badge, MultiSelect, Button, ButtonList, divButtonProps, Tooltip, Separator, useDiscardAlertDialog, Dialog, DropdownItemMenu, useAlertDialog, useToast } from "@overmap-ai/blocks";
|
|
9
9
|
import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
|
|
10
|
-
import React, { useMemo, memo, useCallback, useState, useEffect, useRef, forwardRef, useReducer } from "react";
|
|
10
|
+
import React, { useMemo, memo, useCallback, useState, useEffect, useRef, forwardRef, Fragment as Fragment$1, useReducer } from "react";
|
|
11
|
+
import { CheckCircledIcon, FontFamilyIcon, CalendarIcon, InputIcon, RowsIcon, PlusIcon, Cross1Icon, ListBulletIcon, DropdownMenuIcon, CheckboxIcon, UploadIcon, StarFilledIcon, StarIcon, QuestionMarkCircledIcon, PersonIcon, Pencil1Icon, TrashIcon, CopyIcon, DragHandleDots2Icon, DotsVerticalIcon } from "@radix-ui/react-icons";
|
|
12
|
+
import { TextField as TextField$1, Box, Card, Heading, Avatar, Em, Strong, Tabs } from "@radix-ui/themes";
|
|
11
13
|
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
|
|
12
14
|
import { slugify, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser, classNames, isToday, getLocalDateString, selectLatestFormRevision, useFileSrc, selectSubmissionsForForm } from "@overmap-ai/core";
|
|
13
15
|
import get from "lodash.get";
|
|
@@ -1146,15 +1148,20 @@ const previewImage = "_previewImage_1ig84_1";
|
|
|
1146
1148
|
const styles$2 = {
|
|
1147
1149
|
previewImage
|
|
1148
1150
|
};
|
|
1149
|
-
const
|
|
1150
|
-
const units = ["
|
|
1151
|
-
let sizeInUnit =
|
|
1151
|
+
const convertKilobytesToLargestUnit = (kilobytes) => {
|
|
1152
|
+
const units = ["kilobyte", "megabyte"];
|
|
1153
|
+
let sizeInUnit = kilobytes;
|
|
1152
1154
|
let unitIndex = 0;
|
|
1153
1155
|
while (sizeInUnit > 1024 && unitIndex < units.length - 1) {
|
|
1154
1156
|
sizeInUnit /= 1024;
|
|
1155
1157
|
unitIndex++;
|
|
1156
1158
|
}
|
|
1157
|
-
const formatter = new Intl.NumberFormat([], {
|
|
1159
|
+
const formatter = new Intl.NumberFormat([], {
|
|
1160
|
+
// 0 for kilobytes, 1 for megabytes
|
|
1161
|
+
maximumFractionDigits: unitIndex,
|
|
1162
|
+
style: "unit",
|
|
1163
|
+
unit: units[unitIndex]
|
|
1164
|
+
});
|
|
1158
1165
|
return formatter.format(sizeInUnit);
|
|
1159
1166
|
};
|
|
1160
1167
|
const NumberInput = memo(function NumberInput22(props) {
|
|
@@ -1168,7 +1175,7 @@ const NumberInput = memo(function NumberInput22(props) {
|
|
|
1168
1175
|
if (helpText)
|
|
1169
1176
|
return helpText;
|
|
1170
1177
|
if (field.maxFileSize) {
|
|
1171
|
-
const size =
|
|
1178
|
+
const size = convertKilobytesToLargestUnit(field.maxFileSize);
|
|
1172
1179
|
return `Maximum file size: ${size}`;
|
|
1173
1180
|
}
|
|
1174
1181
|
return null;
|
|
@@ -1236,7 +1243,7 @@ const DisplayFile = memo(function DisplayFile2({ file, field, onRemove, disabled
|
|
|
1236
1243
|
}
|
|
1237
1244
|
if (resolvedFile) {
|
|
1238
1245
|
name2 = resolvedFile.name;
|
|
1239
|
-
size2 =
|
|
1246
|
+
size2 = convertKilobytesToLargestUnit(resolvedFile.size);
|
|
1240
1247
|
} else {
|
|
1241
1248
|
name2 = "Downloading...";
|
|
1242
1249
|
size2 = "...";
|
|
@@ -1272,7 +1279,7 @@ const DisplayFile = memo(function DisplayFile2({ file, field, onRemove, disabled
|
|
|
1272
1279
|
url && /* @__PURE__ */ jsx("img", { className: styles$2.previewImage, src: url, alt: name })
|
|
1273
1280
|
] }) });
|
|
1274
1281
|
});
|
|
1275
|
-
const largestSupportedSize = 50 * 1024
|
|
1282
|
+
const largestSupportedSize = 50 * 1024;
|
|
1276
1283
|
const _UploadField = class _UploadField extends BaseField {
|
|
1277
1284
|
constructor(options) {
|
|
1278
1285
|
const { extensions, maximum_files, maximum_size, ...base } = options;
|
|
@@ -1299,11 +1306,13 @@ const _UploadField = class _UploadField extends BaseField {
|
|
|
1299
1306
|
required: false,
|
|
1300
1307
|
minimum: 1,
|
|
1301
1308
|
maximum: 10,
|
|
1302
|
-
identifier: "maximum_files"
|
|
1309
|
+
identifier: "maximum_files",
|
|
1310
|
+
integers: true
|
|
1303
1311
|
}),
|
|
1304
1312
|
new NumberField({
|
|
1313
|
+
// TODO: Default value
|
|
1305
1314
|
label: "What is the maximum size of each file?",
|
|
1306
|
-
description: "Maximum file size in
|
|
1315
|
+
description: "Maximum file size in kilobytes.",
|
|
1307
1316
|
required: false,
|
|
1308
1317
|
identifier: "maximum_size",
|
|
1309
1318
|
minimum: 1,
|
|
@@ -1346,7 +1355,7 @@ const _UploadField = class _UploadField extends BaseField {
|
|
|
1346
1355
|
const maxFiles = this.maxFiles ?? 1;
|
|
1347
1356
|
validators.push((value) => {
|
|
1348
1357
|
if (value && value.some((file) => file.size > maxFileSize)) {
|
|
1349
|
-
return `Files must be at most ${
|
|
1358
|
+
return `Files must be at most ${convertKilobytesToLargestUnit(maxFileSize)}.`;
|
|
1350
1359
|
}
|
|
1351
1360
|
});
|
|
1352
1361
|
validators.push((value) => {
|
|
@@ -1986,7 +1995,7 @@ const FieldOptionsForm = memo(function FieldOptionsForm2(props) {
|
|
|
1986
1995
|
);
|
|
1987
1996
|
});
|
|
1988
1997
|
const FieldBuilder = memo(function FieldBuilder2(props) {
|
|
1989
|
-
const { parentPath, index,
|
|
1998
|
+
const { parentPath, index, isOpen, setIsOpen, initial, editing, conditionalSourceFields } = props;
|
|
1990
1999
|
const [fieldType, setFieldType] = useState();
|
|
1991
2000
|
const [formIsDirty, setFormIsDirty] = useState(false);
|
|
1992
2001
|
const type = (initial == null ? void 0 : initial.type) ?? fieldType;
|
|
@@ -2002,24 +2011,21 @@ const FieldBuilder = memo(function FieldBuilder2(props) {
|
|
|
2002
2011
|
setFieldType(void 0);
|
|
2003
2012
|
setFormIsDirty(false);
|
|
2004
2013
|
}, []);
|
|
2005
|
-
const
|
|
2006
|
-
(
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
},
|
|
2019
|
-
[formIsDirty, openConfirmDiscardChangesDialog]
|
|
2020
|
-
);
|
|
2014
|
+
const handleCloseDialog = useCallback(() => {
|
|
2015
|
+
if (!formIsDirty) {
|
|
2016
|
+
setFieldType(void 0);
|
|
2017
|
+
setIsOpen(false);
|
|
2018
|
+
} else {
|
|
2019
|
+
openConfirmDiscardChangesDialog({
|
|
2020
|
+
onDiscard: () => {
|
|
2021
|
+
setFieldType(void 0);
|
|
2022
|
+
setIsOpen(false);
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
}
|
|
2026
|
+
}, [formIsDirty, openConfirmDiscardChangesDialog, setIsOpen]);
|
|
2021
2027
|
const handleCreateField = useCallback(
|
|
2022
|
-
(form
|
|
2028
|
+
(form) => {
|
|
2023
2029
|
const { label } = form;
|
|
2024
2030
|
if (!type)
|
|
2025
2031
|
throw new Error("Field type must be selected before creating a field.");
|
|
@@ -2043,42 +2049,55 @@ const FieldBuilder = memo(function FieldBuilder2(props) {
|
|
|
2043
2049
|
newFields = insert(parent, index, field);
|
|
2044
2050
|
}
|
|
2045
2051
|
setFieldValue(parentPath, newFields).then();
|
|
2046
|
-
|
|
2052
|
+
setIsOpen(false);
|
|
2047
2053
|
},
|
|
2048
|
-
[
|
|
2054
|
+
[type, values, parentPath, editing, setFieldValue, setIsOpen, index]
|
|
2049
2055
|
);
|
|
2050
2056
|
const handleDirtyChange = useCallback((dirty) => setFormIsDirty(dirty), []);
|
|
2051
|
-
const dialogContent = useCallback(
|
|
2052
|
-
(
|
|
2053
|
-
|
|
2054
|
-
|
|
2057
|
+
const dialogContent = useCallback(() => {
|
|
2058
|
+
if (showChooseField) {
|
|
2059
|
+
return /* @__PURE__ */ jsx(ChooseFieldToAdd, { setFieldType });
|
|
2060
|
+
}
|
|
2061
|
+
return /* @__PURE__ */ jsx(
|
|
2062
|
+
FieldOptionsForm,
|
|
2063
|
+
{
|
|
2064
|
+
conditionalSourceFields,
|
|
2065
|
+
handleCancel,
|
|
2066
|
+
handleCreateField,
|
|
2067
|
+
fieldType: type,
|
|
2068
|
+
defaultField: initial,
|
|
2069
|
+
handleDirtyChange
|
|
2055
2070
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
},
|
|
2068
|
-
[conditionalSourceFields, handleCancel, handleCreateField, handleDirtyChange, initial, showChooseField, type]
|
|
2071
|
+
);
|
|
2072
|
+
}, [conditionalSourceFields, handleCancel, handleCreateField, handleDirtyChange, initial, showChooseField, type]);
|
|
2073
|
+
return /* @__PURE__ */ jsx(
|
|
2074
|
+
Dialog,
|
|
2075
|
+
{
|
|
2076
|
+
title: title2,
|
|
2077
|
+
description: description2,
|
|
2078
|
+
content: dialogContent,
|
|
2079
|
+
open: isOpen,
|
|
2080
|
+
onOpenChange: handleCloseDialog
|
|
2081
|
+
}
|
|
2069
2082
|
);
|
|
2070
|
-
return /* @__PURE__ */ jsx(Dialog, { onCloseInterrupt: handleCloseInterrupt, title: title2, description: description2, content: dialogContent, children });
|
|
2071
2083
|
});
|
|
2072
|
-
const
|
|
2084
|
+
const forMobile = (mobile, display) => ({
|
|
2085
|
+
initial: mobile ? display : "none",
|
|
2086
|
+
sm: mobile ? "none" : display
|
|
2087
|
+
});
|
|
2073
2088
|
const FieldActions = memo(function FieldActions2(props) {
|
|
2074
|
-
const { remove: remove2, editProps, insertAfterProps, duplicateProps
|
|
2089
|
+
const { remove: remove2, dragHandleProps, editProps, insertAfterProps, duplicateProps } = props;
|
|
2090
|
+
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
|
|
2091
|
+
const [isDuplicateDialogOpen, setIsDuplicateDialogOpen] = useState(false);
|
|
2092
|
+
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
2075
2093
|
const actions = useMemo(
|
|
2076
2094
|
() => [
|
|
2077
2095
|
{
|
|
2078
|
-
|
|
2079
|
-
|
|
2096
|
+
SelectedContent: FieldBuilder,
|
|
2097
|
+
selectedContentProps: { ...editProps, isOpen: isEditDialogOpen, setIsOpen: setIsEditDialogOpen },
|
|
2080
2098
|
Icon: Pencil1Icon,
|
|
2081
|
-
text: "Edit"
|
|
2099
|
+
text: "Edit",
|
|
2100
|
+
buttonProps: { onClick: () => setIsEditDialogOpen(true) }
|
|
2082
2101
|
},
|
|
2083
2102
|
{
|
|
2084
2103
|
Icon: TrashIcon,
|
|
@@ -2088,41 +2107,75 @@ const FieldActions = memo(function FieldActions2(props) {
|
|
|
2088
2107
|
text: "Delete"
|
|
2089
2108
|
},
|
|
2090
2109
|
{
|
|
2091
|
-
|
|
2092
|
-
|
|
2110
|
+
SelectedContent: FieldBuilder,
|
|
2111
|
+
selectedContentProps: {
|
|
2112
|
+
...duplicateProps,
|
|
2113
|
+
isOpen: isDuplicateDialogOpen,
|
|
2114
|
+
setIsOpen: setIsDuplicateDialogOpen
|
|
2115
|
+
},
|
|
2093
2116
|
Icon: CopyIcon,
|
|
2094
|
-
text: "Duplicate"
|
|
2117
|
+
text: "Duplicate",
|
|
2118
|
+
buttonProps: { onClick: () => setIsDuplicateDialogOpen(true) }
|
|
2095
2119
|
},
|
|
2096
2120
|
{
|
|
2097
|
-
|
|
2098
|
-
|
|
2121
|
+
SelectedContent: FieldBuilder,
|
|
2122
|
+
selectedContentProps: { ...insertAfterProps, isOpen: isAddDialogOpen, setIsOpen: setIsAddDialogOpen },
|
|
2099
2123
|
Icon: PlusIcon,
|
|
2100
|
-
text:
|
|
2124
|
+
text: "Add after",
|
|
2125
|
+
buttonProps: { onClick: () => setIsAddDialogOpen(true) }
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
// Wrapping icon in a div so that the asChild turns the button into a div
|
|
2129
|
+
// so that the drag handle props are not applied to the icon
|
|
2130
|
+
// Note: b/c the <button> does not handle the space-press event correctly
|
|
2131
|
+
Icon: (props2) => /* @__PURE__ */ jsx("div", { ...props2, children: /* @__PURE__ */ jsx(DragHandleDots2Icon, {}) }),
|
|
2132
|
+
text: "Reorder",
|
|
2133
|
+
disableOnMobile: true,
|
|
2134
|
+
buttonProps: { ...dragHandleProps, asChild: true }
|
|
2101
2135
|
}
|
|
2102
2136
|
],
|
|
2103
|
-
[
|
|
2137
|
+
[
|
|
2138
|
+
dragHandleProps,
|
|
2139
|
+
duplicateProps,
|
|
2140
|
+
editProps,
|
|
2141
|
+
insertAfterProps,
|
|
2142
|
+
isAddDialogOpen,
|
|
2143
|
+
isDuplicateDialogOpen,
|
|
2144
|
+
isEditDialogOpen,
|
|
2145
|
+
remove2
|
|
2146
|
+
]
|
|
2104
2147
|
);
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2148
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2149
|
+
/* @__PURE__ */ jsx(Flex, { gap: "4", display: forMobile(false, "flex"), children: actions.map((Action) => {
|
|
2150
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2151
|
+
/* @__PURE__ */ jsx(IconButton, { type: "button", variant: "ghost", "aria-label": Action.text, ...Action.buttonProps, children: /* @__PURE__ */ jsx(Action.Icon, {}) }),
|
|
2152
|
+
Action.SelectedContent && /* @__PURE__ */ jsx(Action.SelectedContent, { ...Action.selectedContentProps })
|
|
2153
|
+
] }, Action.text);
|
|
2154
|
+
}) }),
|
|
2155
|
+
/* @__PURE__ */ jsx(Box, { display: forMobile(true, "block"), children: /* @__PURE__ */ jsx(
|
|
2156
|
+
DropdownItemMenu,
|
|
2157
|
+
{
|
|
2158
|
+
trigger: /* @__PURE__ */ jsx(IconButton, { variant: "ghost", "aria-label": "Actions menu", children: /* @__PURE__ */ jsx(DotsVerticalIcon, {}) }),
|
|
2159
|
+
closeOnSelect: false,
|
|
2160
|
+
items: actions.map((Action) => {
|
|
2161
|
+
var _a;
|
|
2162
|
+
if (Action.disableOnMobile)
|
|
2163
|
+
return null;
|
|
2164
|
+
return {
|
|
2165
|
+
...Action.buttonProps,
|
|
2166
|
+
onSelect: (_a = Action.buttonProps) == null ? void 0 : _a.onClick,
|
|
2167
|
+
content: /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2168
|
+
/* @__PURE__ */ jsxs(Flex, { gap: "2", align: "center", children: [
|
|
2169
|
+
/* @__PURE__ */ jsx(Action.Icon, {}),
|
|
2170
|
+
Action.text
|
|
2171
|
+
] }),
|
|
2172
|
+
Action.SelectedContent && /* @__PURE__ */ jsx(Action.SelectedContent, { ...Action.selectedContentProps })
|
|
2173
|
+
] }, Action.text)
|
|
2174
|
+
};
|
|
2175
|
+
}).filter((x) => x !== null)
|
|
2176
|
+
}
|
|
2177
|
+
) })
|
|
2178
|
+
] });
|
|
2126
2179
|
});
|
|
2127
2180
|
const formId = "form-builder";
|
|
2128
2181
|
const FieldWithActions = memo(function FieldWithActions2(props) {
|
|
@@ -2132,10 +2185,8 @@ const FieldWithActions = memo(function FieldWithActions2(props) {
|
|
|
2132
2185
|
const updateXarrow = useXarrow();
|
|
2133
2186
|
const duplicateField = useCallback(
|
|
2134
2187
|
(field2) => {
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
}
|
|
2138
|
-
return { ...field2, label: incrementFieldLabel(field2.label, takenLabels), identifier: "" };
|
|
2188
|
+
const fieldLabel = field2.label ?? "Untitled field";
|
|
2189
|
+
return { ...field2, label: incrementFieldLabel(fieldLabel, takenLabels), identifier: "" };
|
|
2139
2190
|
},
|
|
2140
2191
|
[takenLabels]
|
|
2141
2192
|
);
|
|
@@ -2182,7 +2233,8 @@ const FieldWithActions = memo(function FieldWithActions2(props) {
|
|
|
2182
2233
|
remove: remove2,
|
|
2183
2234
|
editProps: editFieldProps,
|
|
2184
2235
|
duplicateProps: duplicateFieldProps,
|
|
2185
|
-
insertAfterProps
|
|
2236
|
+
insertAfterProps,
|
|
2237
|
+
dragHandleProps: draggableProvided.dragHandleProps
|
|
2186
2238
|
}
|
|
2187
2239
|
)
|
|
2188
2240
|
] })
|
|
@@ -2249,12 +2301,12 @@ const ConditionalArrow = (props) => {
|
|
|
2249
2301
|
/* @__PURE__ */ jsx(
|
|
2250
2302
|
Xarrow,
|
|
2251
2303
|
{
|
|
2252
|
-
start: `${identifier}-
|
|
2253
|
-
end: `${
|
|
2304
|
+
start: `${condition.identifier}-card`,
|
|
2305
|
+
end: `${identifier}-floating-point`,
|
|
2254
2306
|
startAnchor: "left",
|
|
2255
2307
|
endAnchor: "right",
|
|
2256
2308
|
path: "grid",
|
|
2257
|
-
gridBreak: "
|
|
2309
|
+
gridBreak: "100%",
|
|
2258
2310
|
...settings
|
|
2259
2311
|
}
|
|
2260
2312
|
)
|
|
@@ -2264,6 +2316,7 @@ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
|
|
|
2264
2316
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
2265
2317
|
const { field, index: sectionIndex, dropState, conditionalFieldCounts } = props;
|
|
2266
2318
|
const isDropDisabled = (_a = dropState[field.identifier]) == null ? void 0 : _a.disabled;
|
|
2319
|
+
const [isAddFieldDialogOpen, setIsAddFieldDialogOpen] = useState(false);
|
|
2267
2320
|
const { setFieldValue, values } = useFormikContext();
|
|
2268
2321
|
const alertDialog = useAlertDialog();
|
|
2269
2322
|
const updateXarrow = useXarrow();
|
|
@@ -2353,12 +2406,10 @@ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
|
|
|
2353
2406
|
]);
|
|
2354
2407
|
const duplicateSection = useCallback(
|
|
2355
2408
|
(field2) => {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
}
|
|
2359
|
-
const newSectionLabel = incrementFieldLabel(field2.label, takenFieldLabels);
|
|
2409
|
+
const fieldLabel = field2.label ?? "Untitled section";
|
|
2410
|
+
const newSectionLabel = incrementFieldLabel(fieldLabel, takenFieldLabels);
|
|
2360
2411
|
const newFields = field2.fields.map((f) => {
|
|
2361
|
-
const newLabel = incrementFieldLabel(f.label, takenFieldLabels);
|
|
2412
|
+
const newLabel = incrementFieldLabel(f.label ?? "Untitled field", takenFieldLabels);
|
|
2362
2413
|
return {
|
|
2363
2414
|
...f,
|
|
2364
2415
|
label: newLabel,
|
|
@@ -2475,10 +2526,26 @@ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
|
|
|
2475
2526
|
child.identifier
|
|
2476
2527
|
)),
|
|
2477
2528
|
droppableProvided.placeholder,
|
|
2478
|
-
/* @__PURE__ */
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2529
|
+
/* @__PURE__ */ jsxs(
|
|
2530
|
+
Button,
|
|
2531
|
+
{
|
|
2532
|
+
type: "button",
|
|
2533
|
+
variant: "outline",
|
|
2534
|
+
onClick: () => setIsAddFieldDialogOpen(true),
|
|
2535
|
+
children: [
|
|
2536
|
+
/* @__PURE__ */ jsx(PlusIcon, {}),
|
|
2537
|
+
" Add a field"
|
|
2538
|
+
]
|
|
2539
|
+
}
|
|
2540
|
+
),
|
|
2541
|
+
/* @__PURE__ */ jsx(
|
|
2542
|
+
FieldBuilder,
|
|
2543
|
+
{
|
|
2544
|
+
...insertFieldAtEndOfSection,
|
|
2545
|
+
isOpen: isAddFieldDialogOpen,
|
|
2546
|
+
setIsOpen: setIsAddFieldDialogOpen
|
|
2547
|
+
}
|
|
2548
|
+
)
|
|
2482
2549
|
]
|
|
2483
2550
|
}
|
|
2484
2551
|
)
|
|
@@ -2492,7 +2559,7 @@ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
|
|
|
2492
2559
|
insertAfterProps: insertSectionProps,
|
|
2493
2560
|
editProps: editSectionProps,
|
|
2494
2561
|
duplicateProps: duplicateSectionProps,
|
|
2495
|
-
|
|
2562
|
+
dragHandleProps: draggableProvided.dragHandleProps
|
|
2496
2563
|
}
|
|
2497
2564
|
)
|
|
2498
2565
|
] })
|
|
@@ -2575,6 +2642,7 @@ const findSection = (fields, sectionId) => {
|
|
|
2575
2642
|
const FieldsEditor = memo(function FieldsEditor2() {
|
|
2576
2643
|
const { values, setFieldValue } = useFormikContext();
|
|
2577
2644
|
const [dropState, dispatch] = useReducer(reducer, values.fields, initializer);
|
|
2645
|
+
const [isAddSectionDialogOpen, setIsAddSectionDialogOpen] = useState(false);
|
|
2578
2646
|
const { showInfo } = useToast();
|
|
2579
2647
|
useEffect(() => {
|
|
2580
2648
|
dispatch({ type: "update", state: initializer(values.fields) });
|
|
@@ -2671,10 +2739,18 @@ const FieldsEditor = memo(function FieldsEditor2() {
|
|
|
2671
2739
|
)),
|
|
2672
2740
|
droppableProvided.placeholder
|
|
2673
2741
|
] }),
|
|
2674
|
-
/* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", onClick: () => setIsAddSectionDialogOpen(true), children: [
|
|
2675
2743
|
/* @__PURE__ */ jsx(PlusIcon, {}),
|
|
2676
2744
|
" Add a section"
|
|
2677
|
-
] })
|
|
2745
|
+
] }),
|
|
2746
|
+
/* @__PURE__ */ jsx(
|
|
2747
|
+
FieldBuilder,
|
|
2748
|
+
{
|
|
2749
|
+
...makeFieldSectionProps,
|
|
2750
|
+
isOpen: isAddSectionDialogOpen,
|
|
2751
|
+
setIsOpen: setIsAddSectionDialogOpen
|
|
2752
|
+
}
|
|
2753
|
+
)
|
|
2678
2754
|
]
|
|
2679
2755
|
}
|
|
2680
2756
|
) }) });
|
|
@@ -2706,8 +2782,7 @@ const previewSubmit = () => {
|
|
|
2706
2782
|
const FormBuilder = memo(
|
|
2707
2783
|
forwardRef((props, ref) => {
|
|
2708
2784
|
const { onCancel, onSave, revision } = props;
|
|
2709
|
-
const
|
|
2710
|
-
const { heading = defaultHeading } = props;
|
|
2785
|
+
const { heading = revision ? "Edit form" : "Create a new form" } = props;
|
|
2711
2786
|
const validate = useCallback((form) => {
|
|
2712
2787
|
const errors = {};
|
|
2713
2788
|
if (!form.title) {
|