@overmap-ai/forms 1.0.12-links.9 → 1.0.13

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.
@@ -18,7 +18,3 @@ export declare const FieldTypeToClsMapping: {
18
18
  readonly "multi-string": typeof MultiStringField;
19
19
  readonly "multi-select": typeof MultiSelectField;
20
20
  };
21
- export declare const linkOptions: {
22
- target: string;
23
- rel: string;
24
- };
package/dist/forms.js CHANGED
@@ -5,14 +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, Select, IconButton, Badge, MultiSelect, Button, TextArea, ButtonList, divButtonProps, Tooltip, Separator, useDiscardAlertDialog, Dialog, DropdownItemMenu, useAlertDialog, useToast } from "@overmap-ai/blocks";
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, 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";
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
12
  import { TextField as TextField$1, Box, Card, Heading, Avatar, Em, Strong, Tabs } from "@radix-ui/themes";
13
13
  import Linkify from "linkify-react";
14
+ import { classNames, slugify, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser, isToday, getLocalDateString, selectLatestFormRevision, useFileSrc, selectSubmissionsForForm } from "@overmap-ai/core";
14
15
  import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
15
- import { slugify, classNames, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser, isToday, getLocalDateString, selectLatestFormRevision, useFileSrc, selectSubmissionsForForm } from "@overmap-ai/core";
16
16
  import get from "lodash.get";
17
17
  import set from "lodash.set";
18
18
  import cloneDeep from "lodash.clonedeep";
@@ -473,12 +473,91 @@ __publicField(StringOrTextField, "_validateMax", (value, allValues) => {
473
473
  }
474
474
  return null;
475
475
  });
476
- const TextFieldRoot = "_TextFieldRoot_8ge74_1";
477
- const TextFieldInputCopy = "_TextFieldInputCopy_8ge74_5";
476
+ const clickableLinkContainer = "_clickableLinkContainer_1ace7_1";
477
+ const TextFieldInputCopy = "_TextFieldInputCopy_1ace7_5";
478
478
  const styles$3 = {
479
- TextFieldRoot,
479
+ clickableLinkContainer,
480
480
  TextFieldInputCopy
481
481
  };
482
+ const StringInput = memo(function StringInput2(props) {
483
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
484
+ const color = useSeverityColor(severity);
485
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: !rest.disabled ? /* @__PURE__ */ jsx(TextField$1.Input, { ...rest, ...fieldProps, type: field.inputType, id: inputId, color }) : /* @__PURE__ */ jsxs(TextField$1.Root, { className: styles$3.clickableLinkContainer, children: [
486
+ /* @__PURE__ */ jsx(
487
+ "div",
488
+ {
489
+ className: classNames(
490
+ "rt-TextFieldInput rt-r-size-2 rt-variant-surface",
491
+ styles$3.TextFieldInputCopy
492
+ ),
493
+ children: /* @__PURE__ */ jsx(
494
+ Linkify,
495
+ {
496
+ options: {
497
+ target: "_blank",
498
+ rel: "noopener"
499
+ },
500
+ children: fieldProps.value
501
+ }
502
+ )
503
+ }
504
+ ),
505
+ /* @__PURE__ */ jsx("div", { className: "rt-TextFieldChrome" })
506
+ ] }) }) });
507
+ });
508
+ const _StringField = class _StringField extends StringOrTextField {
509
+ constructor(options) {
510
+ const { inputType = "text", ...rest } = options;
511
+ const maxLength = options.maxLength ? Math.min(500, options.maxLength) : 500;
512
+ const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
513
+ super({ ...rest, maxLength, minLength, type: "string" });
514
+ __publicField(this, "inputType");
515
+ this.inputType = inputType;
516
+ }
517
+ serialize() {
518
+ return { ...super._serialize(), input_type: this.inputType };
519
+ }
520
+ static deserialize(data) {
521
+ if (data.type !== "string")
522
+ throw new Error("Type mismatch.");
523
+ const { maximum_length, minimum_length, input_type, ...rest } = data;
524
+ return new _StringField({ ...rest, maxLength: maximum_length, minLength: minimum_length, inputType: input_type });
525
+ }
526
+ getInput(props) {
527
+ return /* @__PURE__ */ jsx(StringInput, { field: this, ...props });
528
+ }
529
+ };
530
+ __publicField(_StringField, "fieldTypeName", "Short Text");
531
+ __publicField(_StringField, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line.");
532
+ __publicField(_StringField, "Icon", InputIcon);
533
+ let StringField = _StringField;
534
+ const TextInput = memo(function TextInput2(props) {
535
+ const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
536
+ 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 }) }) });
537
+ });
538
+ const _TextField = class _TextField extends StringOrTextField {
539
+ constructor(options) {
540
+ const maxLength = options.maxLength ? Math.min(5e3, options.maxLength) : 5e3;
541
+ const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
542
+ super({ ...options, maxLength, minLength, type: "text" });
543
+ }
544
+ serialize() {
545
+ return super._serialize();
546
+ }
547
+ static deserialize(data) {
548
+ if (data.type !== "text")
549
+ throw new Error("Type mismatch.");
550
+ const { maximum_length, minimum_length, ...rest } = data;
551
+ return new _TextField({ ...rest, maxLength: maximum_length, minLength: minimum_length });
552
+ }
553
+ getInput(props) {
554
+ return /* @__PURE__ */ jsx(TextInput, { field: this, ...props });
555
+ }
556
+ };
557
+ __publicField(_TextField, "fieldTypeName", "Paragraph");
558
+ __publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
559
+ __publicField(_TextField, "Icon", RowsIcon);
560
+ let TextField = _TextField;
482
561
  const SelectInput = memo(function SelectInput2(props) {
483
562
  const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
484
563
  const { onChange, onBlur } = fieldProps;
@@ -903,6 +982,16 @@ __publicField(_MultiSelectField, "fieldTypeName", "Multi-select");
903
982
  __publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
904
983
  __publicField(_MultiSelectField, "Icon", CheckboxIcon);
905
984
  let MultiSelectField = _MultiSelectField;
985
+ const FieldInputCloner = memo(function FieldInputCloner2({ field, ...props }) {
986
+ const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
987
+ const deserializedField = useMemo(() => {
988
+ const options = field.options.getFieldToClone(identifier);
989
+ if (!options)
990
+ return null;
991
+ return deserialize(options);
992
+ }, [field.options, identifier]);
993
+ return useFieldInput(deserializedField, props);
994
+ });
906
995
  class CustomField extends BaseField {
907
996
  constructor(options, Component) {
908
997
  super({ ...options, type: "custom" });
@@ -922,6 +1011,164 @@ class CustomField extends BaseField {
922
1011
  }
923
1012
  __publicField(CustomField, "fieldTypeName", "Custom");
924
1013
  __publicField(CustomField, "fieldTypeDescription", "Allows re-rendering of field already in the form");
1014
+ class FieldInputClonerField extends CustomField {
1015
+ constructor(options) {
1016
+ super(options, FieldInputCloner);
1017
+ }
1018
+ }
1019
+ const FieldSectionLayout = memo(function FieldSectionLayout2(props) {
1020
+ const { field: section, ...rest } = props;
1021
+ const { label, description: description2, fields, condition } = section;
1022
+ const { values, setFieldValue } = useFormikContext();
1023
+ const conditionValue = (condition == null ? void 0 : condition.identifier) ? get(values, condition.identifier) : void 0;
1024
+ const conditionMet = useMemo(() => isConditionMet(condition, conditionValue), [condition, conditionValue]);
1025
+ useEffect(() => {
1026
+ if (!conditionMet) {
1027
+ for (const childField of fields) {
1028
+ setFieldValue(childField.getId(), "").then();
1029
+ }
1030
+ }
1031
+ }, [conditionMet, fields, setFieldValue]);
1032
+ const inputs = useFieldInputs(fields, rest);
1033
+ if (!conditionMet) {
1034
+ return null;
1035
+ }
1036
+ if (!label) {
1037
+ return inputs;
1038
+ }
1039
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
1040
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
1041
+ /* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
1042
+ /* @__PURE__ */ jsx(Text, { className: styles$4.description, children: description2 })
1043
+ ] }),
1044
+ inputs
1045
+ ] }) });
1046
+ });
1047
+ const _FieldSection = class _FieldSection extends BaseFormElement {
1048
+ constructor(options) {
1049
+ const { label = null, fields, condition = null, conditional, ...base } = options;
1050
+ super({ ...base, type: "section" });
1051
+ __publicField(this, "label");
1052
+ __publicField(this, "fields");
1053
+ __publicField(this, "condition");
1054
+ this.fields = fields;
1055
+ this.condition = condition;
1056
+ this.label = label;
1057
+ if (conditional === false) {
1058
+ this.condition = null;
1059
+ }
1060
+ }
1061
+ static getFieldCreationSchema(options) {
1062
+ if (options.length === 0)
1063
+ return [];
1064
+ return [
1065
+ new BooleanField({
1066
+ label: "Conditional",
1067
+ description: "Conditionally show or hide this section.",
1068
+ identifier: "conditional",
1069
+ required: false
1070
+ }),
1071
+ // Declare a section that will hold options for the condition (if any).
1072
+ new _FieldSection({
1073
+ label: "Conditional settings",
1074
+ identifier: "conditional-settings",
1075
+ // This section will only be rendered if the above "Conditional" field is checked.
1076
+ condition: {
1077
+ identifier: "conditional",
1078
+ value: true
1079
+ },
1080
+ // These are the options of the condition.
1081
+ fields: [
1082
+ // Declare a select field that will be used to select the field against which we will check the
1083
+ // condition. This must be selected before the next field is rendered.
1084
+ new SelectField({
1085
+ label: "Field",
1086
+ description: "The field to use for the condition.",
1087
+ // The options (for the field against which we will check the condition) are all the labels of
1088
+ // the fields in the previous section(s) (or fields declared before with no section) that
1089
+ // support conditions. We pass in both the label and the identifier of each supported field. The
1090
+ // identifier becomes the value of the option.
1091
+ options: options.map((option) => {
1092
+ if (!option.label)
1093
+ return null;
1094
+ if (option.type === "upload")
1095
+ return null;
1096
+ return {
1097
+ label: option.label,
1098
+ value: option.identifier
1099
+ };
1100
+ }).filter((option) => !!option),
1101
+ identifier: "condition.identifier",
1102
+ required: true
1103
+ }),
1104
+ // Declare a custom field that will be used to input a value for the condition. The value of the
1105
+ // conditional field selected in the previous step must be equal to the value the user inputs into
1106
+ // this field for the section to be rendered.
1107
+ new FieldInputClonerField({
1108
+ label: "Value",
1109
+ identifier: "condition.value",
1110
+ required: true,
1111
+ clonedFieldIdentifier: "condition.identifier",
1112
+ getFieldToClone(identifier) {
1113
+ if (!identifier) {
1114
+ return null;
1115
+ }
1116
+ const option = options.find((option2) => option2.identifier === identifier);
1117
+ if (!option) {
1118
+ console.error("Could not find field with identifier", identifier);
1119
+ return null;
1120
+ }
1121
+ return {
1122
+ ...option,
1123
+ // Override some options to make it make sense in the context and to make it work with the framework.
1124
+ label: "Value",
1125
+ identifier: "condition.value",
1126
+ description: "The value to compare against.",
1127
+ required: option.type !== "boolean"
1128
+ };
1129
+ }
1130
+ })
1131
+ ]
1132
+ })
1133
+ ];
1134
+ }
1135
+ static deserialize(data) {
1136
+ var _a;
1137
+ if (data.type !== "section")
1138
+ throw new Error("Invalid type");
1139
+ const fields = ((_a = data.fields) == null ? void 0 : _a.map(deserializeField)) ?? [];
1140
+ return new _FieldSection({ ...data, fields });
1141
+ }
1142
+ conditional() {
1143
+ return this.condition !== null;
1144
+ }
1145
+ serialize() {
1146
+ return {
1147
+ ...super._serialize(),
1148
+ label: this.label,
1149
+ condition: this.condition,
1150
+ conditional: this.conditional(),
1151
+ fields: this.fields.map((field) => field.serialize())
1152
+ };
1153
+ }
1154
+ getErrors(allValues) {
1155
+ const errors = {};
1156
+ for (const field of this.fields) {
1157
+ const id = field.getId();
1158
+ const error = field.getError(get(allValues, id), allValues);
1159
+ if (error) {
1160
+ set(errors, field.getId(), error);
1161
+ }
1162
+ }
1163
+ return errors;
1164
+ }
1165
+ getInput(props) {
1166
+ return /* @__PURE__ */ jsx(FieldSectionLayout, { field: this, ...props });
1167
+ }
1168
+ };
1169
+ __publicField(_FieldSection, "fieldTypeName", "Section");
1170
+ __publicField(_FieldSection, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
1171
+ let FieldSection = _FieldSection;
925
1172
  const previewImage = "_previewImage_1ig84_1";
926
1173
  const styles$2 = {
927
1174
  previewImage
@@ -1177,253 +1424,6 @@ const FieldTypeToClsMapping = {
1177
1424
  "multi-string": MultiStringField,
1178
1425
  "multi-select": MultiSelectField
1179
1426
  };
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;
1427
1427
  const deserializeField = (serializedField) => {
1428
1428
  const fieldType = serializedField.type;
1429
1429
  const fieldCls = FieldTypeToClsMapping[fieldType];