@overmap-ai/forms 1.0.12-links.0 → 1.0.12-links.10
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/fields/constants.d.ts +4 -0
- package/dist/forms.js +261 -234
- package/dist/forms.js.map +1 -1
- package/dist/forms.umd.cjs +258 -232
- package/dist/forms.umd.cjs.map +1 -1
- package/dist/style.css +7 -0
- package/package.json +3 -1
package/dist/forms.js
CHANGED
|
@@ -5,13 +5,14 @@ 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, Select, IconButton, Badge, MultiSelect, Button, TextArea, 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,
|
|
11
|
-
import { CheckCircledIcon, FontFamilyIcon, CalendarIcon,
|
|
10
|
+
import React, { useMemo, memo, useCallback, useState, useRef, useEffect, forwardRef, Fragment as Fragment$1, useReducer } from "react";
|
|
11
|
+
import { CheckCircledIcon, FontFamilyIcon, CalendarIcon, PlusIcon, Cross1Icon, ListBulletIcon, DropdownMenuIcon, CheckboxIcon, UploadIcon, InputIcon, RowsIcon, StarFilledIcon, StarIcon, QuestionMarkCircledIcon, PersonIcon, Pencil1Icon, TrashIcon, CopyIcon, DragHandleDots2Icon, DotsVerticalIcon } from "@radix-ui/react-icons";
|
|
12
12
|
import { TextField as TextField$1, Box, Card, Heading, Avatar, Em, Strong, Tabs } from "@radix-ui/themes";
|
|
13
|
+
import Linkify from "linkify-react";
|
|
13
14
|
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
|
|
14
|
-
import { slugify, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser,
|
|
15
|
+
import { slugify, classNames, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser, isToday, getLocalDateString, selectLatestFormRevision, useFileSrc, selectSubmissionsForForm } from "@overmap-ai/core";
|
|
15
16
|
import get from "lodash.get";
|
|
16
17
|
import set from "lodash.set";
|
|
17
18
|
import cloneDeep from "lodash.clonedeep";
|
|
@@ -106,7 +107,7 @@ class BaseField extends BaseFormElement {
|
|
|
106
107
|
__publicField(BaseField, "fieldTypeName");
|
|
107
108
|
__publicField(BaseField, "fieldTypeDescription");
|
|
108
109
|
const description$1 = "_description_17zed_1";
|
|
109
|
-
const styles$
|
|
110
|
+
const styles$4 = {
|
|
110
111
|
description: description$1
|
|
111
112
|
};
|
|
112
113
|
const InputWithLabel = (props) => {
|
|
@@ -120,7 +121,7 @@ const InputWithLabelAndHelpText = (props) => {
|
|
|
120
121
|
const { helpText, children, severity } = props;
|
|
121
122
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", children: [
|
|
122
123
|
children,
|
|
123
|
-
/* @__PURE__ */ jsx(Flex, { direction: "column", children: /* @__PURE__ */ jsx(Text, { size: "1", severity, className: styles$
|
|
124
|
+
/* @__PURE__ */ jsx(Flex, { direction: "column", children: /* @__PURE__ */ jsx(Text, { size: "1", severity, className: styles$4.description, children: helpText }) })
|
|
124
125
|
] });
|
|
125
126
|
};
|
|
126
127
|
const useFormikInput = (props) => {
|
|
@@ -472,64 +473,12 @@ __publicField(StringOrTextField, "_validateMax", (value, allValues) => {
|
|
|
472
473
|
}
|
|
473
474
|
return null;
|
|
474
475
|
});
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const _StringField = class _StringField extends StringOrTextField {
|
|
481
|
-
constructor(options) {
|
|
482
|
-
const { inputType = "text", ...rest } = options;
|
|
483
|
-
const maxLength = options.maxLength ? Math.min(500, options.maxLength) : 500;
|
|
484
|
-
const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
|
|
485
|
-
super({ ...rest, maxLength, minLength, type: "string" });
|
|
486
|
-
__publicField(this, "inputType");
|
|
487
|
-
this.inputType = inputType;
|
|
488
|
-
}
|
|
489
|
-
serialize() {
|
|
490
|
-
return { ...super._serialize(), input_type: this.inputType };
|
|
491
|
-
}
|
|
492
|
-
static deserialize(data) {
|
|
493
|
-
if (data.type !== "string")
|
|
494
|
-
throw new Error("Type mismatch.");
|
|
495
|
-
const { maximum_length, minimum_length, input_type, ...rest } = data;
|
|
496
|
-
return new _StringField({ ...rest, maxLength: maximum_length, minLength: minimum_length, inputType: input_type });
|
|
497
|
-
}
|
|
498
|
-
getInput(props) {
|
|
499
|
-
return /* @__PURE__ */ jsx(StringInput, { field: this, ...props });
|
|
500
|
-
}
|
|
501
|
-
};
|
|
502
|
-
__publicField(_StringField, "fieldTypeName", "Short Text");
|
|
503
|
-
__publicField(_StringField, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line.");
|
|
504
|
-
__publicField(_StringField, "Icon", InputIcon);
|
|
505
|
-
let StringField = _StringField;
|
|
506
|
-
const TextInput = memo(function TextInput2(props) {
|
|
507
|
-
const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
|
|
508
|
-
return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(TextArea, { ...rest, ...fieldProps, resize: "vertical", id: inputId, severity }) }) });
|
|
509
|
-
});
|
|
510
|
-
const _TextField = class _TextField extends StringOrTextField {
|
|
511
|
-
constructor(options) {
|
|
512
|
-
const maxLength = options.maxLength ? Math.min(5e3, options.maxLength) : 5e3;
|
|
513
|
-
const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
|
|
514
|
-
super({ ...options, maxLength, minLength, type: "text" });
|
|
515
|
-
}
|
|
516
|
-
serialize() {
|
|
517
|
-
return super._serialize();
|
|
518
|
-
}
|
|
519
|
-
static deserialize(data) {
|
|
520
|
-
if (data.type !== "text")
|
|
521
|
-
throw new Error("Type mismatch.");
|
|
522
|
-
const { maximum_length, minimum_length, ...rest } = data;
|
|
523
|
-
return new _TextField({ ...rest, maxLength: maximum_length, minLength: minimum_length });
|
|
524
|
-
}
|
|
525
|
-
getInput(props) {
|
|
526
|
-
return /* @__PURE__ */ jsx(TextInput, { field: this, ...props });
|
|
527
|
-
}
|
|
476
|
+
const TextFieldRoot = "_TextFieldRoot_8ge74_1";
|
|
477
|
+
const TextFieldInputCopy = "_TextFieldInputCopy_8ge74_5";
|
|
478
|
+
const styles$3 = {
|
|
479
|
+
TextFieldRoot,
|
|
480
|
+
TextFieldInputCopy
|
|
528
481
|
};
|
|
529
|
-
__publicField(_TextField, "fieldTypeName", "Paragraph");
|
|
530
|
-
__publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
|
|
531
|
-
__publicField(_TextField, "Icon", RowsIcon);
|
|
532
|
-
let TextField = _TextField;
|
|
533
482
|
const SelectInput = memo(function SelectInput2(props) {
|
|
534
483
|
const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
|
|
535
484
|
const { onChange, onBlur } = fieldProps;
|
|
@@ -954,16 +903,6 @@ __publicField(_MultiSelectField, "fieldTypeName", "Multi-select");
|
|
|
954
903
|
__publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
|
|
955
904
|
__publicField(_MultiSelectField, "Icon", CheckboxIcon);
|
|
956
905
|
let MultiSelectField = _MultiSelectField;
|
|
957
|
-
const FieldInputCloner = memo(function FieldInputCloner2({ field, ...props }) {
|
|
958
|
-
const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
|
|
959
|
-
const deserializedField = useMemo(() => {
|
|
960
|
-
const options = field.options.getFieldToClone(identifier);
|
|
961
|
-
if (!options)
|
|
962
|
-
return null;
|
|
963
|
-
return deserialize(options);
|
|
964
|
-
}, [field.options, identifier]);
|
|
965
|
-
return useFieldInput(deserializedField, props);
|
|
966
|
-
});
|
|
967
906
|
class CustomField extends BaseField {
|
|
968
907
|
constructor(options, Component) {
|
|
969
908
|
super({ ...options, type: "custom" });
|
|
@@ -983,164 +922,6 @@ class CustomField extends BaseField {
|
|
|
983
922
|
}
|
|
984
923
|
__publicField(CustomField, "fieldTypeName", "Custom");
|
|
985
924
|
__publicField(CustomField, "fieldTypeDescription", "Allows re-rendering of field already in the form");
|
|
986
|
-
class FieldInputClonerField extends CustomField {
|
|
987
|
-
constructor(options) {
|
|
988
|
-
super(options, FieldInputCloner);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
const FieldSectionLayout = memo(function FieldSectionLayout2(props) {
|
|
992
|
-
const { field: section, ...rest } = props;
|
|
993
|
-
const { label, description: description2, fields, condition } = section;
|
|
994
|
-
const { values, setFieldValue } = useFormikContext();
|
|
995
|
-
const conditionValue = (condition == null ? void 0 : condition.identifier) ? get(values, condition.identifier) : void 0;
|
|
996
|
-
const conditionMet = useMemo(() => isConditionMet(condition, conditionValue), [condition, conditionValue]);
|
|
997
|
-
useEffect(() => {
|
|
998
|
-
if (!conditionMet) {
|
|
999
|
-
for (const childField of fields) {
|
|
1000
|
-
setFieldValue(childField.getId(), "").then();
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
}, [conditionMet, fields, setFieldValue]);
|
|
1004
|
-
const inputs = useFieldInputs(fields, rest);
|
|
1005
|
-
if (!conditionMet) {
|
|
1006
|
-
return null;
|
|
1007
|
-
}
|
|
1008
|
-
if (!label) {
|
|
1009
|
-
return inputs;
|
|
1010
|
-
}
|
|
1011
|
-
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
|
|
1012
|
-
/* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
1013
|
-
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
|
|
1014
|
-
/* @__PURE__ */ jsx(Text, { className: styles$3.description, children: description2 })
|
|
1015
|
-
] }),
|
|
1016
|
-
inputs
|
|
1017
|
-
] }) });
|
|
1018
|
-
});
|
|
1019
|
-
const _FieldSection = class _FieldSection extends BaseFormElement {
|
|
1020
|
-
constructor(options) {
|
|
1021
|
-
const { label = null, fields, condition = null, conditional, ...base } = options;
|
|
1022
|
-
super({ ...base, type: "section" });
|
|
1023
|
-
__publicField(this, "label");
|
|
1024
|
-
__publicField(this, "fields");
|
|
1025
|
-
__publicField(this, "condition");
|
|
1026
|
-
this.fields = fields;
|
|
1027
|
-
this.condition = condition;
|
|
1028
|
-
this.label = label;
|
|
1029
|
-
if (conditional === false) {
|
|
1030
|
-
this.condition = null;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
static getFieldCreationSchema(options) {
|
|
1034
|
-
if (options.length === 0)
|
|
1035
|
-
return [];
|
|
1036
|
-
return [
|
|
1037
|
-
new BooleanField({
|
|
1038
|
-
label: "Conditional",
|
|
1039
|
-
description: "Conditionally show or hide this section.",
|
|
1040
|
-
identifier: "conditional",
|
|
1041
|
-
required: false
|
|
1042
|
-
}),
|
|
1043
|
-
// Declare a section that will hold options for the condition (if any).
|
|
1044
|
-
new _FieldSection({
|
|
1045
|
-
label: "Conditional settings",
|
|
1046
|
-
identifier: "conditional-settings",
|
|
1047
|
-
// This section will only be rendered if the above "Conditional" field is checked.
|
|
1048
|
-
condition: {
|
|
1049
|
-
identifier: "conditional",
|
|
1050
|
-
value: true
|
|
1051
|
-
},
|
|
1052
|
-
// These are the options of the condition.
|
|
1053
|
-
fields: [
|
|
1054
|
-
// Declare a select field that will be used to select the field against which we will check the
|
|
1055
|
-
// condition. This must be selected before the next field is rendered.
|
|
1056
|
-
new SelectField({
|
|
1057
|
-
label: "Field",
|
|
1058
|
-
description: "The field to use for the condition.",
|
|
1059
|
-
// The options (for the field against which we will check the condition) are all the labels of
|
|
1060
|
-
// the fields in the previous section(s) (or fields declared before with no section) that
|
|
1061
|
-
// support conditions. We pass in both the label and the identifier of each supported field. The
|
|
1062
|
-
// identifier becomes the value of the option.
|
|
1063
|
-
options: options.map((option) => {
|
|
1064
|
-
if (!option.label)
|
|
1065
|
-
return null;
|
|
1066
|
-
if (option.type === "upload")
|
|
1067
|
-
return null;
|
|
1068
|
-
return {
|
|
1069
|
-
label: option.label,
|
|
1070
|
-
value: option.identifier
|
|
1071
|
-
};
|
|
1072
|
-
}).filter((option) => !!option),
|
|
1073
|
-
identifier: "condition.identifier",
|
|
1074
|
-
required: true
|
|
1075
|
-
}),
|
|
1076
|
-
// Declare a custom field that will be used to input a value for the condition. The value of the
|
|
1077
|
-
// conditional field selected in the previous step must be equal to the value the user inputs into
|
|
1078
|
-
// this field for the section to be rendered.
|
|
1079
|
-
new FieldInputClonerField({
|
|
1080
|
-
label: "Value",
|
|
1081
|
-
identifier: "condition.value",
|
|
1082
|
-
required: true,
|
|
1083
|
-
clonedFieldIdentifier: "condition.identifier",
|
|
1084
|
-
getFieldToClone(identifier) {
|
|
1085
|
-
if (!identifier) {
|
|
1086
|
-
return null;
|
|
1087
|
-
}
|
|
1088
|
-
const option = options.find((option2) => option2.identifier === identifier);
|
|
1089
|
-
if (!option) {
|
|
1090
|
-
console.error("Could not find field with identifier", identifier);
|
|
1091
|
-
return null;
|
|
1092
|
-
}
|
|
1093
|
-
return {
|
|
1094
|
-
...option,
|
|
1095
|
-
// Override some options to make it make sense in the context and to make it work with the framework.
|
|
1096
|
-
label: "Value",
|
|
1097
|
-
identifier: "condition.value",
|
|
1098
|
-
description: "The value to compare against.",
|
|
1099
|
-
required: option.type !== "boolean"
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1102
|
-
})
|
|
1103
|
-
]
|
|
1104
|
-
})
|
|
1105
|
-
];
|
|
1106
|
-
}
|
|
1107
|
-
static deserialize(data) {
|
|
1108
|
-
var _a;
|
|
1109
|
-
if (data.type !== "section")
|
|
1110
|
-
throw new Error("Invalid type");
|
|
1111
|
-
const fields = ((_a = data.fields) == null ? void 0 : _a.map(deserializeField)) ?? [];
|
|
1112
|
-
return new _FieldSection({ ...data, fields });
|
|
1113
|
-
}
|
|
1114
|
-
conditional() {
|
|
1115
|
-
return this.condition !== null;
|
|
1116
|
-
}
|
|
1117
|
-
serialize() {
|
|
1118
|
-
return {
|
|
1119
|
-
...super._serialize(),
|
|
1120
|
-
label: this.label,
|
|
1121
|
-
condition: this.condition,
|
|
1122
|
-
conditional: this.conditional(),
|
|
1123
|
-
fields: this.fields.map((field) => field.serialize())
|
|
1124
|
-
};
|
|
1125
|
-
}
|
|
1126
|
-
getErrors(allValues) {
|
|
1127
|
-
const errors = {};
|
|
1128
|
-
for (const field of this.fields) {
|
|
1129
|
-
const id = field.getId();
|
|
1130
|
-
const error = field.getError(get(allValues, id), allValues);
|
|
1131
|
-
if (error) {
|
|
1132
|
-
set(errors, field.getId(), error);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
return errors;
|
|
1136
|
-
}
|
|
1137
|
-
getInput(props) {
|
|
1138
|
-
return /* @__PURE__ */ jsx(FieldSectionLayout, { field: this, ...props });
|
|
1139
|
-
}
|
|
1140
|
-
};
|
|
1141
|
-
__publicField(_FieldSection, "fieldTypeName", "Section");
|
|
1142
|
-
__publicField(_FieldSection, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
|
|
1143
|
-
let FieldSection = _FieldSection;
|
|
1144
925
|
const previewImage = "_previewImage_1ig84_1";
|
|
1145
926
|
const styles$2 = {
|
|
1146
927
|
previewImage
|
|
@@ -1396,6 +1177,253 @@ const FieldTypeToClsMapping = {
|
|
|
1396
1177
|
"multi-string": MultiStringField,
|
|
1397
1178
|
"multi-select": MultiSelectField
|
|
1398
1179
|
};
|
|
1180
|
+
const linkOptions = { target: "_blank", rel: "noopener" };
|
|
1181
|
+
const StringInput = memo(function StringInput2(props) {
|
|
1182
|
+
const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
|
|
1183
|
+
const color = useSeverityColor(severity);
|
|
1184
|
+
console.log(inputId, label, fieldProps, field, rest);
|
|
1185
|
+
return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxs(InputWithLabel, { severity, inputId, labelId, label, children: [
|
|
1186
|
+
/* @__PURE__ */ jsx(TextField$1.Input, { ...rest, ...fieldProps, type: field.inputType, id: inputId, color }),
|
|
1187
|
+
/* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$3.TextFieldRoot, children: [
|
|
1188
|
+
/* @__PURE__ */ jsx(
|
|
1189
|
+
"div",
|
|
1190
|
+
{
|
|
1191
|
+
className: classNames(
|
|
1192
|
+
"rt-TextFieldInput rt-r-size-2 rt-variant-surface",
|
|
1193
|
+
styles$3.TextFieldInputCopy
|
|
1194
|
+
),
|
|
1195
|
+
children: /* @__PURE__ */ jsx(Linkify, { options: linkOptions, children: fieldProps.value })
|
|
1196
|
+
}
|
|
1197
|
+
),
|
|
1198
|
+
/* @__PURE__ */ jsx("div", { className: "rt-TextFieldChrome" })
|
|
1199
|
+
] })
|
|
1200
|
+
] }) });
|
|
1201
|
+
});
|
|
1202
|
+
const _StringField = class _StringField extends StringOrTextField {
|
|
1203
|
+
constructor(options) {
|
|
1204
|
+
const { inputType = "text", ...rest } = options;
|
|
1205
|
+
const maxLength = options.maxLength ? Math.min(500, options.maxLength) : 500;
|
|
1206
|
+
const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
|
|
1207
|
+
super({ ...rest, maxLength, minLength, type: "string" });
|
|
1208
|
+
__publicField(this, "inputType");
|
|
1209
|
+
this.inputType = inputType;
|
|
1210
|
+
}
|
|
1211
|
+
serialize() {
|
|
1212
|
+
return { ...super._serialize(), input_type: this.inputType };
|
|
1213
|
+
}
|
|
1214
|
+
static deserialize(data) {
|
|
1215
|
+
if (data.type !== "string")
|
|
1216
|
+
throw new Error("Type mismatch.");
|
|
1217
|
+
const { maximum_length, minimum_length, input_type, ...rest } = data;
|
|
1218
|
+
return new _StringField({ ...rest, maxLength: maximum_length, minLength: minimum_length, inputType: input_type });
|
|
1219
|
+
}
|
|
1220
|
+
getInput(props) {
|
|
1221
|
+
return /* @__PURE__ */ jsx(StringInput, { field: this, ...props });
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
__publicField(_StringField, "fieldTypeName", "Short Text");
|
|
1225
|
+
__publicField(_StringField, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line.");
|
|
1226
|
+
__publicField(_StringField, "Icon", InputIcon);
|
|
1227
|
+
let StringField = _StringField;
|
|
1228
|
+
const TextInput = memo(function TextInput2(props) {
|
|
1229
|
+
const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
|
|
1230
|
+
return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxs(InputWithLabel, { severity, inputId, labelId, label, children: [
|
|
1231
|
+
/* @__PURE__ */ jsx(TextArea, { ...rest, ...fieldProps, resize: "vertical", id: inputId, severity }),
|
|
1232
|
+
/* @__PURE__ */ jsx("div", { className: "rt-TextAreaInput", children: /* @__PURE__ */ jsx(Linkify, { options: linkOptions, children: fieldProps.value }) }),
|
|
1233
|
+
/* @__PURE__ */ jsx("div", { className: "rt-TextAreaChrome" })
|
|
1234
|
+
] }) });
|
|
1235
|
+
});
|
|
1236
|
+
const _TextField = class _TextField extends StringOrTextField {
|
|
1237
|
+
constructor(options) {
|
|
1238
|
+
const maxLength = options.maxLength ? Math.min(5e3, options.maxLength) : 5e3;
|
|
1239
|
+
const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
|
|
1240
|
+
super({ ...options, maxLength, minLength, type: "text" });
|
|
1241
|
+
}
|
|
1242
|
+
serialize() {
|
|
1243
|
+
return super._serialize();
|
|
1244
|
+
}
|
|
1245
|
+
static deserialize(data) {
|
|
1246
|
+
if (data.type !== "text")
|
|
1247
|
+
throw new Error("Type mismatch.");
|
|
1248
|
+
const { maximum_length, minimum_length, ...rest } = data;
|
|
1249
|
+
return new _TextField({ ...rest, maxLength: maximum_length, minLength: minimum_length });
|
|
1250
|
+
}
|
|
1251
|
+
getInput(props) {
|
|
1252
|
+
return /* @__PURE__ */ jsx(TextInput, { field: this, ...props });
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
__publicField(_TextField, "fieldTypeName", "Paragraph");
|
|
1256
|
+
__publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
|
|
1257
|
+
__publicField(_TextField, "Icon", RowsIcon);
|
|
1258
|
+
let TextField = _TextField;
|
|
1259
|
+
const FieldInputCloner = memo(function FieldInputCloner2({ field, ...props }) {
|
|
1260
|
+
const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
|
|
1261
|
+
const deserializedField = useMemo(() => {
|
|
1262
|
+
const options = field.options.getFieldToClone(identifier);
|
|
1263
|
+
if (!options)
|
|
1264
|
+
return null;
|
|
1265
|
+
return deserialize(options);
|
|
1266
|
+
}, [field.options, identifier]);
|
|
1267
|
+
return useFieldInput(deserializedField, props);
|
|
1268
|
+
});
|
|
1269
|
+
class FieldInputClonerField extends CustomField {
|
|
1270
|
+
constructor(options) {
|
|
1271
|
+
super(options, FieldInputCloner);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
const FieldSectionLayout = memo(function FieldSectionLayout2(props) {
|
|
1275
|
+
const { field: section, ...rest } = props;
|
|
1276
|
+
const { label, description: description2, fields, condition } = section;
|
|
1277
|
+
const { values, setFieldValue } = useFormikContext();
|
|
1278
|
+
const conditionValue = (condition == null ? void 0 : condition.identifier) ? get(values, condition.identifier) : void 0;
|
|
1279
|
+
const conditionMet = useMemo(() => isConditionMet(condition, conditionValue), [condition, conditionValue]);
|
|
1280
|
+
useEffect(() => {
|
|
1281
|
+
if (!conditionMet) {
|
|
1282
|
+
for (const childField of fields) {
|
|
1283
|
+
setFieldValue(childField.getId(), "").then();
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
}, [conditionMet, fields, setFieldValue]);
|
|
1287
|
+
const inputs = useFieldInputs(fields, rest);
|
|
1288
|
+
if (!conditionMet) {
|
|
1289
|
+
return null;
|
|
1290
|
+
}
|
|
1291
|
+
if (!label) {
|
|
1292
|
+
return inputs;
|
|
1293
|
+
}
|
|
1294
|
+
return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
|
|
1295
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
1296
|
+
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
|
|
1297
|
+
/* @__PURE__ */ jsx(Text, { className: styles$4.description, children: description2 })
|
|
1298
|
+
] }),
|
|
1299
|
+
inputs
|
|
1300
|
+
] }) });
|
|
1301
|
+
});
|
|
1302
|
+
const _FieldSection = class _FieldSection extends BaseFormElement {
|
|
1303
|
+
constructor(options) {
|
|
1304
|
+
const { label = null, fields, condition = null, conditional, ...base } = options;
|
|
1305
|
+
super({ ...base, type: "section" });
|
|
1306
|
+
__publicField(this, "label");
|
|
1307
|
+
__publicField(this, "fields");
|
|
1308
|
+
__publicField(this, "condition");
|
|
1309
|
+
this.fields = fields;
|
|
1310
|
+
this.condition = condition;
|
|
1311
|
+
this.label = label;
|
|
1312
|
+
if (conditional === false) {
|
|
1313
|
+
this.condition = null;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
static getFieldCreationSchema(options) {
|
|
1317
|
+
if (options.length === 0)
|
|
1318
|
+
return [];
|
|
1319
|
+
return [
|
|
1320
|
+
new BooleanField({
|
|
1321
|
+
label: "Conditional",
|
|
1322
|
+
description: "Conditionally show or hide this section.",
|
|
1323
|
+
identifier: "conditional",
|
|
1324
|
+
required: false
|
|
1325
|
+
}),
|
|
1326
|
+
// Declare a section that will hold options for the condition (if any).
|
|
1327
|
+
new _FieldSection({
|
|
1328
|
+
label: "Conditional settings",
|
|
1329
|
+
identifier: "conditional-settings",
|
|
1330
|
+
// This section will only be rendered if the above "Conditional" field is checked.
|
|
1331
|
+
condition: {
|
|
1332
|
+
identifier: "conditional",
|
|
1333
|
+
value: true
|
|
1334
|
+
},
|
|
1335
|
+
// These are the options of the condition.
|
|
1336
|
+
fields: [
|
|
1337
|
+
// Declare a select field that will be used to select the field against which we will check the
|
|
1338
|
+
// condition. This must be selected before the next field is rendered.
|
|
1339
|
+
new SelectField({
|
|
1340
|
+
label: "Field",
|
|
1341
|
+
description: "The field to use for the condition.",
|
|
1342
|
+
// The options (for the field against which we will check the condition) are all the labels of
|
|
1343
|
+
// the fields in the previous section(s) (or fields declared before with no section) that
|
|
1344
|
+
// support conditions. We pass in both the label and the identifier of each supported field. The
|
|
1345
|
+
// identifier becomes the value of the option.
|
|
1346
|
+
options: options.map((option) => {
|
|
1347
|
+
if (!option.label)
|
|
1348
|
+
return null;
|
|
1349
|
+
if (option.type === "upload")
|
|
1350
|
+
return null;
|
|
1351
|
+
return {
|
|
1352
|
+
label: option.label,
|
|
1353
|
+
value: option.identifier
|
|
1354
|
+
};
|
|
1355
|
+
}).filter((option) => !!option),
|
|
1356
|
+
identifier: "condition.identifier",
|
|
1357
|
+
required: true
|
|
1358
|
+
}),
|
|
1359
|
+
// Declare a custom field that will be used to input a value for the condition. The value of the
|
|
1360
|
+
// conditional field selected in the previous step must be equal to the value the user inputs into
|
|
1361
|
+
// this field for the section to be rendered.
|
|
1362
|
+
new FieldInputClonerField({
|
|
1363
|
+
label: "Value",
|
|
1364
|
+
identifier: "condition.value",
|
|
1365
|
+
required: true,
|
|
1366
|
+
clonedFieldIdentifier: "condition.identifier",
|
|
1367
|
+
getFieldToClone(identifier) {
|
|
1368
|
+
if (!identifier) {
|
|
1369
|
+
return null;
|
|
1370
|
+
}
|
|
1371
|
+
const option = options.find((option2) => option2.identifier === identifier);
|
|
1372
|
+
if (!option) {
|
|
1373
|
+
console.error("Could not find field with identifier", identifier);
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
...option,
|
|
1378
|
+
// Override some options to make it make sense in the context and to make it work with the framework.
|
|
1379
|
+
label: "Value",
|
|
1380
|
+
identifier: "condition.value",
|
|
1381
|
+
description: "The value to compare against.",
|
|
1382
|
+
required: option.type !== "boolean"
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
})
|
|
1386
|
+
]
|
|
1387
|
+
})
|
|
1388
|
+
];
|
|
1389
|
+
}
|
|
1390
|
+
static deserialize(data) {
|
|
1391
|
+
var _a;
|
|
1392
|
+
if (data.type !== "section")
|
|
1393
|
+
throw new Error("Invalid type");
|
|
1394
|
+
const fields = ((_a = data.fields) == null ? void 0 : _a.map(deserializeField)) ?? [];
|
|
1395
|
+
return new _FieldSection({ ...data, fields });
|
|
1396
|
+
}
|
|
1397
|
+
conditional() {
|
|
1398
|
+
return this.condition !== null;
|
|
1399
|
+
}
|
|
1400
|
+
serialize() {
|
|
1401
|
+
return {
|
|
1402
|
+
...super._serialize(),
|
|
1403
|
+
label: this.label,
|
|
1404
|
+
condition: this.condition,
|
|
1405
|
+
conditional: this.conditional(),
|
|
1406
|
+
fields: this.fields.map((field) => field.serialize())
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
getErrors(allValues) {
|
|
1410
|
+
const errors = {};
|
|
1411
|
+
for (const field of this.fields) {
|
|
1412
|
+
const id = field.getId();
|
|
1413
|
+
const error = field.getError(get(allValues, id), allValues);
|
|
1414
|
+
if (error) {
|
|
1415
|
+
set(errors, field.getId(), error);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
return errors;
|
|
1419
|
+
}
|
|
1420
|
+
getInput(props) {
|
|
1421
|
+
return /* @__PURE__ */ jsx(FieldSectionLayout, { field: this, ...props });
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
__publicField(_FieldSection, "fieldTypeName", "Section");
|
|
1425
|
+
__publicField(_FieldSection, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
|
|
1426
|
+
let FieldSection = _FieldSection;
|
|
1399
1427
|
const deserializeField = (serializedField) => {
|
|
1400
1428
|
const fieldType = serializedField.type;
|
|
1401
1429
|
const fieldCls = FieldTypeToClsMapping[fieldType];
|
|
@@ -1445,7 +1473,6 @@ const useFieldInput = (field, props) => {
|
|
|
1445
1473
|
}, [field, props]);
|
|
1446
1474
|
};
|
|
1447
1475
|
const useFieldInputs = (fields, props) => {
|
|
1448
|
-
console.log(fields, props);
|
|
1449
1476
|
const inputs = useMemo(() => {
|
|
1450
1477
|
return fields.map((field) => {
|
|
1451
1478
|
return /* @__PURE__ */ jsx("div", { children: field.getInput(props) }, field.getId());
|
|
@@ -1535,7 +1562,7 @@ const FormRenderer = memo(
|
|
|
1535
1562
|
[schema.title]
|
|
1536
1563
|
);
|
|
1537
1564
|
const Description = useMemo(
|
|
1538
|
-
() => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text, { className: styles$
|
|
1565
|
+
() => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text, { className: styles$4.description, children: schema.description }) : schema.description,
|
|
1539
1566
|
[schema.description]
|
|
1540
1567
|
);
|
|
1541
1568
|
const inputs = useFieldInputs(schema.fields, { formId: formId2, disabled: readonly });
|
|
@@ -2399,7 +2426,7 @@ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
|
|
|
2399
2426
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", grow: "1", children: [
|
|
2400
2427
|
/* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
|
|
2401
2428
|
/* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: field.label }),
|
|
2402
|
-
/* @__PURE__ */ jsx(Text, { className: styles$
|
|
2429
|
+
/* @__PURE__ */ jsx(Text, { className: styles$4.description, children: field.description })
|
|
2403
2430
|
] }),
|
|
2404
2431
|
field.condition && /* @__PURE__ */ jsx(Text, { size: "1", children: /* @__PURE__ */ jsxs(Em, { children: [
|
|
2405
2432
|
"Display only if ",
|