@overmap-ai/core 1.0.31-display-invited-projects.1 → 1.0.31-revamp-forms-builder.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.
Files changed (40) hide show
  1. package/dist/forms/builder/FieldActions.d.ts +8 -7
  2. package/dist/forms/builder/FieldBuilder.d.ts +5 -18
  3. package/dist/forms/builder/FieldSectionWithActions.d.ts +2 -2
  4. package/dist/forms/builder/FieldWithActions.d.ts +1 -1
  5. package/dist/forms/builder/FieldsEditor.d.ts +1 -1
  6. package/dist/forms/builder/FormBuilder.d.ts +1 -5
  7. package/dist/forms/builder/componentConstants.d.ts +8 -0
  8. package/dist/forms/builder/utils.d.ts +13 -1
  9. package/dist/forms/fields/BaseField/BaseField.d.ts +15 -5
  10. package/dist/forms/fields/BaseField/hooks.d.ts +2 -1
  11. package/dist/forms/fields/BaseField/layouts.d.ts +7 -2
  12. package/dist/forms/fields/BooleanField/BooleanField.d.ts +6 -0
  13. package/dist/forms/fields/CustomField/CustomField.d.ts +6 -0
  14. package/dist/forms/fields/DateField/DateField.d.ts +6 -0
  15. package/dist/forms/fields/FieldSection/FieldSection.d.ts +12 -6
  16. package/dist/forms/fields/MultiStringField/MultiStringField.d.ts +8 -0
  17. package/dist/forms/fields/NumberField/NumberField.d.ts +18 -3
  18. package/dist/forms/fields/SelectField/BaseSelectField.d.ts +4 -1
  19. package/dist/forms/fields/SelectField/MultiSelectField.d.ts +7 -0
  20. package/dist/forms/fields/SelectField/SelectField.d.ts +7 -0
  21. package/dist/forms/fields/StringOrTextFields/StringField/StringField.d.ts +8 -0
  22. package/dist/forms/fields/StringOrTextFields/StringOrTextField.d.ts +8 -5
  23. package/dist/forms/fields/StringOrTextFields/TextField/TextField.d.ts +7 -0
  24. package/dist/forms/fields/UploadField/UploadField.d.ts +16 -1
  25. package/dist/forms/fields/constants.d.ts +75 -0
  26. package/dist/forms/fields/typings.d.ts +4 -1
  27. package/dist/forms/fields/utils.d.ts +3 -1
  28. package/dist/forms/renderer/PatchForm/Field.d.ts +3 -1
  29. package/dist/forms/renderer/PatchForm/Provider.d.ts +2 -1
  30. package/dist/forms/utils.d.ts +2 -1
  31. package/dist/overmap-core.js +1489 -1153
  32. package/dist/overmap-core.js.map +1 -1
  33. package/dist/overmap-core.umd.cjs +1490 -1154
  34. package/dist/overmap-core.umd.cjs.map +1 -1
  35. package/dist/sdk/services/ProjectService.d.ts +0 -1
  36. package/dist/store/slices/projectSlice.d.ts +1 -5
  37. package/dist/style.css +2 -0
  38. package/dist/typings/models/projects.d.ts +0 -1
  39. package/package.json +2 -2
  40. package/dist/forms/builder/constants.d.ts +0 -1
@@ -5,8 +5,8 @@ var __publicField = (obj, key, value) => {
5
5
  return value;
6
6
  };
7
7
  (function(global2, factory) {
8
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("@overmap-ai/blocks"), require("dependency-graph"), require("@redux-offline/redux-offline"), require("@redux-offline/redux-offline/lib/defaults"), require("localforage"), require("redux-persist-migrate"), require("@reduxjs/toolkit"), require("superagent"), require("react-redux"), require("uuid"), require("color"), require("jwt-decode"), require("@redux-offline/redux-offline/lib/constants"), require("idb"), require("formik"), require("linkify-react"), require("@hello-pangea/dnd"), require("lodash.get"), require("lodash.set"), require("lodash.clonedeep"), require("react-dom")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime", "@overmap-ai/blocks", "dependency-graph", "@redux-offline/redux-offline", "@redux-offline/redux-offline/lib/defaults", "localforage", "redux-persist-migrate", "@reduxjs/toolkit", "superagent", "react-redux", "uuid", "color", "jwt-decode", "@redux-offline/redux-offline/lib/constants", "idb", "formik", "linkify-react", "@hello-pangea/dnd", "lodash.get", "lodash.set", "lodash.clonedeep", "react-dom"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2["overmap-core"] = {}, global2.React, global2.jsxRuntime, global2.blocks, global2.dependencyGraph, global2.reduxOffline, global2.offlineConfig, global2.localforage, global2.createMigration, global2.toolkit, global2.request, global2.reactRedux, global2.uuid, global2.ColorCls, global2.jwtDecode, global2.constants, global2.idb, global2.formik, global2.Linkify, global2.dnd, global2.get, global2.set, global2.cloneDeep, global2.ReactDOM));
9
- })(this, function(exports2, React, jsxRuntime, blocks, dependencyGraph, reduxOffline, offlineConfig, localforage, createMigration, toolkit, request, reactRedux, uuid, ColorCls, jwtDecode, constants, idb, formik, Linkify, dnd, get, set, cloneDeep, ReactDOM) {
8
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("@overmap-ai/blocks"), require("dependency-graph"), require("@redux-offline/redux-offline"), require("@redux-offline/redux-offline/lib/defaults"), require("localforage"), require("redux-persist-migrate"), require("@reduxjs/toolkit"), require("superagent"), require("react-redux"), require("uuid"), require("color"), require("jwt-decode"), require("@redux-offline/redux-offline/lib/constants"), require("idb"), require("formik"), require("lodash.get"), require("linkify-react"), require("@hello-pangea/dnd"), require("lodash.set"), require("lodash.clonedeep"), require("react-dom")) : typeof define === "function" && define.amd ? define(["exports", "react", "react/jsx-runtime", "@overmap-ai/blocks", "dependency-graph", "@redux-offline/redux-offline", "@redux-offline/redux-offline/lib/defaults", "localforage", "redux-persist-migrate", "@reduxjs/toolkit", "superagent", "react-redux", "uuid", "color", "jwt-decode", "@redux-offline/redux-offline/lib/constants", "idb", "formik", "lodash.get", "linkify-react", "@hello-pangea/dnd", "lodash.set", "lodash.clonedeep", "react-dom"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2["overmap-core"] = {}, global2.React, global2.jsxRuntime, global2.blocks, global2.dependencyGraph, global2.reduxOffline, global2.offlineConfig, global2.localforage, global2.createMigration, global2.toolkit, global2.request, global2.reactRedux, global2.uuid, global2.ColorCls, global2.jwtDecode, global2.constants, global2.idb, global2.formik, global2.get, global2.Linkify, global2.dnd, global2.set, global2.cloneDeep, global2.ReactDOM));
9
+ })(this, function(exports2, React, jsxRuntime, blocks, dependencyGraph, reduxOffline, offlineConfig, localforage, createMigration, toolkit, request, reactRedux, uuid, ColorCls, jwtDecode, constants, idb, formik, get, Linkify, dnd, set, cloneDeep, ReactDOM) {
10
10
  var _a;
11
11
  "use strict";
12
12
  function _interopNamespaceDefault(e) {
@@ -372,7 +372,7 @@ var __publicField = (obj, key, value) => {
372
372
  Item.prototype.run = function() {
373
373
  this.fun.apply(null, this.array);
374
374
  };
375
- var title$1 = "browser";
375
+ var title = "browser";
376
376
  var platform = "browser";
377
377
  var browser = true;
378
378
  var env = {};
@@ -428,7 +428,7 @@ var __publicField = (obj, key, value) => {
428
428
  }
429
429
  var browser$1 = {
430
430
  nextTick,
431
- title: title$1,
431
+ title,
432
432
  browser,
433
433
  env,
434
434
  argv,
@@ -2685,13 +2685,6 @@ var __publicField = (obj, key, value) => {
2685
2685
  deleteProject: (state, action) => {
2686
2686
  delete state.projects[action.payload.id];
2687
2687
  state.recentProjectIds = state.recentProjectIds.filter((id) => id !== action.payload.id);
2688
- },
2689
- acceptProjectInvite: (state, action) => {
2690
- if (action.payload in state.projects) {
2691
- state.projects[action.payload].invited = false;
2692
- } else {
2693
- throw new Error("Accept project invite: user is not in this project");
2694
- }
2695
2688
  }
2696
2689
  }
2697
2690
  });
@@ -2701,8 +2694,7 @@ var __publicField = (obj, key, value) => {
2701
2694
  updateOrCreateProjects: addOrReplaceProjects,
2702
2695
  setActiveProjectId,
2703
2696
  setCreateProjectType,
2704
- deleteProject,
2705
- acceptProjectInvite
2697
+ deleteProject
2706
2698
  } = projectSlice.actions;
2707
2699
  const selectProjects = (state) => state.projectReducer.projects;
2708
2700
  const selectActiveProjectId = (state) => state.projectReducer.activeProjectId;
@@ -2726,10 +2718,6 @@ var __publicField = (obj, key, value) => {
2726
2718
  [selectProjectUsersIds, selectUsersAsMapping],
2727
2719
  (projectUserIds, users) => projectUserIds.reduce((accum, userId) => ({ ...accum, [userId]: users[userId] }), {})
2728
2720
  );
2729
- const selectProjectsWithAccess = toolkit.createSelector(
2730
- [selectProjects],
2731
- (projects) => Object.values(projects).filter((project) => !project.invited)
2732
- );
2733
2721
  const selectSortedProjectUsers = toolkit.createSelector(
2734
2722
  [selectCurrentUser, selectProjectUsersAsMapping, selectProjectAccessUserMapping],
2735
2723
  (currentUser, userMapping, projectAccessMapping) => {
@@ -4380,7 +4368,7 @@ var __publicField = (obj, key, value) => {
4380
4368
  });
4381
4369
  return promise;
4382
4370
  }
4383
- async refreshStore(replace2) {
4371
+ async refreshStore(replace) {
4384
4372
  const { store } = this.client;
4385
4373
  const result = await this.enqueueRequest({
4386
4374
  description: "Get components",
@@ -4389,7 +4377,7 @@ var __publicField = (obj, key, value) => {
4389
4377
  blockers: [],
4390
4378
  blocks: []
4391
4379
  });
4392
- if (replace2) {
4380
+ if (replace) {
4393
4381
  store.dispatch(setComponents(result));
4394
4382
  } else {
4395
4383
  store.dispatch(addComponentsInBatches(result));
@@ -4864,16 +4852,14 @@ var __publicField = (obj, key, value) => {
4864
4852
  // Don't accept updateStore in ComponentService.list. Just return the offline objects and promise. Here, if
4865
4853
  // overwrite, use setComponents. Otherwise, use bulkAddComponents.
4866
4854
  async _processInitialData(data, overwrite) {
4867
- var _a2, _b, _c;
4855
+ var _a2, _b;
4868
4856
  const workspaces = {};
4869
4857
  const projects = [];
4870
4858
  const categories = [];
4871
4859
  const projectsData = data.projects;
4872
4860
  const { store } = this.client;
4873
- const oldProjectId = (_a2 = projectsData.find(
4874
- (projectData) => projectData.id === store.getState().projectReducer.activeProjectId && !projectData.invited
4875
- )) == null ? void 0 : _a2.id;
4876
- let currentProjectId = oldProjectId ?? ((_b = projectsData.find((projectData) => !projectData.invited)) == null ? void 0 : _b.id);
4861
+ const oldProjectId = store.getState().projectReducer.activeProjectId;
4862
+ let currentProjectId = oldProjectId ?? ((_a2 = projectsData[0]) == null ? void 0 : _a2.id);
4877
4863
  store.dispatch(setActiveProjectId(currentProjectId ?? null));
4878
4864
  let isProjectIdValid = false;
4879
4865
  for (const projectData of projectsData) {
@@ -4882,10 +4868,9 @@ var __publicField = (obj, key, value) => {
4882
4868
  name: projectData.name,
4883
4869
  owner_organization: projectData.organization_owner,
4884
4870
  owner_user: projectData.user_owner,
4885
- bounds: projectData.bounds,
4886
- invited: projectData.invited || false
4871
+ bounds: projectData.bounds
4887
4872
  });
4888
- if (currentProjectId === projectData.id && !projectData.invited) {
4873
+ if (currentProjectId === projectData.id) {
4889
4874
  isProjectIdValid = true;
4890
4875
  for (const workspaceData of projectData.workspaces) {
4891
4876
  const workspace = { ...workspaceData, project: projectData.id };
@@ -4902,7 +4887,6 @@ var __publicField = (obj, key, value) => {
4902
4887
  store.dispatch(setCurrentUser(data.user));
4903
4888
  const organizationsData = data.organizations;
4904
4889
  store.dispatch(setOrganizations(organizationsData));
4905
- const validProjects = projects.filter((project) => !project.invited);
4906
4890
  const firstOrg = organizationsData[0];
4907
4891
  const currProjObj = projects.find((project) => project.id === currentProjectId);
4908
4892
  const isOrgProject = !!(currProjObj == null ? void 0 : currProjObj.owner_organization);
@@ -4922,21 +4906,19 @@ var __publicField = (obj, key, value) => {
4922
4906
  store.dispatch(addUsers(orgUsersResult));
4923
4907
  }
4924
4908
  if (!isProjectIdValid) {
4925
- if (validProjects.length !== 0) {
4926
- currentProjectId = validProjects[0].id;
4909
+ if (projects.length !== 0) {
4910
+ currentProjectId = projects[0].id;
4927
4911
  store.dispatch(setActiveProjectId(currentProjectId));
4928
- const projectData = projectsData.find((projectData2) => projectData2.id === currentProjectId);
4929
- if (projectData) {
4930
- for (const workspaceData of projectData.workspaces) {
4931
- const workspace = { ...workspaceData, project: projectData.id };
4932
- if (workspace.categories) {
4933
- for (const category of workspace.categories) {
4934
- categories.push(category);
4935
- }
4912
+ const projectData = projectsData[0];
4913
+ for (const workspaceData of projectData.workspaces) {
4914
+ const workspace = { ...workspaceData, project: projectData.id };
4915
+ if (workspace.categories) {
4916
+ for (const category of workspace.categories) {
4917
+ categories.push(category);
4936
4918
  }
4937
- delete workspace.categories;
4938
- workspaces[workspace.offline_id] = workspace;
4939
4919
  }
4920
+ delete workspace.categories;
4921
+ workspaces[workspace.offline_id] = workspace;
4940
4922
  }
4941
4923
  } else {
4942
4924
  currentProjectId = null;
@@ -4953,7 +4935,7 @@ var __publicField = (obj, key, value) => {
4953
4935
  let currentWorkspaceId;
4954
4936
  const oldWorkspaceId = this.client.store.getState().workspaceReducer.activeWorkspaceId;
4955
4937
  if (overwrite || !oldWorkspaceId) {
4956
- currentWorkspaceId = (_c = Object.values(workspaces).at(0)) == null ? void 0 : _c.offline_id;
4938
+ currentWorkspaceId = (_b = Object.values(workspaces).at(0)) == null ? void 0 : _b.offline_id;
4957
4939
  } else {
4958
4940
  currentWorkspaceId = oldWorkspaceId;
4959
4941
  }
@@ -5264,17 +5246,6 @@ var __publicField = (obj, key, value) => {
5264
5246
  blocks: []
5265
5247
  });
5266
5248
  }
5267
- async acceptInvite(projectId) {
5268
- return this.enqueueRequest({
5269
- description: "Accept project invite",
5270
- method: HttpMethod.PATCH,
5271
- url: `/projects/${projectId}/accept-invite/`,
5272
- blockers: [projectId.toString()],
5273
- blocks: [projectId.toString()]
5274
- }).then(() => {
5275
- this.client.store.dispatch(acceptProjectInvite(projectId));
5276
- });
5277
- }
5278
5249
  }
5279
5250
  class UserFormService extends BaseApiService {
5280
5251
  add(state, initialRevision, url, ownerUser, ownerOrganization) {
@@ -6079,6 +6050,11 @@ var __publicField = (obj, key, value) => {
6079
6050
  };
6080
6051
  }
6081
6052
  }
6053
+ const emptyBaseField = {
6054
+ label: "",
6055
+ required: false,
6056
+ description: ""
6057
+ };
6082
6058
  class BaseField extends BaseFormElement {
6083
6059
  constructor(options) {
6084
6060
  const { label, required, fieldValidators = [], formValidators = [], ...base } = options;
@@ -6143,25 +6119,29 @@ var __publicField = (obj, key, value) => {
6143
6119
  __publicField(BaseField, "fieldTypeName");
6144
6120
  __publicField(BaseField, "fieldTypeDescription");
6145
6121
  const description$1 = "_description_17zed_1";
6146
- const styles$4 = {
6122
+ const styles$5 = {
6147
6123
  description: description$1
6148
6124
  };
6149
6125
  const InputWithLabel = (props) => {
6150
- const { label, children, severity, inputId, labelId, flexProps } = props;
6126
+ const { label, children, size, severity, inputId, labelId, flexProps } = props;
6151
6127
  return /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", gap: "1", asChild: true, ...flexProps, children: /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, children: [
6152
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { severity, id: labelId, children: label }),
6128
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size, severity, id: labelId, children: label }),
6153
6129
  children
6154
6130
  ] }) });
6155
6131
  };
6156
- const InputWithLabelAndHelpText = (props) => {
6132
+ const InputWithHelpText = (props) => {
6157
6133
  const { helpText, children, severity } = props;
6158
6134
  return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "1", children: [
6159
6135
  children,
6160
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "1", severity, className: styles$4.description, children: helpText }) })
6136
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", children: /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "1", severity, className: styles$5.description, children: helpText }) })
6161
6137
  ] });
6162
6138
  };
6139
+ const InputWithLabelAndHelpText = (props) => {
6140
+ const { children, ...restProps } = props;
6141
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithHelpText, { ...restProps, children });
6142
+ };
6163
6143
  const useFormikInput = (props) => {
6164
- const { id, field, formId: formId2, ...rest } = props;
6144
+ const { id, field, formId: formId2, size, ...rest } = props;
6165
6145
  const [fieldProps, meta, helpers] = formik.useField(field.getId());
6166
6146
  const { touched } = meta;
6167
6147
  const helpText = meta.error ?? field.description;
@@ -6190,6 +6170,7 @@ var __publicField = (obj, key, value) => {
6190
6170
  return [
6191
6171
  {
6192
6172
  helpText,
6173
+ size,
6193
6174
  severity,
6194
6175
  inputId,
6195
6176
  labelId,
@@ -6203,12 +6184,13 @@ var __publicField = (obj, key, value) => {
6203
6184
  };
6204
6185
  const truthyValues = [true, "true"];
6205
6186
  const BooleanInput = React.memo(function BooleanInput2(props) {
6206
- const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
6187
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
6207
6188
  const color = blocks.useSeverityColor(severity);
6208
6189
  const value = truthyValues.includes(fieldProps.value);
6209
6190
  return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(
6210
6191
  InputWithLabel,
6211
6192
  {
6193
+ size,
6212
6194
  severity,
6213
6195
  inputId,
6214
6196
  labelId,
@@ -6224,6 +6206,7 @@ var __publicField = (obj, key, value) => {
6224
6206
  value: value.toString(),
6225
6207
  checked: value,
6226
6208
  onCheckedChange: fieldProps.onChange,
6209
+ alwaysShow: true,
6227
6210
  onChange: void 0,
6228
6211
  onBlur: void 0
6229
6212
  }
@@ -6245,6 +6228,42 @@ var __publicField = (obj, key, value) => {
6245
6228
  }
6246
6229
  return target;
6247
6230
  }
6231
+ var _excluded$e = ["color"];
6232
+ var ArrowDownIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6233
+ var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$e);
6234
+ return React.createElement("svg", Object.assign({
6235
+ width: "15",
6236
+ height: "15",
6237
+ viewBox: "0 0 15 15",
6238
+ fill: "none",
6239
+ xmlns: "http://www.w3.org/2000/svg"
6240
+ }, props, {
6241
+ ref: forwardedRef
6242
+ }), React.createElement("path", {
6243
+ d: "M7.5 2C7.77614 2 8 2.22386 8 2.5L8 11.2929L11.1464 8.14645C11.3417 7.95118 11.6583 7.95118 11.8536 8.14645C12.0488 8.34171 12.0488 8.65829 11.8536 8.85355L7.85355 12.8536C7.75979 12.9473 7.63261 13 7.5 13C7.36739 13 7.24021 12.9473 7.14645 12.8536L3.14645 8.85355C2.95118 8.65829 2.95118 8.34171 3.14645 8.14645C3.34171 7.95118 3.65829 7.95118 3.85355 8.14645L7 11.2929L7 2.5C7 2.22386 7.22386 2 7.5 2Z",
6244
+ fill: color,
6245
+ fillRule: "evenodd",
6246
+ clipRule: "evenodd"
6247
+ }));
6248
+ });
6249
+ var _excluded$j = ["color"];
6250
+ var ArrowUpIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6251
+ var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$j);
6252
+ return React.createElement("svg", Object.assign({
6253
+ width: "15",
6254
+ height: "15",
6255
+ viewBox: "0 0 15 15",
6256
+ fill: "none",
6257
+ xmlns: "http://www.w3.org/2000/svg"
6258
+ }, props, {
6259
+ ref: forwardedRef
6260
+ }), React.createElement("path", {
6261
+ d: "M7.14645 2.14645C7.34171 1.95118 7.65829 1.95118 7.85355 2.14645L11.8536 6.14645C12.0488 6.34171 12.0488 6.65829 11.8536 6.85355C11.6583 7.04882 11.3417 7.04882 11.1464 6.85355L8 3.70711L8 12.5C8 12.7761 7.77614 13 7.5 13C7.22386 13 7 12.7761 7 12.5L7 3.70711L3.85355 6.85355C3.65829 7.04882 3.34171 7.04882 3.14645 6.85355C2.95118 6.65829 2.95118 6.34171 3.14645 6.14645L7.14645 2.14645Z",
6262
+ fill: color,
6263
+ fillRule: "evenodd",
6264
+ clipRule: "evenodd"
6265
+ }));
6266
+ });
6248
6267
  var _excluded$I = ["color"];
6249
6268
  var CalendarIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6250
6269
  var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$I);
@@ -6353,24 +6372,6 @@ var __publicField = (obj, key, value) => {
6353
6372
  clipRule: "evenodd"
6354
6373
  }));
6355
6374
  });
6356
- var _excluded$1R = ["color"];
6357
- var DragHandleDots2Icon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6358
- var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$1R);
6359
- return React.createElement("svg", Object.assign({
6360
- width: "15",
6361
- height: "15",
6362
- viewBox: "0 0 15 15",
6363
- fill: "none",
6364
- xmlns: "http://www.w3.org/2000/svg"
6365
- }, props, {
6366
- ref: forwardedRef
6367
- }), React.createElement("path", {
6368
- d: "M5.5 4.625C6.12132 4.625 6.625 4.12132 6.625 3.5C6.625 2.87868 6.12132 2.375 5.5 2.375C4.87868 2.375 4.375 2.87868 4.375 3.5C4.375 4.12132 4.87868 4.625 5.5 4.625ZM9.5 4.625C10.1213 4.625 10.625 4.12132 10.625 3.5C10.625 2.87868 10.1213 2.375 9.5 2.375C8.87868 2.375 8.375 2.87868 8.375 3.5C8.375 4.12132 8.87868 4.625 9.5 4.625ZM10.625 7.5C10.625 8.12132 10.1213 8.625 9.5 8.625C8.87868 8.625 8.375 8.12132 8.375 7.5C8.375 6.87868 8.87868 6.375 9.5 6.375C10.1213 6.375 10.625 6.87868 10.625 7.5ZM5.5 8.625C6.12132 8.625 6.625 8.12132 6.625 7.5C6.625 6.87868 6.12132 6.375 5.5 6.375C4.87868 6.375 4.375 6.87868 4.375 7.5C4.375 8.12132 4.87868 8.625 5.5 8.625ZM10.625 11.5C10.625 12.1213 10.1213 12.625 9.5 12.625C8.87868 12.625 8.375 12.1213 8.375 11.5C8.375 10.8787 8.87868 10.375 9.5 10.375C10.1213 10.375 10.625 10.8787 10.625 11.5ZM5.5 12.625C6.12132 12.625 6.625 12.1213 6.625 11.5C6.625 10.8787 6.12132 10.375 5.5 10.375C4.87868 10.375 4.375 10.8787 4.375 11.5C4.375 12.1213 4.87868 12.625 5.5 12.625Z",
6369
- fill: color,
6370
- fillRule: "evenodd",
6371
- clipRule: "evenodd"
6372
- }));
6373
- });
6374
6375
  var _excluded$1W = ["color"];
6375
6376
  var DropdownMenuIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6376
6377
  var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$1W);
@@ -6405,9 +6406,9 @@ var __publicField = (obj, key, value) => {
6405
6406
  fill: color
6406
6407
  }));
6407
6408
  });
6408
- var _excluded$2E = ["color"];
6409
- var InputIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6410
- var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$2E);
6409
+ var _excluded$2l = ["color"];
6410
+ var GearIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6411
+ var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$2l);
6411
6412
  return React.createElement("svg", Object.assign({
6412
6413
  width: "15",
6413
6414
  height: "15",
@@ -6417,15 +6418,15 @@ var __publicField = (obj, key, value) => {
6417
6418
  }, props, {
6418
6419
  ref: forwardedRef
6419
6420
  }), React.createElement("path", {
6420
- d: "M6.5 1C6.22386 1 6 1.22386 6 1.5C6 1.77614 6.22386 2 6.5 2C7.12671 2 7.45718 2.20028 7.65563 2.47812C7.8781 2.78957 8 3.28837 8 4V11C8 11.7116 7.8781 12.2104 7.65563 12.5219C7.45718 12.7997 7.12671 13 6.5 13C6.22386 13 6 13.2239 6 13.5C6 13.7761 6.22386 14 6.5 14C7.37329 14 8.04282 13.7003 8.46937 13.1031C8.47976 13.0886 8.48997 13.0739 8.5 13.0591C8.51003 13.0739 8.52024 13.0886 8.53063 13.1031C8.95718 13.7003 9.62671 14 10.5 14C10.7761 14 11 13.7761 11 13.5C11 13.2239 10.7761 13 10.5 13C9.87329 13 9.54282 12.7997 9.34437 12.5219C9.1219 12.2104 9 11.7116 9 11V4C9 3.28837 9.1219 2.78957 9.34437 2.47812C9.54282 2.20028 9.87329 2 10.5 2C10.7761 2 11 1.77614 11 1.5C11 1.22386 10.7761 1 10.5 1C9.62671 1 8.95718 1.29972 8.53063 1.89688C8.52024 1.91143 8.51003 1.92611 8.5 1.9409C8.48997 1.92611 8.47976 1.91143 8.46937 1.89688C8.04282 1.29972 7.37329 1 6.5 1ZM14 5H11V4H14C14.5523 4 15 4.44772 15 5V10C15 10.5523 14.5523 11 14 11H11V10H14V5ZM6 4V5H1L1 10H6V11H1C0.447715 11 0 10.5523 0 10V5C0 4.44772 0.447715 4 1 4H6Z",
6421
+ d: "M7.07095 0.650238C6.67391 0.650238 6.32977 0.925096 6.24198 1.31231L6.0039 2.36247C5.6249 2.47269 5.26335 2.62363 4.92436 2.81013L4.01335 2.23585C3.67748 2.02413 3.23978 2.07312 2.95903 2.35386L2.35294 2.95996C2.0722 3.2407 2.0232 3.6784 2.23493 4.01427L2.80942 4.92561C2.62307 5.2645 2.47227 5.62594 2.36216 6.00481L1.31209 6.24287C0.924883 6.33065 0.650024 6.6748 0.650024 7.07183V7.92897C0.650024 8.32601 0.924883 8.67015 1.31209 8.75794L2.36228 8.99603C2.47246 9.375 2.62335 9.73652 2.80979 10.0755L2.2354 10.9867C2.02367 11.3225 2.07267 11.7602 2.35341 12.041L2.95951 12.6471C3.24025 12.9278 3.67795 12.9768 4.01382 12.7651L4.92506 12.1907C5.26384 12.377 5.62516 12.5278 6.0039 12.6379L6.24198 13.6881C6.32977 14.0753 6.67391 14.3502 7.07095 14.3502H7.92809C8.32512 14.3502 8.66927 14.0753 8.75705 13.6881L8.99505 12.6383C9.37411 12.5282 9.73573 12.3773 10.0748 12.1909L10.986 12.7653C11.3218 12.977 11.7595 12.928 12.0403 12.6473L12.6464 12.0412C12.9271 11.7604 12.9761 11.3227 12.7644 10.9869L12.1902 10.076C12.3768 9.73688 12.5278 9.37515 12.638 8.99596L13.6879 8.75794C14.0751 8.67015 14.35 8.32601 14.35 7.92897V7.07183C14.35 6.6748 14.0751 6.33065 13.6879 6.24287L12.6381 6.00488C12.528 5.62578 12.3771 5.26414 12.1906 4.92507L12.7648 4.01407C12.9766 3.6782 12.9276 3.2405 12.6468 2.95975L12.0407 2.35366C11.76 2.07292 11.3223 2.02392 10.9864 2.23565L10.0755 2.80989C9.73622 2.62328 9.37437 2.47229 8.99505 2.36209L8.75705 1.31231C8.66927 0.925096 8.32512 0.650238 7.92809 0.650238H7.07095ZM4.92053 3.81251C5.44724 3.44339 6.05665 3.18424 6.71543 3.06839L7.07095 1.50024H7.92809L8.28355 3.06816C8.94267 3.18387 9.5524 3.44302 10.0794 3.81224L11.4397 2.9547L12.0458 3.56079L11.1882 4.92117C11.5573 5.44798 11.8164 6.0575 11.9321 6.71638L13.5 7.07183V7.92897L11.932 8.28444C11.8162 8.94342 11.557 9.55301 11.1878 10.0798L12.0453 11.4402L11.4392 12.0462L10.0787 11.1886C9.55192 11.5576 8.94241 11.8166 8.28355 11.9323L7.92809 13.5002H7.07095L6.71543 11.932C6.0569 11.8162 5.44772 11.5572 4.92116 11.1883L3.56055 12.046L2.95445 11.4399L3.81213 10.0794C3.4431 9.55266 3.18403 8.94326 3.06825 8.2845L1.50002 7.92897V7.07183L3.06818 6.71632C3.18388 6.05765 3.44283 5.44833 3.81171 4.92165L2.95398 3.561L3.56008 2.95491L4.92053 3.81251ZM9.02496 7.50008C9.02496 8.34226 8.34223 9.02499 7.50005 9.02499C6.65786 9.02499 5.97513 8.34226 5.97513 7.50008C5.97513 6.65789 6.65786 5.97516 7.50005 5.97516C8.34223 5.97516 9.02496 6.65789 9.02496 7.50008ZM9.92496 7.50008C9.92496 8.83932 8.83929 9.92499 7.50005 9.92499C6.1608 9.92499 5.07513 8.83932 5.07513 7.50008C5.07513 6.16084 6.1608 5.07516 7.50005 5.07516C8.83929 5.07516 9.92496 6.16084 9.92496 7.50008Z",
6421
6422
  fill: color,
6422
6423
  fillRule: "evenodd",
6423
6424
  clipRule: "evenodd"
6424
6425
  }));
6425
6426
  });
6426
- var _excluded$2Z = ["color"];
6427
- var ListBulletIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6428
- var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$2Z);
6427
+ var _excluded$2E = ["color"];
6428
+ var InputIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6429
+ var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$2E);
6429
6430
  return React.createElement("svg", Object.assign({
6430
6431
  width: "15",
6431
6432
  height: "15",
@@ -6435,15 +6436,15 @@ var __publicField = (obj, key, value) => {
6435
6436
  }, props, {
6436
6437
  ref: forwardedRef
6437
6438
  }), React.createElement("path", {
6438
- d: "M1.5 5.25C1.91421 5.25 2.25 4.91421 2.25 4.5C2.25 4.08579 1.91421 3.75 1.5 3.75C1.08579 3.75 0.75 4.08579 0.75 4.5C0.75 4.91421 1.08579 5.25 1.5 5.25ZM4 4.5C4 4.22386 4.22386 4 4.5 4H13.5C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H4.5C4.22386 5 4 4.77614 4 4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H13.5C13.7761 8 14 7.77614 14 7.5C14 7.22386 13.7761 7 13.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H13.5C13.7761 11 14 10.7761 14 10.5C14 10.2239 13.7761 10 13.5 10H4.5ZM2.25 7.5C2.25 7.91421 1.91421 8.25 1.5 8.25C1.08579 8.25 0.75 7.91421 0.75 7.5C0.75 7.08579 1.08579 6.75 1.5 6.75C1.91421 6.75 2.25 7.08579 2.25 7.5ZM1.5 11.25C1.91421 11.25 2.25 10.9142 2.25 10.5C2.25 10.0858 1.91421 9.75 1.5 9.75C1.08579 9.75 0.75 10.0858 0.75 10.5C0.75 10.9142 1.08579 11.25 1.5 11.25Z",
6439
+ d: "M6.5 1C6.22386 1 6 1.22386 6 1.5C6 1.77614 6.22386 2 6.5 2C7.12671 2 7.45718 2.20028 7.65563 2.47812C7.8781 2.78957 8 3.28837 8 4V11C8 11.7116 7.8781 12.2104 7.65563 12.5219C7.45718 12.7997 7.12671 13 6.5 13C6.22386 13 6 13.2239 6 13.5C6 13.7761 6.22386 14 6.5 14C7.37329 14 8.04282 13.7003 8.46937 13.1031C8.47976 13.0886 8.48997 13.0739 8.5 13.0591C8.51003 13.0739 8.52024 13.0886 8.53063 13.1031C8.95718 13.7003 9.62671 14 10.5 14C10.7761 14 11 13.7761 11 13.5C11 13.2239 10.7761 13 10.5 13C9.87329 13 9.54282 12.7997 9.34437 12.5219C9.1219 12.2104 9 11.7116 9 11V4C9 3.28837 9.1219 2.78957 9.34437 2.47812C9.54282 2.20028 9.87329 2 10.5 2C10.7761 2 11 1.77614 11 1.5C11 1.22386 10.7761 1 10.5 1C9.62671 1 8.95718 1.29972 8.53063 1.89688C8.52024 1.91143 8.51003 1.92611 8.5 1.9409C8.48997 1.92611 8.47976 1.91143 8.46937 1.89688C8.04282 1.29972 7.37329 1 6.5 1ZM14 5H11V4H14C14.5523 4 15 4.44772 15 5V10C15 10.5523 14.5523 11 14 11H11V10H14V5ZM6 4V5H1L1 10H6V11H1C0.447715 11 0 10.5523 0 10V5C0 4.44772 0.447715 4 1 4H6Z",
6439
6440
  fill: color,
6440
6441
  fillRule: "evenodd",
6441
6442
  clipRule: "evenodd"
6442
6443
  }));
6443
6444
  });
6444
- var _excluded$3n = ["color"];
6445
- var Pencil1Icon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6446
- var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$3n);
6445
+ var _excluded$2Z = ["color"];
6446
+ var ListBulletIcon = /* @__PURE__ */ React.forwardRef(function(_ref, forwardedRef) {
6447
+ var _ref$color = _ref.color, color = _ref$color === void 0 ? "currentColor" : _ref$color, props = _objectWithoutPropertiesLoose(_ref, _excluded$2Z);
6447
6448
  return React.createElement("svg", Object.assign({
6448
6449
  width: "15",
6449
6450
  height: "15",
@@ -6453,7 +6454,7 @@ var __publicField = (obj, key, value) => {
6453
6454
  }, props, {
6454
6455
  ref: forwardedRef
6455
6456
  }), React.createElement("path", {
6456
- d: "M11.8536 1.14645C11.6583 0.951184 11.3417 0.951184 11.1465 1.14645L3.71455 8.57836C3.62459 8.66832 3.55263 8.77461 3.50251 8.89155L2.04044 12.303C1.9599 12.491 2.00189 12.709 2.14646 12.8536C2.29103 12.9981 2.50905 13.0401 2.69697 12.9596L6.10847 11.4975C6.2254 11.4474 6.3317 11.3754 6.42166 11.2855L13.8536 3.85355C14.0488 3.65829 14.0488 3.34171 13.8536 3.14645L11.8536 1.14645ZM4.42166 9.28547L11.5 2.20711L12.7929 3.5L5.71455 10.5784L4.21924 11.2192L3.78081 10.7808L4.42166 9.28547Z",
6457
+ d: "M1.5 5.25C1.91421 5.25 2.25 4.91421 2.25 4.5C2.25 4.08579 1.91421 3.75 1.5 3.75C1.08579 3.75 0.75 4.08579 0.75 4.5C0.75 4.91421 1.08579 5.25 1.5 5.25ZM4 4.5C4 4.22386 4.22386 4 4.5 4H13.5C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H4.5C4.22386 5 4 4.77614 4 4.5ZM4.5 7C4.22386 7 4 7.22386 4 7.5C4 7.77614 4.22386 8 4.5 8H13.5C13.7761 8 14 7.77614 14 7.5C14 7.22386 13.7761 7 13.5 7H4.5ZM4.5 10C4.22386 10 4 10.2239 4 10.5C4 10.7761 4.22386 11 4.5 11H13.5C13.7761 11 14 10.7761 14 10.5C14 10.2239 13.7761 10 13.5 10H4.5ZM2.25 7.5C2.25 7.91421 1.91421 8.25 1.5 8.25C1.08579 8.25 0.75 7.91421 0.75 7.5C0.75 7.08579 1.08579 6.75 1.5 6.75C1.91421 6.75 2.25 7.08579 2.25 7.5ZM1.5 11.25C1.91421 11.25 2.25 10.9142 2.25 10.5C2.25 10.0858 1.91421 9.75 1.5 9.75C1.08579 9.75 0.75 10.0858 0.75 10.5C0.75 10.9142 1.08579 11.25 1.5 11.25Z",
6457
6458
  fill: color,
6458
6459
  fillRule: "evenodd",
6459
6460
  clipRule: "evenodd"
@@ -6601,6 +6602,10 @@ var __publicField = (obj, key, value) => {
6601
6602
  clipRule: "evenodd"
6602
6603
  }));
6603
6604
  });
6605
+ const emptyBooleanField = {
6606
+ ...emptyBaseField,
6607
+ type: "boolean"
6608
+ };
6604
6609
  const _BooleanField = class _BooleanField extends BaseField {
6605
6610
  constructor(options) {
6606
6611
  super({ ...options, type: "boolean" });
@@ -8025,9 +8030,9 @@ var __publicField = (obj, key, value) => {
8025
8030
  Content: TabsContent
8026
8031
  });
8027
8032
  const NumberInput$1 = React.memo(function NumberInput2(props) {
8028
- const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8033
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8029
8034
  const color = blocks.useSeverityColor(severity);
8030
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8035
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8031
8036
  TextField$1.Input,
8032
8037
  {
8033
8038
  ...rest,
@@ -8041,144 +8046,6 @@ var __publicField = (obj, key, value) => {
8041
8046
  }
8042
8047
  ) }) });
8043
8048
  });
8044
- const _NumberField = class _NumberField extends BaseField {
8045
- constructor(options) {
8046
- const {
8047
- minimum = Number.MIN_SAFE_INTEGER,
8048
- maximum = Number.MAX_SAFE_INTEGER,
8049
- integers = false,
8050
- ...base
8051
- } = options;
8052
- super({ ...base, type: "number" });
8053
- __publicField(this, "minimum");
8054
- __publicField(this, "maximum");
8055
- __publicField(this, "integers");
8056
- this.minimum = minimum;
8057
- this.maximum = maximum;
8058
- this.integers = integers;
8059
- }
8060
- getValueFromChangeEvent(event) {
8061
- const number = Number.parseFloat(event.target.value);
8062
- if (Number.isNaN(number))
8063
- return "";
8064
- return number;
8065
- }
8066
- static getFieldCreationSchema() {
8067
- return [
8068
- new _NumberField({
8069
- label: "Minimum",
8070
- description: "Minimum value",
8071
- integers: true,
8072
- required: false,
8073
- identifier: "minimum",
8074
- formValidators: [this._validateMin]
8075
- }),
8076
- new _NumberField({
8077
- label: "Maximum",
8078
- description: "Maximum value",
8079
- integers: true,
8080
- required: false,
8081
- identifier: "maximum",
8082
- formValidators: [this._validateMax]
8083
- }),
8084
- new BooleanField({
8085
- label: "Integers",
8086
- description: "Whole numbers only",
8087
- required: false,
8088
- identifier: "integers"
8089
- })
8090
- ];
8091
- }
8092
- getFieldValidators() {
8093
- const validators = super.getFieldValidators();
8094
- const min = this.minimum;
8095
- const max = this.maximum;
8096
- if (typeof min === "number") {
8097
- validators.push((value) => {
8098
- if (typeof value === "number" && value < min) {
8099
- return `Must be at least ${this.minimum}.`;
8100
- }
8101
- });
8102
- }
8103
- if (typeof max === "number") {
8104
- validators.push((value) => {
8105
- if (typeof value === "number" && value > max) {
8106
- return `Must be at most ${this.maximum}.`;
8107
- }
8108
- });
8109
- }
8110
- if (this.integers) {
8111
- validators.push((value) => {
8112
- if (typeof value === "number" && !Number.isInteger(value)) {
8113
- return "Must be a whole number.";
8114
- }
8115
- });
8116
- }
8117
- return validators;
8118
- }
8119
- serialize() {
8120
- return {
8121
- ...super._serialize(),
8122
- minimum: this.minimum,
8123
- maximum: this.maximum,
8124
- integers: this.integers
8125
- };
8126
- }
8127
- static deserialize(data) {
8128
- if (data.type !== "number")
8129
- throw new Error("Type mismatch.");
8130
- return new _NumberField(data);
8131
- }
8132
- getInput(props) {
8133
- return /* @__PURE__ */ jsxRuntime.jsx(NumberInput$1, { field: this, ...props });
8134
- }
8135
- };
8136
- __publicField(_NumberField, "fieldTypeName", "Number");
8137
- __publicField(_NumberField, "fieldTypeDescription", "Allows specifying a number within a given range.");
8138
- __publicField(_NumberField, "Icon", FontFamilyIcon);
8139
- __publicField(_NumberField, "_validateMin", (value, allValues) => {
8140
- if (typeof allValues.maximum === "number" && typeof value === "number" && allValues.maximum < value) {
8141
- return "Minimum cannot be greater than minimum.";
8142
- }
8143
- return null;
8144
- });
8145
- __publicField(_NumberField, "_validateMax", (value, allValues) => {
8146
- if (typeof allValues.minimum === "number" && typeof value === "number" && allValues.minimum > value) {
8147
- return "Maximum cannot be less than minimum.";
8148
- }
8149
- return null;
8150
- });
8151
- let NumberField = _NumberField;
8152
- const DateInput = React.memo(function DateInput2(props) {
8153
- const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8154
- const color = blocks.useSeverityColor(severity);
8155
- const value = fieldProps.value ? fieldProps.value.split("T")[0] : "";
8156
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(TextField$1.Input, { ...rest, ...fieldProps, type: "date", id: inputId, color, value }) }) });
8157
- });
8158
- const _DateField = class _DateField extends BaseField {
8159
- constructor(options) {
8160
- super({ ...options, type: "date" });
8161
- __publicField(this, "onlyValidateAfterTouched", false);
8162
- }
8163
- serialize() {
8164
- return super._serialize();
8165
- }
8166
- getValueFromChangeEvent(event) {
8167
- return new Date(event.target.value).toISOString();
8168
- }
8169
- static deserialize(data) {
8170
- if (data.type !== "date")
8171
- throw new Error("Type mismatch.");
8172
- return new _DateField(data);
8173
- }
8174
- getInput(props) {
8175
- return /* @__PURE__ */ jsxRuntime.jsx(DateInput, { field: this, ...props });
8176
- }
8177
- };
8178
- __publicField(_DateField, "fieldTypeName", "Date");
8179
- __publicField(_DateField, "fieldTypeDescription", "Allows specifying a date.");
8180
- __publicField(_DateField, "Icon", CalendarIcon);
8181
- let DateField = _DateField;
8182
8049
  class StringOrTextField extends BaseField {
8183
8050
  constructor(options) {
8184
8051
  const { minLength, maxLength = 5e3, ...base } = options;
@@ -8188,31 +8055,40 @@ var __publicField = (obj, key, value) => {
8188
8055
  this.minLength = minLength ? Math.max(minLength, 0) : void 0;
8189
8056
  this.maxLength = maxLength ? Math.max(maxLength, 0) : 5e3;
8190
8057
  }
8191
- static getFieldCreationSchema() {
8058
+ static getFieldCreationSchema(parentPath = "") {
8059
+ const path = parentPath && `${parentPath}.`;
8192
8060
  return [
8193
- // min, max
8194
- new NumberField({
8195
- label: "Minimum length",
8196
- description: "Minimum number of characters",
8197
- required: false,
8198
- identifier: "minimum_length",
8199
- minimum: 0,
8200
- maximum: 100,
8201
- formValidators: [this._validateMin],
8202
- integers: true
8203
- }),
8204
- new NumberField({
8205
- label: "Maximum length",
8206
- description: "Maximum number of characters",
8207
- required: false,
8208
- identifier: "maximum_length",
8209
- minimum: 1,
8210
- maximum: 5e3,
8211
- // TODO: depends on short vs long text
8212
- formValidators: [this._validateMax],
8213
- // TODO: default: 500 (see: "Short text fields can hold up to 500 characters on a single line.")
8214
- integers: true
8215
- })
8061
+ {
8062
+ field: (
8063
+ // min, max
8064
+ new NumberField({
8065
+ label: "Minimum length",
8066
+ description: "Minimum number of characters",
8067
+ required: false,
8068
+ identifier: `${path}minimum_length`,
8069
+ minimum: 0,
8070
+ maximum: 100,
8071
+ formValidators: [this._validateMin(parentPath)],
8072
+ integers: true
8073
+ })
8074
+ ),
8075
+ showDirectly: false
8076
+ },
8077
+ {
8078
+ field: new NumberField({
8079
+ label: "Maximum length",
8080
+ description: "Maximum number of characters",
8081
+ required: false,
8082
+ identifier: `${path}maximum_length`,
8083
+ minimum: 1,
8084
+ maximum: 5e3,
8085
+ // TODO: depends on short vs long text
8086
+ formValidators: [this._validateMax(parentPath)],
8087
+ // TODO: default: 500 (see: "Short text fields can hold up to 500 characters on a single line.")
8088
+ integers: true
8089
+ }),
8090
+ showDirectly: false
8091
+ }
8216
8092
  ];
8217
8093
  }
8218
8094
  getFieldValidators() {
@@ -8247,23 +8123,24 @@ var __publicField = (obj, key, value) => {
8247
8123
  }
8248
8124
  }
8249
8125
  /**
8250
- * This function validates that the value given for "minimum length" (when creating a new field) is less than or
8126
+ * This function returns a function that validates that the value given for "minimum length" (when creating a new field) is less than or
8251
8127
  * equal to the value given for "maximum length".
8252
8128
  */
8253
- __publicField(StringOrTextField, "_validateMin", (value, allValues) => {
8254
- if (typeof allValues.maximum_length === "number" && typeof value === "number" && allValues.maximum_length < value) {
8129
+ __publicField(StringOrTextField, "_validateMin", (path) => (value, allValues) => {
8130
+ const field = valueIsFormikUserFormRevision(allValues) ? get(allValues, path) : allValues;
8131
+ if (typeof field.maximum_length === "number" && typeof value === "number" && field.maximum_length < value) {
8255
8132
  return "Minimum cannot be greater than maximum.";
8256
8133
  }
8257
8134
  return null;
8258
8135
  });
8259
8136
  /**
8260
- * This function validates that the value given for "maximum length" (when creating a new field) is greater than or
8137
+ * This function returns a function that validates that the value given for "maximum length" (when creating a new field) is greater than or
8261
8138
  * equal to the value given for "minimum length".
8262
8139
  */
8263
- __publicField(StringOrTextField, "_validateMax", (value, allValues) => {
8140
+ __publicField(StringOrTextField, "_validateMax", (path) => (value, allValues) => {
8264
8141
  if (typeof value !== "number")
8265
8142
  return null;
8266
- const { minimum_length: minimumLength } = allValues;
8143
+ const { minimum_length: minimumLength } = valueIsFormikUserFormRevision(allValues) ? get(allValues, path) : allValues;
8267
8144
  if (typeof minimumLength !== "number") {
8268
8145
  return null;
8269
8146
  }
@@ -8274,20 +8151,20 @@ var __publicField = (obj, key, value) => {
8274
8151
  });
8275
8152
  const clickableLinkContainer = "_clickableLinkContainer_1ace7_1";
8276
8153
  const TextFieldInputCopy = "_TextFieldInputCopy_1ace7_5";
8277
- const styles$3 = {
8154
+ const styles$4 = {
8278
8155
  clickableLinkContainer,
8279
8156
  TextFieldInputCopy
8280
8157
  };
8281
8158
  const StringInput = React.memo(function StringInput2(props) {
8282
- const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8159
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8283
8160
  const color = blocks.useSeverityColor(severity);
8284
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: !rest.disabled ? /* @__PURE__ */ jsxRuntime.jsx(TextField$1.Input, { ...rest, ...fieldProps, type: field.inputType, id: inputId, color }) : /* @__PURE__ */ jsxRuntime.jsxs(TextField$1.Root, { className: styles$3.clickableLinkContainer, children: [
8161
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: !rest.disabled ? /* @__PURE__ */ jsxRuntime.jsx(TextField$1.Input, { ...rest, ...fieldProps, type: field.inputType, id: inputId, color }) : /* @__PURE__ */ jsxRuntime.jsxs(TextField$1.Root, { className: styles$4.clickableLinkContainer, children: [
8285
8162
  /* @__PURE__ */ jsxRuntime.jsx(
8286
8163
  "div",
8287
8164
  {
8288
8165
  className: classNames$1(
8289
8166
  "rt-TextFieldInput rt-r-size-2 rt-variant-surface",
8290
- styles$3.TextFieldInputCopy
8167
+ styles$4.TextFieldInputCopy
8291
8168
  ),
8292
8169
  children: /* @__PURE__ */ jsxRuntime.jsx(
8293
8170
  Linkify,
@@ -8304,6 +8181,12 @@ var __publicField = (obj, key, value) => {
8304
8181
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rt-TextFieldChrome" })
8305
8182
  ] }) }) });
8306
8183
  });
8184
+ const emptyStringField = {
8185
+ ...emptyBaseField,
8186
+ type: "string",
8187
+ maximum_length: 500,
8188
+ input_type: "text"
8189
+ };
8307
8190
  const _StringField = class _StringField extends StringOrTextField {
8308
8191
  constructor(options) {
8309
8192
  const { inputType = "text", ...rest } = options;
@@ -8331,9 +8214,14 @@ var __publicField = (obj, key, value) => {
8331
8214
  __publicField(_StringField, "Icon", InputIcon);
8332
8215
  let StringField = _StringField;
8333
8216
  const TextInput = React.memo(function TextInput2(props) {
8334
- const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8335
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.TextArea, { ...rest, ...fieldProps, resize: "vertical", id: inputId, severity }) }) });
8217
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8218
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.TextArea, { ...rest, ...fieldProps, resize: "vertical", id: inputId, severity }) }) });
8336
8219
  });
8220
+ const emptyTextField = {
8221
+ ...emptyBaseField,
8222
+ type: "text",
8223
+ maximum_length: 5e3
8224
+ };
8337
8225
  const _TextField = class _TextField extends StringOrTextField {
8338
8226
  constructor(options) {
8339
8227
  const maxLength = options.maxLength ? Math.min(5e3, options.maxLength) : 5e3;
@@ -8357,8 +8245,42 @@ var __publicField = (obj, key, value) => {
8357
8245
  __publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
8358
8246
  __publicField(_TextField, "Icon", RowsIcon);
8359
8247
  let TextField = _TextField;
8248
+ const DateInput = React.memo(function DateInput2(props) {
8249
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8250
+ const color = blocks.useSeverityColor(severity);
8251
+ const value = fieldProps.value ? fieldProps.value.split("T")[0] : "";
8252
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(TextField$1.Input, { ...rest, ...fieldProps, type: "date", id: inputId, color, value }) }) });
8253
+ });
8254
+ const emptyDateField = {
8255
+ ...emptyBaseField,
8256
+ type: "date"
8257
+ };
8258
+ const _DateField = class _DateField extends BaseField {
8259
+ constructor(options) {
8260
+ super({ ...options, type: "date" });
8261
+ __publicField(this, "onlyValidateAfterTouched", false);
8262
+ }
8263
+ serialize() {
8264
+ return super._serialize();
8265
+ }
8266
+ getValueFromChangeEvent(event) {
8267
+ return new Date(event.target.value).toISOString();
8268
+ }
8269
+ static deserialize(data) {
8270
+ if (data.type !== "date")
8271
+ throw new Error("Type mismatch.");
8272
+ return new _DateField(data);
8273
+ }
8274
+ getInput(props) {
8275
+ return /* @__PURE__ */ jsxRuntime.jsx(DateInput, { field: this, ...props });
8276
+ }
8277
+ };
8278
+ __publicField(_DateField, "fieldTypeName", "Date");
8279
+ __publicField(_DateField, "fieldTypeDescription", "Allows specifying a date.");
8280
+ __publicField(_DateField, "Icon", CalendarIcon);
8281
+ let DateField = _DateField;
8360
8282
  const SelectInput = React.memo(function SelectInput2(props) {
8361
- const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8283
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8362
8284
  const { onChange, onBlur } = fieldProps;
8363
8285
  const options = React.useMemo(
8364
8286
  () => field.options.map((option) => ({ value: option.value, itemContent: option.label })),
@@ -8371,7 +8293,7 @@ var __publicField = (obj, key, value) => {
8371
8293
  },
8372
8294
  [onChange, onBlur]
8373
8295
  );
8374
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8296
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8375
8297
  blocks.Select,
8376
8298
  {
8377
8299
  items: options,
@@ -8422,11 +8344,6 @@ var __publicField = (obj, key, value) => {
8422
8344
  result.splice(destination, 0, removed);
8423
8345
  return result;
8424
8346
  }
8425
- function replace(list, index2, value) {
8426
- const result = Array.from(list);
8427
- result[index2] = value;
8428
- return result;
8429
- }
8430
8347
  function insert(list, index2, value) {
8431
8348
  const result = Array.from(list ?? []);
8432
8349
  result.splice(index2, 0, value);
@@ -8461,9 +8378,7 @@ var __publicField = (obj, key, value) => {
8461
8378
  return sections.filter((_, i) => i < index2).flatMap((field) => field.fields);
8462
8379
  };
8463
8380
  const getTakenFieldLabels = (fields) => {
8464
- return fields.flatMap(
8465
- (field) => field.type === "section" ? [...field.fields.map((f) => f.label), field.label] : field.label
8466
- ).filter((id) => id !== null);
8381
+ return fields.flatMap((field) => [...field.fields.map((f) => f.label), field.label]).filter((id) => id !== null);
8467
8382
  };
8468
8383
  const incrementFieldLabel = (label, takenLabels) => {
8469
8384
  let count = 1;
@@ -8473,16 +8388,98 @@ var __publicField = (obj, key, value) => {
8473
8388
  }
8474
8389
  return newLabel;
8475
8390
  };
8476
- const MultiStringInput = React.memo(function MultiStringInput2(props) {
8477
- const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8478
- const color = blocks.useSeverityColor(severity);
8479
- const value = React.useMemo(
8480
- () => Array.isArray(fieldProps.value) ? fieldProps.value : [],
8481
- [fieldProps.value]
8391
+ const createNewField = (parentPath, index2, initialValues2, values, setFieldValue) => {
8392
+ const { label } = initialValues2;
8393
+ const newField = {
8394
+ ...initialValues2,
8395
+ identifier: makeIdentifier(null, label)
8396
+ };
8397
+ const parent = get(values, parentPath);
8398
+ if (parent === void 0) {
8399
+ throw new Error("Parent path must point to an existing field.");
8400
+ }
8401
+ if (!Array.isArray(parent)) {
8402
+ throw new Error("Parent path must point to an array.");
8403
+ }
8404
+ const updatedFields = insert(parent, index2, newField);
8405
+ void setFieldValue(parentPath, updatedFields).then();
8406
+ };
8407
+ const createNewEmptySection = (index2, values, setFieldValue) => {
8408
+ const initialValues2 = {
8409
+ ...emptySection(),
8410
+ label: ""
8411
+ };
8412
+ createNewField("fields", index2, initialValues2, values, setFieldValue);
8413
+ };
8414
+ const useFieldReordering = () => {
8415
+ const { showError } = blocks.useToast();
8416
+ const reorderSection = React.useCallback(
8417
+ (dropState, sectionId, sectionIndex, destinationIndex, values, setFieldValue) => {
8418
+ const state = dropState[sectionId];
8419
+ if (!state)
8420
+ throw new Error("Could not find section context.");
8421
+ let dest = typeof state.conditionIndex !== "undefined" ? (
8422
+ // cannot move a section with a condition before the condition's field
8423
+ Math.max(state.conditionIndex + 1, destinationIndex)
8424
+ ) : destinationIndex;
8425
+ for (const section of Object.values(dropState)) {
8426
+ if (section.conditionIndex === sectionIndex) {
8427
+ dest = Math.min(dest, section.index - 1);
8428
+ }
8429
+ }
8430
+ if (dest !== destinationIndex) {
8431
+ showError({
8432
+ title: "Could not reorder sections",
8433
+ description: "Sections with conditions must be below the fields they reference."
8434
+ });
8435
+ return;
8436
+ }
8437
+ void setFieldValue("fields", reorder(values.fields, sectionIndex, dest));
8438
+ },
8439
+ [showError]
8482
8440
  );
8483
- const { onChange, onBlur } = fieldProps;
8484
- const droppableId = `${inputId}-droppable`;
8485
- const { disabled } = rest;
8441
+ const reorderField = React.useCallback(
8442
+ (srcSection, srcSectionIndex, srcFieldIndex, destSection, destSectionIndex, destFieldIndex, setFieldValue) => {
8443
+ var _a2;
8444
+ if (!(srcSection == null ? void 0 : srcSection.fields) || !destSection)
8445
+ throw new Error("Could not find section with fields.");
8446
+ if (srcSection.identifier === destSection.identifier) {
8447
+ void setFieldValue(
8448
+ `fields.${srcSectionIndex}.fields`,
8449
+ reorder(srcSection.fields, srcFieldIndex, destFieldIndex)
8450
+ ).then();
8451
+ } else {
8452
+ const removed = srcSection.fields[srcFieldIndex];
8453
+ if (!removed)
8454
+ throw new Error("Could not find field to reorder.");
8455
+ if (((_a2 = destSection.condition) == null ? void 0 : _a2.identifier) === removed.identifier) {
8456
+ showError({
8457
+ title: "Could not reorder field",
8458
+ description: "Field must be above the section whose condition references it."
8459
+ });
8460
+ return;
8461
+ }
8462
+ void setFieldValue(`fields.${srcSectionIndex}.fields`, remove(srcSection.fields, srcFieldIndex)).then();
8463
+ void setFieldValue(
8464
+ `fields.${destSectionIndex}.fields`,
8465
+ insert(destSection.fields, destFieldIndex, removed)
8466
+ ).then();
8467
+ }
8468
+ },
8469
+ [showError]
8470
+ );
8471
+ return { reorderSection, reorderField };
8472
+ };
8473
+ const MultiStringInput = React.memo(function MultiStringInput2(props) {
8474
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
8475
+ const color = blocks.useSeverityColor(severity);
8476
+ const value = React.useMemo(
8477
+ () => Array.isArray(fieldProps.value) ? fieldProps.value : [],
8478
+ [fieldProps.value]
8479
+ );
8480
+ const { onChange, onBlur } = fieldProps;
8481
+ const droppableId = `${inputId}-droppable`;
8482
+ const { disabled } = rest;
8486
8483
  const [intermediateValue, setIntermediateValue] = React.useState("");
8487
8484
  const [internalError, setInternalError] = React.useState("");
8488
8485
  const updatedHelpText = internalError || helpText;
@@ -8544,7 +8541,7 @@ var __publicField = (obj, key, value) => {
8544
8541
  [setValueAndTouched, value]
8545
8542
  );
8546
8543
  return /* @__PURE__ */ jsxRuntime.jsx(dnd.DragDropContext, { onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", children: [
8547
- /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: (!disabled || value.length === 0) && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", children: [
8544
+ /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: (!disabled || value.length === 0) && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", children: [
8548
8545
  /* @__PURE__ */ jsxRuntime.jsx(Box, { grow: "1", children: /* @__PURE__ */ jsxRuntime.jsx(
8549
8546
  TextField$1.Input,
8550
8547
  {
@@ -8615,6 +8612,12 @@ var __publicField = (obj, key, value) => {
8615
8612
  ] }) })
8616
8613
  ] }) });
8617
8614
  });
8615
+ const emptyMultiStringField = {
8616
+ ...emptyBaseField,
8617
+ type: "multi-string",
8618
+ minimum_length: 0,
8619
+ maximum_length: null
8620
+ };
8618
8621
  const _MultiStringField = class _MultiStringField extends BaseField {
8619
8622
  constructor(options) {
8620
8623
  const { minimum_length, maximum_length, ...rest } = options;
@@ -8689,19 +8692,28 @@ var __publicField = (obj, key, value) => {
8689
8692
  options: this.options
8690
8693
  };
8691
8694
  }
8692
- static getFieldCreationSchema() {
8695
+ static getFieldCreationSchema(parentPath = "") {
8696
+ const path = parentPath && `${parentPath}.`;
8693
8697
  return [
8694
- new MultiStringField({
8695
- label: "Options",
8696
- description: "List possible options for the user to select from.",
8697
- required: true,
8698
- identifier: "options",
8699
- minimum_length: 2,
8700
- maximum_length: 20
8701
- })
8698
+ {
8699
+ field: new MultiStringField({
8700
+ label: "Options",
8701
+ description: "List possible options for the user to select from.",
8702
+ required: true,
8703
+ identifier: `${path}options`,
8704
+ minimum_length: 2,
8705
+ maximum_length: 20
8706
+ }),
8707
+ showDirectly: true
8708
+ }
8702
8709
  ];
8703
8710
  }
8704
8711
  }
8712
+ const emptySelectField = {
8713
+ ...emptyBaseField,
8714
+ type: "select",
8715
+ options: []
8716
+ };
8705
8717
  const _SelectField = class _SelectField extends BaseSelectField {
8706
8718
  constructor(options) {
8707
8719
  super({ ...options, type: "select" });
@@ -8735,7 +8747,7 @@ var __publicField = (obj, key, value) => {
8735
8747
  return [value];
8736
8748
  };
8737
8749
  const MultiSelectInput = React.memo(function MultiSelectInput2(props) {
8738
- const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8750
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8739
8751
  const { onChange, onBlur } = fieldProps;
8740
8752
  const value = React.useMemo(() => parseValueToArray(fieldProps.value), [fieldProps.value]);
8741
8753
  const handleChange = React.useCallback(
@@ -8745,7 +8757,7 @@ var __publicField = (obj, key, value) => {
8745
8757
  },
8746
8758
  [onChange, onBlur]
8747
8759
  );
8748
- return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8760
+ return /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsxRuntime.jsx(InputWithLabel, { size, severity, inputId, labelId, label, children: /* @__PURE__ */ jsxRuntime.jsx(
8749
8761
  blocks.MultiSelect,
8750
8762
  {
8751
8763
  value,
@@ -8759,6 +8771,11 @@ var __publicField = (obj, key, value) => {
8759
8771
  }
8760
8772
  ) }) });
8761
8773
  });
8774
+ const emptyMultiSelectField = {
8775
+ ...emptyBaseField,
8776
+ type: "multi-select",
8777
+ options: []
8778
+ };
8762
8779
  const _MultiSelectField = class _MultiSelectField extends BaseSelectField {
8763
8780
  constructor(options) {
8764
8781
  super({ ...options, type: "multi-select" });
@@ -8787,16 +8804,10 @@ var __publicField = (obj, key, value) => {
8787
8804
  __publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
8788
8805
  __publicField(_MultiSelectField, "Icon", CheckboxIcon);
8789
8806
  let MultiSelectField = _MultiSelectField;
8790
- const FieldInputCloner = React.memo(function FieldInputCloner2({ field, ...props }) {
8791
- const [{ value: identifier }] = formik.useField(field.options.clonedFieldIdentifier);
8792
- const deserializedField = React.useMemo(() => {
8793
- const options = field.options.getFieldToClone(identifier);
8794
- if (!options)
8795
- return null;
8796
- return deserialize(options);
8797
- }, [field.options, identifier]);
8798
- return useFieldInput(deserializedField, props);
8799
- });
8807
+ const emptyCustomField = {
8808
+ ...emptyBaseField,
8809
+ type: "custom"
8810
+ };
8800
8811
  class CustomField extends BaseField {
8801
8812
  constructor(options, Component) {
8802
8813
  super({ ...options, type: "custom" });
@@ -8816,13 +8827,8 @@ var __publicField = (obj, key, value) => {
8816
8827
  }
8817
8828
  __publicField(CustomField, "fieldTypeName", "Custom");
8818
8829
  __publicField(CustomField, "fieldTypeDescription", "Allows re-rendering of field already in the form");
8819
- class FieldInputClonerField extends CustomField {
8820
- constructor(options) {
8821
- super(options, FieldInputCloner);
8822
- }
8823
- }
8824
8830
  const previewImage = "_previewImage_1ig84_1";
8825
- const styles$2 = {
8831
+ const styles$3 = {
8826
8832
  previewImage
8827
8833
  };
8828
8834
  const convertBytesToLargestUnit = (bytes) => {
@@ -8843,7 +8849,7 @@ var __publicField = (obj, key, value) => {
8843
8849
  };
8844
8850
  const NumberInput = React.memo(function NumberInput2(props) {
8845
8851
  var _a2;
8846
- const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8852
+ const [{ inputId, labelId, size, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
8847
8853
  const { onChange } = fieldProps;
8848
8854
  const color = blocks.useSeverityColor(severity);
8849
8855
  const input = React.useRef(null);
@@ -8873,7 +8879,7 @@ var __publicField = (obj, key, value) => {
8873
8879
  const singleButtonText = value ? "Select new file" : "Select a file";
8874
8880
  const buttonText = field.maxFiles > 1 ? multipleButtonText : singleButtonText;
8875
8881
  return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", children: [
8876
- /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsxRuntime.jsxs(InputWithLabel, { severity, inputId, labelId, label, children: [
8882
+ /* @__PURE__ */ jsxRuntime.jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsxRuntime.jsxs(InputWithLabel, { size, severity, inputId, labelId, label, children: [
8877
8883
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "row", gap: "2", children: /* @__PURE__ */ jsxRuntime.jsx(Box, { width: "max-content", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Button, { ...rest, onClick: handleClick, children: [
8878
8884
  /* @__PURE__ */ jsxRuntime.jsx(UploadIcon, {}),
8879
8885
  " ",
@@ -8954,9 +8960,16 @@ var __publicField = (obj, key, value) => {
8954
8960
  error && /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "1", severity: "danger", children: error })
8955
8961
  ] })
8956
8962
  ] }),
8957
- url && /* @__PURE__ */ jsxRuntime.jsx("img", { className: styles$2.previewImage, src: url, alt: name })
8963
+ url && /* @__PURE__ */ jsxRuntime.jsx("img", { className: styles$3.previewImage, src: url, alt: name })
8958
8964
  ] }) });
8959
8965
  });
8966
+ const emptyUploadField = {
8967
+ ...emptyBaseField,
8968
+ type: "upload",
8969
+ extensions: [],
8970
+ maximum_size: void 0,
8971
+ maximum_files: 1
8972
+ };
8960
8973
  const largestSupportedSize = 50;
8961
8974
  const _UploadField = class _UploadField extends BaseField {
8962
8975
  constructor(options) {
@@ -8976,55 +8989,65 @@ var __publicField = (obj, key, value) => {
8976
8989
  isBlank(value) {
8977
8990
  return super.isBlank(value) || value.length === 0;
8978
8991
  }
8979
- static getFieldCreationSchema() {
8992
+ static getFieldCreationSchema(parentPath = "") {
8993
+ const path = parentPath && `${parentPath}.`;
8980
8994
  return [
8981
- new NumberField({
8982
- label: "How many files can be uploaded?",
8983
- description: "By default, only one file can be uploaded.",
8984
- required: false,
8985
- minimum: 1,
8986
- maximum: 10,
8987
- identifier: "maximum_files",
8988
- integers: true
8989
- }),
8990
- new NumberField({
8991
- // TODO: Default value
8992
- label: "What is the maximum size of each file?",
8993
- description: `Maximum file size in megabytes (between 1MB–${largestSupportedSize}MB).`,
8994
- required: false,
8995
- identifier: "maximum_size",
8996
- minimum: 1,
8997
- maximum: largestSupportedSize,
8998
- integers: true
8999
- }),
9000
- new MultiSelectField({
9001
- label: "Accepted file types",
9002
- description: "Types of allowed files to upload. If left blank, all files will be accepted.",
9003
- required: false,
9004
- identifier: "extensions",
9005
- options: [
9006
- {
9007
- value: "image/*",
9008
- label: "Images"
9009
- },
9010
- {
9011
- value: "audio/*",
9012
- label: "Audio files"
9013
- },
9014
- {
9015
- value: "video/*",
9016
- label: "Videos"
9017
- },
9018
- {
9019
- value: "text/*",
9020
- label: "Text files"
9021
- },
9022
- {
9023
- value: "application/*",
9024
- label: "Application files (includes PDFs and Word documents)"
9025
- }
9026
- ]
9027
- })
8995
+ {
8996
+ field: new NumberField({
8997
+ label: "How many files can be uploaded?",
8998
+ description: "By default, only one file can be uploaded.",
8999
+ required: false,
9000
+ minimum: 1,
9001
+ maximum: 10,
9002
+ identifier: `${path}maximum_files`,
9003
+ integers: true
9004
+ }),
9005
+ showDirectly: false
9006
+ },
9007
+ {
9008
+ field: new NumberField({
9009
+ // TODO: Default value
9010
+ label: "What is the maximum size of each file?",
9011
+ description: `Maximum file size in megabytes (between 1MB–${largestSupportedSize}MB).`,
9012
+ required: false,
9013
+ identifier: `${path}maximum_size`,
9014
+ minimum: 1,
9015
+ maximum: largestSupportedSize,
9016
+ integers: true
9017
+ }),
9018
+ showDirectly: false
9019
+ },
9020
+ {
9021
+ field: new MultiSelectField({
9022
+ label: "Accepted file types",
9023
+ description: "Types of allowed files to upload. If left blank, all files will be accepted.",
9024
+ required: false,
9025
+ identifier: `${path}extensions`,
9026
+ options: [
9027
+ {
9028
+ value: "image/*",
9029
+ label: "Images"
9030
+ },
9031
+ {
9032
+ value: "audio/*",
9033
+ label: "Audio files"
9034
+ },
9035
+ {
9036
+ value: "video/*",
9037
+ label: "Videos"
9038
+ },
9039
+ {
9040
+ value: "text/*",
9041
+ label: "Text files"
9042
+ },
9043
+ {
9044
+ value: "application/*",
9045
+ label: "Application files (includes PDFs and Word documents)"
9046
+ }
9047
+ ]
9048
+ }),
9049
+ showDirectly: false
9050
+ }
9028
9051
  ];
9029
9052
  }
9030
9053
  getFieldValidators() {
@@ -9078,44 +9101,33 @@ var __publicField = (obj, key, value) => {
9078
9101
  "multi-string": MultiStringField,
9079
9102
  "multi-select": MultiSelectField
9080
9103
  };
9081
- const deserializeField = (serializedField) => {
9082
- const fieldType = serializedField.type;
9083
- const fieldCls = FieldTypeToClsMapping[fieldType];
9084
- return fieldCls.deserialize(serializedField);
9085
- };
9086
- const deserialize = (serialized) => {
9087
- if (serialized.type === "section") {
9088
- return FieldSection.deserialize(serialized);
9089
- }
9090
- return deserializeField(serialized);
9104
+ const FieldTypeToEmptyFieldMapping = {
9105
+ date: emptyDateField,
9106
+ number: emptyNumberField,
9107
+ boolean: emptyBooleanField,
9108
+ select: emptySelectField,
9109
+ string: emptyStringField,
9110
+ text: emptyTextField,
9111
+ custom: emptyCustomField,
9112
+ upload: emptyUploadField,
9113
+ // TODO: Underscore
9114
+ "multi-string": emptyMultiStringField,
9115
+ "multi-select": emptyMultiSelectField
9091
9116
  };
9092
- function formRevisionToSchema(formRevision, meta = {}) {
9093
- const { readonly = false } = meta;
9094
- return {
9095
- title: formRevision.title,
9096
- description: formRevision.description,
9097
- fields: formRevision.fields.map((serializedField) => deserialize(serializedField)),
9098
- meta: { readonly }
9099
- };
9100
- }
9101
- function valueIsFile(v) {
9102
- return Array.isArray(v) && v.some((v2) => v2 instanceof File || v2 instanceof Promise);
9103
- }
9104
- function isConditionMet(condition, value) {
9105
- if (!condition)
9106
- return true;
9107
- if (valueIsFile(value) || valueIsFile(condition.value))
9108
- throw new Error("Conditions do not support file uploads");
9109
- const valueAsPrimitive = Array.isArray(value) ? value.map((v) => typeof v === "string" ? v : v.value) : value;
9110
- const valueToCompare = Array.isArray(condition.value) ? condition.value.map((v) => typeof v === "string" ? v : v.value) : condition.value;
9111
- if (Array.isArray(valueToCompare) && Array.isArray(valueAsPrimitive)) {
9112
- for (const v of valueToCompare) {
9113
- if (!valueAsPrimitive.includes(v))
9114
- return false;
9115
- }
9116
- return true;
9117
+ const FieldInputCloner = React.memo(function FieldInputCloner2({ field, ...props }) {
9118
+ const [{ value: identifier }] = formik.useField(field.options.clonedFieldIdentifier);
9119
+ const deserializedField = React.useMemo(() => {
9120
+ const options = field.options.getFieldToClone(identifier);
9121
+ if (!options)
9122
+ return null;
9123
+ return deserialize(options);
9124
+ }, [field.options, identifier]);
9125
+ return useFieldInput(deserializedField, props);
9126
+ });
9127
+ class FieldInputClonerField extends CustomField {
9128
+ constructor(options) {
9129
+ super(options, FieldInputCloner);
9117
9130
  }
9118
- return valueToCompare === value;
9119
9131
  }
9120
9132
  const useFieldInput = (field, props) => {
9121
9133
  return React.useMemo(() => {
@@ -9158,7 +9170,7 @@ var __publicField = (obj, key, value) => {
9158
9170
  return /* @__PURE__ */ jsxRuntime.jsx(Card, { children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "3", children: [
9159
9171
  /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", children: [
9160
9172
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { as: "h3", size: "3", children: label }),
9161
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { className: styles$4.description, children: description2 })
9173
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { className: styles$5.description, children: description2 })
9162
9174
  ] }),
9163
9175
  inputs
9164
9176
  ] }) });
@@ -9177,85 +9189,89 @@ var __publicField = (obj, key, value) => {
9177
9189
  this.condition = null;
9178
9190
  }
9179
9191
  }
9180
- static getFieldCreationSchema(options) {
9192
+ static getFieldCreationSchema(options, parentPath) {
9181
9193
  if (options.length === 0)
9182
9194
  return [];
9195
+ const path = parentPath ? `${parentPath}.` : "";
9183
9196
  return [
9184
- new BooleanField({
9185
- label: "Conditional",
9186
- description: "Conditionally show or hide this section.",
9187
- identifier: "conditional",
9188
- required: false
9189
- }),
9190
- // Declare a section that will hold options for the condition (if any).
9191
- new _FieldSection({
9192
- label: "Conditional settings",
9193
- identifier: "conditional-settings",
9194
- // This section will only be rendered if the above "Conditional" field is checked.
9195
- condition: {
9196
- identifier: "conditional",
9197
- value: true
9198
- },
9199
- // These are the options of the condition.
9200
- fields: [
9201
- // Declare a select field that will be used to select the field against which we will check the
9202
- // condition. This must be selected before the next field is rendered.
9203
- new SelectField({
9204
- label: "Field",
9205
- description: "The field to use for the condition.",
9206
- // The options (for the field against which we will check the condition) are all the labels of
9207
- // the fields in the previous section(s) (or fields declared before with no section) that
9208
- // support conditions. We pass in both the label and the identifier of each supported field. The
9209
- // identifier becomes the value of the option.
9210
- options: options.map((option) => {
9211
- if (!option.label)
9212
- return null;
9213
- if (option.type === "upload")
9214
- return null;
9215
- return {
9216
- label: option.label,
9217
- value: option.identifier
9218
- };
9219
- }).filter((option) => !!option),
9220
- identifier: "condition.identifier",
9221
- required: true
9222
- }),
9223
- // Declare a custom field that will be used to input a value for the condition. The value of the
9224
- // conditional field selected in the previous step must be equal to the value the user inputs into
9225
- // this field for the section to be rendered.
9226
- new FieldInputClonerField({
9227
- label: "Value",
9228
- identifier: "condition.value",
9229
- required: true,
9230
- clonedFieldIdentifier: "condition.identifier",
9231
- getFieldToClone(identifier) {
9232
- if (!identifier) {
9233
- return null;
9234
- }
9235
- const option = options.find((option2) => option2.identifier === identifier);
9236
- if (!option) {
9237
- console.error("Could not find field with identifier", identifier);
9238
- return null;
9197
+ {
9198
+ field: new BooleanField({
9199
+ label: "Conditionally render section",
9200
+ identifier: `${path}conditional`,
9201
+ required: false
9202
+ }),
9203
+ showDirectly: true
9204
+ },
9205
+ {
9206
+ // Declare a section that will hold options for the condition (if any).
9207
+ field: new _FieldSection({
9208
+ label: "Conditional settings",
9209
+ identifier: `${path}conditional-settings`,
9210
+ // This section will only be rendered if the above "Conditional" field is checked.
9211
+ condition: {
9212
+ identifier: `${path}conditional`,
9213
+ value: true
9214
+ },
9215
+ // These are the options of the condition.
9216
+ fields: [
9217
+ // Declare a select field that will be used to select the field against which we will check the
9218
+ // condition. This must be selected before the next field is rendered.
9219
+ new SelectField({
9220
+ label: "Field",
9221
+ description: "The field to use for the condition.",
9222
+ // The options (for the field against which we will check the condition) are all the labels of
9223
+ // the fields in the previous section(s) (or fields declared before with no section) that
9224
+ // support conditions. We pass in both the label and the identifier of each supported field. The
9225
+ // identifier becomes the value of the option.
9226
+ options: options.map((option) => {
9227
+ if (!option.label)
9228
+ return null;
9229
+ if (option.type === "upload")
9230
+ return null;
9231
+ return {
9232
+ label: option.label,
9233
+ value: option.identifier
9234
+ };
9235
+ }).filter((option) => !!option),
9236
+ identifier: `${path}condition.identifier`,
9237
+ required: true
9238
+ }),
9239
+ // Declare a custom field that will be used to input a value for the condition. The value of the
9240
+ // conditional field selected in the previous step must be equal to the value the user inputs into
9241
+ // this field for the section to be rendered.
9242
+ new FieldInputClonerField({
9243
+ label: "Value",
9244
+ identifier: `${path}condition.value`,
9245
+ required: true,
9246
+ clonedFieldIdentifier: `${path}condition.identifier`,
9247
+ getFieldToClone(identifier) {
9248
+ if (!identifier) {
9249
+ return null;
9250
+ }
9251
+ const option = options.find((option2) => option2.identifier === identifier);
9252
+ if (!option) {
9253
+ console.error("Could not find field with identifier", identifier);
9254
+ return null;
9255
+ }
9256
+ return {
9257
+ ...option,
9258
+ // Override some options to make it make sense in the context and to make it work with the framework.
9259
+ label: "Value",
9260
+ identifier: `${path}condition.value`,
9261
+ description: "The value to compare against.",
9262
+ required: option.type !== "boolean"
9263
+ };
9239
9264
  }
9240
- return {
9241
- ...option,
9242
- // Override some options to make it make sense in the context and to make it work with the framework.
9243
- label: "Value",
9244
- identifier: "condition.value",
9245
- description: "The value to compare against.",
9246
- required: option.type !== "boolean"
9247
- };
9248
- }
9249
- })
9250
- ]
9251
- })
9265
+ })
9266
+ ]
9267
+ }),
9268
+ showDirectly: false
9269
+ }
9252
9270
  ];
9253
9271
  }
9254
9272
  static deserialize(data) {
9255
9273
  if (data.type !== "section")
9256
9274
  throw new Error("Invalid type");
9257
- if (!Array.isArray(data.fields))
9258
- throw new Error(`Invalid fields: ${data.fields} (not an array)`);
9259
9275
  const fields = data.fields.map(deserializeField);
9260
9276
  return new _FieldSection({ ...data, fields });
9261
9277
  }
@@ -9289,89 +9305,258 @@ var __publicField = (obj, key, value) => {
9289
9305
  __publicField(_FieldSection, "fieldTypeName", "Section");
9290
9306
  __publicField(_FieldSection, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
9291
9307
  let FieldSection = _FieldSection;
9292
- const hasKeys = (errors) => {
9293
- return Object.keys(errors).length > 0;
9308
+ const deserializeField = (serializedField) => {
9309
+ const fieldType = serializedField.type;
9310
+ const fieldCls = FieldTypeToClsMapping[fieldType];
9311
+ return fieldCls.deserialize(serializedField);
9294
9312
  };
9295
- const validateForm = (schema, form) => {
9296
- const errors = {};
9297
- for (const field of schema.fields) {
9298
- if (field instanceof FieldSection) {
9299
- if (field.condition) {
9300
- const { identifier } = field.condition;
9301
- if (!isConditionMet(field.condition, get(form, identifier))) {
9302
- continue;
9303
- }
9304
- }
9305
- Object.assign(errors, field.getErrors(form));
9306
- } else {
9307
- if (!(field instanceof BaseField)) {
9308
- throw new Error("Invalid field type");
9309
- }
9310
- const id = field.getId();
9311
- const error = field.getError(get(form, id), form);
9312
- if (error)
9313
- set(errors, id, error);
9314
- }
9313
+ const deserialize = (serialized) => {
9314
+ if (serialized.type === "section") {
9315
+ return FieldSection.deserialize(serialized);
9315
9316
  }
9316
- if (hasKeys(errors))
9317
- return errors;
9317
+ return deserializeField(serialized);
9318
9318
  };
9319
- const uncontrolledValues = [null, void 0];
9320
- const initialFormValues = (fields, values) => {
9321
- return fields.reduce(
9322
- (acc, field) => {
9323
- if (field instanceof FieldSection) {
9324
- return { ...acc, ...initialFormValues(field.fields, values) };
9325
- }
9326
- if (uncontrolledValues.includes(get(acc, field.getId()))) {
9327
- set(acc, field.getId(), "");
9328
- }
9329
- return acc;
9330
- },
9331
- // TODO: Had to do this because of this error:
9332
- // > Uncaught TypeError: can't define property "description":
9333
- // > Object is not extensible"
9334
- // This means that we can't mutate `acc` because it's frozen for some
9335
- // unknown reason.
9336
- cloneDeep(values)
9337
- );
9319
+ function formRevisionToSchema(formRevision, meta = {}) {
9320
+ const { readonly = false } = meta;
9321
+ return {
9322
+ title: formRevision.title,
9323
+ description: formRevision.description,
9324
+ fields: formRevision.fields.map((serializedField) => deserialize(serializedField)),
9325
+ meta: { readonly }
9326
+ };
9327
+ }
9328
+ function valueIsFile(v) {
9329
+ return Array.isArray(v) && v.some((v2) => v2 instanceof File || v2 instanceof Promise);
9330
+ }
9331
+ const valueIsFormikUserFormRevision = (form) => {
9332
+ return "fields" in form;
9338
9333
  };
9339
- const defaultHandleSubmit = () => {
9340
- throw new Error("onSubmit must be provided if form is not readonly.");
9334
+ function isConditionMet(condition, value) {
9335
+ if (!condition)
9336
+ return true;
9337
+ if (valueIsFile(value) || valueIsFile(condition.value))
9338
+ throw new Error("Conditions do not support file uploads");
9339
+ const valueAsPrimitive = Array.isArray(value) ? value.map((v) => typeof v === "string" ? v : v.value) : value;
9340
+ const valueToCompare = Array.isArray(condition.value) ? condition.value.map((v) => typeof v === "string" ? v : v.value) : condition.value;
9341
+ if (Array.isArray(valueToCompare) && Array.isArray(valueAsPrimitive)) {
9342
+ for (const v of valueToCompare) {
9343
+ if (!valueAsPrimitive.includes(v))
9344
+ return false;
9345
+ }
9346
+ return true;
9347
+ }
9348
+ return valueToCompare === value;
9349
+ }
9350
+ const emptyNumberField = {
9351
+ ...emptyBaseField,
9352
+ type: "number",
9353
+ minimum: Number.MIN_SAFE_INTEGER,
9354
+ maximum: Number.MAX_SAFE_INTEGER,
9355
+ integers: false
9341
9356
  };
9342
- const FormRenderer = React.memo(
9343
- React.forwardRef((props, ref) => {
9357
+ const _NumberField = class _NumberField extends BaseField {
9358
+ constructor(options) {
9344
9359
  const {
9345
- schema,
9346
- values = {},
9347
- onSubmit = defaultHandleSubmit,
9348
- submitText = "Submit",
9349
- cancelText,
9350
- onCancel,
9351
- onDirty,
9352
- onDirtyChange,
9353
- // if the title isn't provided, hide it by default
9354
- hideTitle = !schema.title,
9355
- hideDescription,
9356
- className
9357
- } = props;
9358
- const { readonly } = schema.meta;
9359
- const formId2 = React.useMemo(() => crypto.randomUUID(), []);
9360
- const formik$1 = formik.useFormik({
9361
- initialValues: initialFormValues(schema.fields, values),
9362
- onSubmit,
9363
- validate: (form) => validateForm(schema, form),
9364
- // only validate the entire form on submit
9365
- validateOnBlur: false,
9366
- validateOnChange: false
9367
- });
9360
+ minimum = Number.MIN_SAFE_INTEGER,
9361
+ maximum = Number.MAX_SAFE_INTEGER,
9362
+ integers = false,
9363
+ ...base
9364
+ } = options;
9365
+ super({ ...base, type: "number" });
9366
+ __publicField(this, "minimum");
9367
+ __publicField(this, "maximum");
9368
+ __publicField(this, "integers");
9369
+ this.minimum = minimum;
9370
+ this.maximum = maximum;
9371
+ this.integers = integers;
9372
+ }
9373
+ getValueFromChangeEvent(event) {
9374
+ const number = Number.parseFloat(event.target.value);
9375
+ if (Number.isNaN(number))
9376
+ return "";
9377
+ return number;
9378
+ }
9379
+ static getFieldCreationSchema(parentPath = "") {
9380
+ const path = parentPath && `${parentPath}.`;
9381
+ return [
9382
+ {
9383
+ field: new _NumberField({
9384
+ label: "Minimum",
9385
+ description: "Minimum value",
9386
+ integers: true,
9387
+ required: false,
9388
+ identifier: `${path}minimum`,
9389
+ formValidators: [this._validateMin(parentPath)]
9390
+ }),
9391
+ showDirectly: false
9392
+ },
9393
+ {
9394
+ field: new _NumberField({
9395
+ label: "Maximum",
9396
+ description: "Maximum value",
9397
+ integers: true,
9398
+ required: false,
9399
+ identifier: `${path}maximum`,
9400
+ formValidators: [this._validateMax(parentPath)]
9401
+ }),
9402
+ showDirectly: false
9403
+ },
9404
+ {
9405
+ field: new BooleanField({
9406
+ label: "Integers",
9407
+ description: "Whole numbers only",
9408
+ required: false,
9409
+ identifier: `${path}integers`
9410
+ }),
9411
+ showDirectly: false
9412
+ }
9413
+ ];
9414
+ }
9415
+ getFieldValidators() {
9416
+ const validators = super.getFieldValidators();
9417
+ const min = this.minimum;
9418
+ const max = this.maximum;
9419
+ if (typeof min === "number") {
9420
+ validators.push((value) => {
9421
+ if (typeof value === "number" && value < min) {
9422
+ return `Must be at least ${this.minimum}.`;
9423
+ }
9424
+ });
9425
+ }
9426
+ if (typeof max === "number") {
9427
+ validators.push((value) => {
9428
+ if (typeof value === "number" && value > max) {
9429
+ return `Must be at most ${this.maximum}.`;
9430
+ }
9431
+ });
9432
+ }
9433
+ if (this.integers) {
9434
+ validators.push((value) => {
9435
+ if (typeof value === "number" && !Number.isInteger(value)) {
9436
+ return "Must be a whole number.";
9437
+ }
9438
+ });
9439
+ }
9440
+ return validators;
9441
+ }
9442
+ serialize() {
9443
+ return {
9444
+ ...super._serialize(),
9445
+ minimum: this.minimum,
9446
+ maximum: this.maximum,
9447
+ integers: this.integers
9448
+ };
9449
+ }
9450
+ static deserialize(data) {
9451
+ if (data.type !== "number")
9452
+ throw new Error("Type mismatch.");
9453
+ return new _NumberField(data);
9454
+ }
9455
+ getInput(props) {
9456
+ return /* @__PURE__ */ jsxRuntime.jsx(NumberInput$1, { field: this, ...props });
9457
+ }
9458
+ };
9459
+ __publicField(_NumberField, "fieldTypeName", "Number");
9460
+ __publicField(_NumberField, "fieldTypeDescription", "Allows specifying a number within a given range.");
9461
+ __publicField(_NumberField, "Icon", FontFamilyIcon);
9462
+ __publicField(_NumberField, "_validateMin", (path) => (value, allValues) => {
9463
+ const field = valueIsFormikUserFormRevision(allValues) ? get(allValues, path) : allValues;
9464
+ if (typeof field.maximum === "number" && typeof value === "number" && field.maximum < value) {
9465
+ return "Minimum cannot be greater than minimum.";
9466
+ }
9467
+ return null;
9468
+ });
9469
+ __publicField(_NumberField, "_validateMax", (path) => (value, allValues) => {
9470
+ const field = valueIsFormikUserFormRevision(allValues) ? get(allValues, path) : allValues;
9471
+ if (typeof field.minimum === "number" && typeof value === "number" && field.minimum > value) {
9472
+ return "Maximum cannot be less than minimum.";
9473
+ }
9474
+ return null;
9475
+ });
9476
+ let NumberField = _NumberField;
9477
+ const hasKeys = (errors) => {
9478
+ return Object.keys(errors).length > 0;
9479
+ };
9480
+ const validateForm = (schema, form) => {
9481
+ const errors = {};
9482
+ for (const field of schema.fields) {
9483
+ if (field instanceof FieldSection) {
9484
+ if (field.condition) {
9485
+ const { identifier } = field.condition;
9486
+ if (!isConditionMet(field.condition, get(form, identifier))) {
9487
+ continue;
9488
+ }
9489
+ }
9490
+ Object.assign(errors, field.getErrors(form));
9491
+ } else {
9492
+ if (!(field instanceof BaseField)) {
9493
+ throw new Error("Invalid field type");
9494
+ }
9495
+ const id = field.getId();
9496
+ const error = field.getError(get(form, id), form);
9497
+ if (error)
9498
+ set(errors, id, error);
9499
+ }
9500
+ }
9501
+ if (hasKeys(errors))
9502
+ return errors;
9503
+ };
9504
+ const uncontrolledValues = [null, void 0];
9505
+ const initialFormValues = (fields, values) => {
9506
+ return fields.reduce(
9507
+ (acc, field) => {
9508
+ if (field instanceof FieldSection) {
9509
+ return { ...acc, ...initialFormValues(field.fields, values) };
9510
+ }
9511
+ if (uncontrolledValues.includes(get(acc, field.getId()))) {
9512
+ set(acc, field.getId(), "");
9513
+ }
9514
+ return acc;
9515
+ },
9516
+ // TODO: Had to do this because of this error:
9517
+ // > Uncaught TypeError: can't define property "description":
9518
+ // > Object is not extensible"
9519
+ // This means that we can't mutate `acc` because it's frozen for some
9520
+ // unknown reason.
9521
+ cloneDeep(values)
9522
+ );
9523
+ };
9524
+ const defaultHandleSubmit = () => {
9525
+ throw new Error("onSubmit must be provided if form is not readonly.");
9526
+ };
9527
+ const FormRenderer = React.memo(
9528
+ React.forwardRef((props, ref) => {
9529
+ const {
9530
+ schema,
9531
+ values = {},
9532
+ onSubmit = defaultHandleSubmit,
9533
+ submitText = "Submit",
9534
+ cancelText,
9535
+ onCancel,
9536
+ onDirty,
9537
+ onDirtyChange,
9538
+ // if the title isn't provided, hide it by default
9539
+ hideTitle = !schema.title,
9540
+ hideDescription,
9541
+ className
9542
+ } = props;
9543
+ const { readonly } = schema.meta;
9544
+ const formId2 = React.useMemo(() => crypto.randomUUID(), []);
9545
+ const formik$1 = formik.useFormik({
9546
+ initialValues: initialFormValues(schema.fields, values),
9547
+ onSubmit,
9548
+ validate: (form) => validateForm(schema, form),
9549
+ // only validate the entire form on submit
9550
+ validateOnBlur: false,
9551
+ validateOnChange: false
9552
+ });
9368
9553
  const { dirty } = formik$1;
9369
9554
  const Title = React.useMemo(
9370
9555
  () => typeof schema.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Heading, { children: schema.title }) : schema.title,
9371
9556
  [schema.title]
9372
9557
  );
9373
9558
  const Description = React.useMemo(
9374
- () => typeof schema.description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { className: styles$4.description, children: schema.description }) : schema.description,
9559
+ () => typeof schema.description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { className: styles$5.description, children: schema.description }) : schema.description,
9375
9560
  [schema.description]
9376
9561
  );
9377
9562
  const inputs = useFieldInputs(schema.fields, { formId: formId2, disabled: readonly });
@@ -9387,10 +9572,23 @@ var __publicField = (obj, key, value) => {
9387
9572
  !hideDescription && Description
9388
9573
  ] }) }),
9389
9574
  inputs,
9390
- !readonly && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { justify: "end", gap: "2", children: [
9391
- cancelText && /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "soft", onClick: onCancel, children: cancelText }),
9392
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", disabled: !formik$1.isValid, children: submitText })
9393
- ] })
9575
+ !readonly && /* @__PURE__ */ jsxRuntime.jsxs(
9576
+ blocks.Flex,
9577
+ {
9578
+ justify: "end",
9579
+ gap: "2",
9580
+ align: "center",
9581
+ style: {
9582
+ position: "sticky",
9583
+ bottom: "0px",
9584
+ paddingBottom: "10px"
9585
+ },
9586
+ children: [
9587
+ cancelText && /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "soft", onClick: onCancel, children: cancelText }),
9588
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", disabled: !formik$1.isValid, children: submitText })
9589
+ ]
9590
+ }
9591
+ )
9394
9592
  ] }) }) });
9395
9593
  })
9396
9594
  );
@@ -9435,7 +9633,7 @@ var __publicField = (obj, key, value) => {
9435
9633
  );
9436
9634
  const favoriteIcon = "_favoriteIcon_1bixi_1";
9437
9635
  const regularIcon = "_regularIcon_1bixi_9";
9438
- const styles$1 = {
9636
+ const styles$2 = {
9439
9637
  favoriteIcon,
9440
9638
  regularIcon
9441
9639
  };
@@ -9547,7 +9745,7 @@ var __publicField = (obj, key, value) => {
9547
9745
  /* @__PURE__ */ jsxRuntime.jsx(
9548
9746
  blocks.IconButton,
9549
9747
  {
9550
- className: classNames$1(form.favorite ? styles$1.favoriteIcon : styles$1.regularIcon),
9748
+ className: classNames$1(form.favorite ? styles$2.favoriteIcon : styles$2.regularIcon),
9551
9749
  variant: "ghost",
9552
9750
  onClick: handleFavoriteClick,
9553
9751
  "aria-label": form.favorite ? "Favorite form" : "Standard form",
@@ -9573,7 +9771,7 @@ var __publicField = (obj, key, value) => {
9573
9771
  };
9574
9772
  const submissionsContainer = "_submissionsContainer_9iirt_1";
9575
9773
  const stopHorizontalOverflow = "_stopHorizontalOverflow_9iirt_6";
9576
- const styles = {
9774
+ const styles$1 = {
9577
9775
  submissionsContainer,
9578
9776
  stopHorizontalOverflow
9579
9777
  };
@@ -9604,7 +9802,7 @@ var __publicField = (obj, key, value) => {
9604
9802
  }
9605
9803
  }, [submission, onSubmissionClick]);
9606
9804
  const row = /* @__PURE__ */ jsxRuntime.jsx(blocks.ButtonList.Item, { onClick: handleClick, asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { grow: "1", width: "100%", p: "2", gap: "2", justify: "between", children: [
9607
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", align: "center", className: styles.stopHorizontalOverflow, children: [
9805
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", align: "center", className: styles$1.stopHorizontalOverflow, children: [
9608
9806
  /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: creatorProfileSrc, size: "1", fallback: creatorProfileFallback }),
9609
9807
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "2", noWrap: true, children: labelType === "creator" ? (createdBy || currentUser).username : revision.title })
9610
9808
  ] }),
@@ -9648,7 +9846,7 @@ var __publicField = (obj, key, value) => {
9648
9846
  return /* @__PURE__ */ jsxRuntime.jsx(
9649
9847
  blocks.ButtonList.Root,
9650
9848
  {
9651
- className: classNames$1(styles.submissionsContainer, className),
9849
+ className: classNames$1(styles$1.submissionsContainer, className),
9652
9850
  size: "small",
9653
9851
  variant,
9654
9852
  before: !compact && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Text, { severity: "info", children: [
@@ -9672,23 +9870,22 @@ var __publicField = (obj, key, value) => {
9672
9870
  );
9673
9871
  });
9674
9872
  const PatchField = React.memo((props) => {
9675
- console.log("PatchField props:", props);
9676
9873
  const { name, render } = props;
9677
9874
  const { submitForm } = formik.useFormikContext();
9678
9875
  const [fieldProps, _meta, helpers] = formik.useField(name);
9679
- const ret = React.useMemo(() => {
9876
+ return React.useMemo(() => {
9680
9877
  const setValue = (value) => {
9681
9878
  void helpers.setValue(value, false);
9682
9879
  };
9683
9880
  return render({
9684
9881
  value: fieldProps.value,
9882
+ meta: _meta,
9685
9883
  setValue,
9686
9884
  patchValue: () => {
9687
9885
  void submitForm();
9688
9886
  }
9689
9887
  });
9690
- }, [submitForm, helpers, fieldProps.value, render]);
9691
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: ret });
9888
+ }, [render, fieldProps.value, _meta, submitForm, helpers]);
9692
9889
  });
9693
9890
  PatchField.displayName = "PatchField";
9694
9891
  const PatchFormProvider = React.memo(
@@ -9737,365 +9934,437 @@ var __publicField = (obj, key, value) => {
9737
9934
  return /* @__PURE__ */ jsxRuntime.jsx(formik.FormikProvider, { value: formik$1, children: /* @__PURE__ */ jsxRuntime.jsx("form", { ...rest, ref, onSubmit: formik$1.handleSubmit, children }) });
9738
9935
  })
9739
9936
  );
9740
- const CompleteFieldTypeToClsMapping = {
9741
- ...FieldTypeToClsMapping,
9742
- section: FieldSection
9743
- };
9744
- const FieldToChoose = React.memo(function FieldToChoose2(props) {
9745
- const { field, setFieldType } = props;
9746
- const typeName = field.fieldTypeName;
9747
- const description2 = field.fieldTypeDescription;
9748
- const Icon = field.Icon;
9749
- return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "4", align: "center", children: [
9750
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "surface", onClick: setFieldType, style: { width: "135px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "3", align: "center", grow: "1", children: [
9751
- /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
9752
- typeName
9753
- ] }) }),
9754
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { children: description2 })
9755
- ] });
9756
- });
9937
+ const formId = "form-builder";
9757
9938
  const fieldsToChoose = [
9758
9939
  ["string", "text"],
9759
9940
  ["select", "multi-select", "upload"],
9760
9941
  ["boolean", "date", "number", "multi-string"]
9761
9942
  ];
9762
- const indexOfLastFieldGroup = fieldsToChoose.length - 1;
9763
- const ChooseFieldToAdd = React.memo(function ChooseFieldToAdd2(props) {
9764
- const { setFieldType } = props;
9765
- return /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", gap: "3", children: fieldsToChoose.map((fieldGroup, index2) => /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "3", children: [
9766
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", gap: "2", children: fieldGroup.map((identifier) => /* @__PURE__ */ jsxRuntime.jsx(
9767
- FieldToChoose,
9768
- {
9769
- field: FieldTypeToClsMapping[identifier],
9770
- setFieldType: () => {
9771
- setFieldType(identifier);
9772
- }
9773
- },
9774
- identifier
9775
- )) }),
9776
- index2 < indexOfLastFieldGroup && /* @__PURE__ */ jsxRuntime.jsx(blocks.Separator, { size: "4" })
9777
- ] }, index2)) });
9778
- });
9779
- const validateNewFieldName = (takenLabels) => {
9780
- return (value) => {
9781
- if (!value || typeof value !== "string")
9782
- return;
9783
- if (takenLabels.includes(value.trim())) {
9784
- return "This name is already taken.";
9785
- }
9786
- };
9787
- };
9788
- const commonFields = (takenLabels, type) => {
9789
- const base = [
9790
- new StringField({
9791
- label: "Label",
9792
- required: true,
9793
- maxLength: 200,
9794
- identifier: "label",
9795
- fieldValidators: [validateNewFieldName(takenLabels)]
9796
- }),
9797
- new TextField({
9798
- label: "Description",
9799
- required: false,
9800
- maxLength: 1e3,
9801
- identifier: "description"
9802
- })
9803
- ];
9804
- if (type === "section")
9805
- return base;
9806
- return [
9807
- ...base,
9808
- new BooleanField({ label: "Required", description: null, required: false, identifier: "required" })
9809
- ];
9943
+ const CompleteFieldTypeToClsMapping = {
9944
+ ...FieldTypeToClsMapping,
9945
+ section: FieldSection
9810
9946
  };
9811
- const FieldOptionsForm = React.memo(function FieldOptionsForm2(props) {
9812
- const { fieldType, handleCancel, handleCreateField, handleDirtyChange, defaultField, conditionalSourceFields } = props;
9813
- const fieldCls = CompleteFieldTypeToClsMapping[fieldType];
9814
- const formik$1 = formik.useFormikContext();
9815
- const schema = React.useMemo(() => {
9816
- const takenFieldLabels = getTakenFieldLabels(formik$1.values.fields).filter((id) => id !== (defaultField == null ? void 0 : defaultField.label));
9817
- let fields = commonFields(takenFieldLabels, fieldType);
9818
- if (fieldCls === FieldSection) {
9819
- if (conditionalSourceFields === void 0) {
9820
- throw new Error("Conditional source fields must be provided when changing sections.");
9821
- }
9822
- fields = fields.concat(fieldCls.getFieldCreationSchema(conditionalSourceFields));
9823
- } else {
9824
- if (!(fieldCls.prototype instanceof BaseField)) {
9825
- throw new Error(`Field must be an instance of BaseField. Got ${fieldCls.toString()}.`);
9826
- }
9827
- fields = [...fields, ...fieldCls.getFieldCreationSchema()];
9828
- }
9829
- return {
9830
- fields,
9831
- meta: { readonly: false },
9832
- // using the dialog title as the form title
9833
- title: null
9834
- };
9835
- }, [formik$1.values.fields, fieldType, fieldCls, defaultField == null ? void 0 : defaultField.label, conditionalSourceFields]);
9836
- return /* @__PURE__ */ jsxRuntime.jsx(
9837
- FormRenderer,
9838
- {
9839
- schema,
9840
- values: defaultField,
9841
- onSubmit: handleCreateField,
9842
- cancelText: defaultField ? void 0 : "Back",
9843
- onCancel: handleCancel,
9844
- onDirtyChange: handleDirtyChange
9845
- }
9846
- );
9847
- });
9848
- const FieldBuilder = React.memo(function FieldBuilder2(props) {
9849
- const { parentPath, index: index2, isOpen, setIsOpen, initial, editing, conditionalSourceFields } = props;
9850
- const [fieldType, setFieldType] = React.useState();
9851
- const [formIsDirty, setFormIsDirty] = React.useState(false);
9852
- const type = (initial == null ? void 0 : initial.type) ?? fieldType;
9853
- const typeName = type ? CompleteFieldTypeToClsMapping[type].fieldTypeName : void 0;
9854
- const { setFieldValue, values } = formik.useFormikContext();
9855
- if (editing && !initial)
9856
- throw new Error("Initial field must be provided if editing is true.");
9857
- const openConfirmDiscardChangesDialog = blocks.useDiscardAlertDialog();
9858
- const showChooseField = !type && !editing && !initial;
9859
- const title2 = showChooseField ? "Choose a field type" : `${typeName} settings`;
9860
- const description2 = showChooseField ? "Select a field type to add to this section." : (typeName == null ? void 0 : typeName.toLowerCase()) === "section" ? "Customize your section" : `Customize your ${typeName == null ? void 0 : typeName.toLowerCase()} field.`;
9861
- const handleCancel = React.useCallback(() => {
9862
- setFieldType(void 0);
9863
- setFormIsDirty(false);
9864
- }, []);
9865
- const handleCloseDialog = React.useCallback(() => {
9866
- if (!formIsDirty) {
9867
- setFieldType(void 0);
9868
- setIsOpen(false);
9869
- } else {
9870
- openConfirmDiscardChangesDialog({
9871
- onDiscard: () => {
9872
- setFieldType(void 0);
9873
- setIsOpen(false);
9874
- }
9947
+ const useFieldTypeItems = (onSelect = () => null) => {
9948
+ return React.useMemo(() => {
9949
+ return fieldsToChoose.map((fieldGroup) => {
9950
+ return fieldGroup.map((identifier) => {
9951
+ const field = FieldTypeToClsMapping[identifier];
9952
+ const Icon = field.Icon;
9953
+ return {
9954
+ content: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", gap: "2", children: [
9955
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
9956
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { children: field.fieldTypeName })
9957
+ ] }, identifier),
9958
+ value: identifier,
9959
+ onSelect: () => {
9960
+ onSelect(identifier);
9961
+ }
9962
+ };
9875
9963
  });
9876
- }
9877
- }, [formIsDirty, openConfirmDiscardChangesDialog, setIsOpen]);
9878
- const handleCreateField = React.useCallback(
9879
- (form) => {
9880
- const { label } = form;
9881
- if (!type)
9882
- throw new Error("Field type must be selected before creating a field.");
9883
- if (!label || typeof label !== "string")
9884
- throw new Error("Label must be provided before creating a field.");
9885
- const field = deserialize({
9886
- type,
9887
- ...form,
9888
- identifier: makeIdentifier(form.identifier, label)
9889
- }).serialize();
9890
- const parent = get(values, parentPath);
9891
- if (parent === void 0) {
9892
- throw new Error("Parent path must point to an existing field.");
9893
- }
9894
- let newFields;
9895
- if (!Array.isArray(parent))
9896
- throw new Error("Parent path must point to an array.");
9897
- if (editing) {
9898
- newFields = replace(parent, index2, field);
9899
- } else {
9900
- newFields = insert(parent, index2, field);
9901
- }
9902
- void setFieldValue(parentPath, newFields).then();
9903
- setIsOpen(false);
9904
- },
9905
- [type, values, parentPath, editing, setFieldValue, setIsOpen, index2]
9906
- );
9907
- const handleDirtyChange = React.useCallback((dirty) => {
9908
- setFormIsDirty(dirty);
9909
- }, []);
9910
- const dialogContent = React.useCallback(() => {
9911
- if (showChooseField) {
9912
- return /* @__PURE__ */ jsxRuntime.jsx(ChooseFieldToAdd, { setFieldType });
9913
- }
9914
- return /* @__PURE__ */ jsxRuntime.jsx(
9915
- FieldOptionsForm,
9916
- {
9917
- conditionalSourceFields,
9918
- handleCancel,
9919
- handleCreateField,
9920
- fieldType: type,
9921
- defaultField: initial,
9922
- handleDirtyChange
9923
- }
9924
- );
9925
- }, [conditionalSourceFields, handleCancel, handleCreateField, handleDirtyChange, initial, showChooseField, type]);
9926
- return /* @__PURE__ */ jsxRuntime.jsx(
9927
- blocks.Dialog,
9928
- {
9929
- title: title2,
9930
- description: description2,
9931
- content: dialogContent,
9932
- open: isOpen,
9933
- onOpenChange: handleCloseDialog
9934
- }
9935
- );
9964
+ });
9965
+ }, [onSelect]);
9966
+ };
9967
+ const FieldTypeDropdown = React.memo((props) => {
9968
+ const { setFieldType, children } = props;
9969
+ const fieldTypeItems = useFieldTypeItems(setFieldType);
9970
+ return /* @__PURE__ */ jsxRuntime.jsx(blocks.DropdownItemMenu, { trigger: children, items: fieldTypeItems.flat() });
9936
9971
  });
9972
+ FieldTypeDropdown.displayName = "FieldTypeDropdown";
9937
9973
  const forMobile = (mobile, display) => ({
9938
9974
  initial: mobile ? display : "none",
9939
9975
  sm: mobile ? "none" : display
9940
9976
  });
9941
- const FieldActions = React.memo(function FieldActions2(props) {
9942
- const { remove: remove2, dragHandleProps, editProps, insertAfterProps, duplicateProps } = props;
9943
- const [isEditDialogOpen, setIsEditDialogOpen] = React.useState(false);
9944
- const [isDuplicateDialogOpen, setIsDuplicateDialogOpen] = React.useState(false);
9945
- const [isAddDialogOpen, setIsAddDialogOpen] = React.useState(false);
9946
- const actions = React.useMemo(
9947
- () => [
9948
- {
9949
- SelectedContent: FieldBuilder,
9950
- selectedContentProps: { ...editProps, isOpen: isEditDialogOpen, setIsOpen: setIsEditDialogOpen },
9951
- Icon: Pencil1Icon,
9952
- text: "Edit",
9953
- buttonProps: {
9954
- onClick: () => {
9955
- setIsEditDialogOpen(true);
9956
- }
9957
- }
9958
- },
9959
- {
9960
- Icon: TrashIcon,
9961
- buttonProps: {
9962
- onClick: remove2
9963
- },
9964
- text: "Delete"
9965
- },
9966
- {
9967
- SelectedContent: FieldBuilder,
9968
- selectedContentProps: {
9969
- ...duplicateProps,
9970
- isOpen: isDuplicateDialogOpen,
9971
- setIsOpen: setIsDuplicateDialogOpen
9972
- },
9973
- Icon: CopyIcon,
9974
- text: "Duplicate",
9975
- buttonProps: {
9976
- onClick: () => {
9977
- setIsDuplicateDialogOpen(true);
9978
- }
9979
- }
9980
- },
9981
- {
9982
- SelectedContent: FieldBuilder,
9983
- selectedContentProps: {
9984
- ...insertAfterProps,
9985
- isOpen: isAddDialogOpen,
9986
- setIsOpen: setIsAddDialogOpen
9977
+ const FieldActions = React.memo((props) => {
9978
+ const { index: index2, sectionIndex, type, remove: remove2, duplicate, addAfter, move } = props;
9979
+ if (type !== "section" && !addAfter) {
9980
+ throw new Error("addAfter is required for non-section fields");
9981
+ }
9982
+ const { values } = formik.useFormikContext();
9983
+ const fieldTypeItems = useFieldTypeItems(addAfter);
9984
+ const [actions, mobileActions] = React.useMemo(() => {
9985
+ const getActions = (isMobile) => {
9986
+ const actions2 = [
9987
+ {
9988
+ Icon: TrashIcon,
9989
+ buttonProps: { onClick: remove2 },
9990
+ key: "delete",
9991
+ text: "Delete"
9987
9992
  },
9988
- Icon: PlusIcon,
9989
- text: "Add after",
9990
- buttonProps: {
9991
- onClick: () => {
9992
- setIsAddDialogOpen(true);
9993
- }
9993
+ {
9994
+ Icon: CopyIcon,
9995
+ key: "duplicate",
9996
+ text: "Duplicate",
9997
+ buttonProps: { onClick: duplicate }
9994
9998
  }
9995
- },
9996
- {
9997
- // Wrapping icon in a div so that the asChild turns the button into a div
9998
- // so that the drag handle props are not applied to the icon
9999
- // Note: b/c the <button> does not handle the space-press event correctly
10000
- Icon: (props2) => /* @__PURE__ */ jsxRuntime.jsx("div", { ...props2, children: /* @__PURE__ */ jsxRuntime.jsx(DragHandleDots2Icon, {}) }),
10001
- text: "Reorder",
10002
- disableOnMobile: true,
10003
- buttonProps: { ...dragHandleProps, asChild: true }
9999
+ ];
10000
+ if (type !== "section") {
10001
+ actions2.push({
10002
+ // We want to show a dropdown with field types if "Add after" is clicked
10003
+ isComponent: true,
10004
+ Component: isMobile ? /* @__PURE__ */ jsxRuntime.jsx(blocks.DropdownMenuItemGroup, { items: fieldTypeItems.flat() }) : /* @__PURE__ */ jsxRuntime.jsx(FieldTypeDropdown, { setFieldType: addAfter, children: /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { type: "button", variant: "ghost", "aria-label": "Add after", children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}) }) }),
10005
+ Icon: PlusIcon,
10006
+ key: "add",
10007
+ text: "Add after"
10008
+ });
10004
10009
  }
10005
- ],
10006
- [
10007
- dragHandleProps,
10008
- duplicateProps,
10009
- editProps,
10010
- insertAfterProps,
10011
- isAddDialogOpen,
10012
- isDuplicateDialogOpen,
10013
- isEditDialogOpen,
10014
- remove2
10015
- ]
10016
- );
10017
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10018
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { gap: "4", display: forMobile(false, "flex"), children: actions.map((action) => {
10019
- return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
10020
- /* @__PURE__ */ jsxRuntime.jsx(
10021
- blocks.IconButton,
10022
- {
10023
- type: "button",
10024
- variant: "ghost",
10025
- "aria-label": action.text,
10026
- ...action.buttonProps,
10027
- children: /* @__PURE__ */ jsxRuntime.jsx(action.Icon, {})
10010
+ if (sectionIndex === void 0 && index2 !== 0 || sectionIndex !== void 0 && (sectionIndex !== 0 || index2 !== 0)) {
10011
+ actions2.push({
10012
+ Icon: ArrowUpIcon,
10013
+ key: "moveUp",
10014
+ text: "Move up",
10015
+ buttonProps: {
10016
+ onClick: () => {
10017
+ move("up");
10018
+ }
10028
10019
  }
10029
- ),
10030
- action.SelectedContent && /* @__PURE__ */ jsxRuntime.jsx(action.SelectedContent, { ...action.selectedContentProps })
10031
- ] }, action.text);
10020
+ });
10021
+ }
10022
+ if (sectionIndex === void 0 && index2 !== values.fields.length - 1 || sectionIndex !== void 0 && (sectionIndex < values.fields.length - 1 || index2 !== values.fields[sectionIndex].fields.length - 1)) {
10023
+ actions2.push({
10024
+ Icon: ArrowDownIcon,
10025
+ key: "moveDown",
10026
+ text: "Move down",
10027
+ buttonProps: {
10028
+ onClick: () => {
10029
+ move("down");
10030
+ }
10031
+ }
10032
+ });
10033
+ }
10034
+ return actions2;
10035
+ };
10036
+ return [getActions(false), getActions(true)];
10037
+ }, [addAfter, duplicate, fieldTypeItems, index2, move, remove2, sectionIndex, type, values.fields]);
10038
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10039
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { gap: "4", display: forMobile(false, "flex"), children: actions.map((Action) => {
10040
+ if (Action.isComponent) {
10041
+ return Action.Component;
10042
+ }
10043
+ return /* @__PURE__ */ jsxRuntime.jsx(
10044
+ blocks.IconButton,
10045
+ {
10046
+ type: "button",
10047
+ variant: "ghost",
10048
+ severity: Action.key.startsWith("move") ? "info" : "primary",
10049
+ "aria-label": Action.text,
10050
+ ...Action.buttonProps,
10051
+ children: /* @__PURE__ */ jsxRuntime.jsx(Action.Icon, {})
10052
+ },
10053
+ Action.key
10054
+ );
10032
10055
  }) }),
10033
- /* @__PURE__ */ jsxRuntime.jsx(Box, { display: forMobile(true, "block"), children: /* @__PURE__ */ jsxRuntime.jsx(
10034
- blocks.DropdownItemMenu,
10056
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { display: forMobile(true, "block"), children: /* @__PURE__ */ jsxRuntime.jsxs(
10057
+ blocks.DropdownMenu,
10035
10058
  {
10036
10059
  trigger: /* @__PURE__ */ jsxRuntime.jsx(blocks.IconButton, { variant: "ghost", "aria-label": "Actions menu", children: /* @__PURE__ */ jsxRuntime.jsx(DotsVerticalIcon, {}) }),
10037
- items: actions.map((action) => {
10038
- if (action.disableOnMobile)
10039
- return null;
10040
- return {
10041
- ...action.buttonProps,
10042
- onSelect: (event) => {
10043
- var _a2, _b;
10044
- (_b = (_a2 = action.buttonProps) == null ? void 0 : _a2.onClick) == null ? void 0 : _b.call(
10045
- _a2,
10046
- // TODO: Clean up types
10047
- event
10048
- );
10049
- },
10050
- content: /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
10051
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", align: "center", children: [
10052
- /* @__PURE__ */ jsxRuntime.jsx(action.Icon, {}),
10053
- action.text
10054
- ] }),
10055
- action.SelectedContent && /* @__PURE__ */ jsxRuntime.jsx(action.SelectedContent, { ...action.selectedContentProps })
10056
- ] }, action.text)
10057
- };
10058
- }).filter((x) => x !== null)
10060
+ children: [
10061
+ /* @__PURE__ */ jsxRuntime.jsx(
10062
+ blocks.DropdownMenuItemGroup,
10063
+ {
10064
+ items: mobileActions.filter((Action) => !Action.isComponent).map((Action) => {
10065
+ var _a2;
10066
+ return {
10067
+ content: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", align: "center", children: [
10068
+ /* @__PURE__ */ jsxRuntime.jsx(Action.Icon, {}),
10069
+ Action.text
10070
+ ] }, Action.key),
10071
+ value: Action.key,
10072
+ onSelect: (_a2 = Action.buttonProps) == null ? void 0 : _a2.onClick
10073
+ };
10074
+ })
10075
+ }
10076
+ ),
10077
+ /* @__PURE__ */ jsxRuntime.jsx(
10078
+ blocks.DropdownMenuSubMenuGroup,
10079
+ {
10080
+ items: mobileActions.filter((Action) => Action.isComponent).map((Action) => ({
10081
+ content: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "2", align: "center", children: [
10082
+ /* @__PURE__ */ jsxRuntime.jsx(Action.Icon, {}),
10083
+ Action.text
10084
+ ] }, Action.key),
10085
+ subContent: Action.Component,
10086
+ triggerIndicator: null
10087
+ }))
10088
+ }
10089
+ )
10090
+ ]
10059
10091
  }
10060
10092
  ) })
10061
10093
  ] });
10062
10094
  });
10063
- const formId = "form-builder";
10064
- const FieldWithActions = React.memo(function FieldWithActions2(props) {
10065
- const { field, index: index2, sectionIndex, takenLabels, remove: remove2 } = props;
10066
- const deserializedField = React.useMemo(() => deserialize(field), [field]);
10067
- const input = useFieldInput(deserializedField, { formId, disabled: true });
10068
- const duplicateField = React.useCallback(
10069
- (field2) => {
10070
- const fieldLabel = field2.label ?? "Untitled field";
10071
- return { ...field2, label: incrementFieldLabel(fieldLabel, takenLabels), identifier: "" };
10072
- },
10073
- [takenLabels]
10095
+ FieldActions.displayName = "FieldActions";
10096
+ const description = "_description_17zed_1";
10097
+ const styles = {
10098
+ description
10099
+ };
10100
+ const FieldSettingsPopover = React.memo((props) => {
10101
+ const { popoverInputs, hasError } = props;
10102
+ return /* @__PURE__ */ jsxRuntime.jsx(
10103
+ blocks.Popover,
10104
+ {
10105
+ size: "1",
10106
+ trigger: /* @__PURE__ */ jsxRuntime.jsxs(
10107
+ blocks.Button,
10108
+ {
10109
+ variant: "soft",
10110
+ size: "small",
10111
+ "aria-label": "settings",
10112
+ ...hasError && { severity: "danger" },
10113
+ hoverEffects: ["spin90Clockwise"],
10114
+ children: [
10115
+ /* @__PURE__ */ jsxRuntime.jsx(GearIcon, {}),
10116
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { children: "Settings" })
10117
+ ]
10118
+ },
10119
+ "settings"
10120
+ ),
10121
+ children: () => /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "column", style: { maxWidth: "240px" }, children: popoverInputs })
10122
+ }
10123
+ );
10124
+ });
10125
+ FieldSettingsPopover.displayName = "FieldSettingsPopover";
10126
+ const FieldBuilder = React.memo((props) => {
10127
+ var _a2, _b, _c, _d, _e, _f;
10128
+ const { parentPath, index: index2, initial, conditionalSourceFields } = props;
10129
+ const RADIX_SM_MIN_WIDTH = 576;
10130
+ const [isLargeScreen, setIsLargeScreen] = React.useState(
10131
+ window.matchMedia(`(min-width: ${RADIX_SM_MIN_WIDTH}px)`).matches
10074
10132
  );
10133
+ React.useEffect(() => {
10134
+ const mediaQuery = window.matchMedia(`(min-width: ${RADIX_SM_MIN_WIDTH}px)`);
10135
+ const handleMediaQueryChange = (event) => {
10136
+ setIsLargeScreen(event.matches);
10137
+ };
10138
+ mediaQuery.addEventListener("change", handleMediaQueryChange);
10139
+ return () => {
10140
+ mediaQuery.removeEventListener("change", handleMediaQueryChange);
10141
+ };
10142
+ }, []);
10143
+ const { values, setFieldValue, errors } = formik.useFormikContext();
10144
+ const fieldTypeItems = useFieldTypeItems();
10145
+ const isSection = React.useCallback((field) => {
10146
+ return field.type === "section";
10147
+ }, []);
10148
+ React.useEffect(() => {
10149
+ if (isSection(initial) && !initial.conditional) {
10150
+ void setFieldValue(`${parentPath}.${index2}.condition`, null).then();
10151
+ }
10152
+ }, [index2, initial, isSection, parentPath, setFieldValue]);
10153
+ const conditionLabel = React.useMemo(
10154
+ () => {
10155
+ var _a3, _b2;
10156
+ return isSection(initial) ? (_b2 = findFieldByIdentifier(values.fields, (_a3 = initial.condition) == null ? void 0 : _a3.identifier)) == null ? void 0 : _b2.label : void 0;
10157
+ },
10158
+ [initial, isSection, values.fields]
10159
+ );
10160
+ const conditionComparison = isSection(initial) ? Array.isArray((_a2 = initial.condition) == null ? void 0 : _a2.value) ? "contains all of" : "equals" : void 0;
10161
+ let conditionValue = void 0;
10162
+ if (isSection(initial)) {
10163
+ if (valueIsFile((_b = initial.condition) == null ? void 0 : _b.value)) {
10164
+ throw new Error("File values are not supported for conditions.");
10165
+ }
10166
+ conditionValue = Array.isArray((_c = initial.condition) == null ? void 0 : _c.value) ? initial.condition.value.map((v) => typeof v === "string" ? v : v.label).join(", ") : (_e = (_d = initial.condition) == null ? void 0 : _d.value) == null ? void 0 : _e.toString();
10167
+ }
10168
+ const type = initial.type;
10169
+ const fieldCls = CompleteFieldTypeToClsMapping[type];
10170
+ const [directlyShownFields, popoverFields] = React.useMemo(() => {
10171
+ let directlyShownFields2 = [];
10172
+ let popoverFields2 = [];
10173
+ if (fieldCls === FieldSection) {
10174
+ if (conditionalSourceFields === void 0) {
10175
+ throw new Error("Conditional source fields must be provided when changing sections.");
10176
+ }
10177
+ const fieldObject = fieldCls.getFieldCreationSchema(conditionalSourceFields, `${parentPath}.${index2}`);
10178
+ directlyShownFields2 = directlyShownFields2.concat(
10179
+ fieldObject.filter((field) => field.showDirectly).map((field) => field.field)
10180
+ );
10181
+ popoverFields2 = popoverFields2.concat(
10182
+ fieldObject.filter((field) => !field.showDirectly).map((field) => field.field)
10183
+ );
10184
+ } else {
10185
+ if (!(fieldCls.prototype instanceof BaseField)) {
10186
+ throw new Error(`Field must be an instance of BaseField. Got ${fieldCls.toString()}.`);
10187
+ }
10188
+ const fieldObject = fieldCls.getFieldCreationSchema(
10189
+ `${parentPath}.${index2}`
10190
+ );
10191
+ if (isLargeScreen) {
10192
+ directlyShownFields2 = [
10193
+ ...directlyShownFields2,
10194
+ ...fieldObject.filter((field) => field.showDirectly).map((field) => field.field)
10195
+ ];
10196
+ popoverFields2 = [
10197
+ ...popoverFields2,
10198
+ ...fieldObject.filter((field) => !field.showDirectly).map((field) => field.field)
10199
+ ];
10200
+ } else {
10201
+ popoverFields2 = [...popoverFields2, ...fieldObject.map((field) => field.field)];
10202
+ }
10203
+ }
10204
+ return [directlyShownFields2, popoverFields2];
10205
+ }, [fieldCls, conditionalSourceFields, parentPath, index2, isLargeScreen]);
10206
+ const directlyShownInputs = useFieldInputs(directlyShownFields, {
10207
+ formId,
10208
+ disabled: false,
10209
+ ...fieldCls === FieldSection && { size: "2" }
10210
+ });
10211
+ const popoverInputs = useFieldInputs(popoverFields, {
10212
+ formId,
10213
+ disabled: false
10214
+ });
10215
+ let showPopoverInputs = popoverFields.length > 0;
10216
+ if (isSection(initial) && popoverFields.length > 0) {
10217
+ showPopoverInputs = initial.conditional;
10218
+ }
10219
+ const popoverHasErrors = popoverFields.some((field) => {
10220
+ const error = get(errors, fieldCls === FieldSection ? `${parentPath}.${index2}.condition` : field.getId());
10221
+ return error && (typeof error !== "object" || hasKeys(error));
10222
+ });
10223
+ return /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", grow: "1", children: [
10224
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", children: [
10225
+ fieldCls === FieldSection && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "1", children: [
10226
+ directlyShownFields.length > 0 && directlyShownInputs,
10227
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", gap: "2", children: [
10228
+ showPopoverInputs && /* @__PURE__ */ jsxRuntime.jsx(FieldSettingsPopover, { popoverInputs, hasError: popoverHasErrors }),
10229
+ isSection(initial) && initial.conditional && /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "1", severity: popoverHasErrors ? "danger" : "primary", children: /* @__PURE__ */ jsxRuntime.jsxs(Em, { children: [
10230
+ "Display only if ",
10231
+ /* @__PURE__ */ jsxRuntime.jsx(Strong, { children: conditionLabel }),
10232
+ " ",
10233
+ conditionComparison,
10234
+ " ",
10235
+ /* @__PURE__ */ jsxRuntime.jsx(Strong, { children: conditionValue })
10236
+ ] }) })
10237
+ ] })
10238
+ ] }),
10239
+ fieldCls !== FieldSection && /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", children: [
10240
+ /* @__PURE__ */ jsxRuntime.jsx(
10241
+ PatchField,
10242
+ {
10243
+ name: `${parentPath}.${index2}.required`,
10244
+ render: ({ setValue, value }) => /* @__PURE__ */ jsxRuntime.jsx(
10245
+ blocks.Checkbox,
10246
+ {
10247
+ checked: value,
10248
+ onCheckedChange: setValue,
10249
+ label: /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "2", children: "Required field" }),
10250
+ alwaysShow: true
10251
+ }
10252
+ )
10253
+ }
10254
+ ),
10255
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { align: "center", gap: "3", children: [
10256
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Badge, { style: { width: "fit-content", height: "24px" }, children: (_f = fieldTypeItems.flat().find((item) => item.value === type)) == null ? void 0 : _f.content }),
10257
+ showPopoverInputs && /* @__PURE__ */ jsxRuntime.jsx(FieldSettingsPopover, { popoverInputs, hasError: popoverHasErrors })
10258
+ ] })
10259
+ ] }),
10260
+ /* @__PURE__ */ jsxRuntime.jsx(
10261
+ PatchField,
10262
+ {
10263
+ name: `${parentPath}.${index2}.label`,
10264
+ render: ({ setValue, value }) => /* @__PURE__ */ jsxRuntime.jsx(
10265
+ blocks.Input,
10266
+ {
10267
+ className: styles.Input,
10268
+ placeholder: `Enter a ${type === "section" ? "section" : "field"} label`,
10269
+ value,
10270
+ onChange: (event) => {
10271
+ setValue(event.target.value);
10272
+ },
10273
+ maxLength: 200,
10274
+ showInputLength: false,
10275
+ variant: "ghost",
10276
+ size: "large"
10277
+ }
10278
+ )
10279
+ }
10280
+ ),
10281
+ /* @__PURE__ */ jsxRuntime.jsx(
10282
+ PatchField,
10283
+ {
10284
+ name: `${parentPath}.${index2}.description`,
10285
+ render: ({ setValue, value }) => /* @__PURE__ */ jsxRuntime.jsx(
10286
+ blocks.TextArea,
10287
+ {
10288
+ style: { minHeight: "max-content" },
10289
+ placeholder: `Enter a ${type === "section" ? "section" : "field"} description`,
10290
+ value,
10291
+ onChange: (event) => {
10292
+ setValue(event.target.value);
10293
+ },
10294
+ resize: "vertical",
10295
+ maxLength: 1e3,
10296
+ showInputLength: false,
10297
+ variant: "ghost"
10298
+ }
10299
+ )
10300
+ }
10301
+ )
10302
+ ] }),
10303
+ fieldCls !== FieldSection && directlyShownFields.length > 0 && directlyShownInputs
10304
+ ] });
10305
+ });
10306
+ FieldBuilder.displayName = "FieldBuilder";
10307
+ const FieldWithActions = React.memo((props) => {
10308
+ const { field, index: index2, sectionIndex, takenLabels, remove: remove2 } = props;
10309
+ const { setFieldValue, values } = formik.useFormikContext();
10310
+ const { reorderField } = useFieldReordering();
10311
+ const parentPath = `fields.${sectionIndex}.fields`;
10075
10312
  const editFieldProps = React.useMemo(
10076
10313
  () => ({
10077
10314
  index: index2,
10078
- parentPath: `fields.${sectionIndex}.fields`,
10079
- initial: field,
10080
- editing: true
10315
+ parentPath,
10316
+ initial: field
10081
10317
  }),
10082
- [field, index2, sectionIndex]
10318
+ [field, index2, parentPath]
10083
10319
  );
10084
- const duplicateFieldProps = React.useMemo(
10085
- () => ({
10086
- parentPath: `fields.${sectionIndex}.fields`,
10087
- index: index2 + 1,
10088
- initial: duplicateField(field)
10089
- }),
10090
- [duplicateField, field, index2, sectionIndex]
10320
+ const duplicateField = React.useCallback(() => {
10321
+ const label = field.label ?? "Unlabelled field";
10322
+ const duplicatedField = {
10323
+ ...field,
10324
+ label: incrementFieldLabel(label, takenLabels)
10325
+ };
10326
+ createNewField(parentPath, index2 + 1, duplicatedField, values, setFieldValue);
10327
+ }, [field, takenLabels, parentPath, index2, values, setFieldValue]);
10328
+ const createFieldAfter = React.useCallback(
10329
+ (type) => {
10330
+ if (type === "section") {
10331
+ throw new Error("Section type unexpected");
10332
+ }
10333
+ createNewField(
10334
+ parentPath,
10335
+ index2 + 1,
10336
+ FieldTypeToEmptyFieldMapping[type],
10337
+ values,
10338
+ setFieldValue
10339
+ );
10340
+ },
10341
+ [parentPath, index2, values, setFieldValue]
10091
10342
  );
10092
- const insertAfterProps = React.useMemo(
10093
- () => ({
10094
- parentPath: `fields.${sectionIndex}.fields`,
10095
- index: index2 + 1,
10096
- initial: void 0
10097
- }),
10098
- [index2, sectionIndex]
10343
+ const moveField = React.useCallback(
10344
+ (direction) => {
10345
+ const srcSectionIndex = sectionIndex;
10346
+ const srcSection = values.fields[srcSectionIndex];
10347
+ let destSectionIndex = sectionIndex;
10348
+ let destFieldIndex = direction === "up" ? index2 - 1 : index2 + 1;
10349
+ if (direction === "up" && index2 === 0) {
10350
+ destSectionIndex = sectionIndex - 1;
10351
+ destFieldIndex = values.fields[destSectionIndex].fields.length;
10352
+ } else if (direction === "down" && index2 === srcSection.fields.length - 1) {
10353
+ destSectionIndex = sectionIndex + 1;
10354
+ destFieldIndex = 0;
10355
+ }
10356
+ const destSection = values.fields[destSectionIndex];
10357
+ reorderField(
10358
+ srcSection,
10359
+ srcSectionIndex,
10360
+ index2,
10361
+ destSection,
10362
+ destSectionIndex,
10363
+ destFieldIndex,
10364
+ setFieldValue
10365
+ );
10366
+ },
10367
+ [sectionIndex, values.fields, index2, reorderField, setFieldValue]
10099
10368
  );
10100
10369
  return /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: field.identifier, index: index2, children: (draggableProvided) => /* @__PURE__ */ jsxRuntime.jsx(
10101
10370
  Card,
@@ -10103,30 +10372,38 @@ var __publicField = (obj, key, value) => {
10103
10372
  ref: draggableProvided.innerRef,
10104
10373
  ...draggableProvided.draggableProps,
10105
10374
  ...draggableProvided.dragHandleProps,
10375
+ style: {
10376
+ ...draggableProvided.draggableProps.style,
10377
+ backgroundColor: "var(--accent-1)",
10378
+ borderColor: "var(--accent-3)"
10379
+ },
10106
10380
  mb: "4",
10107
10381
  children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "4", justify: "between", align: "center", children: [
10108
- input,
10382
+ /* @__PURE__ */ jsxRuntime.jsx(FieldBuilder, { ...editFieldProps }),
10109
10383
  /* @__PURE__ */ jsxRuntime.jsx(
10110
10384
  FieldActions,
10111
10385
  {
10386
+ index: index2,
10387
+ sectionIndex,
10388
+ type: field.type,
10112
10389
  remove: remove2,
10113
- editProps: editFieldProps,
10114
- duplicateProps: duplicateFieldProps,
10115
- insertAfterProps,
10116
- dragHandleProps: draggableProvided.dragHandleProps
10390
+ duplicate: duplicateField,
10391
+ addAfter: createFieldAfter,
10392
+ move: moveField
10117
10393
  }
10118
10394
  )
10119
10395
  ] })
10120
10396
  }
10121
10397
  ) });
10122
10398
  });
10123
- const FieldSectionWithActions = React.memo(function FieldSectionWithActions2(props) {
10124
- var _a2, _b, _c, _d, _e, _f, _g;
10399
+ FieldWithActions.displayName = "FieldWithActions";
10400
+ const FieldSectionWithActions = React.memo((props) => {
10401
+ var _a2;
10125
10402
  const { field, index: sectionIndex, dropState } = props;
10126
10403
  const isDropDisabled = (_a2 = dropState[field.identifier]) == null ? void 0 : _a2.disabled;
10127
- const [isAddFieldDialogOpen, setIsAddFieldDialogOpen] = React.useState(false);
10128
10404
  const { setFieldValue, values } = formik.useFormikContext();
10129
10405
  const alertDialog = blocks.useAlertDialog();
10406
+ const { reorderSection } = useFieldReordering();
10130
10407
  const takenFieldLabels = getTakenFieldLabels(values.fields);
10131
10408
  const removeSectionConditions = React.useCallback(
10132
10409
  (sectionsToUpdate, allSections) => {
@@ -10213,152 +10490,113 @@ var __publicField = (obj, key, value) => {
10213
10490
  alertDialog,
10214
10491
  removeSectionConditions
10215
10492
  ]);
10216
- const duplicateSection = React.useCallback(
10217
- (field2) => {
10218
- const fieldLabel = field2.label ?? "Untitled section";
10219
- const newSectionLabel = incrementFieldLabel(fieldLabel, takenFieldLabels);
10220
- const newFields = field2.fields.map((f) => {
10221
- const newLabel = incrementFieldLabel(f.label || "Untitled field", takenFieldLabels);
10222
- return {
10223
- ...f,
10224
- label: newLabel,
10225
- identifier: makeIdentifier(void 0, newLabel)
10226
- };
10227
- });
10228
- return { ...field2, label: newSectionLabel, fields: newFields, identifier: "" };
10493
+ const moveSection = React.useCallback(
10494
+ (direction) => {
10495
+ const destinationIndex = direction === "up" ? sectionIndex - 1 : sectionIndex + 1;
10496
+ reorderSection(dropState, field.identifier, sectionIndex, destinationIndex, values, setFieldValue);
10229
10497
  },
10230
- [takenFieldLabels]
10498
+ [sectionIndex, reorderSection, dropState, field.identifier, values, setFieldValue]
10231
10499
  );
10232
10500
  const editSectionProps = React.useMemo(
10233
10501
  () => ({
10234
10502
  index: sectionIndex,
10235
10503
  parentPath: "fields",
10236
10504
  initial: field,
10237
- editing: true,
10238
10505
  conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex)
10239
10506
  }),
10240
10507
  [field, sectionIndex, values.fields]
10241
10508
  );
10242
- const insertSectionProps = React.useMemo(
10243
- () => ({
10244
- index: sectionIndex + 1,
10245
- parentPath: "fields",
10246
- initial: emptySection(),
10247
- conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex + 1)
10248
- }),
10249
- [sectionIndex, values.fields]
10250
- );
10251
- const insertFieldAtEndOfSection = React.useMemo(
10252
- () => ({
10253
- parentPath: `fields.${sectionIndex}.fields`,
10254
- index: field.fields.length,
10255
- initial: void 0
10256
- }),
10257
- [field.fields.length, sectionIndex]
10258
- );
10259
- const duplicateSectionProps = React.useMemo(
10260
- () => ({
10261
- index: sectionIndex + 1,
10262
- parentPath: "fields",
10263
- initial: duplicateSection(field),
10264
- conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex + 1)
10265
- }),
10266
- [duplicateSection, field, sectionIndex, values.fields]
10267
- );
10268
- const conditionLabel = React.useMemo(
10269
- () => {
10270
- var _a3, _b2;
10271
- return (_b2 = findFieldByIdentifier(values.fields, (_a3 = field.condition) == null ? void 0 : _a3.identifier)) == null ? void 0 : _b2.label;
10509
+ const duplicateSection = React.useCallback(() => {
10510
+ const fieldLabel = field.label ?? "Untitled section";
10511
+ const newSectionLabel = incrementFieldLabel(fieldLabel, takenFieldLabels);
10512
+ const newFields = field.fields.map((f) => {
10513
+ const newLabel = incrementFieldLabel(f.label, takenFieldLabels);
10514
+ return {
10515
+ ...f,
10516
+ label: newLabel,
10517
+ identifier: makeIdentifier(null, newLabel)
10518
+ };
10519
+ });
10520
+ const duplicatedField = { ...field, label: newSectionLabel, fields: newFields };
10521
+ createNewField("fields", sectionIndex + 1, duplicatedField, values, setFieldValue);
10522
+ }, [field, takenFieldLabels, sectionIndex, values, setFieldValue]);
10523
+ const handleCreateField = React.useCallback(
10524
+ (type) => {
10525
+ createNewField(
10526
+ `fields.${sectionIndex}.fields`,
10527
+ field.fields.length,
10528
+ FieldTypeToEmptyFieldMapping[type],
10529
+ values,
10530
+ setFieldValue
10531
+ );
10272
10532
  },
10273
- [(_b = field.condition) == null ? void 0 : _b.identifier, values.fields]
10533
+ [sectionIndex, field.fields.length, values, setFieldValue]
10274
10534
  );
10275
- const conditionComparison = Array.isArray((_c = field.condition) == null ? void 0 : _c.value) ? "contains all of" : "equals";
10276
- if (valueIsFile((_d = field.condition) == null ? void 0 : _d.value))
10277
- throw new Error("File values are not supported for conditions.");
10278
- const conditionValue = Array.isArray((_e = field.condition) == null ? void 0 : _e.value) ? field.condition.value.map((v) => typeof v === "string" ? v : v.label).join(", ") : (_g = (_f = field.condition) == null ? void 0 : _f.value) == null ? void 0 : _g.toString();
10279
- return /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: field.identifier, index: sectionIndex, children: (draggableProvided) => /* @__PURE__ */ jsxRuntime.jsx(
10280
- Card,
10281
- {
10282
- ref: draggableProvided.innerRef,
10283
- ...draggableProvided.draggableProps,
10284
- ...draggableProvided.dragHandleProps,
10285
- mb: "4",
10286
- children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "3", justify: "between", align: "center", children: [
10287
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", grow: "1", children: [
10288
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", children: [
10289
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { as: "h3", size: "3", children: field.label }),
10290
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { className: styles$4.description, children: field.description })
10291
- ] }),
10292
- field.condition && /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(Em, { children: [
10293
- "Display only if ",
10294
- /* @__PURE__ */ jsxRuntime.jsx(Strong, { children: conditionLabel }),
10295
- " ",
10296
- conditionComparison,
10297
- " ",
10298
- /* @__PURE__ */ jsxRuntime.jsx(Strong, { children: conditionValue })
10299
- ] }) }),
10300
- /* @__PURE__ */ jsxRuntime.jsx(dnd.Droppable, { droppableId: field.identifier, type: "SECTION", isDropDisabled, children: (droppableProvided) => /* @__PURE__ */ jsxRuntime.jsxs(
10301
- blocks.Flex,
10302
- {
10303
- ref: droppableProvided.innerRef,
10304
- ...droppableProvided.droppableProps,
10305
- direction: "column",
10306
- gap: "0",
10307
- children: [
10308
- field.fields.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(
10309
- FieldWithActions,
10310
- {
10311
- field: child,
10312
- index: i,
10313
- sectionIndex,
10314
- remove: () => {
10315
- removeField(i);
10316
- },
10317
- takenLabels: takenFieldLabels
10318
- },
10319
- child.identifier
10320
- )),
10321
- droppableProvided.placeholder,
10322
- /* @__PURE__ */ jsxRuntime.jsxs(
10323
- blocks.Button,
10535
+ return /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: field.identifier, index: sectionIndex, children: (draggableProvided) => {
10536
+ return /* @__PURE__ */ jsxRuntime.jsx(
10537
+ Card,
10538
+ {
10539
+ ref: draggableProvided.innerRef,
10540
+ ...draggableProvided.draggableProps,
10541
+ ...draggableProvided.dragHandleProps,
10542
+ mb: "4",
10543
+ children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { gap: "3", justify: "between", align: "center", children: [
10544
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", grow: "1", children: [
10545
+ /* @__PURE__ */ jsxRuntime.jsx(FieldBuilder, { ...editSectionProps }),
10546
+ /* @__PURE__ */ jsxRuntime.jsx(
10547
+ dnd.Droppable,
10548
+ {
10549
+ droppableId: field.identifier,
10550
+ type: "SECTION",
10551
+ isDropDisabled,
10552
+ children: (droppableProvided) => /* @__PURE__ */ jsxRuntime.jsxs(
10553
+ blocks.Flex,
10324
10554
  {
10325
- type: "button",
10326
- variant: "outline",
10327
- onClick: () => {
10328
- setIsAddFieldDialogOpen(true);
10329
- },
10555
+ ref: droppableProvided.innerRef,
10556
+ ...droppableProvided.droppableProps,
10557
+ direction: "column",
10558
+ gap: "0",
10330
10559
  children: [
10331
- /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
10332
- " Add a field"
10560
+ field.fields.map((child, i) => /* @__PURE__ */ jsxRuntime.jsx(
10561
+ FieldWithActions,
10562
+ {
10563
+ field: child,
10564
+ index: i,
10565
+ sectionIndex,
10566
+ remove: () => {
10567
+ removeField(i);
10568
+ },
10569
+ takenLabels: takenFieldLabels
10570
+ },
10571
+ child.identifier
10572
+ )),
10573
+ droppableProvided.placeholder,
10574
+ /* @__PURE__ */ jsxRuntime.jsx(FieldTypeDropdown, { setFieldType: handleCreateField, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Button, { type: "button", variant: "soft", children: [
10575
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
10576
+ " Add field"
10577
+ ] }) })
10333
10578
  ]
10334
10579
  }
10335
- ),
10336
- /* @__PURE__ */ jsxRuntime.jsx(
10337
- FieldBuilder,
10338
- {
10339
- ...insertFieldAtEndOfSection,
10340
- isOpen: isAddFieldDialogOpen,
10341
- setIsOpen: setIsAddFieldDialogOpen
10342
- }
10343
10580
  )
10344
- ]
10581
+ }
10582
+ )
10583
+ ] }),
10584
+ /* @__PURE__ */ jsxRuntime.jsx(
10585
+ FieldActions,
10586
+ {
10587
+ index: sectionIndex,
10588
+ type: field.type,
10589
+ remove: removeSection,
10590
+ duplicate: duplicateSection,
10591
+ move: moveSection
10345
10592
  }
10346
- ) })
10347
- ] }),
10348
- /* @__PURE__ */ jsxRuntime.jsx(
10349
- FieldActions,
10350
- {
10351
- remove: removeSection,
10352
- insertAfterProps: insertSectionProps,
10353
- dragHandleProps: draggableProvided.dragHandleProps,
10354
- editProps: editSectionProps,
10355
- duplicateProps: duplicateSectionProps
10356
- }
10357
- )
10358
- ] })
10359
- }
10360
- ) });
10593
+ )
10594
+ ] })
10595
+ }
10596
+ );
10597
+ } });
10361
10598
  });
10599
+ FieldSectionWithActions.displayName = "FieldSectionWithActions";
10362
10600
  const reducer = (state, action) => {
10363
10601
  var _a2;
10364
10602
  const next = { ...state };
@@ -10420,11 +10658,40 @@ var __publicField = (obj, key, value) => {
10420
10658
  return [section, i];
10421
10659
  }
10422
10660
  };
10423
- const FieldsEditor = React.memo(function FieldsEditor2() {
10661
+ const BasicFieldSection = React.memo((props) => {
10662
+ const { field, provided } = props;
10663
+ return /* @__PURE__ */ jsxRuntime.jsx(
10664
+ Card,
10665
+ {
10666
+ ref: provided == null ? void 0 : provided.innerRef,
10667
+ ...provided == null ? void 0 : provided.draggableProps,
10668
+ ...provided == null ? void 0 : provided.dragHandleProps,
10669
+ style: { ...provided == null ? void 0 : provided.draggableProps.style, height: "80px" },
10670
+ children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", children: [
10671
+ /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "row", gap: "2", children: [
10672
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { size: "4", children: field.label }),
10673
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Badge, { style: { width: "fit-content" }, children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Text, { children: [
10674
+ field.fields.length,
10675
+ " Fields"
10676
+ ] }) })
10677
+ ] }),
10678
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { direction: "row", gap: "2", children: field.fields.map((child) => {
10679
+ const childInfo = FieldTypeToClsMapping[child.type];
10680
+ const Icon = childInfo.Icon;
10681
+ return /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { gap: "3", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Badge, { style: { width: "fit-content" }, children: [
10682
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
10683
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { children: childInfo.fieldTypeName })
10684
+ ] }) }, child.identifier);
10685
+ }) })
10686
+ ] })
10687
+ }
10688
+ );
10689
+ });
10690
+ BasicFieldSection.displayName = "BasicFieldSection";
10691
+ const FieldsEditor = React.memo(() => {
10424
10692
  const { values, setFieldValue } = formik.useFormikContext();
10425
10693
  const [dropState, dispatch] = React.useReducer(reducer, values.fields, initializer);
10426
- const [isAddSectionDialogOpen, setIsAddSectionDialogOpen] = React.useState(false);
10427
- const { showInfo } = blocks.useToast();
10694
+ const { reorderSection, reorderField } = useFieldReordering();
10428
10695
  React.useEffect(() => {
10429
10696
  dispatch({ type: "update", state: initializer(values.fields) });
10430
10697
  }, [dispatch, values.fields]);
@@ -10440,58 +10707,30 @@ var __publicField = (obj, key, value) => {
10440
10707
  if (!destination || reason === "CANCEL")
10441
10708
  return;
10442
10709
  if (type === "ROOT") {
10443
- const state = dropState[draggableId];
10444
- if (!state)
10445
- throw new Error("Could not find section context.");
10446
- let dest = typeof state.conditionIndex !== "undefined" ? (
10447
- // cannot move a section with a condition before the condition's field
10448
- Math.max(state.conditionIndex + 1, destination.index)
10449
- ) : destination.index;
10450
- for (const section of Object.values(dropState)) {
10451
- if (section.conditionIndex === source.index) {
10452
- dest = Math.min(dest, section.index - 1);
10453
- }
10454
- }
10455
- if (dest != destination.index) {
10456
- showInfo({
10457
- title: "Reordered sections",
10458
- description: "Sections with conditions must be below the fields they reference."
10459
- });
10460
- }
10461
- return setFieldValue("fields", reorder(values.fields, source.index, dest));
10710
+ reorderSection(dropState, draggableId, source.index, destination.index, values, setFieldValue);
10711
+ return;
10462
10712
  }
10463
10713
  if (type !== "SECTION")
10464
10714
  throw new Error("Unexpected droppable type.");
10465
10715
  const [sourceSection, srcIndex] = findSection(values.fields, source.droppableId) ?? [];
10466
10716
  const [destinationSection, destIndex] = findSection(values.fields, destination.droppableId) ?? [];
10467
- if (!(sourceSection == null ? void 0 : sourceSection.fields) || !destinationSection)
10468
- throw new Error("Could not find section with fields.");
10469
- if (sourceSection.identifier === destinationSection.identifier) {
10470
- void setFieldValue(
10471
- `fields.${srcIndex}.fields`,
10472
- reorder(sourceSection.fields, source.index, destination.index)
10473
- ).then();
10474
- } else {
10475
- const removed = sourceSection.fields[source.index];
10476
- if (!removed)
10477
- throw new Error("Could not find field to reorder.");
10478
- void setFieldValue(`fields.${srcIndex}.fields`, remove(sourceSection.fields, source.index)).then();
10479
- void setFieldValue(
10480
- `fields.${destIndex}.fields`,
10481
- insert(destinationSection.fields, destination.index, removed)
10482
- ).then();
10483
- }
10717
+ reorderField(
10718
+ sourceSection,
10719
+ srcIndex,
10720
+ source.index,
10721
+ destinationSection,
10722
+ destIndex,
10723
+ destination.index,
10724
+ setFieldValue
10725
+ );
10484
10726
  },
10485
- [values.fields, setFieldValue, dropState, showInfo]
10727
+ [values, reorderField, setFieldValue, reorderSection, dropState]
10486
10728
  );
10487
- const makeFieldSectionProps = React.useMemo(
10488
- () => ({
10489
- index: values.fields.length,
10490
- parentPath: "fields",
10491
- initial: emptySection(),
10492
- conditionalSourceFields: makeConditionalSourceFields(values.fields, values.fields.length)
10493
- }),
10494
- [values.fields]
10729
+ const handleCreateEmptySection = React.useCallback(
10730
+ (index2) => {
10731
+ createNewEmptySection(index2 + 1, values, setFieldValue);
10732
+ },
10733
+ [values, setFieldValue]
10495
10734
  );
10496
10735
  return /* @__PURE__ */ jsxRuntime.jsx(dnd.DragDropContext, { onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsxRuntime.jsx(dnd.Droppable, { droppableId: "droppable", type: "ROOT", children: (droppableProvided) => /* @__PURE__ */ jsxRuntime.jsxs(
10497
10736
  blocks.Flex,
@@ -10501,123 +10740,200 @@ var __publicField = (obj, key, value) => {
10501
10740
  direction: "column",
10502
10741
  gap: "0",
10503
10742
  children: [
10504
- values.fields.map((field, index2) => /* @__PURE__ */ jsxRuntime.jsx(
10505
- FieldSectionWithActions,
10506
- {
10507
- field,
10508
- index: index2,
10509
- dropState
10510
- },
10511
- field.label
10512
- )),
10513
- droppableProvided.placeholder,
10514
- /* @__PURE__ */ jsxRuntime.jsxs(
10515
- blocks.Button,
10516
- {
10517
- type: "button",
10518
- variant: "outline",
10519
- onClick: () => {
10520
- setIsAddSectionDialogOpen(true);
10521
- },
10522
- children: [
10523
- /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
10524
- " Add a section"
10525
- ]
10526
- }
10527
- ),
10528
- /* @__PURE__ */ jsxRuntime.jsx(
10529
- FieldBuilder,
10530
- {
10531
- ...makeFieldSectionProps,
10532
- isOpen: isAddSectionDialogOpen,
10533
- setIsOpen: setIsAddSectionDialogOpen
10534
- }
10535
- )
10743
+ values.fields.map((field, index2) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
10744
+ /* @__PURE__ */ jsxRuntime.jsx(FieldSectionWithActions, { field, index: index2, dropState }),
10745
+ /* @__PURE__ */ jsxRuntime.jsxs(
10746
+ blocks.Button,
10747
+ {
10748
+ type: "button",
10749
+ variant: "surface",
10750
+ severity: "info",
10751
+ onClick: () => {
10752
+ handleCreateEmptySection(index2);
10753
+ },
10754
+ style: { marginBottom: "4px" },
10755
+ children: [
10756
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
10757
+ " Add section"
10758
+ ]
10759
+ }
10760
+ )
10761
+ ] }, field.identifier)),
10762
+ droppableProvided.placeholder
10536
10763
  ]
10537
10764
  }
10538
10765
  ) }) });
10539
10766
  });
10767
+ FieldsEditor.displayName = "FieldsEditor";
10540
10768
  const initialValues = {
10541
10769
  title: "",
10542
10770
  description: "",
10543
- fields: []
10544
- };
10545
- const title = new StringField({
10546
- label: "Title",
10547
- minLength: 0,
10548
- maxLength: 100,
10549
- required: true,
10550
- identifier: "title"
10551
- });
10552
- const titleProps = { formId, placeholder: "Give your form a title." };
10553
- const description = new TextField({
10554
- label: "Description",
10555
- minLength: 0,
10556
- maxLength: 1e3,
10557
- required: false,
10558
- identifier: "description"
10559
- });
10560
- const descriptionProps = { formId, placeholder: "Explain the purpose of this form." };
10771
+ fields: [{ ...emptySection(makeIdentifier(null, "")), label: "" }]
10772
+ };
10561
10773
  const previewSubmit = () => {
10562
10774
  alert("This is a form preview, your data will not be saved.");
10563
10775
  };
10564
10776
  const FormBuilder = React.memo(
10565
10777
  React.forwardRef((props, ref) => {
10566
10778
  const { onCancel, onSave, revision } = props;
10567
- const { heading = revision ? "Edit form" : "Create a new form" } = props;
10568
- const validate = React.useCallback((form) => {
10569
- const errors = {};
10570
- if (!form.title) {
10571
- errors.title = "Title is required.";
10572
- }
10573
- if (!form.fields || form.fields.length === 0) {
10574
- errors.fields = "At least one field is required.";
10575
- }
10576
- if (hasKeys(errors)) {
10577
- return errors;
10578
- }
10579
- }, []);
10779
+ const { showError } = blocks.useToast();
10780
+ const validate = React.useCallback(
10781
+ (form) => {
10782
+ const errors = {};
10783
+ if (!form.title) {
10784
+ errors.title = "Title is required.";
10785
+ }
10786
+ if (form.fields.length === 0) {
10787
+ errors.fields = "At least one field is required.";
10788
+ }
10789
+ let fieldsToValidate = [];
10790
+ for (const [sectionIndex, section] of form.fields.entries()) {
10791
+ const fieldCls = CompleteFieldTypeToClsMapping.section;
10792
+ const sectionSettings = fieldCls.getFieldCreationSchema(
10793
+ makeConditionalSourceFields(form.fields, sectionIndex),
10794
+ `fields.${sectionIndex}`
10795
+ ).map((field) => field.field);
10796
+ fieldsToValidate = [...fieldsToValidate, ...sectionSettings];
10797
+ for (const [fieldIndex, field] of section.fields.entries()) {
10798
+ const fieldCls2 = CompleteFieldTypeToClsMapping[field.type];
10799
+ const fieldSettings = fieldCls2.getFieldCreationSchema(`fields.${sectionIndex}.fields.${fieldIndex}`).map((field2) => field2.field);
10800
+ fieldsToValidate = [...fieldsToValidate, ...fieldSettings];
10801
+ }
10802
+ }
10803
+ const fieldErrors = validateForm(
10804
+ {
10805
+ title: "Validate form builder",
10806
+ fields: fieldsToValidate,
10807
+ meta: { readonly: true }
10808
+ },
10809
+ form
10810
+ );
10811
+ if (fieldErrors) {
10812
+ errors.fields = fieldErrors.fields;
10813
+ }
10814
+ if (hasKeys(errors)) {
10815
+ showError({
10816
+ title: "Some form settings are invalid",
10817
+ description: "Please check settings highlighted in red."
10818
+ });
10819
+ return errors;
10820
+ }
10821
+ },
10822
+ [showError]
10823
+ );
10580
10824
  const formik$1 = formik.useFormik({
10581
10825
  initialValues: wrapRootFieldsWithFieldSection(revision) ?? initialValues,
10582
10826
  validate,
10583
- onSubmit: onSave,
10584
- // only validate the entire for on submit
10827
+ // onSubmit: (form) => console.log("SUBMITTED", form),
10828
+ onSubmit: (form) => {
10829
+ onSave(form);
10830
+ },
10831
+ // only validate the entire form on submit
10585
10832
  validateOnChange: false,
10586
10833
  validateOnBlur: false
10587
10834
  });
10588
10835
  const previewSchema = React.useMemo(() => formRevisionToSchema(formik$1.values), [formik$1.values]);
10589
- const titleInput = useFieldInput(title, titleProps);
10590
- const descriptionInput = useFieldInput(description, descriptionProps);
10591
- const FormBuilderHeading = React.useMemo(
10592
- () => typeof heading === "object" ? heading : /* @__PURE__ */ jsxRuntime.jsx(Heading, { children: heading }),
10593
- [heading]
10594
- );
10595
10836
  return /* @__PURE__ */ jsxRuntime.jsx(Tabs.Root, { ref, defaultValue: "edit", children: /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { direction: "column", gap: "2", children: [
10596
- /* @__PURE__ */ jsxRuntime.jsxs(Tabs.List, { children: [
10597
- /* @__PURE__ */ jsxRuntime.jsx(Tabs.Trigger, { value: "edit", children: "Edit" }),
10598
- /* @__PURE__ */ jsxRuntime.jsx(Tabs.Trigger, { value: "preview", children: "Preview" })
10599
- ] }),
10837
+ /* @__PURE__ */ jsxRuntime.jsxs(
10838
+ Tabs.List,
10839
+ {
10840
+ style: {
10841
+ display: "flex",
10842
+ position: "sticky",
10843
+ top: 0,
10844
+ zIndex: 2e3,
10845
+ backgroundColor: "var(--color-background)"
10846
+ },
10847
+ children: [
10848
+ /* @__PURE__ */ jsxRuntime.jsx(Tabs.Trigger, { style: { flex: 1 }, value: "edit", children: "Edit" }),
10849
+ /* @__PURE__ */ jsxRuntime.jsx(Tabs.Trigger, { style: { flex: 1 }, value: "preview", children: "Preview" })
10850
+ ]
10851
+ }
10852
+ ),
10600
10853
  /* @__PURE__ */ jsxRuntime.jsxs(Tabs.Content, { value: "edit", children: [
10601
- FormBuilderHeading,
10602
10854
  /* @__PURE__ */ jsxRuntime.jsxs(blocks.Text, { children: [
10603
- "Add a new form field by clicking a + button. Specify options for each field, then drag and drop to rearrange them. You can see what a submitted form might look like in the",
10855
+ "Create your form using various field types. Sections can be",
10604
10856
  " ",
10605
- /* @__PURE__ */ jsxRuntime.jsx("em", { children: "Preview" }),
10606
- " tab, but",
10857
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "conditionally rendered" }),
10858
+ " based on",
10607
10859
  " ",
10608
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "field values entered on this page will not be saved." })
10860
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "answers to fields in preceding sections. " })
10609
10861
  ] }),
10610
10862
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Flex, { asChild: true, direction: "column", gap: "2", mt: "3", children: /* @__PURE__ */ jsxRuntime.jsxs("form", { id: formId, onSubmit: formik$1.handleSubmit, children: [
10611
10863
  /* @__PURE__ */ jsxRuntime.jsxs(formik.FormikProvider, { value: formik$1, children: [
10612
- titleInput,
10613
- descriptionInput,
10864
+ /* @__PURE__ */ jsxRuntime.jsx(
10865
+ PatchField,
10866
+ {
10867
+ name: "title",
10868
+ render: ({ setValue, value, meta }) => /* @__PURE__ */ jsxRuntime.jsx(InputWithHelpText, { severity: "danger", helpText: meta.error ?? null, children: /* @__PURE__ */ jsxRuntime.jsx(
10869
+ blocks.Input,
10870
+ {
10871
+ style: {
10872
+ // var(--accent-a11) for red and var(--accent-1) for gray
10873
+ border: meta.error ? "1px solid #ff9592" : "1px solid #5a6169",
10874
+ paddingLeft: "8px",
10875
+ fontWeight: "bold"
10876
+ },
10877
+ placeholder: "Form title",
10878
+ value,
10879
+ onChange: (event) => {
10880
+ setValue(event.target.value);
10881
+ },
10882
+ maxLength: 100,
10883
+ showInputLength: false,
10884
+ variant: "ghost",
10885
+ size: "large"
10886
+ }
10887
+ ) })
10888
+ }
10889
+ ),
10890
+ /* @__PURE__ */ jsxRuntime.jsx(
10891
+ PatchField,
10892
+ {
10893
+ name: "description",
10894
+ render: ({ setValue, value }) => /* @__PURE__ */ jsxRuntime.jsx(
10895
+ blocks.TextArea,
10896
+ {
10897
+ style: {
10898
+ minHeight: "max-content",
10899
+ border: "1px solid #5a6169",
10900
+ paddingLeft: "8px",
10901
+ paddingTop: "8px"
10902
+ },
10903
+ placeholder: "Explain the purpose of this form",
10904
+ value,
10905
+ onChange: (event) => {
10906
+ setValue(event.target.value);
10907
+ },
10908
+ resize: "vertical",
10909
+ maxLength: 1e3,
10910
+ showInputLength: false,
10911
+ variant: "ghost"
10912
+ }
10913
+ )
10914
+ }
10915
+ ),
10614
10916
  /* @__PURE__ */ jsxRuntime.jsx(FieldsEditor, {}),
10615
10917
  /* @__PURE__ */ jsxRuntime.jsx(blocks.Text, { severity: "danger", size: "1", children: typeof formik$1.errors.fields === "string" && formik$1.errors.fields })
10616
10918
  ] }),
10617
- /* @__PURE__ */ jsxRuntime.jsxs(blocks.Flex, { justify: "end", gap: "2", children: [
10618
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "soft", onClick: onCancel, children: "Cancel" }),
10619
- /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", disabled: !formik$1.isValid, children: "Save" })
10620
- ] })
10919
+ /* @__PURE__ */ jsxRuntime.jsxs(
10920
+ blocks.Flex,
10921
+ {
10922
+ justify: "end",
10923
+ align: "center",
10924
+ gap: "2",
10925
+ style: {
10926
+ position: "sticky",
10927
+ bottom: 0,
10928
+ paddingBottom: "10px",
10929
+ paddingRight: "10px"
10930
+ },
10931
+ children: [
10932
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "button", variant: "solid", severity: "info", onClick: onCancel, children: "Cancel" }),
10933
+ /* @__PURE__ */ jsxRuntime.jsx(blocks.Button, { type: "submit", children: "Save form" })
10934
+ ]
10935
+ }
10936
+ )
10621
10937
  ] }) })
10622
10938
  ] }),
10623
10939
  /* @__PURE__ */ jsxRuntime.jsx(Tabs.Content, { value: "preview", children: /* @__PURE__ */ jsxRuntime.jsx(FormRenderer, { schema: previewSchema, onSubmit: previewSubmit }) })
@@ -10638,6 +10954,7 @@ var __publicField = (obj, key, value) => {
10638
10954
  FormRenderer,
10639
10955
  FormSubmissionBrowser,
10640
10956
  FormSubmissionViewer,
10957
+ InputWithHelpText,
10641
10958
  InputWithLabel,
10642
10959
  InputWithLabelAndHelpText,
10643
10960
  MultiSelectField,
@@ -10656,12 +10973,22 @@ var __publicField = (obj, key, value) => {
10656
10973
  TextInput,
10657
10974
  deserialize,
10658
10975
  deserializeField,
10976
+ emptyBaseField,
10977
+ emptyBooleanField,
10978
+ emptyDateField,
10979
+ emptyMultiSelectField,
10980
+ emptyMultiStringField,
10981
+ emptyNumberField,
10982
+ emptySelectField,
10983
+ emptyStringField,
10984
+ emptyTextField,
10659
10985
  formRevisionToSchema,
10660
10986
  isConditionMet,
10661
10987
  useFieldInput,
10662
10988
  useFieldInputs,
10663
10989
  useFormikInput,
10664
- valueIsFile
10990
+ valueIsFile,
10991
+ valueIsFormikUserFormRevision
10665
10992
  }, Symbol.toStringTag, { value: "Module" }));
10666
10993
  exports2.APIError = APIError;
10667
10994
  exports2.AttachmentService = AttachmentService;
@@ -10693,6 +11020,7 @@ var __publicField = (obj, key, value) => {
10693
11020
  exports2.FormSubmissionViewer = FormSubmissionViewer;
10694
11021
  exports2.GREEN = GREEN;
10695
11022
  exports2.HttpMethod = HttpMethod;
11023
+ exports2.InputWithHelpText = InputWithHelpText;
10696
11024
  exports2.InputWithLabel = InputWithLabel;
10697
11025
  exports2.InputWithLabelAndHelpText = InputWithLabelAndHelpText;
10698
11026
  exports2.IssueCommentService = IssueCommentService;
@@ -10736,7 +11064,6 @@ var __publicField = (obj, key, value) => {
10736
11064
  exports2.WorkspaceService = WorkspaceService;
10737
11065
  exports2.YELLOW = YELLOW;
10738
11066
  exports2._setLatestRetryTime = _setLatestRetryTime;
10739
- exports2.acceptProjectInvite = acceptProjectInvite;
10740
11067
  exports2.addAttachment = addAttachment;
10741
11068
  exports2.addAttachments = addAttachments;
10742
11069
  exports2.addCategory = addCategory;
@@ -10807,6 +11134,15 @@ var __publicField = (obj, key, value) => {
10807
11134
  exports2.emailDomainsReducer = emailDomainsReducer;
10808
11135
  exports2.emailDomainsSlice = emailDomainsSlice;
10809
11136
  exports2.emailRegex = emailRegex;
11137
+ exports2.emptyBaseField = emptyBaseField;
11138
+ exports2.emptyBooleanField = emptyBooleanField;
11139
+ exports2.emptyDateField = emptyDateField;
11140
+ exports2.emptyMultiSelectField = emptyMultiSelectField;
11141
+ exports2.emptyMultiStringField = emptyMultiStringField;
11142
+ exports2.emptyNumberField = emptyNumberField;
11143
+ exports2.emptySelectField = emptySelectField;
11144
+ exports2.emptyStringField = emptyStringField;
11145
+ exports2.emptyTextField = emptyTextField;
10810
11146
  exports2.enqueue = enqueue;
10811
11147
  exports2.enqueueRequest = enqueueRequest;
10812
11148
  exports2.errorColor = errorColor;
@@ -10985,7 +11321,6 @@ var __publicField = (obj, key, value) => {
10985
11321
  exports2.selectProjectUsersAsMapping = selectProjectUsersAsMapping;
10986
11322
  exports2.selectProjectUsersIds = selectProjectUsersIds;
10987
11323
  exports2.selectProjects = selectProjects;
10988
- exports2.selectProjectsWithAccess = selectProjectsWithAccess;
10989
11324
  exports2.selectRecentIssueIds = selectRecentIssueIds;
10990
11325
  exports2.selectRecentIssuesAsSearchResults = selectRecentIssuesAsSearchResults;
10991
11326
  exports2.selectRecentProjects = selectRecentProjects;
@@ -11091,6 +11426,7 @@ var __publicField = (obj, key, value) => {
11091
11426
  exports2.userReducer = userReducer;
11092
11427
  exports2.userSlice = userSlice;
11093
11428
  exports2.valueIsFile = valueIsFile;
11429
+ exports2.valueIsFormikUserFormRevision = valueIsFormikUserFormRevision;
11094
11430
  exports2.warningColor = warningColor;
11095
11431
  exports2.workspaceReducer = workspaceReducer;
11096
11432
  exports2.workspaceSlice = workspaceSlice;