@overmap-ai/forms 1.0.4-form-editor-revamp.0 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/forms.js CHANGED
@@ -1,31 +1,37 @@
1
- var jt = Object.defineProperty;
2
- var Ht = (o, i, e) => i in o ? jt(o, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[i] = e;
3
- var m = (o, i, e) => (Ht(o, typeof i != "symbol" ? i + "" : i, e), e);
4
- import { jsx as r, jsxs as b, Fragment as Ze } from "react/jsx-runtime";
5
- import { Flex as y, Text as V, useSeverityColor as ue, Checkbox as Ut, CheckCircledIcon as Gt, TextField as ae, FontFamilyIcon as Kt, CalendarIcon as Yt, InputIcon as Qt, TextArea as Xt, RowsIcon as Zt, Select as vt, Box as ge, IconButton as K, PlusIcon as _e, Badge as He, Cross1Icon as wt, ListBulletIcon as Jt, DropdownMenuIcon as ei, MultiSelect as ti, CheckboxIcon as ii, Card as fe, Heading as Me, Button as H, UploadIcon as xt, ButtonList as Oe, divButtonProps as ni, StarFilledIcon as ri, StarIcon as oi, QuestionMarkCircledIcon as si, PersonIcon as li, Tooltip as ai, Avatar as ci, Separator as di, Pencil1Icon as ui, TrashIcon as fi, CopyIcon as mi, DragHandleDots2Icon as pi, DropdownMenu as hi, DotsVerticalIcon as gi, useAlertDialog as bi, Em as yi, Strong as ut, useToast as vi, Tabs as Z } from "@overmap-ai/blocks";
6
- import { useField as Je, useFormikContext as me, useFormik as et, FormikProvider as tt } from "formik";
7
- import wi, { useMemo as x, memo as S, useCallback as T, useState as Y, useEffect as ve, useRef as xi, forwardRef as pe, createElement as ft, useReducer as Ii } from "react";
8
- import { DragDropContext as It, Droppable as it, Draggable as nt } from "@hello-pangea/dnd";
9
- import { slugify as Ci, useAppSelector as M, selectFormRevision as Ct, useSDK as Ft, selectSubmissionAttachments as Fi, selectFilteredUserForms as Ti, selectUserFormMapping as Si, selectOrganization as Tt, selectUser as rt, selectNumberOfUserForms as zi, selectCurrentUser as St, classNames as zt, isToday as Ei, getLocalDateString as Li, selectLatestFormRevision as Ai, useFileSrc as Pi, selectSubmissionsForForm as ki } from "@overmap-ai/core";
10
- import ce from "lodash.get";
11
- import ot from "lodash.set";
12
- class Et {
13
- constructor(i) {
14
- m(this, "type");
15
- m(this, "identifier");
16
- m(this, "description");
17
- const { description: e = null, identifier: t, type: n } = i;
18
- this.identifier = t, this.description = e, this.type = n;
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
8
+ import { Flex, Text, useSeverityColor, Checkbox, CheckCircledIcon, TextField as TextField$1, FontFamilyIcon, CalendarIcon, InputIcon, TextArea, RowsIcon, Select, Box, IconButton, PlusIcon, Badge, Cross1Icon, ListBulletIcon, DropdownMenuIcon, MultiSelect, CheckboxIcon, Card, Heading, Button, UploadIcon, ButtonList, divButtonProps, StarFilledIcon, StarIcon, QuestionMarkCircledIcon, PersonIcon, Tooltip, Avatar, Separator, Dialog, Pencil1Icon, TrashIcon, CopyIcon, DragHandleDots2Icon, DropdownMenu, DotsVerticalIcon, useAlertDialog, Em, Strong, useToast, Tabs } from "@overmap-ai/blocks";
9
+ import { useField, useFormikContext, useFormik, FormikProvider } from "formik";
10
+ import React, { useMemo, memo, useCallback, useState, useEffect, useRef, forwardRef, useReducer } from "react";
11
+ import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
12
+ import { slugify, useAppSelector, selectFormRevision, useSDK, selectSubmissionAttachments, selectFilteredUserForms, selectUserFormMapping, selectOrganization, selectUser, selectNumberOfUserForms, selectCurrentUser, classNames, isToday, getLocalDateString, selectLatestFormRevision, useFileSrc, selectSubmissionsForForm } from "@overmap-ai/core";
13
+ import get from "lodash.get";
14
+ import set from "lodash.set";
15
+ class BaseFormElement {
16
+ constructor(options) {
17
+ __publicField(this, "type");
18
+ __publicField(this, "identifier");
19
+ __publicField(this, "description");
20
+ const { description: description2 = null, identifier, type } = options;
21
+ this.identifier = identifier;
22
+ this.description = description2;
23
+ this.type = type;
19
24
  }
20
25
  getId() {
21
26
  return this.identifier;
22
27
  }
23
- static deserialize(i) {
28
+ static deserialize(_data) {
24
29
  throw new Error(`${this.name} must implement deserialize.`);
25
30
  }
26
31
  _serialize() {
27
- if (!this.identifier)
32
+ if (!this.identifier) {
28
33
  throw new Error("Field identifier must be set before serializing.");
34
+ }
29
35
  return {
30
36
  type: this.type,
31
37
  identifier: this.identifier,
@@ -33,46 +39,51 @@ class Et {
33
39
  };
34
40
  }
35
41
  }
36
- class O extends Et {
37
- constructor(e) {
38
- const { label: t, required: n, fieldValidators: s = [], formValidators: a = [], ...c } = e;
39
- super(c);
40
- m(this, "required");
41
- m(this, "formValidators");
42
- m(this, "fieldValidators");
43
- m(this, "label");
42
+ class BaseField extends BaseFormElement {
43
+ constructor(options) {
44
+ const { label, required, fieldValidators = [], formValidators = [], ...base } = options;
45
+ super(base);
46
+ __publicField(this, "required");
47
+ __publicField(this, "formValidators");
48
+ __publicField(this, "fieldValidators");
49
+ __publicField(this, "label");
44
50
  /**
45
51
  * By default, validation doesn't execute on `onChange` events when editing fields
46
52
  * until the field has been `touched`. This can be overridden by setting this to `false`
47
53
  * if you want to validate on every `onChange` event. This is important for fields like booleans
48
54
  * which don't have a `onBlur` event (which is used to set the `touched` state).
49
55
  */
50
- m(this, "onlyValidateAfterTouched", !0);
51
- this.label = t, this.required = n, this.fieldValidators = s, this.formValidators = a;
56
+ __publicField(this, "onlyValidateAfterTouched", true);
57
+ this.label = label;
58
+ this.required = required;
59
+ this.fieldValidators = fieldValidators;
60
+ this.formValidators = formValidators;
52
61
  }
53
62
  static getFieldCreationSchema() {
54
63
  return [];
55
64
  }
56
- isBlank(e) {
57
- return e == null || e === "";
65
+ isBlank(value) {
66
+ return value === null || value === void 0 || value === "";
58
67
  }
59
- getValueFromChangeEvent(e) {
60
- return e.target.value;
68
+ getValueFromChangeEvent(event) {
69
+ return event.target.value;
61
70
  }
62
- getError(e, t) {
63
- if (this.required && this.isBlank(e))
71
+ getError(value, allValues) {
72
+ if (this.required && this.isBlank(value)) {
64
73
  return "This field is required.";
65
- for (const n of this.getFieldValidators()) {
66
- const s = n(e);
67
- if (s)
68
- return s;
69
74
  }
70
- if (t)
71
- for (const n of this.getFormValidators()) {
72
- const s = n(e, t);
73
- if (s)
74
- return s;
75
+ for (const validator of this.getFieldValidators()) {
76
+ const error = validator(value);
77
+ if (error)
78
+ return error;
79
+ }
80
+ if (allValues) {
81
+ for (const validator of this.getFormValidators()) {
82
+ const error = validator(value, allValues);
83
+ if (error)
84
+ return error;
75
85
  }
86
+ }
76
87
  }
77
88
  // TODO: We can probably combine _serialize and serialize.
78
89
  _serialize() {
@@ -89,168 +100,218 @@ class O extends Et {
89
100
  return [...this.formValidators];
90
101
  }
91
102
  }
92
- m(O, "fieldTypeName"), m(O, "fieldTypeDescription");
93
- const Vi = "_description_17zed_1", Re = {
94
- description: Vi
95
- }, q = (o) => {
96
- const { label: i, children: e, severity: t, inputId: n, labelId: s, flexProps: a } = o;
97
- return /* @__PURE__ */ r(y, { direction: "column", gap: "1", asChild: !0, ...a, children: /* @__PURE__ */ b("label", { htmlFor: n, children: [
98
- /* @__PURE__ */ r(V, { severity: t, id: s, children: i }),
99
- e
103
+ __publicField(BaseField, "fieldTypeName");
104
+ __publicField(BaseField, "fieldTypeDescription");
105
+ const description$1 = "_description_17zed_1";
106
+ const styles$3 = {
107
+ description: description$1
108
+ };
109
+ const InputWithLabel = (props) => {
110
+ const { label, children, severity, inputId, labelId, flexProps } = props;
111
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "1", asChild: true, ...flexProps, children: /* @__PURE__ */ jsxs("label", { htmlFor: inputId, children: [
112
+ /* @__PURE__ */ jsx(Text, { severity, id: labelId, children: label }),
113
+ children
100
114
  ] }) });
101
- }, W = (o) => {
102
- const { helpText: i, children: e, severity: t } = o;
103
- return /* @__PURE__ */ b(y, { direction: "column", gap: "1", children: [
104
- e,
105
- /* @__PURE__ */ r(y, { direction: "column", children: /* @__PURE__ */ r(V, { size: "1", severity: t, className: Re.description, children: i }) })
115
+ };
116
+ const InputWithLabelAndHelpText = (props) => {
117
+ const { helpText, children, severity } = props;
118
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", children: [
119
+ children,
120
+ /* @__PURE__ */ jsx(Flex, { direction: "column", children: /* @__PURE__ */ jsx(Text, { size: "1", severity, className: styles$3.description, children: helpText }) })
106
121
  ] });
107
- }, j = (o) => {
108
- const { id: i, field: e, formId: t, ...n } = o, [s, a, c] = Je(e.getId()), { touched: l } = a, d = a.error ?? e.description, u = a.error ? "danger" : void 0, f = i ?? `${t}-${e.getId()}-input`, p = `${f}-label`, h = e.required ? `${e.label} *` : e.label, g = x(() => ({
109
- ...s,
110
- onChange: (I) => {
111
- const w = e.getValueFromChangeEvent(I);
112
- c.setValue(w, !1).then(), (l || !e.onlyValidateAfterTouched) && c.setError(e.getError(w));
113
- },
114
- onBlur: (I) => {
115
- c.setTouched(!0, !1).then(), c.setError(e.getError(e.getValueFromChangeEvent(I)));
116
- }
117
- }), [e, s, c, l]);
122
+ };
123
+ const useFormikInput = (props) => {
124
+ const { id, field, formId: formId2, ...rest } = props;
125
+ const [fieldProps, meta, helpers] = useField(field.getId());
126
+ const { touched } = meta;
127
+ const helpText = meta.error ?? field.description;
128
+ const severity = meta.error ? "danger" : void 0;
129
+ const inputId = id ?? `${formId2}-${field.getId()}-input`;
130
+ const labelId = `${inputId}-label`;
131
+ const label = field.required ? `${field.label} *` : field.label;
132
+ const fieldPropsWithValidation = useMemo(() => {
133
+ const handleChange = (e) => {
134
+ const value = field.getValueFromChangeEvent(e);
135
+ helpers.setValue(value, false).then();
136
+ if (touched || !field.onlyValidateAfterTouched) {
137
+ helpers.setError(field.getError(value));
138
+ }
139
+ };
140
+ const handleBlur = (e) => {
141
+ helpers.setTouched(true, false).then();
142
+ helpers.setError(field.getError(field.getValueFromChangeEvent(e)));
143
+ };
144
+ return {
145
+ ...fieldProps,
146
+ onChange: handleChange,
147
+ onBlur: handleBlur
148
+ };
149
+ }, [field, fieldProps, helpers, touched]);
118
150
  return [
119
151
  {
120
- helpText: d,
121
- severity: u,
122
- inputId: f,
123
- labelId: p,
124
- label: h,
125
- fieldProps: g,
126
- helpers: c,
127
- field: e
152
+ helpText,
153
+ severity,
154
+ inputId,
155
+ labelId,
156
+ label,
157
+ fieldProps: fieldPropsWithValidation,
158
+ helpers,
159
+ field
128
160
  },
129
- { ...n, "aria-labelledby": p }
161
+ { ...rest, "aria-labelledby": labelId }
130
162
  ];
131
- }, $i = [!0, "true"], Di = S(function(i) {
132
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c }, l] = j(i), d = ue(n), u = $i.includes(c.value);
133
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(
134
- q,
163
+ };
164
+ const truthyValues = [true, "true"];
165
+ const BooleanInput = memo(function BooleanInput2(props) {
166
+ const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
167
+ const color = useSeverityColor(severity);
168
+ const value = truthyValues.includes(fieldProps.value);
169
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(
170
+ InputWithLabel,
135
171
  {
136
- severity: n,
137
- inputId: e,
138
- labelId: t,
139
- label: a,
172
+ severity,
173
+ inputId,
174
+ labelId,
175
+ label,
140
176
  flexProps: { direction: "row-reverse", justify: "end", align: "center", gap: "2" },
141
- children: /* @__PURE__ */ r(
142
- Ut,
177
+ children: /* @__PURE__ */ jsx(
178
+ Checkbox,
143
179
  {
144
- ...l,
145
- ...c,
146
- id: e,
147
- color: d,
148
- value: u.toString(),
149
- checked: u,
150
- onCheckedChange: c.onChange,
180
+ ...rest,
181
+ ...fieldProps,
182
+ id: inputId,
183
+ color,
184
+ value: value.toString(),
185
+ checked: value,
186
+ onCheckedChange: fieldProps.onChange,
151
187
  onChange: void 0,
152
188
  onBlur: void 0
153
189
  }
154
190
  )
155
191
  }
156
192
  ) });
157
- }), J = class J extends O {
158
- constructor(e) {
159
- super({ ...e, type: "boolean" });
160
- m(this, "onlyValidateAfterTouched", !1);
193
+ });
194
+ const _BooleanField = class _BooleanField extends BaseField {
195
+ constructor(options) {
196
+ super({ ...options, type: "boolean" });
197
+ __publicField(this, "onlyValidateAfterTouched", false);
161
198
  }
162
199
  // if a BooleanField is required, `false` is considered blank
163
- isBlank(e) {
164
- return this.required && !e;
200
+ isBlank(value) {
201
+ return this.required && !value;
165
202
  }
166
- getValueFromChangeEvent(e) {
167
- return typeof e == "boolean" ? e : e.target.checked;
203
+ getValueFromChangeEvent(event) {
204
+ if (typeof event === "boolean")
205
+ return event;
206
+ return event.target.checked;
168
207
  }
169
208
  serialize() {
170
209
  return super._serialize();
171
210
  }
172
- static deserialize(e) {
173
- if (e.type !== "boolean")
211
+ static deserialize(data) {
212
+ if (data.type !== "boolean")
174
213
  throw new Error("Type mismatch.");
175
- return new J(e);
214
+ return new _BooleanField(data);
176
215
  }
177
- getInput(e) {
178
- return /* @__PURE__ */ r(Di, { ...e, field: this });
216
+ getInput(props) {
217
+ return /* @__PURE__ */ jsx(BooleanInput, { ...props, field: this });
179
218
  }
180
219
  };
181
- m(J, "fieldTypeName", "Checkbox"), m(J, "fieldTypeDescription", "Perfect for both optional and required yes/no questions."), m(J, "Icon", Gt);
182
- let de = J;
183
- const _i = S(function(i) {
184
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c, field: l }, d] = j(i), u = ue(n);
185
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(
186
- ae.Input,
220
+ __publicField(_BooleanField, "fieldTypeName", "Checkbox");
221
+ __publicField(_BooleanField, "fieldTypeDescription", "Perfect for both optional and required yes/no questions.");
222
+ __publicField(_BooleanField, "Icon", CheckCircledIcon);
223
+ let BooleanField = _BooleanField;
224
+ const NumberInput$1 = memo(function NumberInput2(props) {
225
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
226
+ const color = useSeverityColor(severity);
227
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(
228
+ TextField$1.Input,
187
229
  {
188
- ...d,
189
- ...c,
230
+ ...rest,
231
+ ...fieldProps,
190
232
  type: "number",
191
- id: e,
192
- min: l.minimum,
193
- max: l.maximum,
194
- step: l.integers ? 1 : 0.1,
195
- color: u
233
+ id: inputId,
234
+ min: field.minimum,
235
+ max: field.maximum,
236
+ step: field.integers ? 1 : 0.1,
237
+ color
196
238
  }
197
239
  ) }) });
198
- }), B = class B extends O {
199
- constructor(e) {
240
+ });
241
+ const _NumberField = class _NumberField extends BaseField {
242
+ constructor(options) {
200
243
  const {
201
- minimum: t = Number.MIN_SAFE_INTEGER,
202
- maximum: n = Number.MAX_SAFE_INTEGER,
203
- integers: s = !1,
204
- ...a
205
- } = e;
206
- super({ ...a, type: "number" });
207
- m(this, "minimum");
208
- m(this, "maximum");
209
- m(this, "integers");
210
- this.minimum = t, this.maximum = n, this.integers = s;
211
- }
212
- getValueFromChangeEvent(e) {
213
- const t = Number.parseFloat(e.target.value);
214
- return Number.isNaN(t) ? "" : t;
244
+ minimum = Number.MIN_SAFE_INTEGER,
245
+ maximum = Number.MAX_SAFE_INTEGER,
246
+ integers = false,
247
+ ...base
248
+ } = options;
249
+ super({ ...base, type: "number" });
250
+ __publicField(this, "minimum");
251
+ __publicField(this, "maximum");
252
+ __publicField(this, "integers");
253
+ this.minimum = minimum;
254
+ this.maximum = maximum;
255
+ this.integers = integers;
256
+ }
257
+ getValueFromChangeEvent(event) {
258
+ const number = Number.parseFloat(event.target.value);
259
+ if (Number.isNaN(number))
260
+ return "";
261
+ return number;
215
262
  }
216
263
  static getFieldCreationSchema() {
217
264
  return [
218
- new B({
265
+ new _NumberField({
219
266
  label: "Minimum",
220
267
  description: "Minimum value",
221
- integers: !0,
222
- required: !1,
268
+ integers: true,
269
+ required: false,
223
270
  identifier: "minimum",
224
271
  formValidators: [this._validateMin]
225
272
  }),
226
- new B({
273
+ new _NumberField({
227
274
  label: "Maximum",
228
275
  description: "Maximum value",
229
- integers: !0,
230
- required: !1,
276
+ integers: true,
277
+ required: false,
231
278
  identifier: "maximum",
232
279
  formValidators: [this._validateMax]
233
280
  }),
234
- new de({
281
+ new BooleanField({
235
282
  label: "Integers",
236
283
  description: "Whole numbers only",
237
- required: !1,
284
+ required: false,
238
285
  identifier: "integers"
239
286
  })
240
287
  ];
241
288
  }
242
289
  getFieldValidators() {
243
- const e = super.getFieldValidators(), t = this.minimum, n = this.maximum;
244
- return typeof t == "number" && e.push((s) => {
245
- if (typeof s == "number" && s < t)
246
- return `Must be at least ${this.minimum}.`;
247
- }), typeof n == "number" && e.push((s) => {
248
- if (typeof s == "number" && s > n)
249
- return `Must be at most ${this.maximum}.`;
250
- }), this.integers && e.push((s) => {
251
- if (typeof s == "number" && !Number.isInteger(s))
252
- return "Must be a whole number.";
253
- }), e;
290
+ const validators = super.getFieldValidators();
291
+ const min = this.minimum;
292
+ const max = this.maximum;
293
+ if (typeof min === "number") {
294
+ validators.push((value) => {
295
+ if (typeof value === "number" && value < min) {
296
+ return `Must be at least ${this.minimum}.`;
297
+ }
298
+ });
299
+ }
300
+ if (typeof max === "number") {
301
+ validators.push((value) => {
302
+ if (typeof value === "number" && value > max) {
303
+ return `Must be at most ${this.maximum}.`;
304
+ }
305
+ });
306
+ }
307
+ if (this.integers) {
308
+ validators.push((value) => {
309
+ if (typeof value === "number" && !Number.isInteger(value)) {
310
+ return "Must be a whole number.";
311
+ }
312
+ });
313
+ }
314
+ return validators;
254
315
  }
255
316
  serialize() {
256
317
  return {
@@ -260,90 +321,121 @@ const _i = S(function(i) {
260
321
  integers: this.integers
261
322
  };
262
323
  }
263
- static deserialize(e) {
264
- if (e.type !== "number")
324
+ static deserialize(data) {
325
+ if (data.type !== "number")
265
326
  throw new Error("Type mismatch.");
266
- return new B(e);
327
+ return new _NumberField(data);
267
328
  }
268
- getInput(e) {
269
- return /* @__PURE__ */ r(_i, { field: this, ...e });
329
+ getInput(props) {
330
+ return /* @__PURE__ */ jsx(NumberInput$1, { field: this, ...props });
270
331
  }
271
332
  };
272
- m(B, "fieldTypeName", "Number"), m(B, "fieldTypeDescription", "Allows specifying a number within a given range."), m(B, "Icon", Kt), m(B, "_validateMin", (e, t) => typeof t.maximum == "number" && typeof e == "number" && t.maximum < e ? "Minimum cannot be greater than minimum." : null), m(B, "_validateMax", (e, t) => typeof t.minimum == "number" && typeof e == "number" && t.minimum > e ? "Maximum cannot be less than minimum." : null);
273
- let Q = B;
274
- const Mi = S(function(i) {
275
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c }, l] = j(i), d = ue(n), u = c.value ? c.value.split("T")[0] : "";
276
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(ae.Input, { ...l, ...c, type: "date", id: e, color: d, value: u }) }) });
277
- }), ee = class ee extends O {
278
- constructor(e) {
279
- super({ ...e, type: "date" });
280
- m(this, "onlyValidateAfterTouched", !1);
333
+ __publicField(_NumberField, "fieldTypeName", "Number");
334
+ __publicField(_NumberField, "fieldTypeDescription", "Allows specifying a number within a given range.");
335
+ __publicField(_NumberField, "Icon", FontFamilyIcon);
336
+ __publicField(_NumberField, "_validateMin", (value, allValues) => {
337
+ if (typeof allValues.maximum === "number" && typeof value === "number" && allValues.maximum < value) {
338
+ return "Minimum cannot be greater than minimum.";
339
+ }
340
+ return null;
341
+ });
342
+ __publicField(_NumberField, "_validateMax", (value, allValues) => {
343
+ if (typeof allValues.minimum === "number" && typeof value === "number" && allValues.minimum > value) {
344
+ return "Maximum cannot be less than minimum.";
345
+ }
346
+ return null;
347
+ });
348
+ let NumberField = _NumberField;
349
+ const DateInput = memo(function DateInput2(props) {
350
+ const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
351
+ const color = useSeverityColor(severity);
352
+ const value = fieldProps.value ? fieldProps.value.split("T")[0] : "";
353
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(TextField$1.Input, { ...rest, ...fieldProps, type: "date", id: inputId, color, value }) }) });
354
+ });
355
+ const _DateField = class _DateField extends BaseField {
356
+ constructor(options) {
357
+ super({ ...options, type: "date" });
358
+ __publicField(this, "onlyValidateAfterTouched", false);
281
359
  }
282
360
  serialize() {
283
361
  return super._serialize();
284
362
  }
285
- getValueFromChangeEvent(e) {
286
- return new Date(e.target.value).toISOString();
363
+ getValueFromChangeEvent(event) {
364
+ return new Date(event.target.value).toISOString();
287
365
  }
288
- static deserialize(e) {
289
- if (e.type !== "date")
366
+ static deserialize(data) {
367
+ if (data.type !== "date")
290
368
  throw new Error("Type mismatch.");
291
- return new ee(e);
369
+ return new _DateField(data);
292
370
  }
293
- getInput(e) {
294
- return /* @__PURE__ */ r(Mi, { field: this, ...e });
371
+ getInput(props) {
372
+ return /* @__PURE__ */ jsx(DateInput, { field: this, ...props });
295
373
  }
296
374
  };
297
- m(ee, "fieldTypeName", "Date"), m(ee, "fieldTypeDescription", "Allows specifying a date."), m(ee, "Icon", Yt);
298
- let Ue = ee;
299
- class ze extends O {
300
- constructor(e) {
301
- const { minLength: t, maxLength: n = 5e3, ...s } = e;
302
- super(s);
303
- m(this, "minLength");
304
- m(this, "maxLength");
305
- this.minLength = t ? Math.max(t, 0) : void 0, this.maxLength = n ? Math.max(n, 0) : 5e3;
375
+ __publicField(_DateField, "fieldTypeName", "Date");
376
+ __publicField(_DateField, "fieldTypeDescription", "Allows specifying a date.");
377
+ __publicField(_DateField, "Icon", CalendarIcon);
378
+ let DateField = _DateField;
379
+ class StringOrTextField extends BaseField {
380
+ constructor(options) {
381
+ const { minLength, maxLength = 5e3, ...base } = options;
382
+ super(base);
383
+ __publicField(this, "minLength");
384
+ __publicField(this, "maxLength");
385
+ this.minLength = minLength ? Math.max(minLength, 0) : void 0;
386
+ this.maxLength = maxLength ? Math.max(maxLength, 0) : 5e3;
306
387
  }
307
388
  static getFieldCreationSchema() {
308
389
  return [
309
390
  // min, max
310
- new Q({
391
+ new NumberField({
311
392
  label: "Minimum length",
312
393
  description: "Minimum number of characters",
313
- required: !1,
394
+ required: false,
314
395
  identifier: "minimum_length",
315
396
  minimum: 0,
316
397
  maximum: 100,
317
398
  formValidators: [this._validateMin],
318
- integers: !0
399
+ integers: true
319
400
  }),
320
- new Q({
401
+ new NumberField({
321
402
  label: "Maximum length",
322
403
  description: "Maximum number of characters",
323
- required: !1,
404
+ required: false,
324
405
  identifier: "maximum_length",
325
406
  minimum: 1,
326
407
  maximum: 5e3,
327
408
  // TODO: depends on short vs long text
328
409
  formValidators: [this._validateMax],
329
410
  // TODO: default: 500 (see: "Short text fields can hold up to 500 characters on a single line.")
330
- integers: !0
411
+ integers: true
331
412
  })
332
413
  ];
333
414
  }
334
415
  getFieldValidators() {
335
- const e = super.getFieldValidators();
336
- return this.minLength && e.push((t) => {
337
- if (this.minLength && (!t || t.length < this.minLength))
338
- return !this.required && !t ? null : `Minimum ${this.minLength} character(s).`;
339
- }), this.maxLength && e.push((t) => {
340
- if (typeof t == "string" && this.maxLength && t.length > this.maxLength)
341
- return `Maximum ${this.maxLength} character(s).`;
342
- }), e;
416
+ const validators = super.getFieldValidators();
417
+ if (this.minLength) {
418
+ validators.push((value) => {
419
+ if (this.minLength && (!value || value.length < this.minLength)) {
420
+ if (!this.required && !value)
421
+ return null;
422
+ return `Minimum ${this.minLength} character(s).`;
423
+ }
424
+ });
425
+ }
426
+ if (this.maxLength) {
427
+ validators.push((value) => {
428
+ if (typeof value === "string" && this.maxLength && value.length > this.maxLength) {
429
+ return `Maximum ${this.maxLength} character(s).`;
430
+ }
431
+ });
432
+ }
433
+ return validators;
343
434
  }
344
435
  _serialize() {
345
- if (!this.identifier)
436
+ if (!this.identifier) {
346
437
  throw new Error("Field identifier must be set before serializing.");
438
+ }
347
439
  return {
348
440
  ...super._serialize(),
349
441
  minimum_length: this.minLength,
@@ -355,301 +447,405 @@ class ze extends O {
355
447
  * This function validates that the value given for "minimum length" (when creating a new field) is less than or
356
448
  * equal to the value given for "maximum length".
357
449
  */
358
- m(ze, "_validateMin", (e, t) => typeof t.maximum_length == "number" && typeof e == "number" && t.maximum_length < e ? "Minimum cannot be greater than maximum." : null), /**
450
+ __publicField(StringOrTextField, "_validateMin", (value, allValues) => {
451
+ if (typeof allValues.maximum_length === "number" && typeof value === "number" && allValues.maximum_length < value) {
452
+ return "Minimum cannot be greater than maximum.";
453
+ }
454
+ return null;
455
+ });
456
+ /**
359
457
  * This function validates that the value given for "maximum length" (when creating a new field) is greater than or
360
458
  * equal to the value given for "minimum length".
361
459
  */
362
- m(ze, "_validateMax", (e, t) => {
363
- if (typeof e != "number")
460
+ __publicField(StringOrTextField, "_validateMax", (value, allValues) => {
461
+ if (typeof value !== "number")
462
+ return null;
463
+ const { minimum_length: minimumLength } = allValues;
464
+ if (typeof minimumLength !== "number") {
364
465
  return null;
365
- const { minimum_length: n } = t;
366
- return typeof n != "number" ? null : n > e ? "Maximum cannot be less than minimum." : null;
466
+ }
467
+ if (minimumLength > value) {
468
+ return "Maximum cannot be less than minimum.";
469
+ }
470
+ return null;
471
+ });
472
+ const StringInput = memo(function StringInput2(props) {
473
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
474
+ const color = useSeverityColor(severity);
475
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(TextField$1.Input, { ...rest, ...fieldProps, type: field.inputType, id: inputId, color }) }) });
367
476
  });
368
- const Oi = S(function(i) {
369
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c, field: l }, d] = j(i), u = ue(n);
370
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(ae.Input, { ...d, ...c, type: l.inputType, id: e, color: u }) }) });
371
- }), te = class te extends ze {
372
- constructor(e) {
373
- const { inputType: t = "text", ...n } = e, s = e.maxLength ? Math.min(500, e.maxLength) : 500, a = e.minLength ? Math.min(e.minLength, s) : void 0;
374
- super({ ...n, maxLength: s, minLength: a, type: "string" });
375
- m(this, "inputType");
376
- this.inputType = t;
477
+ const _StringField = class _StringField extends StringOrTextField {
478
+ constructor(options) {
479
+ const { inputType = "text", ...rest } = options;
480
+ const maxLength = options.maxLength ? Math.min(500, options.maxLength) : 500;
481
+ const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
482
+ super({ ...rest, maxLength, minLength, type: "string" });
483
+ __publicField(this, "inputType");
484
+ this.inputType = inputType;
377
485
  }
378
486
  serialize() {
379
487
  return { ...super._serialize(), input_type: this.inputType };
380
488
  }
381
- static deserialize(e) {
382
- if (e.type !== "string")
489
+ static deserialize(data) {
490
+ if (data.type !== "string")
383
491
  throw new Error("Type mismatch.");
384
- const { maximum_length: t, minimum_length: n, input_type: s, ...a } = e;
385
- return new te({ ...a, maxLength: t, minLength: n, inputType: s });
492
+ const { maximum_length, minimum_length, input_type, ...rest } = data;
493
+ return new _StringField({ ...rest, maxLength: maximum_length, minLength: minimum_length, inputType: input_type });
386
494
  }
387
- getInput(e) {
388
- return /* @__PURE__ */ r(Oi, { field: this, ...e });
495
+ getInput(props) {
496
+ return /* @__PURE__ */ jsx(StringInput, { field: this, ...props });
389
497
  }
390
498
  };
391
- m(te, "fieldTypeName", "Short Text"), m(te, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line."), m(te, "Icon", Qt);
392
- let be = te;
393
- const Ri = S(function(i) {
394
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c }, l] = j(i);
395
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(Xt, { ...l, ...c, resize: "vertical", id: e, severity: n }) }) });
396
- }), ie = class ie extends ze {
397
- constructor(i) {
398
- const e = i.maxLength ? Math.min(5e3, i.maxLength) : 5e3, t = i.minLength ? Math.min(i.minLength, e) : void 0;
399
- super({ ...i, maxLength: e, minLength: t, type: "text" });
499
+ __publicField(_StringField, "fieldTypeName", "Short Text");
500
+ __publicField(_StringField, "fieldTypeDescription", "Short text fields can hold up to 500 characters on a single line.");
501
+ __publicField(_StringField, "Icon", InputIcon);
502
+ let StringField = _StringField;
503
+ const TextInput = memo(function TextInput2(props) {
504
+ const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
505
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(TextArea, { ...rest, ...fieldProps, resize: "vertical", id: inputId, severity }) }) });
506
+ });
507
+ const _TextField = class _TextField extends StringOrTextField {
508
+ constructor(options) {
509
+ const maxLength = options.maxLength ? Math.min(5e3, options.maxLength) : 5e3;
510
+ const minLength = options.minLength ? Math.min(options.minLength, maxLength) : void 0;
511
+ super({ ...options, maxLength, minLength, type: "text" });
400
512
  }
401
513
  serialize() {
402
514
  return super._serialize();
403
515
  }
404
- static deserialize(i) {
405
- if (i.type !== "text")
516
+ static deserialize(data) {
517
+ if (data.type !== "text")
406
518
  throw new Error("Type mismatch.");
407
- const { maximum_length: e, minimum_length: t, ...n } = i;
408
- return new ie({ ...n, maxLength: e, minLength: t });
519
+ const { maximum_length, minimum_length, ...rest } = data;
520
+ return new _TextField({ ...rest, maxLength: maximum_length, minLength: minimum_length });
409
521
  }
410
- getInput(i) {
411
- return /* @__PURE__ */ r(Ri, { field: this, ...i });
522
+ getInput(props) {
523
+ return /* @__PURE__ */ jsx(TextInput, { field: this, ...props });
412
524
  }
413
525
  };
414
- m(ie, "fieldTypeName", "Paragraph"), m(ie, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines."), m(ie, "Icon", Zt);
415
- let ye = ie;
416
- const Ni = S(function(i) {
417
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c, field: l }, d] = j(i), { onChange: u, onBlur: f } = c, p = x(
418
- () => l.options.map((g) => ({ value: g.value, itemContent: g.label })),
419
- [l.options]
420
- ), h = T(
421
- (g) => {
422
- u(g), f(g);
526
+ __publicField(_TextField, "fieldTypeName", "Paragraph");
527
+ __publicField(_TextField, "fieldTypeDescription", "Paragraph fields can hold up to 5000 characters and can have multiple lines.");
528
+ __publicField(_TextField, "Icon", RowsIcon);
529
+ let TextField = _TextField;
530
+ const SelectInput = memo(function SelectInput2(props) {
531
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
532
+ const { onChange, onBlur } = fieldProps;
533
+ const options = useMemo(
534
+ () => field.options.map((option) => ({ value: option.value, itemContent: option.label })),
535
+ [field.options]
536
+ );
537
+ const handleChange = useCallback(
538
+ (value) => {
539
+ onChange(value);
540
+ onBlur(value);
423
541
  },
424
- [u, f]
542
+ [onChange, onBlur]
425
543
  );
426
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(
427
- vt,
544
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(
545
+ Select,
428
546
  {
429
- items: p,
430
- ...c,
431
- onValueChange: h,
547
+ items: options,
548
+ ...fieldProps,
549
+ onValueChange: handleChange,
432
550
  placeholder: "Select one...",
433
- id: e,
434
- severity: n,
435
- ...d
551
+ id: inputId,
552
+ severity,
553
+ ...rest
436
554
  }
437
555
  ) }) });
438
- }), Ee = (o = "", i = []) => ({
556
+ });
557
+ const emptySection = (id = "", fields = []) => ({
439
558
  type: "section",
440
- fields: i,
441
- identifier: o,
559
+ fields,
560
+ identifier: id,
442
561
  label: null,
443
562
  condition: null,
444
- conditional: !1
445
- }), Bi = (o) => {
446
- if (!o)
447
- return;
448
- const i = o.fields;
449
- let e = [];
450
- const t = [];
451
- for (const n of i)
452
- n.type === "section" ? (e.length > 0 && (t.push(Ee(`AUTO_section-${i.indexOf(n)}`, e)), e = []), t.push(n)) : e.push(n);
453
- return e.length > 0 && t.push(Ee("AUTO_section-last", e)), { ...o, fields: t, description: o.description ?? "" };
563
+ conditional: false
564
+ });
565
+ const wrapRootFieldsWithFieldSection = (revision) => {
566
+ if (!revision)
567
+ return void 0;
568
+ const fields = revision.fields;
569
+ let pending = [];
570
+ const sections = [];
571
+ for (const field of fields) {
572
+ if (field.type === "section") {
573
+ if (pending.length > 0) {
574
+ sections.push(emptySection(`AUTO_section-${fields.indexOf(field)}`, pending));
575
+ pending = [];
576
+ }
577
+ sections.push(field);
578
+ } else {
579
+ pending.push(field);
580
+ }
581
+ }
582
+ if (pending.length > 0) {
583
+ sections.push(emptySection("AUTO_section-last", pending));
584
+ }
585
+ return { ...revision, fields: sections, description: revision.description ?? "" };
454
586
  };
455
- function Ge(o, i, e) {
456
- const t = Array.from(o), [n] = t.splice(i, 1);
457
- if (!n)
587
+ function reorder(list, source, destination) {
588
+ const result = Array.from(list);
589
+ const [removed] = result.splice(source, 1);
590
+ if (!removed)
458
591
  throw new Error("Could not find field to reorder.");
459
- return t.splice(e, 0, n), t;
592
+ result.splice(destination, 0, removed);
593
+ return result;
460
594
  }
461
- function qi(o, i, e) {
462
- const t = Array.from(o);
463
- return t[i] = e, t;
595
+ function replace(list, index, value) {
596
+ const result = Array.from(list);
597
+ result[index] = value;
598
+ return result;
464
599
  }
465
- function Lt(o, i, e) {
466
- const t = Array.from(o ?? []);
467
- return t.splice(i, 0, e), t;
600
+ function insert(list, index, value) {
601
+ const result = Array.from(list ?? []);
602
+ result.splice(index, 0, value);
603
+ return result;
468
604
  }
469
- function Le(o, i) {
470
- const e = Array.from(o);
471
- return e.splice(i, 1), e;
605
+ function remove(list, index) {
606
+ const result = Array.from(list);
607
+ result.splice(index, 1);
608
+ return result;
472
609
  }
473
- const At = (o, i) => {
474
- if (typeof o == "string" && o.length > 0)
475
- return o;
476
- const e = /* @__PURE__ */ new Date();
477
- return `${Ci(i)}-${e.getTime()}`;
478
- }, Pt = (o, i) => {
479
- if (!i)
610
+ const makeIdentifier = (existing, label) => {
611
+ if (typeof existing === "string" && existing.length > 0)
612
+ return existing;
613
+ const now = /* @__PURE__ */ new Date();
614
+ return `${slugify(label)}-${now.getTime()}`;
615
+ };
616
+ const findFieldByIdentifier = (fields, identifier) => {
617
+ if (!identifier)
480
618
  return null;
481
- for (const e of o)
482
- if (e.type === "section") {
483
- const t = Pt(e.fields, i);
484
- if (t)
485
- return t;
486
- } else if (e.identifier === i)
487
- return e;
619
+ for (const field of fields) {
620
+ if (field.type === "section") {
621
+ const result = findFieldByIdentifier(field.fields, identifier);
622
+ if (result)
623
+ return result;
624
+ } else if (field.identifier === identifier) {
625
+ return field;
626
+ }
627
+ }
488
628
  return null;
489
- }, Se = (o, i) => o.filter((e, t) => t < i).flatMap((e) => e.fields), kt = (o) => o.flatMap(
490
- (i) => i.type === "section" ? [...i.fields.map((e) => e.label), i.label] : i.label
491
- ).filter((i) => i !== null), Ke = (o, i) => {
492
- let e = 1, t = `${o} (${e})`;
493
- for (; i.includes(t); )
494
- t = `${o} (${++e})`;
495
- return t;
496
- }, Wi = S(function(i) {
497
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c }, l] = j(i), d = ue(n), u = x(() => Array.isArray(c.value) ? c.value : [], [c.value]), { onChange: f, onBlur: p } = c, h = `${e}-droppable`, { disabled: g } = l, [v, z] = Y(""), [I, w] = Y(""), k = I || s, A = I ? "red" : d, C = T(
498
- (L) => {
499
- f(L), p(L);
629
+ };
630
+ const makeConditionalSourceFields = (sections, index) => {
631
+ return sections.filter((_, i) => i < index).flatMap((field) => field.fields);
632
+ };
633
+ const getTakenFieldLabels = (fields) => {
634
+ return fields.flatMap(
635
+ (field) => field.type === "section" ? [...field.fields.map((f) => f.label), field.label] : field.label
636
+ ).filter((id) => id !== null);
637
+ };
638
+ const incrementFieldLabel = (label, takenLabels) => {
639
+ let count = 1;
640
+ let newLabel = `${label} (${count})`;
641
+ while (takenLabels.includes(newLabel)) {
642
+ newLabel = `${label} (${++count})`;
643
+ }
644
+ return newLabel;
645
+ };
646
+ const MultiStringInput = memo(function MultiStringInput2(props) {
647
+ const [{ inputId, labelId, severity, helpText, label, fieldProps }, rest] = useFormikInput(props);
648
+ const color = useSeverityColor(severity);
649
+ const value = useMemo(() => Array.isArray(fieldProps.value) ? fieldProps.value : [], [fieldProps.value]);
650
+ const { onChange, onBlur } = fieldProps;
651
+ const droppableId = `${inputId}-droppable`;
652
+ const { disabled } = rest;
653
+ const [intermediateValue, setIntermediateValue] = useState("");
654
+ const [internalError, setInternalError] = useState("");
655
+ const updatedHelpText = internalError || helpText;
656
+ const updatedColor = internalError ? "red" : color;
657
+ const setValueAndTouched = useCallback(
658
+ (newValue) => {
659
+ onChange(newValue);
660
+ onBlur(newValue);
500
661
  },
501
- [f, p]
502
- ), $ = T(
503
- (L) => {
504
- u.findIndex((N) => N.value === L.target.value.trim()) >= 0 ? w("All options must be unique") : L.target.value ? w("") : w("Option cannot be empty"), z(L.target.value);
662
+ [onChange, onBlur]
663
+ );
664
+ const handleChange = useCallback(
665
+ (e) => {
666
+ if (value.findIndex((option) => option.value === e.target.value.trim()) >= 0) {
667
+ setInternalError("All options must be unique");
668
+ } else if (!e.target.value) {
669
+ setInternalError("Option cannot be empty");
670
+ } else {
671
+ setInternalError("");
672
+ }
673
+ setIntermediateValue(e.target.value);
505
674
  },
506
- [z, u]
507
- ), R = T(() => {
508
- if (I)
675
+ [setIntermediateValue, value]
676
+ );
677
+ const addOption = useCallback(() => {
678
+ if (internalError)
509
679
  return;
510
- if (!v.trim())
511
- return w("Option cannot be empty");
512
- const L = v.trim();
513
- C([...u, { value: L, label: L }]), z("");
514
- }, [v, I, C, u]), U = T(
515
- (L) => {
516
- L.key === "Enter" && (L.preventDefault(), R());
680
+ if (!intermediateValue.trim()) {
681
+ return setInternalError("Option cannot be empty");
682
+ }
683
+ const trimmedValue = intermediateValue.trim();
684
+ setValueAndTouched([...value, { value: trimmedValue, label: trimmedValue }]);
685
+ setIntermediateValue("");
686
+ }, [intermediateValue, internalError, setValueAndTouched, value]);
687
+ const handleKeyDown = useCallback(
688
+ (e) => {
689
+ if (e.key === "Enter") {
690
+ e.preventDefault();
691
+ addOption();
692
+ }
517
693
  },
518
- [R]
519
- ), we = T(
520
- (L) => {
521
- C(Le(u, L));
694
+ [addOption]
695
+ );
696
+ const handleDeleteOption = useCallback(
697
+ (index) => {
698
+ setValueAndTouched(remove(value, index));
522
699
  },
523
- [u, C]
524
- ), xe = T(
525
- (L) => {
526
- if (!L.destination)
700
+ [value, setValueAndTouched]
701
+ );
702
+ const handleDragEnd = useCallback(
703
+ (result) => {
704
+ if (!result.destination)
527
705
  return;
528
- const N = L.source.index, G = L.destination.index;
529
- C(Ge(u, N, G));
706
+ const sourceIndex = result.source.index;
707
+ const destinationIndex = result.destination.index;
708
+ setValueAndTouched(reorder(value, sourceIndex, destinationIndex));
530
709
  },
531
- [C, u]
710
+ [setValueAndTouched, value]
532
711
  );
533
- return /* @__PURE__ */ r(It, { onDragEnd: xe, children: /* @__PURE__ */ b(y, { direction: "column", gap: "2", children: [
534
- /* @__PURE__ */ r(W, { helpText: k, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: (!g || u.length === 0) && /* @__PURE__ */ b(y, { gap: "2", children: [
535
- /* @__PURE__ */ r(ge, { grow: "1", children: /* @__PURE__ */ r(
536
- ae.Input,
712
+ return /* @__PURE__ */ jsx(DragDropContext, { onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
713
+ /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: (!disabled || value.length === 0) && /* @__PURE__ */ jsxs(Flex, { gap: "2", children: [
714
+ /* @__PURE__ */ jsx(Box, { grow: "1", children: /* @__PURE__ */ jsx(
715
+ TextField$1.Input,
537
716
  {
538
717
  placeholder: "Press enter to add a new option",
539
- ...l,
540
- ...c,
541
- value: v,
542
- onChange: $,
543
- onKeyDown: U,
544
- id: e,
545
- color: A,
718
+ ...rest,
719
+ ...fieldProps,
720
+ value: intermediateValue,
721
+ onChange: handleChange,
722
+ onKeyDown: handleKeyDown,
723
+ id: inputId,
724
+ color: updatedColor,
546
725
  onBlur: void 0
547
726
  }
548
727
  ) }),
549
- /* @__PURE__ */ r(
550
- K,
728
+ /* @__PURE__ */ jsx(
729
+ IconButton,
551
730
  {
552
731
  type: "button",
553
732
  "aria-label": "Add option",
554
- disabled: !!I || g,
555
- onClick: R,
556
- children: /* @__PURE__ */ r(_e, {})
733
+ disabled: !!internalError || disabled,
734
+ onClick: addOption,
735
+ children: /* @__PURE__ */ jsx(PlusIcon, {})
557
736
  }
558
737
  )
559
738
  ] }) }) }),
560
- /* @__PURE__ */ r(it, { droppableId: h, children: (L) => /* @__PURE__ */ b(y, { ...L.droppableProps, ref: L.innerRef, direction: "column", children: [
561
- u.map((N, G) => /* @__PURE__ */ r(
562
- nt,
739
+ /* @__PURE__ */ jsx(Droppable, { droppableId, children: (droppableProvided) => /* @__PURE__ */ jsxs(Flex, { ...droppableProvided.droppableProps, ref: droppableProvided.innerRef, direction: "column", children: [
740
+ value.map((option, index) => /* @__PURE__ */ jsx(
741
+ Draggable,
563
742
  {
564
- draggableId: `${N.value}-draggable`,
565
- index: G,
566
- isDragDisabled: g,
567
- children: ({ draggableProps: Ie, dragHandleProps: Ce, innerRef: F }) => /* @__PURE__ */ r(
568
- y,
743
+ draggableId: `${option.value}-draggable`,
744
+ index,
745
+ isDragDisabled: disabled,
746
+ children: ({ draggableProps, dragHandleProps, innerRef }) => /* @__PURE__ */ jsx(
747
+ Flex,
569
748
  {
570
- ...Ce,
571
- ...Ie,
572
- ref: F,
749
+ ...dragHandleProps,
750
+ ...draggableProps,
751
+ ref: innerRef,
573
752
  gap: "2",
574
753
  align: "center",
575
754
  justify: "between",
576
755
  mb: "1",
577
- asChild: !0,
578
- children: /* @__PURE__ */ b(He, { color: "gray", size: "2", children: [
579
- /* @__PURE__ */ r("span", { children: N.label }),
580
- /* @__PURE__ */ r(
581
- K,
756
+ asChild: true,
757
+ children: /* @__PURE__ */ jsxs(Badge, { color: "gray", size: "2", children: [
758
+ /* @__PURE__ */ jsx("span", { children: option.label }),
759
+ /* @__PURE__ */ jsx(
760
+ IconButton,
582
761
  {
583
762
  size: "small",
584
763
  variant: "ghost",
585
764
  type: "button",
586
765
  "aria-label": "Delete option",
587
766
  severity: "info",
588
- disabled: g,
589
- onClick: () => we(G),
590
- children: /* @__PURE__ */ r(wt, {})
767
+ disabled,
768
+ onClick: () => handleDeleteOption(index),
769
+ children: /* @__PURE__ */ jsx(Cross1Icon, {})
591
770
  }
592
771
  )
593
772
  ] })
594
773
  }
595
774
  )
596
775
  },
597
- N.value
776
+ option.value
598
777
  )),
599
- L.placeholder
778
+ droppableProvided.placeholder
600
779
  ] }) })
601
780
  ] }) });
602
- }), ne = class ne extends O {
603
- constructor(e) {
604
- const { minimum_length: t, maximum_length: n, ...s } = e;
605
- super({ ...s, type: "multi-string" });
606
- m(this, "minLength");
607
- m(this, "maxLength");
608
- m(this, "onlyValidateAfterTouched", !1);
609
- this.minLength = t ?? 0, this.maxLength = n ?? 1 / 0;
610
- }
611
- getValueFromChangeEvent(e) {
612
- if (Array.isArray(e))
613
- return e;
781
+ });
782
+ const _MultiStringField = class _MultiStringField extends BaseField {
783
+ constructor(options) {
784
+ const { minimum_length, maximum_length, ...rest } = options;
785
+ super({ ...rest, type: "multi-string" });
786
+ __publicField(this, "minLength");
787
+ __publicField(this, "maxLength");
788
+ __publicField(this, "onlyValidateAfterTouched", false);
789
+ this.minLength = minimum_length ?? 0;
790
+ this.maxLength = maximum_length ?? Infinity;
791
+ }
792
+ getValueFromChangeEvent(event) {
793
+ if (Array.isArray(event))
794
+ return event;
614
795
  throw new Error("Expected an array.");
615
796
  }
616
- getInput(e) {
617
- return /* @__PURE__ */ r(Wi, { field: this, ...e });
797
+ getInput(props) {
798
+ return /* @__PURE__ */ jsx(MultiStringInput, { field: this, ...props });
618
799
  }
619
800
  serialize() {
620
801
  return { ...super._serialize(), minimum_length: this.minLength, maximum_length: this.maxLength };
621
802
  }
622
- isBlank(e) {
623
- return super.isBlank(e) || e.length === 0;
803
+ isBlank(value) {
804
+ return super.isBlank(value) || value.length === 0;
624
805
  }
625
806
  getFieldValidators() {
626
- const e = super.getFieldValidators();
627
- return e.push((t) => {
628
- if (Array.isArray(t) && t.length < this.minLength)
807
+ const validators = super.getFieldValidators();
808
+ validators.push((value) => {
809
+ if (Array.isArray(value) && value.length < this.minLength) {
629
810
  return `Must have at least ${this.minLength} options.`;
630
- }), e.push((t) => {
631
- if (Array.isArray(t) && t.length > this.maxLength)
811
+ }
812
+ });
813
+ validators.push((value) => {
814
+ if (Array.isArray(value) && value.length > this.maxLength) {
632
815
  return `Must have at most ${this.maxLength} options.`;
633
- }), e;
816
+ }
817
+ });
818
+ return validators;
634
819
  }
635
- static deserialize(e) {
636
- if (e.type !== "multi-string")
820
+ static deserialize(data) {
821
+ if (data.type !== "multi-string")
637
822
  throw new Error("Type mismatch.");
638
- return new ne(e);
823
+ return new _MultiStringField(data);
639
824
  }
640
825
  };
641
- m(ne, "fieldTypeName", "Multi-string"), m(ne, "fieldTypeDescription", "Allows the user to provide multiple unique strings."), m(ne, "Icon", Jt);
642
- let Ae = ne;
643
- class Vt extends O {
644
- constructor(e) {
645
- super(e);
646
- m(this, "options");
647
- m(this, "onlyValidateAfterTouched", !1);
648
- const t = /* @__PURE__ */ new Set();
649
- this.options = e.options.map((n) => (typeof n == "string" && (n = { label: n, value: n }), t.add(n.label), n)), t.size !== e.options.length && console.error(
650
- `${e.options.length - t.size} duplicate identifiers found in options. This may cause unexpected behavior. Options:`,
651
- e.options
652
- );
826
+ __publicField(_MultiStringField, "fieldTypeName", "Multi-string");
827
+ __publicField(_MultiStringField, "fieldTypeDescription", "Allows the user to provide multiple unique strings.");
828
+ __publicField(_MultiStringField, "Icon", ListBulletIcon);
829
+ let MultiStringField = _MultiStringField;
830
+ class BaseSelectField extends BaseField {
831
+ constructor(options) {
832
+ super(options);
833
+ __publicField(this, "options");
834
+ __publicField(this, "onlyValidateAfterTouched", false);
835
+ const encounteredIds = /* @__PURE__ */ new Set();
836
+ this.options = options.options.map((option) => {
837
+ if (typeof option === "string") {
838
+ option = { label: option, value: option };
839
+ }
840
+ encounteredIds.add(option.label);
841
+ return option;
842
+ });
843
+ if (encounteredIds.size !== options.options.length) {
844
+ console.error(
845
+ `${options.options.length - encounteredIds.size} duplicate identifiers found in options. This may cause unexpected behavior. Options:`,
846
+ options.options
847
+ );
848
+ }
653
849
  }
654
850
  _serialize() {
655
851
  return {
@@ -659,10 +855,10 @@ class Vt extends O {
659
855
  }
660
856
  static getFieldCreationSchema() {
661
857
  return [
662
- new Ae({
858
+ new MultiStringField({
663
859
  label: "Options",
664
860
  description: "List possible options for the user to select from.",
665
- required: !0,
861
+ required: true,
666
862
  identifier: "options",
667
863
  minimum_length: 2,
668
864
  maximum_length: 20
@@ -670,193 +866,247 @@ class Vt extends O {
670
866
  ];
671
867
  }
672
868
  }
673
- const re = class re extends Vt {
674
- constructor(i) {
675
- super({ ...i, type: "select" });
869
+ const _SelectField = class _SelectField extends BaseSelectField {
870
+ constructor(options) {
871
+ super({ ...options, type: "select" });
676
872
  }
677
- getValueFromChangeEvent(i) {
678
- return typeof i == "string" ? i : i.target.value;
873
+ getValueFromChangeEvent(event) {
874
+ if (typeof event === "string")
875
+ return event;
876
+ return event.target.value;
679
877
  }
680
878
  serialize() {
681
879
  return super._serialize();
682
880
  }
683
- static deserialize(i) {
684
- if (i.type !== "select")
881
+ static deserialize(data) {
882
+ if (data.type !== "select")
685
883
  throw new Error("Type mismatch.");
686
- return new re(i);
884
+ return new _SelectField(data);
687
885
  }
688
- getInput(i) {
689
- return /* @__PURE__ */ r(Ni, { field: this, ...i });
886
+ getInput(props) {
887
+ return /* @__PURE__ */ jsx(SelectInput, { field: this, ...props });
690
888
  }
691
889
  };
692
- m(re, "fieldTypeName", "Dropdown"), m(re, "fieldTypeDescription", "Allows the user to select a single option from a list of options."), m(re, "Icon", ei);
693
- let Pe = re;
694
- const ji = (o) => o ? Array.isArray(o) ? o : [o] : [], Hi = S(function(i) {
695
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c, field: l }, d] = j(i), { onChange: u, onBlur: f } = c, p = x(() => ji(c.value), [c.value]), h = T(
696
- (g) => {
697
- u(g), f(g);
890
+ __publicField(_SelectField, "fieldTypeName", "Dropdown");
891
+ __publicField(_SelectField, "fieldTypeDescription", "Allows the user to select a single option from a list of options.");
892
+ __publicField(_SelectField, "Icon", DropdownMenuIcon);
893
+ let SelectField = _SelectField;
894
+ const parseValueToArray = (value) => {
895
+ if (!value)
896
+ return [];
897
+ if (Array.isArray(value))
898
+ return value;
899
+ return [value];
900
+ };
901
+ const MultiSelectInput = memo(function MultiSelectInput2(props) {
902
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
903
+ const { onChange, onBlur } = fieldProps;
904
+ const value = useMemo(() => parseValueToArray(fieldProps.value), [fieldProps.value]);
905
+ const handleChange = useCallback(
906
+ (value2) => {
907
+ onChange(value2);
908
+ onBlur(value2);
698
909
  },
699
- [u, f]
910
+ [onChange, onBlur]
700
911
  );
701
- return /* @__PURE__ */ r(W, { helpText: s, severity: n, children: /* @__PURE__ */ r(q, { severity: n, inputId: e, labelId: t, label: a, children: /* @__PURE__ */ r(
702
- ti,
912
+ return /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText, severity, children: /* @__PURE__ */ jsx(InputWithLabel, { severity, inputId, labelId, label, children: /* @__PURE__ */ jsx(
913
+ MultiSelect,
703
914
  {
704
- value: p,
705
- onValueChange: h,
706
- options: l.options,
707
- name: c.name,
915
+ value,
916
+ onValueChange: handleChange,
917
+ options: field.options,
918
+ name: fieldProps.name,
708
919
  placeholder: "Select one or more...",
709
- id: e,
710
- severity: n,
711
- ...d
920
+ id: inputId,
921
+ severity,
922
+ ...rest
712
923
  }
713
924
  ) }) });
714
- }), oe = class oe extends Vt {
715
- constructor(i) {
716
- super({ ...i, type: "multi-select" });
925
+ });
926
+ const _MultiSelectField = class _MultiSelectField extends BaseSelectField {
927
+ constructor(options) {
928
+ super({ ...options, type: "multi-select" });
717
929
  }
718
- getValueFromChangeEvent(i) {
719
- if (Array.isArray(i))
720
- return i;
930
+ getValueFromChangeEvent(event) {
931
+ if (Array.isArray(event))
932
+ return event;
721
933
  throw new Error("Expected an array.");
722
934
  }
723
- isBlank(i) {
724
- return super.isBlank(i) || i.length === 0;
935
+ isBlank(value) {
936
+ return super.isBlank(value) || value.length === 0;
725
937
  }
726
938
  serialize() {
727
939
  return super._serialize();
728
940
  }
729
- static deserialize(i) {
730
- if (i.type !== "multi-select")
941
+ static deserialize(data) {
942
+ if (data.type !== "multi-select")
731
943
  throw new Error("Type mismatch.");
732
- return new oe(i);
944
+ return new _MultiSelectField(data);
733
945
  }
734
- getInput(i) {
735
- return /* @__PURE__ */ r(Hi, { field: this, ...i });
946
+ getInput(props) {
947
+ return /* @__PURE__ */ jsx(MultiSelectInput, { field: this, ...props });
736
948
  }
737
949
  };
738
- m(oe, "fieldTypeName", "Multi-select"), m(oe, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options."), m(oe, "Icon", ii);
739
- let ke = oe;
740
- const Ui = S(function({ field: i, ...e }) {
741
- const [{ value: t }] = Je(i.options.clonedFieldIdentifier), n = x(() => {
742
- const s = i.options.getFieldToClone(t);
743
- return s ? Ne(s) : null;
744
- }, [i.options, t]);
745
- return $e(n, e);
950
+ __publicField(_MultiSelectField, "fieldTypeName", "Multi-select");
951
+ __publicField(_MultiSelectField, "fieldTypeDescription", "Allows the user to select a multiple options from a list of options.");
952
+ __publicField(_MultiSelectField, "Icon", CheckboxIcon);
953
+ let MultiSelectField = _MultiSelectField;
954
+ const FieldInputCloner = memo(function FieldInputCloner2({ field, ...props }) {
955
+ const [{ value: identifier }] = useField(field.options.clonedFieldIdentifier);
956
+ const deserializedField = useMemo(() => {
957
+ const options = field.options.getFieldToClone(identifier);
958
+ if (!options)
959
+ return null;
960
+ return deserialize(options);
961
+ }, [field.options, identifier]);
962
+ return useFieldInput(deserializedField, props);
746
963
  });
747
- class Ve extends O {
748
- constructor(e, t) {
749
- super({ ...e, type: "custom" });
750
- m(this, "Component");
964
+ class CustomField extends BaseField {
965
+ constructor(options, Component) {
966
+ super({ ...options, type: "custom" });
967
+ __publicField(this, "Component");
751
968
  // identifier of the field whose value is the label of the field to re-render
752
- m(this, "options");
753
- this.options = e, this.Component = t;
969
+ __publicField(this, "options");
970
+ this.options = options;
971
+ this.Component = Component;
754
972
  }
755
973
  serialize() {
756
974
  throw new Error("Serializing only supported for public input types.");
757
975
  }
758
- getInput(e) {
759
- const t = this.Component;
760
- return /* @__PURE__ */ r(t, { field: this, ...e });
976
+ getInput(props) {
977
+ const CustomInput = this.Component;
978
+ return /* @__PURE__ */ jsx(CustomInput, { field: this, ...props });
761
979
  }
762
980
  }
763
- m(Ve, "fieldTypeName", "Custom"), m(Ve, "fieldTypeDescription", "Allows re-rendering of field already in the form");
764
- class Gi extends Ve {
765
- constructor(i) {
766
- super(i, Ui);
981
+ __publicField(CustomField, "fieldTypeName", "Custom");
982
+ __publicField(CustomField, "fieldTypeDescription", "Allows re-rendering of field already in the form");
983
+ class FieldInputClonerField extends CustomField {
984
+ constructor(options) {
985
+ super(options, FieldInputCloner);
767
986
  }
768
987
  }
769
- const Ki = S(function(i) {
770
- const { field: e, ...t } = i, { label: n, description: s, fields: a, condition: c } = e, { values: l, setFieldValue: d } = me(), u = c != null && c.identifier ? ce(l, c.identifier) : void 0, f = x(() => _t(c, u), [c, u]);
771
- ve(() => {
772
- if (!f)
773
- for (const h of a)
774
- d(h.getId(), "").then();
775
- }, [f, a, d]);
776
- const p = Mt(a, t);
777
- return f ? n ? /* @__PURE__ */ r(fe, { children: /* @__PURE__ */ b(y, { direction: "column", gap: "3", children: [
778
- /* @__PURE__ */ b(y, { direction: "column", children: [
779
- /* @__PURE__ */ r(Me, { as: "h3", size: "3", children: n }),
780
- /* @__PURE__ */ r(V, { className: Re.description, children: s })
988
+ const FieldSectionLayout = memo(function FieldSectionLayout2(props) {
989
+ const { field: section, ...rest } = props;
990
+ const { label, description: description2, fields, condition } = section;
991
+ const { values, setFieldValue } = useFormikContext();
992
+ const conditionValue = (condition == null ? void 0 : condition.identifier) ? get(values, condition.identifier) : void 0;
993
+ const conditionMet = useMemo(() => isConditionMet(condition, conditionValue), [condition, conditionValue]);
994
+ useEffect(() => {
995
+ if (!conditionMet) {
996
+ for (const childField of fields) {
997
+ setFieldValue(childField.getId(), "").then();
998
+ }
999
+ }
1000
+ }, [conditionMet, fields, setFieldValue]);
1001
+ const inputs = useFieldInputs(fields, rest);
1002
+ if (!conditionMet) {
1003
+ return null;
1004
+ }
1005
+ if (!label) {
1006
+ return inputs;
1007
+ }
1008
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
1009
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
1010
+ /* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: label }),
1011
+ /* @__PURE__ */ jsx(Text, { className: styles$3.description, children: description2 })
781
1012
  ] }),
782
- p
783
- ] }) }) : p : null;
784
- }), se = class se extends Et {
785
- constructor(e) {
786
- const { label: t = null, fields: n, condition: s = null, conditional: a, ...c } = e;
787
- super({ ...c, type: "section" });
788
- m(this, "label");
789
- m(this, "fields");
790
- m(this, "condition");
791
- this.fields = n, this.condition = s, this.label = t, a === !1 && (this.condition = null);
792
- }
793
- static getFieldCreationSchema(e) {
794
- return e.length === 0 ? [] : [
795
- new de({
1013
+ inputs
1014
+ ] }) });
1015
+ });
1016
+ const _FieldSection = class _FieldSection extends BaseFormElement {
1017
+ constructor(options) {
1018
+ const { label = null, fields, condition = null, conditional, ...base } = options;
1019
+ super({ ...base, type: "section" });
1020
+ __publicField(this, "label");
1021
+ __publicField(this, "fields");
1022
+ __publicField(this, "condition");
1023
+ this.fields = fields;
1024
+ this.condition = condition;
1025
+ this.label = label;
1026
+ if (conditional === false) {
1027
+ this.condition = null;
1028
+ }
1029
+ }
1030
+ static getFieldCreationSchema(options) {
1031
+ if (options.length === 0)
1032
+ return [];
1033
+ return [
1034
+ new BooleanField({
796
1035
  label: "Conditional",
797
1036
  description: "Conditionally show or hide this section.",
798
1037
  identifier: "conditional",
799
- required: !1
1038
+ required: false
800
1039
  }),
801
1040
  // Declare a section that will hold options for the condition (if any).
802
- new se({
1041
+ new _FieldSection({
803
1042
  label: "Conditional settings",
804
1043
  identifier: "conditional-settings",
805
1044
  // This section will only be rendered if the above "Conditional" field is checked.
806
1045
  condition: {
807
1046
  identifier: "conditional",
808
- value: !0
1047
+ value: true
809
1048
  },
810
1049
  // These are the options of the condition.
811
1050
  fields: [
812
1051
  // Declare a select field that will be used to select the field against which we will check the
813
1052
  // condition. This must be selected before the next field is rendered.
814
- new Pe({
1053
+ new SelectField({
815
1054
  label: "Field",
816
1055
  description: "The field to use for the condition.",
817
1056
  // The options (for the field against which we will check the condition) are all the labels of
818
1057
  // the fields in the previous section(s) (or fields declared before with no section) that
819
1058
  // support conditions. We pass in both the label and the identifier of each supported field. The
820
1059
  // identifier becomes the value of the option.
821
- options: e.map((t) => !t.label || t.type === "upload" ? null : {
822
- label: t.label,
823
- value: t.identifier
824
- }).filter((t) => !!t),
1060
+ options: options.map((option) => {
1061
+ if (!option.label)
1062
+ return null;
1063
+ if (option.type === "upload")
1064
+ return null;
1065
+ return {
1066
+ label: option.label,
1067
+ value: option.identifier
1068
+ };
1069
+ }).filter((option) => !!option),
825
1070
  identifier: "condition.identifier",
826
- required: !0
1071
+ required: true
827
1072
  }),
828
1073
  // Declare a custom field that will be used to input a value for the condition. The value of the
829
1074
  // conditional field selected in the previous step must be equal to the value the user inputs into
830
1075
  // this field for the section to be rendered.
831
- new Gi({
1076
+ new FieldInputClonerField({
832
1077
  label: "Value",
833
1078
  identifier: "condition.value",
834
- required: !0,
1079
+ required: true,
835
1080
  clonedFieldIdentifier: "condition.identifier",
836
- getFieldToClone(t) {
837
- if (!t)
1081
+ getFieldToClone(identifier) {
1082
+ if (!identifier) {
838
1083
  return null;
839
- const n = e.find((s) => s.identifier === t);
840
- return n ? {
841
- ...n,
1084
+ }
1085
+ const option = options.find((option2) => option2.identifier === identifier);
1086
+ if (!option) {
1087
+ console.error("Could not find field with identifier", identifier);
1088
+ return null;
1089
+ }
1090
+ return {
1091
+ ...option,
842
1092
  // Override some options to make it make sense in the context and to make it work with the framework.
843
1093
  label: "Value",
844
1094
  identifier: "condition.value",
845
1095
  description: "The value to compare against.",
846
- required: n.type !== "boolean"
847
- } : (console.error("Could not find field with identifier", t), null);
1096
+ required: option.type !== "boolean"
1097
+ };
848
1098
  }
849
1099
  })
850
1100
  ]
851
1101
  })
852
1102
  ];
853
1103
  }
854
- static deserialize(e) {
855
- var n;
856
- if (e.type !== "section")
1104
+ static deserialize(data) {
1105
+ var _a;
1106
+ if (data.type !== "section")
857
1107
  throw new Error("Invalid type");
858
- const t = ((n = e.fields) == null ? void 0 : n.map($t)) ?? [];
859
- return new se({ ...e, fields: t });
1108
+ const fields = ((_a = data.fields) == null ? void 0 : _a.map(deserializeField)) ?? [];
1109
+ return new _FieldSection({ ...data, fields });
860
1110
  }
861
1111
  conditional() {
862
1112
  return this.condition !== null;
@@ -867,144 +1117,199 @@ const Ki = S(function(i) {
867
1117
  label: this.label,
868
1118
  condition: this.condition,
869
1119
  conditional: this.conditional(),
870
- fields: this.fields.map((e) => e.serialize())
1120
+ fields: this.fields.map((field) => field.serialize())
871
1121
  };
872
1122
  }
873
- getErrors(e) {
874
- const t = {};
875
- for (const n of this.fields) {
876
- const s = n.getId(), a = n.getError(ce(e, s), e);
877
- a && ot(t, n.getId(), a);
1123
+ getErrors(allValues) {
1124
+ const errors = {};
1125
+ for (const field of this.fields) {
1126
+ const id = field.getId();
1127
+ const error = field.getError(get(allValues, id), allValues);
1128
+ if (error) {
1129
+ set(errors, field.getId(), error);
1130
+ }
878
1131
  }
879
- return t;
1132
+ return errors;
880
1133
  }
881
- getInput(e) {
882
- return /* @__PURE__ */ r(Ki, { field: this, ...e });
1134
+ getInput(props) {
1135
+ return /* @__PURE__ */ jsx(FieldSectionLayout, { field: this, ...props });
883
1136
  }
884
1137
  };
885
- m(se, "fieldTypeName", "Section"), m(se, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
886
- let X = se;
887
- const Yi = "_previewImage_1ig84_1", Qi = {
888
- previewImage: Yi
889
- }, st = (o) => {
890
- const i = ["byte", "kilobyte", "megabyte"];
891
- let e = o, t = 0;
892
- for (; e > 1024 && t < i.length - 1; )
893
- e /= 1024, t++;
894
- return new Intl.NumberFormat([], { maximumFractionDigits: 2, style: "unit", unit: i[t] }).format(e);
895
- }, Xi = S(function(i) {
896
- var A;
897
- const [{ inputId: e, labelId: t, severity: n, helpText: s, label: a, fieldProps: c, field: l }, d] = j(i), { onChange: u } = c, f = ue(n), p = xi(null), { value: h } = c, g = x(() => s || (l.maxFileSize ? `Maximum file size: ${st(l.maxFileSize)}` : null), [l.maxFileSize, s]), v = T(() => {
898
- var C;
899
- (C = p.current) == null || C.click();
900
- }, []), z = T(
901
- (C) => {
902
- const $ = [...h];
903
- $.splice(C, 1), u({ target: { files: $ } });
1138
+ __publicField(_FieldSection, "fieldTypeName", "Section");
1139
+ __publicField(_FieldSection, "fieldTypeDescription", "Sections can be useful for grouping fields together. They can also be conditionally shown or hidden.");
1140
+ let FieldSection = _FieldSection;
1141
+ const previewImage = "_previewImage_1ig84_1";
1142
+ const styles$2 = {
1143
+ previewImage
1144
+ };
1145
+ const convertBytesToLargestUnit = (bytes) => {
1146
+ const units = ["byte", "kilobyte", "megabyte"];
1147
+ let sizeInUnit = bytes;
1148
+ let unitIndex = 0;
1149
+ while (sizeInUnit > 1024 && unitIndex < units.length - 1) {
1150
+ sizeInUnit /= 1024;
1151
+ unitIndex++;
1152
+ }
1153
+ const formatter = new Intl.NumberFormat([], { maximumFractionDigits: 2, style: "unit", unit: units[unitIndex] });
1154
+ return formatter.format(sizeInUnit);
1155
+ };
1156
+ const NumberInput = memo(function NumberInput22(props) {
1157
+ var _a;
1158
+ const [{ inputId, labelId, severity, helpText, label, fieldProps, field }, rest] = useFormikInput(props);
1159
+ const { onChange } = fieldProps;
1160
+ const color = useSeverityColor(severity);
1161
+ const input = useRef(null);
1162
+ const { value } = fieldProps;
1163
+ const updatedHelpText = useMemo(() => {
1164
+ if (helpText)
1165
+ return helpText;
1166
+ if (field.maxFileSize) {
1167
+ const size = convertBytesToLargestUnit(field.maxFileSize);
1168
+ return `Maximum file size: ${size}`;
1169
+ }
1170
+ return null;
1171
+ }, [field.maxFileSize, helpText]);
1172
+ const handleClick = useCallback(() => {
1173
+ var _a2;
1174
+ (_a2 = input.current) == null ? void 0 : _a2.click();
1175
+ }, []);
1176
+ const handleRemove = useCallback(
1177
+ (index) => {
1178
+ const files = [...value];
1179
+ files.splice(index, 1);
1180
+ const event = { target: { files } };
1181
+ onChange(event);
904
1182
  },
905
- [h, u]
906
- ), I = h ? "Select new files" : "Select files", w = h ? "Select new file" : "Select a file", k = l.maxFiles > 1 ? I : w;
907
- return /* @__PURE__ */ b(y, { direction: "column", gap: "2", children: [
908
- /* @__PURE__ */ r(W, { helpText: g, severity: n, children: /* @__PURE__ */ b(q, { severity: n, inputId: e, labelId: t, label: a, children: [
909
- /* @__PURE__ */ r(y, { direction: "row", gap: "2", children: /* @__PURE__ */ r(ge, { width: "max-content", asChild: !0, children: /* @__PURE__ */ b(H, { ...d, onClick: v, children: [
910
- /* @__PURE__ */ r(xt, {}),
1183
+ [value, onChange]
1184
+ );
1185
+ const multipleButtonText = value ? "Select new files" : "Select files";
1186
+ const singleButtonText = value ? "Select new file" : "Select a file";
1187
+ const buttonText = field.maxFiles > 1 ? multipleButtonText : singleButtonText;
1188
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
1189
+ /* @__PURE__ */ jsx(InputWithLabelAndHelpText, { helpText: updatedHelpText, severity, children: /* @__PURE__ */ jsxs(InputWithLabel, { severity, inputId, labelId, label, children: [
1190
+ /* @__PURE__ */ jsx(Flex, { direction: "row", gap: "2", children: /* @__PURE__ */ jsx(Box, { width: "max-content", asChild: true, children: /* @__PURE__ */ jsxs(Button, { ...rest, onClick: handleClick, children: [
1191
+ /* @__PURE__ */ jsx(UploadIcon, {}),
911
1192
  " ",
912
- k
1193
+ buttonText
913
1194
  ] }) }) }),
914
- /* @__PURE__ */ r(
1195
+ /* @__PURE__ */ jsx(
915
1196
  "input",
916
1197
  {
917
- ...d,
1198
+ ...rest,
918
1199
  type: "file",
919
- ref: p,
920
- id: e,
921
- accept: (A = l.extensions) == null ? void 0 : A.join(","),
922
- multiple: l.maxFiles > 1,
923
- color: f,
1200
+ ref: input,
1201
+ id: inputId,
1202
+ accept: (_a = field.extensions) == null ? void 0 : _a.join(","),
1203
+ multiple: field.maxFiles > 1,
1204
+ color,
924
1205
  style: { display: "none" },
925
- ...c,
1206
+ ...fieldProps,
926
1207
  value: ""
927
1208
  }
928
1209
  )
929
1210
  ] }) }),
930
- Array.isArray(h) && h.length > 0 && /* @__PURE__ */ r(y, { direction: "column", gap: "2", children: h.map((C, $) => /* @__PURE__ */ r(
931
- Zi,
1211
+ Array.isArray(value) && value.length > 0 && /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "2", children: value.map((file, index) => /* @__PURE__ */ jsx(
1212
+ DisplayFile,
932
1213
  {
933
- field: l,
934
- file: C,
935
- onRemove: () => z($),
936
- disabled: d.disabled
1214
+ field,
1215
+ file,
1216
+ onRemove: () => handleRemove(index),
1217
+ disabled: rest.disabled
937
1218
  },
938
- $
1219
+ index
939
1220
  )) })
940
1221
  ] });
941
- }), Zi = S(function({ file: i, field: e, onRemove: t, disabled: n }) {
942
- const [s, a] = Y(null), c = x(() => s && e.getError([s]), [e, s]), { url: l, name: d, size: u } = x(() => {
943
- let f = null, p, h;
944
- return s != null && s.type.startsWith("image/") && (f = URL.createObjectURL(s)), s ? (p = s.name, h = st(s.size)) : (p = "Downloading...", h = "..."), { url: f, name: p, size: h };
945
- }, [s]);
946
- return ve(() => {
947
- i instanceof Promise ? i.then(a) : a(i);
948
- }, [i]), /* @__PURE__ */ r(fe, { children: /* @__PURE__ */ b(y, { direction: { initial: "column", sm: "row" }, gap: "3", justify: "between", children: [
949
- /* @__PURE__ */ b(y, { direction: "row", gap: "3", align: "center", grow: "1", shrink: "0", children: [
950
- /* @__PURE__ */ r(
951
- K,
1222
+ });
1223
+ const DisplayFile = memo(function DisplayFile2({ file, field, onRemove, disabled }) {
1224
+ const [resolvedFile, setResolvedFile] = useState(null);
1225
+ const error = useMemo(() => resolvedFile && field.getError([resolvedFile]), [field, resolvedFile]);
1226
+ const { url, name, size } = useMemo(() => {
1227
+ let url2 = null;
1228
+ let name2;
1229
+ let size2;
1230
+ if (resolvedFile == null ? void 0 : resolvedFile.type.startsWith("image/")) {
1231
+ url2 = URL.createObjectURL(resolvedFile);
1232
+ }
1233
+ if (resolvedFile) {
1234
+ name2 = resolvedFile.name;
1235
+ size2 = convertBytesToLargestUnit(resolvedFile.size);
1236
+ } else {
1237
+ name2 = "Downloading...";
1238
+ size2 = "...";
1239
+ }
1240
+ return { url: url2, name: name2, size: size2 };
1241
+ }, [resolvedFile]);
1242
+ useEffect(() => {
1243
+ if (file instanceof Promise) {
1244
+ file.then(setResolvedFile);
1245
+ } else {
1246
+ setResolvedFile(file);
1247
+ }
1248
+ }, [file]);
1249
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: { initial: "column", sm: "row" }, gap: "3", justify: "between", children: [
1250
+ /* @__PURE__ */ jsxs(Flex, { direction: "row", gap: "3", align: "center", grow: "1", shrink: "0", children: [
1251
+ /* @__PURE__ */ jsx(
1252
+ IconButton,
952
1253
  {
953
1254
  severity: "info",
954
1255
  variant: "outline",
955
- "aria-label": `Remove ${d}`,
956
- disabled: n,
957
- onClick: t,
958
- children: /* @__PURE__ */ r(wt, {})
1256
+ "aria-label": `Remove ${name}`,
1257
+ disabled,
1258
+ onClick: onRemove,
1259
+ children: /* @__PURE__ */ jsx(Cross1Icon, {})
959
1260
  }
960
1261
  ),
961
- /* @__PURE__ */ b(y, { direction: "column", gap: "1", children: [
962
- /* @__PURE__ */ r(V, { children: d }),
963
- /* @__PURE__ */ r(V, { size: "1", children: u }),
964
- c && /* @__PURE__ */ r(V, { size: "1", severity: "danger", children: c })
1262
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", children: [
1263
+ /* @__PURE__ */ jsx(Text, { children: name }),
1264
+ /* @__PURE__ */ jsx(Text, { size: "1", children: size }),
1265
+ error && /* @__PURE__ */ jsx(Text, { size: "1", severity: "danger", children: error })
965
1266
  ] })
966
1267
  ] }),
967
- l && /* @__PURE__ */ r("img", { className: Qi.previewImage, src: l, alt: d })
1268
+ url && /* @__PURE__ */ jsx("img", { className: styles$2.previewImage, src: url, alt: name })
968
1269
  ] }) });
969
- }), mt = 50 * 1024 * 1024, le = class le extends O {
970
- constructor(e) {
971
- const { extensions: t, maximum_files: n, maximum_size: s, ...a } = e;
972
- super({ ...a, type: "upload" });
973
- m(this, "extensions");
974
- m(this, "maxFileSize");
975
- m(this, "maxFiles");
976
- m(this, "onlyValidateAfterTouched", !1);
977
- this.maxFileSize = typeof s == "number" ? s : void 0, this.maxFiles = Math.max(typeof n == "number" ? n : 1, 1), this.extensions = t;
978
- }
979
- getValueFromChangeEvent(e) {
980
- return Array.from(e.target.files || []);
981
- }
982
- isBlank(e) {
983
- return super.isBlank(e) || e.length === 0;
1270
+ });
1271
+ const largestSupportedSize = 50 * 1024 * 1024;
1272
+ const _UploadField = class _UploadField extends BaseField {
1273
+ constructor(options) {
1274
+ const { extensions, maximum_files, maximum_size, ...base } = options;
1275
+ super({ ...base, type: "upload" });
1276
+ __publicField(this, "extensions");
1277
+ __publicField(this, "maxFileSize");
1278
+ __publicField(this, "maxFiles");
1279
+ __publicField(this, "onlyValidateAfterTouched", false);
1280
+ this.maxFileSize = typeof maximum_size === "number" ? maximum_size : void 0;
1281
+ this.maxFiles = Math.max(typeof maximum_files === "number" ? maximum_files : 1, 1);
1282
+ this.extensions = extensions;
1283
+ }
1284
+ getValueFromChangeEvent(event) {
1285
+ return Array.from(event.target.files || []);
1286
+ }
1287
+ isBlank(value) {
1288
+ return super.isBlank(value) || value.length === 0;
984
1289
  }
985
1290
  static getFieldCreationSchema() {
986
1291
  return [
987
- new Q({
1292
+ new NumberField({
988
1293
  label: "How many files can be uploaded?",
989
1294
  description: "By default, only one file can be uploaded.",
990
- required: !1,
1295
+ required: false,
991
1296
  minimum: 1,
992
1297
  maximum: 10,
993
1298
  identifier: "maximum_files"
994
1299
  }),
995
- new Q({
1300
+ new NumberField({
996
1301
  label: "What is the maximum size of each file?",
997
1302
  description: "Maximum file size in bytes.",
998
- required: !1,
1303
+ required: false,
999
1304
  identifier: "maximum_size",
1000
1305
  minimum: 1,
1001
- maximum: mt,
1002
- integers: !0
1306
+ maximum: largestSupportedSize,
1307
+ integers: true
1003
1308
  }),
1004
- new ke({
1309
+ new MultiSelectField({
1005
1310
  label: "Accepted file types",
1006
1311
  description: "Types of allowed files to upload. If left blank, all files will be accepted.",
1007
- required: !1,
1312
+ required: false,
1008
1313
  identifier: "extensions",
1009
1314
  options: [
1010
1315
  {
@@ -1032,14 +1337,20 @@ const Yi = "_previewImage_1ig84_1", Qi = {
1032
1337
  ];
1033
1338
  }
1034
1339
  getFieldValidators() {
1035
- const e = super.getFieldValidators(), t = this.maxFileSize ?? mt, n = this.maxFiles ?? 1;
1036
- return e.push((s) => {
1037
- if (s && s.some((a) => a.size > t))
1038
- return `Files must be at most ${st(t)}.`;
1039
- }), e.push((s) => {
1040
- if (s && s.length > n)
1041
- return `You can only upload ${n} files.`;
1042
- }), e;
1340
+ const validators = super.getFieldValidators();
1341
+ const maxFileSize = this.maxFileSize ?? largestSupportedSize;
1342
+ const maxFiles = this.maxFiles ?? 1;
1343
+ validators.push((value) => {
1344
+ if (value && value.some((file) => file.size > maxFileSize)) {
1345
+ return `Files must be at most ${convertBytesToLargestUnit(maxFileSize)}.`;
1346
+ }
1347
+ });
1348
+ validators.push((value) => {
1349
+ if (value && value.length > maxFiles) {
1350
+ return `You can only upload ${maxFiles} files.`;
1351
+ }
1352
+ });
1353
+ return validators;
1043
1354
  }
1044
1355
  serialize() {
1045
1356
  return {
@@ -1049,1044 +1360,1312 @@ const Yi = "_previewImage_1ig84_1", Qi = {
1049
1360
  maximum_files: this.maxFiles
1050
1361
  };
1051
1362
  }
1052
- static deserialize(e) {
1053
- if (e.type !== "upload")
1363
+ static deserialize(data) {
1364
+ if (data.type !== "upload")
1054
1365
  throw new Error("Type mismatch.");
1055
- return new le(e);
1366
+ return new _UploadField(data);
1056
1367
  }
1057
- getInput(e) {
1058
- return /* @__PURE__ */ r(Xi, { field: this, ...e });
1368
+ getInput(props) {
1369
+ return /* @__PURE__ */ jsx(NumberInput, { field: this, ...props });
1059
1370
  }
1060
1371
  };
1061
- m(le, "fieldTypeName", "Upload"), m(le, "fieldTypeDescription", "Allows a file to be uploaded."), m(le, "Icon", xt);
1062
- let Ye = le;
1063
- const lt = {
1064
- date: Ue,
1065
- number: Q,
1066
- boolean: de,
1067
- select: Pe,
1068
- string: be,
1069
- text: ye,
1070
- custom: Ve,
1071
- upload: Ye,
1372
+ __publicField(_UploadField, "fieldTypeName", "Upload");
1373
+ __publicField(_UploadField, "fieldTypeDescription", "Allows a file to be uploaded.");
1374
+ __publicField(_UploadField, "Icon", UploadIcon);
1375
+ let UploadField = _UploadField;
1376
+ const FieldTypeToClsMapping = {
1377
+ date: DateField,
1378
+ number: NumberField,
1379
+ boolean: BooleanField,
1380
+ select: SelectField,
1381
+ string: StringField,
1382
+ text: TextField,
1383
+ custom: CustomField,
1384
+ upload: UploadField,
1072
1385
  // TODO: Underscore
1073
- "multi-string": Ae,
1074
- "multi-select": ke
1075
- }, $t = (o) => {
1076
- const i = o.type;
1077
- return lt[i].deserialize(o);
1078
- }, Ne = (o) => o.type === "section" ? X.deserialize(o) : $t(o);
1079
- function Dt(o, i = {}) {
1080
- const { readonly: e = !1 } = i;
1386
+ "multi-string": MultiStringField,
1387
+ "multi-select": MultiSelectField
1388
+ };
1389
+ const deserializeField = (serializedField) => {
1390
+ const fieldType = serializedField.type;
1391
+ const fieldCls = FieldTypeToClsMapping[fieldType];
1392
+ return fieldCls.deserialize(serializedField);
1393
+ };
1394
+ const deserialize = (serialized) => {
1395
+ if (serialized.type === "section") {
1396
+ return FieldSection.deserialize(serialized);
1397
+ }
1398
+ return deserializeField(serialized);
1399
+ };
1400
+ function formRevisionToSchema(formRevision, meta = {}) {
1401
+ const { readonly = false } = meta;
1081
1402
  return {
1082
- title: o.title,
1083
- description: o.description,
1084
- fields: o.fields.map((t) => Ne(t)),
1085
- meta: { readonly: e }
1403
+ title: formRevision.title,
1404
+ description: formRevision.description,
1405
+ fields: formRevision.fields.map((serializedField) => deserialize(serializedField)),
1406
+ meta: { readonly }
1086
1407
  };
1087
1408
  }
1088
- function Qe(o) {
1089
- return !!(Array.isArray(o) && o.some((i) => i instanceof File || i instanceof Promise));
1409
+ function valueIsFile(v) {
1410
+ if (Array.isArray(v) && v.some((v2) => v2 instanceof File || v2 instanceof Promise))
1411
+ return true;
1412
+ return false;
1090
1413
  }
1091
- function _t(o, i) {
1092
- if (!o)
1093
- return !0;
1094
- if (Qe(i) || Qe(o.value))
1414
+ function isConditionMet(condition, value) {
1415
+ if (!condition)
1416
+ return true;
1417
+ if (valueIsFile(value) || valueIsFile(condition.value))
1095
1418
  throw new Error("Conditions do not support file uploads");
1096
- const e = Array.isArray(i) ? i.map((n) => typeof n == "string" ? n : n.value) : i, t = Array.isArray(o.value) ? o.value.map((n) => typeof n == "string" ? n : n.value) : o.value;
1097
- if (Array.isArray(t) && Array.isArray(e)) {
1098
- for (const n of t)
1099
- if (!e.includes(n))
1100
- return !1;
1101
- return !0;
1102
- }
1103
- return t === i;
1419
+ const valueAsPrimitive = Array.isArray(value) ? value.map((v) => typeof v === "string" ? v : v.value) : value;
1420
+ const valueToCompare = Array.isArray(condition.value) ? condition.value.map((v) => typeof v === "string" ? v : v.value) : condition.value;
1421
+ if (Array.isArray(valueToCompare) && Array.isArray(valueAsPrimitive)) {
1422
+ for (const v of valueToCompare) {
1423
+ if (!valueAsPrimitive.includes(v))
1424
+ return false;
1425
+ }
1426
+ return true;
1427
+ }
1428
+ return valueToCompare === value;
1104
1429
  }
1105
- const $e = (o, i) => x(() => !i || !o ? null : o.getInput(i), [o, i]), Mt = (o, i) => {
1106
- const e = x(() => o.map((t) => /* @__PURE__ */ r("div", { children: t.getInput(i) }, t.getId())), [o, i]);
1107
- return /* @__PURE__ */ r(y, { direction: "column", gap: "2", children: e });
1108
- }, De = (o) => Object.keys(o).length > 0, Ot = async (o, i) => {
1109
- const e = {};
1110
- for (const t of o.fields)
1111
- if (t instanceof X) {
1112
- if (t.condition) {
1113
- const { identifier: n } = t.condition;
1114
- if (!_t(t.condition, ce(i, n)))
1430
+ const useFieldInput = (field, props) => {
1431
+ return useMemo(() => {
1432
+ if (!props || !field)
1433
+ return null;
1434
+ return field.getInput(props);
1435
+ }, [field, props]);
1436
+ };
1437
+ const useFieldInputs = (fields, props) => {
1438
+ const inputs = useMemo(() => {
1439
+ return fields.map((field) => {
1440
+ return /* @__PURE__ */ jsx("div", { children: field.getInput(props) }, field.getId());
1441
+ });
1442
+ }, [fields, props]);
1443
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "2", children: inputs });
1444
+ };
1445
+ const hasKeys = (errors) => {
1446
+ return Object.keys(errors).length > 0;
1447
+ };
1448
+ const validateForm = async (schema, form) => {
1449
+ const errors = {};
1450
+ for (const field of schema.fields) {
1451
+ if (field instanceof FieldSection) {
1452
+ if (field.condition) {
1453
+ const { identifier } = field.condition;
1454
+ if (!isConditionMet(field.condition, get(form, identifier))) {
1115
1455
  continue;
1456
+ }
1116
1457
  }
1117
- Object.assign(e, t.getErrors(i));
1458
+ Object.assign(errors, field.getErrors(form));
1118
1459
  } else {
1119
- if (!(t instanceof O))
1460
+ if (!(field instanceof BaseField)) {
1120
1461
  throw new Error("Invalid field type");
1121
- const n = t.getId(), s = t.getError(ce(i, n), i);
1122
- s && ot(e, n, s);
1462
+ }
1463
+ const id = field.getId();
1464
+ const error = field.getError(get(form, id), form);
1465
+ if (error)
1466
+ set(errors, id, error);
1467
+ }
1468
+ }
1469
+ if (hasKeys(errors))
1470
+ return errors;
1471
+ };
1472
+ const uncontrolledValues = [null, void 0];
1473
+ const initialFormValues = (fields, values) => {
1474
+ return fields.reduce((acc, field) => {
1475
+ if (field instanceof FieldSection) {
1476
+ return { ...acc, ...initialFormValues(field.fields, values) };
1123
1477
  }
1124
- if (De(e))
1125
- return e;
1126
- }, Ji = [null, void 0], at = (o, i) => o.reduce((e, t) => t instanceof X ? { ...e, ...at(t.fields, i) } : (Ji.includes(ce(e, t.getId())) && ot(e, t.getId(), ""), e), i), en = () => {
1478
+ if (uncontrolledValues.includes(get(acc, field.getId()))) {
1479
+ set(acc, field.getId(), "");
1480
+ }
1481
+ return acc;
1482
+ }, values);
1483
+ };
1484
+ const defaultHandleSubmit = () => {
1127
1485
  throw new Error("onSubmit must be provided if form is not readonly.");
1128
- }, ct = S(
1129
- pe((o, i) => {
1486
+ };
1487
+ const FormRenderer = memo(
1488
+ forwardRef((props, ref) => {
1130
1489
  const {
1131
- schema: e,
1132
- values: t = {},
1133
- onSubmit: n = en,
1134
- submitText: s = "Submit",
1135
- cancelText: a,
1136
- onCancel: c,
1137
- onDirty: l,
1490
+ schema,
1491
+ values = {},
1492
+ onSubmit = defaultHandleSubmit,
1493
+ submitText = "Submit",
1494
+ cancelText,
1495
+ onCancel,
1496
+ onDirty,
1138
1497
  // if the title isn't provided, hide it by default
1139
- hideTitle: d = !e.title,
1140
- hideDescription: u,
1141
- className: f
1142
- } = o, { readonly: p } = e.meta, h = x(() => crypto.randomUUID(), []), g = et({
1143
- initialValues: at(e.fields, t),
1144
- onSubmit: n,
1145
- validate: (k) => Ot(e, k),
1498
+ hideTitle = !schema.title,
1499
+ hideDescription,
1500
+ className
1501
+ } = props;
1502
+ const { readonly } = schema.meta;
1503
+ const formId2 = useMemo(() => crypto.randomUUID(), []);
1504
+ const formik = useFormik({
1505
+ initialValues: initialFormValues(schema.fields, values),
1506
+ onSubmit,
1507
+ validate: (form) => validateForm(schema, form),
1146
1508
  // only validate the entire form on submit
1147
- validateOnBlur: !1,
1148
- validateOnChange: !1
1149
- }), { dirty: v } = g, z = x(
1150
- () => typeof e.title == "string" ? /* @__PURE__ */ r(Me, { children: e.title }) : e.title,
1151
- [e.title]
1152
- ), I = x(
1153
- () => typeof e.description == "string" ? /* @__PURE__ */ r(V, { className: Re.description, children: e.description }) : e.description,
1154
- [e.description]
1155
- ), w = Mt(e.fields, { formId: h, disabled: p });
1156
- return ve(() => {
1157
- v && l && l();
1158
- }, [v, l]), /* @__PURE__ */ r(tt, { value: g, children: /* @__PURE__ */ r(y, { ref: i, direction: "column", gap: "2", className: f, asChild: !0, children: /* @__PURE__ */ b("form", { id: h, onSubmit: g.handleSubmit, children: [
1159
- !d && /* @__PURE__ */ r(fe, { children: /* @__PURE__ */ b(y, { direction: "column", gap: "1", children: [
1160
- z,
1161
- !u && I
1509
+ validateOnBlur: false,
1510
+ validateOnChange: false
1511
+ });
1512
+ const { dirty } = formik;
1513
+ const Title = useMemo(
1514
+ () => typeof schema.title === "string" ? /* @__PURE__ */ jsx(Heading, { children: schema.title }) : schema.title,
1515
+ [schema.title]
1516
+ );
1517
+ const Description = useMemo(
1518
+ () => typeof schema.description === "string" ? /* @__PURE__ */ jsx(Text, { className: styles$3.description, children: schema.description }) : schema.description,
1519
+ [schema.description]
1520
+ );
1521
+ const inputs = useFieldInputs(schema.fields, { formId: formId2, disabled: readonly });
1522
+ useEffect(() => {
1523
+ if (dirty && onDirty)
1524
+ onDirty();
1525
+ }, [dirty, onDirty]);
1526
+ return /* @__PURE__ */ jsx(FormikProvider, { value: formik, children: /* @__PURE__ */ jsx(Flex, { ref, direction: "column", gap: "2", className, asChild: true, children: /* @__PURE__ */ jsxs("form", { id: formId2, onSubmit: formik.handleSubmit, children: [
1527
+ !hideTitle && /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "1", children: [
1528
+ Title,
1529
+ !hideDescription && Description
1162
1530
  ] }) }),
1163
- w,
1164
- !p && /* @__PURE__ */ b(y, { justify: "end", gap: "2", children: [
1165
- a && /* @__PURE__ */ r(H, { type: "button", variant: "soft", onClick: c, children: a }),
1166
- /* @__PURE__ */ r(H, { type: "submit", disabled: !g.isValid, children: s })
1531
+ inputs,
1532
+ !readonly && /* @__PURE__ */ jsxs(Flex, { justify: "end", gap: "2", children: [
1533
+ cancelText && /* @__PURE__ */ jsx(Button, { type: "button", variant: "soft", onClick: onCancel, children: cancelText }),
1534
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !formik.isValid, children: submitText })
1167
1535
  ] })
1168
1536
  ] }) }) });
1169
1537
  })
1170
- ), Mn = S(
1171
- pe((o, i) => {
1172
- const { submission: e, showFormDescription: t = !1, showFormTitle: n = !0 } = o, s = M(Ct(e.form_revision)), { sdk: a } = Ft();
1173
- if (!s)
1538
+ );
1539
+ const FormSubmissionViewer = memo(
1540
+ forwardRef((props, ref) => {
1541
+ const { submission, showFormDescription = false, showFormTitle = true } = props;
1542
+ const revision = useAppSelector(selectFormRevision(submission.form_revision));
1543
+ const { sdk } = useSDK();
1544
+ if (!revision) {
1174
1545
  throw new Error(
1175
- `Could not find revision ${e.form_revision} for submission ${e.offline_id}.`
1546
+ `Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`
1176
1547
  );
1177
- const c = x(() => Dt(s, { readonly: !0 }), [s]), l = x(() => {
1178
- const d = Fi(e.offline_id)(a.store.getState()) ?? [], u = {};
1179
- for (const f of d) {
1180
- const p = a.files.fetchFileFromUrl(f.file, f.file_sha1, f.file_name).then((g) => {
1181
- if (!g.success)
1182
- throw new Error(`Failed to download attachment ${f.file_name}.`);
1183
- return g.body;
1184
- }), h = u[f.field_identifier];
1185
- h ? h.push(p) : u[f.field_identifier] = [p];
1548
+ }
1549
+ const schema = useMemo(() => {
1550
+ return formRevisionToSchema(revision, { readonly: true });
1551
+ }, [revision]);
1552
+ const submissionValuesWithAttachments = useMemo(() => {
1553
+ const attachments = selectSubmissionAttachments(submission.offline_id)(sdk.store.getState()) ?? [];
1554
+ const downloadedAttachments = {};
1555
+ for (const attachment of attachments) {
1556
+ const promise = sdk.files.fetchFileFromUrl(attachment.file, attachment.file_sha1, attachment.file_name).then((response) => {
1557
+ if (!response.success)
1558
+ throw new Error(`Failed to download attachment ${attachment.file_name}.`);
1559
+ return response.body;
1560
+ });
1561
+ const fieldAttachments = downloadedAttachments[attachment.field_identifier];
1562
+ if (fieldAttachments) {
1563
+ fieldAttachments.push(promise);
1564
+ } else {
1565
+ downloadedAttachments[attachment.field_identifier] = [promise];
1566
+ }
1186
1567
  }
1187
- return { ...e.values, ...u };
1188
- }, [a.files, a.store, e.offline_id, e.values]);
1189
- return /* @__PURE__ */ r(
1190
- ct,
1568
+ return { ...submission.values, ...downloadedAttachments };
1569
+ }, [sdk.files, sdk.store, submission.offline_id, submission.values]);
1570
+ return /* @__PURE__ */ jsx(
1571
+ FormRenderer,
1191
1572
  {
1192
- ref: i,
1193
- schema: c,
1194
- values: l,
1195
- hideDescription: !t,
1196
- hideTitle: !n
1573
+ ref,
1574
+ schema,
1575
+ values: submissionValuesWithAttachments,
1576
+ hideDescription: !showFormDescription,
1577
+ hideTitle: !showFormTitle
1197
1578
  }
1198
1579
  );
1199
1580
  })
1200
- ), tn = "_favoriteIcon_1bixi_1", nn = "_regularIcon_1bixi_9", pt = {
1201
- favoriteIcon: tn,
1202
- regularIcon: nn
1203
- }, We = "organization:", je = "user:", On = S(
1204
- pe((o, i) => {
1205
- const { maxResults: e = 20, ...t } = o, [n, s] = Y(""), [a, c] = Y(""), { sdk: l } = Ft(), d = x(() => {
1206
- const w = { maxResults: e, searchTerm: n };
1207
- return a && (a.startsWith(We) ? w.owner_organization = parseInt(a.slice(We.length)) : a.startsWith(je) && (w.owner_user = parseInt(a.slice(je.length)))), w;
1208
- }, [n, e, a]), u = M(Ti(d)) ?? [], f = M(Si), p = T(
1209
- (w) => {
1210
- w.favorite ? l.userForms.unfavorite(w.offline_id).then() : l.userForms.favorite(w.offline_id).then();
1581
+ );
1582
+ const favoriteIcon = "_favoriteIcon_1bixi_1";
1583
+ const regularIcon = "_regularIcon_1bixi_9";
1584
+ const styles$1 = {
1585
+ favoriteIcon,
1586
+ regularIcon
1587
+ };
1588
+ const orgOptionPrefix = "organization:";
1589
+ const userOptionPrefix = "user:";
1590
+ const FormBrowser = memo(
1591
+ forwardRef((props, ref) => {
1592
+ const { maxResults = 20, ...entryProps } = props;
1593
+ const [filter, setFilter] = useState("");
1594
+ const [ownerFilter, setOwnerFilter] = useState("");
1595
+ const { sdk } = useSDK();
1596
+ const ownerFilterOptions = useMemo(() => {
1597
+ const ret = { maxResults, searchTerm: filter };
1598
+ if (ownerFilter) {
1599
+ if (ownerFilter.startsWith(orgOptionPrefix)) {
1600
+ ret.owner_organization = parseInt(ownerFilter.slice(orgOptionPrefix.length));
1601
+ } else if (ownerFilter.startsWith(userOptionPrefix)) {
1602
+ ret.owner_user = parseInt(ownerFilter.slice(userOptionPrefix.length));
1603
+ }
1604
+ }
1605
+ return ret;
1606
+ }, [filter, maxResults, ownerFilter]);
1607
+ const userForms = useAppSelector(selectFilteredUserForms(ownerFilterOptions)) ?? [];
1608
+ const userFormMapping = useAppSelector(selectUserFormMapping);
1609
+ const handleToggleFavorite = useCallback(
1610
+ (form) => {
1611
+ if (form.favorite) {
1612
+ sdk.userForms.unfavorite(form.offline_id).then();
1613
+ } else {
1614
+ sdk.userForms.favorite(form.offline_id).then();
1615
+ }
1211
1616
  },
1212
- [l]
1213
- ), h = x(() => {
1214
- const w = l.store.getState(), k = {};
1215
- for (const A of Object.values(f)) {
1216
- const C = Tt(A.owner_organization || -1)(w);
1217
- C && (k[`${We}${C.id}`] = C.name);
1218
- const $ = rt(A.owner_user || -1)(w);
1219
- $ && (k[`${je}${$.id}`] = $.username);
1617
+ [sdk]
1618
+ );
1619
+ const options = useMemo(() => {
1620
+ const state = sdk.store.getState();
1621
+ const accumulator = {};
1622
+ for (const form of Object.values(userFormMapping)) {
1623
+ const organization = selectOrganization(form.owner_organization || -1)(state);
1624
+ if (organization) {
1625
+ accumulator[`${orgOptionPrefix}${organization.id}`] = organization.name;
1626
+ }
1627
+ const user = selectUser(form.owner_user || -1)(state);
1628
+ if (user) {
1629
+ accumulator[`${userOptionPrefix}${user.id}`] = user.username;
1630
+ }
1220
1631
  }
1221
- return Object.entries(k).map(([A, C]) => ({ itemContent: C, value: A }));
1222
- }, [f, l.store]), g = T((w) => {
1223
- s(w.currentTarget.value);
1224
- }, []), z = (M(zi) || 0) - u.length, I = u.length == e && z > 0 ? `Only the first ${e} results are shown (${z} hidden)` : z > 0 && `${z} hidden forms`;
1225
- return /* @__PURE__ */ b(y, { ref: i, direction: "column", gap: "2", children: [
1226
- /* @__PURE__ */ b(y, { gap: "2", grow: "1", children: [
1227
- /* @__PURE__ */ r(ge, { grow: "1", asChild: !0, children: /* @__PURE__ */ r(ae.Root, { size: "3", children: /* @__PURE__ */ r(ae.Input, { placeholder: "Filter", value: n, onChange: g }) }) }),
1228
- /* @__PURE__ */ r(
1229
- vt,
1632
+ return Object.entries(accumulator).map(([value, label]) => ({ itemContent: label, value }));
1633
+ }, [userFormMapping, sdk.store]);
1634
+ const handleChange = useCallback((e) => {
1635
+ setFilter(e.currentTarget.value);
1636
+ }, []);
1637
+ const numberOfForms = useAppSelector(selectNumberOfUserForms) || 0;
1638
+ const numberOfHiddenForms = numberOfForms - userForms.length;
1639
+ const overflowMessage = userForms.length == maxResults && numberOfHiddenForms > 0 ? `Only the first ${maxResults} results are shown (${numberOfHiddenForms} hidden)` : numberOfHiddenForms > 0 && `${numberOfHiddenForms} hidden forms`;
1640
+ return /* @__PURE__ */ jsxs(Flex, { ref, direction: "column", gap: "2", children: [
1641
+ /* @__PURE__ */ jsxs(Flex, { gap: "2", grow: "1", children: [
1642
+ /* @__PURE__ */ jsx(Box, { grow: "1", asChild: true, children: /* @__PURE__ */ jsx(TextField$1.Root, { size: "3", children: /* @__PURE__ */ jsx(TextField$1.Input, { placeholder: "Filter", value: filter, onChange: handleChange }) }) }),
1643
+ /* @__PURE__ */ jsx(
1644
+ Select,
1230
1645
  {
1231
- items: h,
1232
- value: a,
1233
- onValueChange: c,
1646
+ items: options,
1647
+ value: ownerFilter,
1648
+ onValueChange: setOwnerFilter,
1234
1649
  placeholder: "Owner",
1235
1650
  size: "large"
1236
1651
  }
1237
1652
  )
1238
1653
  ] }),
1239
- u.length > 0 && /* @__PURE__ */ r(Oe.Root, { children: u.map((w) => /* @__PURE__ */ r(
1240
- rn,
1654
+ userForms.length > 0 && /* @__PURE__ */ jsx(ButtonList.Root, { children: userForms.map((form) => /* @__PURE__ */ jsx(
1655
+ FormBrowserEntry,
1241
1656
  {
1242
- ...t,
1243
- form: w,
1244
- handleToggleFavorite: () => p(w)
1657
+ ...entryProps,
1658
+ form,
1659
+ handleToggleFavorite: () => handleToggleFavorite(form)
1245
1660
  },
1246
- w.offline_id
1661
+ form.offline_id
1247
1662
  )) }),
1248
- /* @__PURE__ */ r(ge, { px: "3", children: /* @__PURE__ */ r(V, { size: "2", severity: "info", children: I }) })
1663
+ /* @__PURE__ */ jsx(Box, { px: "3", children: /* @__PURE__ */ jsx(Text, { size: "2", severity: "info", children: overflowMessage }) })
1249
1664
  ] });
1250
1665
  })
1251
- ), rn = (o) => {
1252
- var p;
1253
- const { form: i, onSelectForm: e, isFavoriteEditable: t, handleToggleFavorite: n } = o, s = (p = M(Tt(i.owner_organization || -1))) == null ? void 0 : p.name, a = M(rt(i.owner_user || -1)), c = M(St).id, l = !!a && a.id === c, d = s ?? (l ? "You" : a == null ? void 0 : a.username) ?? "Unknown", u = T(
1254
- (h) => {
1255
- h.stopPropagation(), n();
1666
+ );
1667
+ const FormBrowserEntry = (props) => {
1668
+ var _a;
1669
+ const { form, onSelectForm, isFavoriteEditable, handleToggleFavorite } = props;
1670
+ const ownerOrganization = (_a = useAppSelector(selectOrganization(form.owner_organization || -1))) == null ? void 0 : _a.name;
1671
+ const ownerUser = useAppSelector(selectUser(form.owner_user || -1));
1672
+ const currentUserId = useAppSelector(selectCurrentUser).id;
1673
+ const ownedByCurrentUser = !!ownerUser && ownerUser.id === currentUserId;
1674
+ const owner = ownerOrganization ?? (ownedByCurrentUser ? "You" : ownerUser == null ? void 0 : ownerUser.username) ?? "Unknown";
1675
+ const handleFavoriteClick = useCallback(
1676
+ (e) => {
1677
+ e.stopPropagation();
1678
+ handleToggleFavorite();
1256
1679
  },
1257
- [n]
1258
- ), f = /* @__PURE__ */ r(Oe.Item, { onClick: () => e(i), asChild: !0, children: /* @__PURE__ */ b(y, { justify: "between", gap: "2", py: "2", px: "3", ...ni, children: [
1259
- /* @__PURE__ */ b(y, { grow: "1", align: "center", gap: "2", children: [
1260
- /* @__PURE__ */ r(
1261
- K,
1680
+ [handleToggleFavorite]
1681
+ );
1682
+ const ret = /* @__PURE__ */ jsx(ButtonList.Item, { onClick: () => onSelectForm(form), asChild: true, children: /* @__PURE__ */ jsxs(Flex, { justify: "between", gap: "2", py: "2", px: "3", ...divButtonProps, children: [
1683
+ /* @__PURE__ */ jsxs(Flex, { grow: "1", align: "center", gap: "2", children: [
1684
+ /* @__PURE__ */ jsx(
1685
+ IconButton,
1262
1686
  {
1263
- className: zt(i.favorite ? pt.favoriteIcon : pt.regularIcon),
1687
+ className: classNames(form.favorite ? styles$1.favoriteIcon : styles$1.regularIcon),
1264
1688
  variant: "ghost",
1265
- onClick: u,
1266
- "aria-label": i.favorite ? "Favorite form" : "Standard form",
1267
- disabled: !t,
1268
- children: i.favorite ? /* @__PURE__ */ r(ri, {}) : /* @__PURE__ */ r(oi, {})
1689
+ onClick: handleFavoriteClick,
1690
+ "aria-label": form.favorite ? "Favorite form" : "Standard form",
1691
+ disabled: !isFavoriteEditable,
1692
+ children: form.favorite ? /* @__PURE__ */ jsx(StarFilledIcon, {}) : /* @__PURE__ */ jsx(StarIcon, {})
1269
1693
  }
1270
1694
  ),
1271
- /* @__PURE__ */ r(V, { noWrap: !0, children: i.latestRevision.title }),
1272
- i.latestRevision.description && /* @__PURE__ */ r(si, {})
1695
+ /* @__PURE__ */ jsx(Text, { noWrap: true, children: form.latestRevision.title }),
1696
+ form.latestRevision.description && /* @__PURE__ */ jsx(QuestionMarkCircledIcon, {})
1273
1697
  ] }),
1274
- d && /* @__PURE__ */ b(y, { align: "center", gap: "2", children: [
1275
- /* @__PURE__ */ r(li, {}),
1698
+ owner && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "2", children: [
1699
+ /* @__PURE__ */ jsx(PersonIcon, {}),
1276
1700
  " ",
1277
- d
1701
+ owner
1278
1702
  ] })
1279
1703
  ] }) });
1280
- return i.latestRevision.description ? /* @__PURE__ */ r(ai, { content: i.latestRevision.description, children: f }, i.offline_id) : f;
1281
- }, on = "_submissionsContainer_9iirt_1", sn = "_stopHorizontalOverflow_9iirt_6", Rt = {
1282
- submissionsContainer: on,
1283
- stopHorizontalOverflow: sn
1284
- }, ln = S(function(i) {
1285
- var w;
1286
- const { submission: e, onSubmissionClick: t, compact: n, labelType: s, rowDecorator: a } = i, c = M(St), l = M(rt("created_by" in e ? e.created_by : c.id)), d = Xe(e), u = Ei(d) ? d.toLocaleTimeString([], {
1704
+ if (form.latestRevision.description) {
1705
+ return /* @__PURE__ */ jsx(Tooltip, { content: form.latestRevision.description, children: ret }, form.offline_id);
1706
+ }
1707
+ return ret;
1708
+ };
1709
+ const submissionsContainer = "_submissionsContainer_9iirt_1";
1710
+ const stopHorizontalOverflow = "_stopHorizontalOverflow_9iirt_6";
1711
+ const styles = {
1712
+ submissionsContainer,
1713
+ stopHorizontalOverflow
1714
+ };
1715
+ const FormSubmissionBrowserEntry = memo(function FormSubmissionBrowserEntry2(props) {
1716
+ var _a;
1717
+ const { submission, onSubmissionClick, compact, labelType, rowDecorator } = props;
1718
+ const currentUser = useAppSelector(selectCurrentUser);
1719
+ const createdBy = useAppSelector(selectUser("created_by" in submission ? submission.created_by : currentUser.id));
1720
+ const dateToUse = getCreatedAtOrSubmittedAtDate(submission);
1721
+ const formattedDateTime = isToday(dateToUse) ? dateToUse.toLocaleTimeString([], {
1287
1722
  hour: "2-digit",
1288
1723
  minute: "2-digit"
1289
- }) : Li(d), f = M(Ct(e.form_revision));
1290
- if (!f)
1291
- throw new Error(`Could not find revision ${e.form_revision} for submission ${e.offline_id}.`);
1292
- const p = (w = M(Ai(f.form))) == null ? void 0 : w.revision, h = Pi({
1293
- file: (l == null ? void 0 : l.profile.file) ?? null,
1294
- fileSha1: (l == null ? void 0 : l.profile.file_sha1) ?? null
1295
- }), g = (l == null ? void 0 : l.username.charAt(0).toUpperCase()) ?? "?", v = f.revision === p, z = wi.useCallback(() => {
1296
- t && t({ submission: e });
1297
- }, [e, t]), I = /* @__PURE__ */ r(Oe.Item, { onClick: z, asChild: !0, children: /* @__PURE__ */ b(y, { grow: "1", width: "100%", p: "2", gap: "2", justify: "between", children: [
1298
- /* @__PURE__ */ b(y, { gap: "2", align: "center", className: Rt.stopHorizontalOverflow, children: [
1299
- /* @__PURE__ */ r(ci, { src: h, size: "1", fallback: g }),
1300
- /* @__PURE__ */ r(V, { size: "2", noWrap: !0, children: s === "creator" ? (l || c).username : f.title })
1724
+ }) : getLocalDateString(dateToUse);
1725
+ const revision = useAppSelector(selectFormRevision(submission.form_revision));
1726
+ if (!revision) {
1727
+ throw new Error(`Could not find revision ${submission.form_revision} for submission ${submission.offline_id}.`);
1728
+ }
1729
+ const latestRevisionNumber = (_a = useAppSelector(selectLatestFormRevision(revision.form))) == null ? void 0 : _a.revision;
1730
+ const creatorProfileSrc = useFileSrc({
1731
+ file: (createdBy == null ? void 0 : createdBy.profile.file) ?? null,
1732
+ fileSha1: (createdBy == null ? void 0 : createdBy.profile.file_sha1) ?? null
1733
+ });
1734
+ const creatorProfileFallback = (createdBy == null ? void 0 : createdBy.username.charAt(0).toUpperCase()) ?? "?";
1735
+ const isLatestRevision = revision.revision === latestRevisionNumber;
1736
+ const handleClick = React.useCallback(() => {
1737
+ if (onSubmissionClick) {
1738
+ onSubmissionClick({ submission });
1739
+ }
1740
+ }, [submission, onSubmissionClick]);
1741
+ const row = /* @__PURE__ */ jsx(ButtonList.Item, { onClick: handleClick, asChild: true, children: /* @__PURE__ */ jsxs(Flex, { grow: "1", width: "100%", p: "2", gap: "2", justify: "between", children: [
1742
+ /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "center", className: styles.stopHorizontalOverflow, children: [
1743
+ /* @__PURE__ */ jsx(Avatar, { src: creatorProfileSrc, size: "1", fallback: creatorProfileFallback }),
1744
+ /* @__PURE__ */ jsx(Text, { size: "2", noWrap: true, children: labelType === "creator" ? (createdBy || currentUser).username : revision.title })
1301
1745
  ] }),
1302
- /* @__PURE__ */ b(y, { gap: "2", align: "center", children: [
1303
- !n && (f.revision ? /* @__PURE__ */ r(He, { variant: "soft", severity: v ? "primary" : "info", children: n ? f.revision.toString() : `Revision #${f.revision}` }) : !!p && /* @__PURE__ */ r(He, { children: "Original" })),
1304
- /* @__PURE__ */ r(V, { size: "2", noWrap: !0, children: u })
1746
+ /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "center", children: [
1747
+ !compact && (revision.revision ? /* @__PURE__ */ jsx(Badge, { variant: "soft", severity: isLatestRevision ? "primary" : "info", children: compact ? revision.revision.toString() : `Revision #${revision.revision}` }) : !!latestRevisionNumber && /* @__PURE__ */ jsx(Badge, { children: "Original" })),
1748
+ /* @__PURE__ */ jsx(Text, { size: "2", noWrap: true, children: formattedDateTime })
1305
1749
  ] })
1306
1750
  ] }) });
1307
- return a ? a(e, I) : I;
1308
- }), Xe = (o) => {
1309
- const i = "created_at" in o ? o.created_at : o.submitted_at;
1310
- return new Date(i);
1311
- }, Rn = S(function(i) {
1751
+ if (rowDecorator) {
1752
+ return rowDecorator(submission, row);
1753
+ }
1754
+ return row;
1755
+ });
1756
+ const getCreatedAtOrSubmittedAtDate = (submission) => {
1757
+ const date = "created_at" in submission ? submission.created_at : submission.submitted_at;
1758
+ return new Date(date);
1759
+ };
1760
+ const FormSubmissionBrowser = memo(function FormSubmissionBrowser2(props) {
1312
1761
  const {
1313
- formId: e,
1314
- submissions: t,
1315
- compact: n = !1,
1316
- className: s,
1317
- after: a,
1318
- variant: c = "outline",
1319
- ...l
1320
- } = i;
1321
- if (!!e == !!t)
1762
+ formId: formId2,
1763
+ submissions: propSubmissions,
1764
+ compact = false,
1765
+ className,
1766
+ after,
1767
+ variant = "outline",
1768
+ ...submissionEntryProps
1769
+ } = props;
1770
+ if (!!formId2 === !!propSubmissions) {
1322
1771
  throw new Error("Either formId or submissions must be provided, but not both.");
1323
- const d = M(
1324
- t ? () => t : ki(e)
1325
- ), u = x(
1326
- () => d == null ? void 0 : d.sort((f, p) => Xe(p).getTime() - Xe(f).getTime()),
1327
- [d]
1772
+ }
1773
+ const submissions = useAppSelector(
1774
+ propSubmissions ? () => propSubmissions : selectSubmissionsForForm(formId2)
1775
+ );
1776
+ const sortedSubmissions = useMemo(
1777
+ () => submissions == null ? void 0 : submissions.sort((a, b) => {
1778
+ return getCreatedAtOrSubmittedAtDate(b).getTime() - getCreatedAtOrSubmittedAtDate(a).getTime();
1779
+ }),
1780
+ [submissions]
1328
1781
  );
1329
- return /* @__PURE__ */ r(
1330
- Oe.Root,
1782
+ return /* @__PURE__ */ jsx(
1783
+ ButtonList.Root,
1331
1784
  {
1332
- className: zt(Rt.submissionsContainer, s),
1785
+ className: classNames(styles.submissionsContainer, className),
1333
1786
  size: "small",
1334
- variant: c,
1335
- before: !n && /* @__PURE__ */ b(V, { severity: "info", children: [
1787
+ variant,
1788
+ before: !compact && /* @__PURE__ */ jsxs(Text, { severity: "info", children: [
1336
1789
  "There are ",
1337
- ((d == null ? void 0 : d.length) || 0).toString(),
1790
+ ((submissions == null ? void 0 : submissions.length) || 0).toString(),
1338
1791
  " submissions of this form."
1339
1792
  ] }),
1340
- after: a,
1341
- children: u == null ? void 0 : u.map((f, p) => /* @__PURE__ */ r(
1342
- ln,
1343
- {
1344
- submission: f,
1345
- compact: n,
1346
- ...l
1347
- },
1348
- p
1349
- ))
1793
+ after,
1794
+ children: sortedSubmissions == null ? void 0 : sortedSubmissions.map((submission, index) => {
1795
+ return /* @__PURE__ */ jsx(
1796
+ FormSubmissionBrowserEntry,
1797
+ {
1798
+ submission,
1799
+ compact,
1800
+ ...submissionEntryProps
1801
+ },
1802
+ index
1803
+ );
1804
+ })
1350
1805
  }
1351
1806
  );
1352
- }), Nn = S(function(i) {
1353
- const { name: e, render: t } = i, { submitForm: n } = me(), [s, a, c] = Je(e);
1354
- return x(() => {
1355
- const l = (d) => c.setValue(d, !1);
1356
- return t({
1357
- value: s.value,
1358
- setValue: l,
1359
- patchValue: n
1807
+ });
1808
+ const PatchField = memo(function PatchField2(props) {
1809
+ const { name, render } = props;
1810
+ const { submitForm } = useFormikContext();
1811
+ const [fieldProps, _meta, helpers] = useField(name);
1812
+ return useMemo(() => {
1813
+ const setValue = (value) => helpers.setValue(value, false);
1814
+ return render({
1815
+ value: fieldProps.value,
1816
+ setValue,
1817
+ patchValue: submitForm
1360
1818
  });
1361
- }, [n, c, s.value, t]);
1362
- }), Bn = S(
1363
- pe((o, i) => {
1364
- const { children: e, schema: t, values: n, onPatch: s, onError: a, ...c } = o, l = x(() => at(t.fields, n), [t.fields, n]), d = T(
1365
- (g) => {
1366
- const v = {};
1367
- for (const z in g) {
1368
- const I = g[z];
1369
- I !== l[z] && I !== void 0 && (v[z] = I);
1819
+ }, [submitForm, helpers, fieldProps.value, render]);
1820
+ });
1821
+ const PatchFormProvider = memo(
1822
+ forwardRef((props, ref) => {
1823
+ const { children, schema, values, onPatch, onError, ...rest } = props;
1824
+ const initialValues2 = useMemo(() => initialFormValues(schema.fields, values), [schema.fields, values]);
1825
+ const handlePatch = useCallback(
1826
+ (values2) => {
1827
+ const diff = {};
1828
+ for (const key in values2) {
1829
+ const value = values2[key];
1830
+ if (value !== initialValues2[key] && value !== void 0) {
1831
+ diff[key] = value;
1832
+ }
1370
1833
  }
1371
- De(v) && s(v);
1834
+ if (!hasKeys(diff))
1835
+ return;
1836
+ onPatch(diff);
1372
1837
  },
1373
- [l, s]
1374
- ), u = T(
1375
- async (g) => {
1376
- const v = await Ot(t, g);
1377
- return v && a(v), v;
1838
+ [initialValues2, onPatch]
1839
+ );
1840
+ const validate = useCallback(
1841
+ async (form) => {
1842
+ const error = await validateForm(schema, form);
1843
+ if (error) {
1844
+ onError(error);
1845
+ }
1846
+ return error;
1378
1847
  },
1379
- [t, a]
1380
- ), f = et({
1381
- initialValues: l,
1382
- onSubmit: d,
1383
- validate: u,
1848
+ [schema, onError]
1849
+ );
1850
+ const formik = useFormik({
1851
+ initialValues: initialValues2,
1852
+ onSubmit: handlePatch,
1853
+ validate,
1384
1854
  // only validate the entire form on submit
1385
- validateOnBlur: !1,
1386
- validateOnChange: !1
1387
- }), { errors: p, resetForm: h } = f;
1388
- return ve(() => {
1389
- De(p) && h({ values: l, errors: {} });
1390
- }, [p, l, h]), /* @__PURE__ */ r(tt, { value: f, children: /* @__PURE__ */ r("form", { ...c, ref: i, onSubmit: f.handleSubmit, children: e }) });
1855
+ validateOnBlur: false,
1856
+ validateOnChange: false
1857
+ });
1858
+ const { errors, resetForm } = formik;
1859
+ useEffect(() => {
1860
+ if (hasKeys(errors)) {
1861
+ resetForm({ values: initialValues2, errors: {} });
1862
+ }
1863
+ }, [errors, initialValues2, resetForm]);
1864
+ return /* @__PURE__ */ jsx(FormikProvider, { value: formik, children: /* @__PURE__ */ jsx("form", { ...rest, ref, onSubmit: formik.handleSubmit, children }) });
1391
1865
  })
1392
1866
  );
1393
- function an(o, i) {
1394
- if (o == null)
1395
- return {};
1396
- var e = {}, t = Object.keys(o), n, s;
1397
- for (s = 0; s < t.length; s++)
1398
- n = t[s], !(i.indexOf(n) >= 0) && (e[n] = o[n]);
1399
- return e;
1400
- }
1401
- var cn = ["color"], dn = /* @__PURE__ */ pe(function(o, i) {
1402
- var e = o.color, t = e === void 0 ? "currentColor" : e, n = an(o, cn);
1403
- return ft("svg", Object.assign({
1404
- width: "15",
1405
- height: "15",
1406
- viewBox: "0 0 15 15",
1407
- fill: "none",
1408
- xmlns: "http://www.w3.org/2000/svg"
1409
- }, n, {
1410
- ref: i
1411
- }), ft("path", {
1412
- d: "M12.8536 2.85355C13.0488 2.65829 13.0488 2.34171 12.8536 2.14645C12.6583 1.95118 12.3417 1.95118 12.1464 2.14645L7.5 6.79289L2.85355 2.14645C2.65829 1.95118 2.34171 1.95118 2.14645 2.14645C1.95118 2.34171 1.95118 2.65829 2.14645 2.85355L6.79289 7.5L2.14645 12.1464C1.95118 12.3417 1.95118 12.6583 2.14645 12.8536C2.34171 13.0488 2.65829 13.0488 2.85355 12.8536L7.5 8.20711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.20711 7.5L12.8536 2.85355Z",
1413
- fill: t,
1414
- fillRule: "evenodd",
1415
- clipRule: "evenodd"
1416
- }));
1417
- });
1418
- const Nt = {
1419
- ...lt,
1420
- section: X
1421
- }, un = S(function(i) {
1422
- const { field: e, setFieldType: t } = i, n = e.fieldTypeName, s = e.fieldTypeDescription, a = e.Icon;
1423
- return /* @__PURE__ */ b(y, { gap: "4", align: "center", children: [
1424
- /* @__PURE__ */ r(H, { type: "button", variant: "surface", onClick: t, style: { width: "135px" }, children: /* @__PURE__ */ b(y, { gap: "3", align: "center", grow: "1", children: [
1425
- /* @__PURE__ */ r(a, {}),
1426
- n
1867
+ const CompleteFieldTypeToClsMapping = {
1868
+ ...FieldTypeToClsMapping,
1869
+ section: FieldSection
1870
+ };
1871
+ const FieldToChoose = memo(function FieldToChoose2(props) {
1872
+ const { field, setFieldType } = props;
1873
+ const typeName = field.fieldTypeName;
1874
+ const description2 = field.fieldTypeDescription;
1875
+ const Icon = field.Icon;
1876
+ return /* @__PURE__ */ jsxs(Flex, { gap: "4", align: "center", children: [
1877
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "surface", onClick: setFieldType, style: { width: "135px" }, children: /* @__PURE__ */ jsxs(Flex, { gap: "3", align: "center", grow: "1", children: [
1878
+ /* @__PURE__ */ jsx(Icon, {}),
1879
+ typeName
1427
1880
  ] }) }),
1428
- /* @__PURE__ */ r(V, { children: s })
1881
+ /* @__PURE__ */ jsx(Text, { children: description2 })
1429
1882
  ] });
1430
- }), Bt = [
1883
+ });
1884
+ const fieldsToChoose = [
1431
1885
  ["string", "text"],
1432
1886
  ["select", "multi-select", "upload"],
1433
1887
  ["boolean", "date", "number", "multi-string"]
1434
- ], fn = Bt.length - 1, mn = S(function(i) {
1435
- const { setFieldType: e } = i;
1436
- return /* @__PURE__ */ r(y, { direction: "column", gap: "3", children: Bt.map((t, n) => /* @__PURE__ */ b(y, { direction: "column", gap: "3", children: [
1437
- /* @__PURE__ */ r(y, { direction: "column", gap: "2", children: t.map((s) => /* @__PURE__ */ r(
1438
- un,
1888
+ ];
1889
+ const indexOfLastFieldGroup = fieldsToChoose.length - 1;
1890
+ const ChooseFieldToAdd = memo(function ChooseFieldToAdd2(props) {
1891
+ const { setFieldType } = props;
1892
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "3", children: fieldsToChoose.map((fieldGroup, index) => /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
1893
+ /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "2", children: fieldGroup.map((identifier) => /* @__PURE__ */ jsx(
1894
+ FieldToChoose,
1439
1895
  {
1440
- field: lt[s],
1441
- setFieldType: () => e(s)
1896
+ field: FieldTypeToClsMapping[identifier],
1897
+ setFieldType: () => setFieldType(identifier)
1442
1898
  },
1443
- s
1899
+ identifier
1444
1900
  )) }),
1445
- n < fn && /* @__PURE__ */ r(di, { size: "4" })
1446
- ] }, n)) });
1447
- }), pn = (o) => (i) => {
1448
- if (!(!i || typeof i != "string") && o.includes(i.trim()))
1449
- return "This name is already taken.";
1450
- }, hn = (o, i) => {
1451
- const e = [
1452
- new be({
1901
+ index < indexOfLastFieldGroup && /* @__PURE__ */ jsx(Separator, { size: "4" })
1902
+ ] }, index)) });
1903
+ });
1904
+ const validateNewFieldName = (takenLabels) => {
1905
+ return (value) => {
1906
+ if (!value || typeof value !== "string")
1907
+ return;
1908
+ if (takenLabels.includes(value.trim())) {
1909
+ return "This name is already taken.";
1910
+ }
1911
+ };
1912
+ };
1913
+ const commonFields = (takenLabels, type) => {
1914
+ const base = [
1915
+ new StringField({
1453
1916
  label: "Label",
1454
- required: !0,
1917
+ required: true,
1455
1918
  maxLength: 200,
1456
1919
  identifier: "label",
1457
- fieldValidators: [pn(o)]
1920
+ fieldValidators: [validateNewFieldName(takenLabels)]
1458
1921
  }),
1459
- new ye({
1922
+ new TextField({
1460
1923
  label: "Description",
1461
- required: !1,
1924
+ required: false,
1462
1925
  maxLength: 1e3,
1463
1926
  identifier: "description"
1464
1927
  })
1465
1928
  ];
1466
- return i === "section" ? e : [
1467
- ...e,
1468
- new de({ label: "Required", description: null, required: !1, identifier: "required" })
1929
+ if (type === "section")
1930
+ return base;
1931
+ return [
1932
+ ...base,
1933
+ new BooleanField({ label: "Required", description: null, required: false, identifier: "required" })
1469
1934
  ];
1470
- }, gn = S(function(i) {
1471
- const { fieldType: e, handleCancel: t, handleCreateField: n, defaultField: s, conditionalSourceFields: a } = i, c = Nt[e], l = me(), d = x(() => {
1472
- const u = kt(l.values.fields).filter((p) => p !== (s == null ? void 0 : s.label));
1473
- let f = hn(u, e);
1474
- if (c === X) {
1475
- if (a === void 0)
1935
+ };
1936
+ const FieldOptionsForm = memo(function FieldOptionsForm2(props) {
1937
+ const { fieldType, handleCancel, handleCreateField, defaultField, conditionalSourceFields } = props;
1938
+ const fieldCls = CompleteFieldTypeToClsMapping[fieldType];
1939
+ const formik = useFormikContext();
1940
+ const schema = useMemo(() => {
1941
+ const takenFieldLabels = getTakenFieldLabels(formik.values.fields).filter((id) => id !== (defaultField == null ? void 0 : defaultField.label));
1942
+ let fields = commonFields(takenFieldLabels, fieldType);
1943
+ if (fieldCls === FieldSection) {
1944
+ if (conditionalSourceFields === void 0) {
1476
1945
  throw new Error("Conditional source fields must be provided when changing sections.");
1477
- f = f.concat(c.getFieldCreationSchema(a));
1946
+ }
1947
+ fields = fields.concat(fieldCls.getFieldCreationSchema(conditionalSourceFields));
1478
1948
  } else {
1479
- if (!(c.prototype instanceof O))
1480
- throw new Error(`Field must be an instance of BaseField. Got ${c}.`);
1481
- f = [...f, ...c.getFieldCreationSchema()];
1949
+ if (!(fieldCls.prototype instanceof BaseField)) {
1950
+ throw new Error(`Field must be an instance of BaseField. Got ${fieldCls}.`);
1951
+ }
1952
+ fields = [...fields, ...fieldCls.getFieldCreationSchema()];
1482
1953
  }
1483
1954
  return {
1484
- fields: f,
1485
- meta: { readonly: !1 },
1955
+ fields,
1956
+ meta: { readonly: false },
1486
1957
  // using the dialog title as the form title
1487
1958
  title: null
1488
1959
  };
1489
- }, [l.values.fields, e, c, s == null ? void 0 : s.label, a]);
1490
- return /* @__PURE__ */ r(
1491
- ct,
1960
+ }, [formik.values.fields, fieldType, fieldCls, defaultField == null ? void 0 : defaultField.label, conditionalSourceFields]);
1961
+ return /* @__PURE__ */ jsx(
1962
+ FormRenderer,
1492
1963
  {
1493
- schema: d,
1494
- values: s,
1495
- onSubmit: n,
1496
- cancelText: s ? void 0 : "Back",
1497
- onCancel: t
1964
+ schema,
1965
+ values: defaultField,
1966
+ onSubmit: handleCreateField,
1967
+ cancelText: defaultField ? void 0 : "Back",
1968
+ onCancel: handleCancel
1498
1969
  }
1499
1970
  );
1500
- }), he = S(function(i) {
1501
- const { parentPath: e, index: t, onComplete: n, initial: s, editing: a, conditionalSourceFields: c } = i, [l, d] = Y(), u = (s == null ? void 0 : s.type) ?? l, f = u ? Nt[u].fieldTypeName : void 0, { setFieldValue: p, values: h } = me();
1502
- if (a && !s)
1971
+ });
1972
+ const FieldBuilder = memo(function FieldBuilder2(props) {
1973
+ const { parentPath, index, children, initial, editing, conditionalSourceFields } = props;
1974
+ const [fieldType, setFieldType] = useState();
1975
+ const type = (initial == null ? void 0 : initial.type) ?? fieldType;
1976
+ const typeName = type ? CompleteFieldTypeToClsMapping[type].fieldTypeName : void 0;
1977
+ const { setFieldValue, values } = useFormikContext();
1978
+ if (editing && !initial)
1503
1979
  throw new Error("Initial field must be provided if editing is true.");
1504
- const g = !u && !a && !s, v = g ? "Choose a field type" : `${f} settings`, z = g ? "Select a field type to add to this section." : (f == null ? void 0 : f.toLowerCase()) === "section" ? "Customize your section" : `Customize your ${f == null ? void 0 : f.toLowerCase()} field.`, I = T(() => d(void 0), []), w = T(() => {
1505
- d(void 0), n();
1506
- }, [n]), k = T(
1507
- (A) => {
1508
- const { label: C } = A;
1509
- if (!u)
1980
+ const showChooseField = !type && !editing && !initial;
1981
+ const title2 = showChooseField ? "Choose a field type" : `${typeName} settings`;
1982
+ 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.`;
1983
+ const handleCancel = useCallback(() => setFieldType(void 0), []);
1984
+ const handleCloseInterrupt = useCallback((confirmClose) => {
1985
+ setFieldType(void 0);
1986
+ confirmClose();
1987
+ }, []);
1988
+ const handleCreateField = useCallback(
1989
+ (form, closeDialog) => {
1990
+ const { label } = form;
1991
+ if (!type)
1510
1992
  throw new Error("Field type must be selected before creating a field.");
1511
- if (!C || typeof C != "string")
1993
+ if (!label || typeof label !== "string")
1512
1994
  throw new Error("Label must be provided before creating a field.");
1513
- const $ = Ne({
1514
- type: u,
1515
- ...A,
1516
- identifier: At(A.identifier, C)
1517
- }).serialize(), R = ce(h, e);
1518
- if (R === void 0)
1995
+ const field = deserialize({
1996
+ type,
1997
+ ...form,
1998
+ identifier: makeIdentifier(form.identifier, label)
1999
+ }).serialize();
2000
+ const parent = get(values, parentPath);
2001
+ if (parent === void 0) {
1519
2002
  throw new Error("Parent path must point to an existing field.");
1520
- let U;
1521
- if (!Array.isArray(R))
2003
+ }
2004
+ let newFields;
2005
+ if (!Array.isArray(parent))
1522
2006
  throw new Error("Parent path must point to an array.");
1523
- a ? U = qi(R, t, $) : U = Lt(R, t, $), p(e, U).then(), n();
2007
+ if (editing) {
2008
+ newFields = replace(parent, index, field);
2009
+ } else {
2010
+ newFields = insert(parent, index, field);
2011
+ }
2012
+ setFieldValue(parentPath, newFields).then();
2013
+ closeDialog();
1524
2014
  },
1525
- [u, h, e, a, p, n, t]
2015
+ [editing, type, values, parentPath, setFieldValue, index]
1526
2016
  );
1527
- return /* @__PURE__ */ r(fe, { children: /* @__PURE__ */ b(y, { direction: "column", gap: "2", children: [
1528
- /* @__PURE__ */ b(y, { justify: "between", children: [
1529
- /* @__PURE__ */ r(V, { children: v }),
1530
- /* @__PURE__ */ r(K, { "aria-label": "Close", onClick: w, type: "button", children: /* @__PURE__ */ r(dn, {}) })
1531
- ] }),
1532
- /* @__PURE__ */ r(V, { children: z }),
1533
- g ? /* @__PURE__ */ r(mn, { setFieldType: d }) : /* @__PURE__ */ r(
1534
- gn,
1535
- {
1536
- conditionalSourceFields: c,
1537
- handleCancel: I,
1538
- handleCreateField: (A) => k(A),
1539
- fieldType: u,
1540
- defaultField: s
2017
+ const dialogContent = useCallback(
2018
+ (closeDialog) => {
2019
+ if (showChooseField) {
2020
+ return /* @__PURE__ */ jsx(ChooseFieldToAdd, { setFieldType });
1541
2021
  }
1542
- )
1543
- ] }) });
1544
- }), ht = ({ children: o }) => /* @__PURE__ */ r(Ze, { children: o }), gt = (o, i) => ({
1545
- initial: o ? i : "none",
1546
- sm: o ? "none" : i
1547
- }), qt = S(function(i) {
1548
- const { remove: e, dragHandleProps: t, editProps: n, insertAfterProps: s, duplicateProps: a } = i, c = x(
2022
+ return /* @__PURE__ */ jsx(
2023
+ FieldOptionsForm,
2024
+ {
2025
+ conditionalSourceFields,
2026
+ handleCancel,
2027
+ handleCreateField: (form) => handleCreateField(form, closeDialog),
2028
+ fieldType: type,
2029
+ defaultField: initial
2030
+ }
2031
+ );
2032
+ },
2033
+ [conditionalSourceFields, handleCancel, handleCreateField, initial, showChooseField, type]
2034
+ );
2035
+ return /* @__PURE__ */ jsx(Dialog, { onCloseInterrupt: handleCloseInterrupt, title: title2, description: description2, content: dialogContent, children });
2036
+ });
2037
+ const DefaultWrapper = ({ children }) => /* @__PURE__ */ jsx(Fragment, { children });
2038
+ const forMobile = (mobile, display) => ({
2039
+ initial: mobile ? display : "none",
2040
+ sm: mobile ? "none" : display
2041
+ });
2042
+ const FieldActions = memo(function FieldActions2(props) {
2043
+ const { remove: remove2, dragHandleProps, editProps, insertAfterProps, duplicateProps } = props;
2044
+ const actions = useMemo(
1549
2045
  () => [
1550
2046
  {
1551
- Wrapper: he,
1552
- wrapperProps: n,
1553
- Icon: ui,
2047
+ Wrapper: FieldBuilder,
2048
+ wrapperProps: editProps,
2049
+ Icon: Pencil1Icon,
1554
2050
  text: "Edit"
1555
2051
  },
1556
2052
  {
1557
- Icon: fi,
2053
+ Icon: TrashIcon,
1558
2054
  buttonProps: {
1559
- onClick: e
2055
+ onClick: remove2
1560
2056
  },
1561
2057
  text: "Delete"
1562
2058
  },
1563
2059
  {
1564
- Wrapper: he,
1565
- wrapperProps: a,
1566
- Icon: mi,
2060
+ Wrapper: FieldBuilder,
2061
+ wrapperProps: duplicateProps,
2062
+ Icon: CopyIcon,
1567
2063
  text: "Duplicate"
1568
2064
  },
1569
2065
  {
1570
- Wrapper: he,
1571
- wrapperProps: s,
1572
- Icon: _e,
2066
+ Wrapper: FieldBuilder,
2067
+ wrapperProps: insertAfterProps,
2068
+ Icon: PlusIcon,
1573
2069
  text: "Add after"
1574
2070
  },
1575
2071
  {
1576
2072
  // Wrapping icon in a div so that the asChild turns the button into a div
1577
2073
  // so that the drag handle props are not applied to the icon
1578
2074
  // Note: b/c the <button> does not handle the space-press event correctly
1579
- Icon: (l) => /* @__PURE__ */ r("div", { ...l, children: /* @__PURE__ */ r(pi, {}) }),
2075
+ Icon: (props2) => /* @__PURE__ */ jsx("div", { ...props2, children: /* @__PURE__ */ jsx(DragHandleDots2Icon, {}) }),
1580
2076
  text: "Reorder",
1581
- disableOnMobile: !0,
1582
- buttonProps: { ...t, asChild: !0 }
2077
+ disableOnMobile: true,
2078
+ buttonProps: { ...dragHandleProps, asChild: true }
1583
2079
  }
1584
2080
  ],
1585
- [t, a, n, s, e]
2081
+ [dragHandleProps, duplicateProps, editProps, insertAfterProps, remove2]
1586
2082
  );
1587
- return /* @__PURE__ */ b(Ze, { children: [
1588
- /* @__PURE__ */ r(y, { gap: "4", display: gt(!1, "flex"), children: c.map((l) => {
1589
- const d = l.Wrapper ?? ht;
1590
- return /* @__PURE__ */ r(d, { ...l.wrapperProps, children: /* @__PURE__ */ r(K, { type: "button", variant: "ghost", "aria-label": l.text, ...l.buttonProps, children: /* @__PURE__ */ r(l.Icon, {}) }) }, l.text);
2083
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2084
+ /* @__PURE__ */ jsx(Flex, { gap: "4", display: forMobile(false, "flex"), children: actions.map((Action) => {
2085
+ const Wrapper = Action.Wrapper ?? DefaultWrapper;
2086
+ return /* @__PURE__ */ jsx(Wrapper, { ...Action.wrapperProps, children: /* @__PURE__ */ jsx(IconButton, { type: "button", variant: "ghost", "aria-label": Action.text, ...Action.buttonProps, children: /* @__PURE__ */ jsx(Action.Icon, {}) }) }, Action.text);
1591
2087
  }) }),
1592
- /* @__PURE__ */ r(ge, { display: gt(!0, "block"), children: /* @__PURE__ */ r(
1593
- hi,
2088
+ /* @__PURE__ */ jsx(Box, { display: forMobile(true, "block"), children: /* @__PURE__ */ jsx(
2089
+ DropdownMenu,
1594
2090
  {
1595
- trigger: /* @__PURE__ */ r(K, { variant: "ghost", "aria-label": "Actions menu", children: /* @__PURE__ */ r(gi, {}) }),
1596
- closeOnSelect: !1,
1597
- items: c.map((l) => {
1598
- var u;
1599
- if (l.disableOnMobile)
2091
+ trigger: /* @__PURE__ */ jsx(IconButton, { variant: "ghost", "aria-label": "Actions menu", children: /* @__PURE__ */ jsx(DotsVerticalIcon, {}) }),
2092
+ closeOnSelect: false,
2093
+ items: actions.map((Action) => {
2094
+ var _a;
2095
+ if (Action.disableOnMobile)
1600
2096
  return null;
1601
- const d = l.Wrapper ?? ht;
2097
+ const Wrapper = Action.Wrapper ?? DefaultWrapper;
1602
2098
  return {
1603
- ...l.buttonProps,
1604
- onSelect: (u = l.buttonProps) == null ? void 0 : u.onClick,
1605
- content: /* @__PURE__ */ r(d, { ...l.wrapperProps, children: /* @__PURE__ */ b(y, { gap: "2", align: "center", children: [
1606
- /* @__PURE__ */ r(l.Icon, {}),
1607
- l.text
2099
+ ...Action.buttonProps,
2100
+ onSelect: (_a = Action.buttonProps) == null ? void 0 : _a.onClick,
2101
+ content: /* @__PURE__ */ jsx(Wrapper, { ...Action.wrapperProps, children: /* @__PURE__ */ jsxs(Flex, { gap: "2", align: "center", children: [
2102
+ /* @__PURE__ */ jsx(Action.Icon, {}),
2103
+ Action.text
1608
2104
  ] }) })
1609
2105
  };
1610
- }).filter((l) => l !== null)
2106
+ }).filter((x) => x !== null)
1611
2107
  }
1612
2108
  ) })
1613
2109
  ] });
1614
- }), Be = "form-builder", bn = S(function(i) {
1615
- const { field: e, index: t, sectionIndex: n, mode: s, takenLabels: a, remove: c, onModeChange: l } = i, d = x(() => Ne(e), [e]), u = $e(d, { formId: Be, disabled: !0 }), f = T(
1616
- (v) => {
1617
- if (v.label === null)
1618
- throw new Error(`Expected a label for field ${v.identifier}`);
1619
- return { ...v, label: Ke(v.label, a), identifier: "" };
2110
+ });
2111
+ const formId = "form-builder";
2112
+ const FieldWithActions = memo(function FieldWithActions2(props) {
2113
+ const { field, index, sectionIndex, takenLabels, remove: remove2 } = props;
2114
+ const deserializedField = useMemo(() => deserialize(field), [field]);
2115
+ const input = useFieldInput(deserializedField, { formId, disabled: true });
2116
+ const duplicateField = useCallback(
2117
+ (field2) => {
2118
+ if (field2.label === null) {
2119
+ throw new Error(`Expected a label for field ${field2.identifier}`);
2120
+ }
2121
+ return { ...field2, label: incrementFieldLabel(field2.label, takenLabels), identifier: "" };
1620
2122
  },
1621
- [a]
1622
- ), p = x(() => (l("edit"), {
1623
- index: t,
1624
- parentPath: `fields.${n}.fields`,
1625
- initial: e,
1626
- editing: !0,
1627
- onComplete: () => l("display")
1628
- }), [e, t, l, n]), h = x(
2123
+ [takenLabels]
2124
+ );
2125
+ const editFieldProps = useMemo(
2126
+ () => ({
2127
+ index,
2128
+ parentPath: `fields.${sectionIndex}.fields`,
2129
+ initial: field,
2130
+ editing: true
2131
+ }),
2132
+ [field, index, sectionIndex]
2133
+ );
2134
+ const duplicateFieldProps = useMemo(
1629
2135
  () => ({
1630
- parentPath: `fields.${n}.fields`,
1631
- index: t + 1,
1632
- initial: f(e),
1633
- onComplete: () => l("display")
2136
+ parentPath: `fields.${sectionIndex}.fields`,
2137
+ index: index + 1,
2138
+ initial: duplicateField(field)
1634
2139
  }),
1635
- [f, e, t, l, n]
1636
- ), g = x(
2140
+ [duplicateField, field, index, sectionIndex]
2141
+ );
2142
+ const insertAfterProps = useMemo(
1637
2143
  () => ({
1638
- parentPath: `fields.${n}.fields`,
1639
- index: t + 1,
1640
- initial: void 0,
1641
- onComplete: () => l("display")
2144
+ parentPath: `fields.${sectionIndex}.fields`,
2145
+ index: index + 1,
2146
+ initial: void 0
1642
2147
  }),
1643
- [t, l, n]
2148
+ [index, sectionIndex]
1644
2149
  );
1645
- return console.log(u), /* @__PURE__ */ r(Ze, { children: s === "display" ? /* @__PURE__ */ r(nt, { draggableId: e.identifier, index: t, children: (v) => /* @__PURE__ */ r(
1646
- fe,
2150
+ return /* @__PURE__ */ jsx(Draggable, { draggableId: field.identifier, index, children: (draggableProvided) => /* @__PURE__ */ jsx(
2151
+ Card,
1647
2152
  {
1648
- ref: v.innerRef,
1649
- ...v.draggableProps,
1650
- ...v.dragHandleProps,
2153
+ ref: draggableProvided.innerRef,
2154
+ ...draggableProvided.draggableProps,
2155
+ ...draggableProvided.dragHandleProps,
1651
2156
  mb: "4",
1652
- children: /* @__PURE__ */ b(y, { gap: "4", justify: "between", align: "center", children: [
1653
- u,
1654
- /* @__PURE__ */ r(
1655
- qt,
2157
+ children: /* @__PURE__ */ jsxs(Flex, { gap: "4", justify: "between", align: "center", children: [
2158
+ input,
2159
+ /* @__PURE__ */ jsx(
2160
+ FieldActions,
1656
2161
  {
1657
- remove: c,
1658
- editProps: p,
1659
- duplicateProps: h,
1660
- insertAfterProps: g,
1661
- dragHandleProps: v.dragHandleProps
2162
+ remove: remove2,
2163
+ editProps: editFieldProps,
2164
+ duplicateProps: duplicateFieldProps,
2165
+ insertAfterProps,
2166
+ dragHandleProps: draggableProvided.dragHandleProps
1662
2167
  }
1663
2168
  )
1664
2169
  ] })
1665
2170
  }
1666
- ) }) : null });
1667
- }), yn = S(function(i) {
1668
- var we, xe, L, N, G, Ie, Ce;
1669
- const { field: e, index: t, dropState: n } = i, [s, a] = Y(Array(e.fields.length).fill("display")), c = (we = n[e.identifier]) == null ? void 0 : we.disabled, { setFieldValue: l, values: d } = me(), u = bi(), f = kt(d.fields), p = T(
1670
- (F, E) => {
1671
- for (const D of F) {
1672
- const P = E.indexOf(D);
1673
- l(`fields.${P}.condition`, null).then(), l(`fields.${P}.conditional`, !1).then();
2171
+ ) });
2172
+ });
2173
+ const FieldSectionWithActions = memo(function FieldSectionWithActions2(props) {
2174
+ var _a, _b, _c, _d, _e, _f, _g;
2175
+ const { field, index: sectionIndex, dropState } = props;
2176
+ const isDropDisabled = (_a = dropState[field.identifier]) == null ? void 0 : _a.disabled;
2177
+ const { setFieldValue, values } = useFormikContext();
2178
+ const alertDialog = useAlertDialog();
2179
+ const takenFieldLabels = getTakenFieldLabels(values.fields);
2180
+ const removeSectionConditions = useCallback(
2181
+ (sectionsToUpdate, allSections) => {
2182
+ for (const section of sectionsToUpdate) {
2183
+ const sectionIndex2 = allSections.indexOf(section);
2184
+ setFieldValue(`fields.${sectionIndex2}.condition`, null).then();
2185
+ setFieldValue(`fields.${sectionIndex2}.conditional`, false).then();
1674
2186
  }
1675
2187
  },
1676
- [l]
1677
- ), h = T(
1678
- (F) => {
1679
- var P;
1680
- const E = e.fields[F];
1681
- if (!E)
2188
+ [setFieldValue]
2189
+ );
2190
+ const makeRemoveFieldAction = useCallback(
2191
+ (fieldIndex) => {
2192
+ var _a2;
2193
+ const removing = field.fields[fieldIndex];
2194
+ if (!removing)
1682
2195
  throw new Error("Could not find field to remove.");
1683
- const D = [];
1684
- for (const _ of d.fields)
1685
- ((P = _.condition) == null ? void 0 : P.identifier) === E.identifier && D.push(_);
2196
+ const sectionsWithMatchingCondition = [];
2197
+ for (const section of values.fields) {
2198
+ if (((_a2 = section.condition) == null ? void 0 : _a2.identifier) === removing.identifier) {
2199
+ sectionsWithMatchingCondition.push(section);
2200
+ }
2201
+ }
1686
2202
  return {
1687
- removing: E,
1688
- affectedSections: D,
1689
- action: () => l(`fields.${t}.fields`, Le(e.fields, F))
2203
+ removing,
2204
+ affectedSections: sectionsWithMatchingCondition,
2205
+ action: () => setFieldValue(`fields.${sectionIndex}.fields`, remove(field.fields, fieldIndex))
1690
2206
  };
1691
2207
  },
1692
- [e.fields, d.fields, l, t]
1693
- ), g = T(
1694
- (F) => {
1695
- const { affectedSections: E, action: D, removing: P } = h(F), _ = () => {
1696
- D().then(), p(E, d.fields);
2208
+ [field.fields, values.fields, setFieldValue, sectionIndex]
2209
+ );
2210
+ const removeField = useCallback(
2211
+ (i) => {
2212
+ const { affectedSections, action, removing } = makeRemoveFieldAction(i);
2213
+ const cmd = () => {
2214
+ action().then();
2215
+ removeSectionConditions(affectedSections, values.fields);
1697
2216
  };
1698
- if (E.length > 0) {
1699
- const qe = E.map((Fe) => Fe.label).join(", ");
1700
- return u({
2217
+ if (affectedSections.length > 0) {
2218
+ const labels = affectedSections.map((section) => section.label).join(", ");
2219
+ return alertDialog({
1701
2220
  title: "Remove condition?",
1702
- description: `${P.label} is being used as a condition, deleting it will remove the condition from the ${qe} section(s).`,
2221
+ description: `${removing.label} is being used as a condition, deleting it will remove the condition from the ${labels} section(s).`,
1703
2222
  severity: "danger",
1704
2223
  actionText: "Remove",
1705
- onAction: _
2224
+ onAction: cmd
1706
2225
  });
1707
2226
  }
1708
- _();
2227
+ cmd();
1709
2228
  },
1710
- [h, p, d.fields, u]
1711
- ), v = T(() => {
1712
- const E = e.fields.map((Te, Wt) => h(Wt)).flatMap((Te) => Te.affectedSections), D = E.length ? "Remove fields and conditions?" : "Remove fields?", P = e.fields.length, _ = E.map((Te) => Te.label).join(", "), qe = E.length ? `Deleting this section will remove the ${P} field(s) it contains and will remove the conditions from following sections: ${_}` : `Deleting this section will remove the ${P} field(s) it contains.`, Fe = Le(d.fields, t), dt = () => l("fields", Fe);
1713
- if (E.length > 0)
1714
- return u({
1715
- title: D,
1716
- description: qe,
2229
+ [makeRemoveFieldAction, removeSectionConditions, values.fields, alertDialog]
2230
+ );
2231
+ const removeSection = useCallback(() => {
2232
+ const fieldSideEffects = field.fields.map((_, i) => makeRemoveFieldAction(i));
2233
+ const affectedSections = fieldSideEffects.flatMap((sideEffect) => sideEffect.affectedSections);
2234
+ const title2 = affectedSections.length ? "Remove fields and conditions?" : "Remove fields?";
2235
+ const numFields = field.fields.length;
2236
+ const sectionLabels = affectedSections.map((section) => section.label).join(", ");
2237
+ const description2 = affectedSections.length ? `Deleting this section will remove the ${numFields} field(s) it contains and will remove the conditions from following sections: ${sectionLabels}` : `Deleting this section will remove the ${numFields} field(s) it contains.`;
2238
+ const updatedSections = remove(values.fields, sectionIndex);
2239
+ const cmd = () => setFieldValue("fields", updatedSections);
2240
+ if (affectedSections.length > 0) {
2241
+ return alertDialog({
2242
+ title: title2,
2243
+ description: description2,
1717
2244
  severity: "danger",
1718
2245
  actionText: "Remove",
1719
2246
  onAction: () => {
1720
- dt().then(() => {
1721
- p(E, Fe);
2247
+ cmd().then(() => {
2248
+ removeSectionConditions(affectedSections, updatedSections);
1722
2249
  });
1723
2250
  }
1724
2251
  });
1725
- dt().then();
2252
+ }
2253
+ cmd().then();
1726
2254
  }, [
1727
- e.fields,
1728
- d.fields,
1729
- t,
1730
- h,
1731
- l,
1732
- u,
1733
- p
1734
- ]), z = T(
1735
- (F) => {
1736
- if (F.label === null)
1737
- throw new Error(`Expected a label for field ${F.identifier}`);
1738
- const E = Ke(F.label, f), D = F.fields.map((P) => {
1739
- const _ = Ke(P.label, f);
2255
+ field.fields,
2256
+ values.fields,
2257
+ sectionIndex,
2258
+ makeRemoveFieldAction,
2259
+ setFieldValue,
2260
+ alertDialog,
2261
+ removeSectionConditions
2262
+ ]);
2263
+ const duplicateSection = useCallback(
2264
+ (field2) => {
2265
+ if (field2.label === null) {
2266
+ throw new Error(`Expected a label for field ${field2.identifier}`);
2267
+ }
2268
+ const newSectionLabel = incrementFieldLabel(field2.label, takenFieldLabels);
2269
+ const newFields = field2.fields.map((f) => {
2270
+ const newLabel = incrementFieldLabel(f.label, takenFieldLabels);
1740
2271
  return {
1741
- ...P,
1742
- label: _,
1743
- identifier: At(void 0, _)
2272
+ ...f,
2273
+ label: newLabel,
2274
+ identifier: makeIdentifier(void 0, newLabel)
1744
2275
  };
1745
2276
  });
1746
- return { ...F, label: E, fields: D, identifier: "" };
2277
+ return { ...field2, label: newSectionLabel, fields: newFields, identifier: "" };
1747
2278
  },
1748
- [f]
1749
- ), I = T((F, E) => {
1750
- a((D) => {
1751
- const P = [...D];
1752
- return P[F] = E, P;
1753
- });
1754
- }, []), w = x(
2279
+ [takenFieldLabels]
2280
+ );
2281
+ const editSectionProps = useMemo(
1755
2282
  () => ({
1756
- index: t,
2283
+ index: sectionIndex,
1757
2284
  parentPath: "fields",
1758
- initial: e,
1759
- editing: !0,
1760
- conditionalSourceFields: Se(d.fields, t),
1761
- onComplete: () => console.log("editsectionprops")
2285
+ initial: field,
2286
+ editing: true,
2287
+ conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex)
1762
2288
  }),
1763
- [e, t, d.fields]
1764
- ), k = x(
2289
+ [field, sectionIndex, values.fields]
2290
+ );
2291
+ const insertSectionProps = useMemo(
1765
2292
  () => ({
1766
- index: t + 1,
2293
+ index: sectionIndex + 1,
1767
2294
  parentPath: "fields",
1768
- initial: Ee(),
1769
- conditionalSourceFields: Se(d.fields, t + 1),
1770
- onComplete: () => console.log("insertsectionprops")
2295
+ initial: emptySection(),
2296
+ conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex + 1)
1771
2297
  }),
1772
- [t, d.fields]
1773
- ), A = x(
2298
+ [sectionIndex, values.fields]
2299
+ );
2300
+ const insertFieldAtEndOfSection = useMemo(
1774
2301
  () => ({
1775
- parentPath: `fields.${t}.fields`,
1776
- index: e.fields.length,
1777
- initial: void 0,
1778
- onComplete: () => console.log("insertfieldatendofsectionprops")
2302
+ parentPath: `fields.${sectionIndex}.fields`,
2303
+ index: field.fields.length,
2304
+ initial: void 0
1779
2305
  }),
1780
- [e.fields.length, t]
1781
- ), C = x(
2306
+ [field.fields.length, sectionIndex]
2307
+ );
2308
+ const duplicateSectionProps = useMemo(
1782
2309
  () => ({
1783
- index: t + 1,
2310
+ index: sectionIndex + 1,
1784
2311
  parentPath: "fields",
1785
- initial: z(e),
1786
- conditionalSourceFields: Se(d.fields, t + 1),
1787
- onComplete: () => console.log("duplicatesectionprops")
2312
+ initial: duplicateSection(field),
2313
+ conditionalSourceFields: makeConditionalSourceFields(values.fields, sectionIndex + 1)
1788
2314
  }),
1789
- [z, e, t, d.fields]
1790
- ), $ = x(
2315
+ [duplicateSection, field, sectionIndex, values.fields]
2316
+ );
2317
+ const conditionLabel = useMemo(
1791
2318
  () => {
1792
- var F, E;
1793
- return (E = Pt(d.fields, (F = e.condition) == null ? void 0 : F.identifier)) == null ? void 0 : E.label;
2319
+ var _a2, _b2;
2320
+ return (_b2 = findFieldByIdentifier(values.fields, (_a2 = field.condition) == null ? void 0 : _a2.identifier)) == null ? void 0 : _b2.label;
1794
2321
  },
1795
- [(xe = e.condition) == null ? void 0 : xe.identifier, d.fields]
1796
- ), R = Array.isArray((L = e.condition) == null ? void 0 : L.value) ? "contains all of" : "equals";
1797
- if (Qe((N = e.condition) == null ? void 0 : N.value))
2322
+ [(_b = field.condition) == null ? void 0 : _b.identifier, values.fields]
2323
+ );
2324
+ const conditionComparison = Array.isArray((_c = field.condition) == null ? void 0 : _c.value) ? "contains all of" : "equals";
2325
+ if (valueIsFile((_d = field.condition) == null ? void 0 : _d.value))
1798
2326
  throw new Error("File values are not supported for conditions.");
1799
- const U = Array.isArray((G = e.condition) == null ? void 0 : G.value) ? (Ie = e.condition) == null ? void 0 : Ie.value.map((F) => typeof F == "string" ? F : F.label).join(", ") : (Ce = e.condition) == null ? void 0 : Ce.value.toString();
1800
- return /* @__PURE__ */ r(nt, { draggableId: e.identifier, index: t, children: (F) => /* @__PURE__ */ r(
1801
- fe,
2327
+ const conditionValue = Array.isArray((_e = field.condition) == null ? void 0 : _e.value) ? (_f = field.condition) == null ? void 0 : _f.value.map((v) => typeof v === "string" ? v : v.label).join(", ") : (_g = field.condition) == null ? void 0 : _g.value.toString();
2328
+ return /* @__PURE__ */ jsx(Draggable, { draggableId: field.identifier, index: sectionIndex, children: (draggableProvided) => /* @__PURE__ */ jsx(
2329
+ Card,
1802
2330
  {
1803
- ref: F.innerRef,
1804
- ...F.draggableProps,
1805
- ...F.dragHandleProps,
2331
+ ref: draggableProvided.innerRef,
2332
+ ...draggableProvided.draggableProps,
2333
+ ...draggableProvided.dragHandleProps,
1806
2334
  mb: "4",
1807
- children: /* @__PURE__ */ b(y, { gap: "3", justify: "between", align: "center", children: [
1808
- /* @__PURE__ */ b(y, { direction: "column", gap: "2", grow: "1", children: [
1809
- /* @__PURE__ */ b(y, { direction: "column", children: [
1810
- /* @__PURE__ */ r(Me, { as: "h3", size: "3", children: e.label }),
1811
- /* @__PURE__ */ r(V, { className: Re.description, children: e.description })
2335
+ children: /* @__PURE__ */ jsxs(Flex, { gap: "3", justify: "between", align: "center", children: [
2336
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", grow: "1", children: [
2337
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
2338
+ /* @__PURE__ */ jsx(Heading, { as: "h3", size: "3", children: field.label }),
2339
+ /* @__PURE__ */ jsx(Text, { className: styles$3.description, children: field.description })
1812
2340
  ] }),
1813
- e.condition && /* @__PURE__ */ r(V, { size: "1", children: /* @__PURE__ */ b(yi, { children: [
2341
+ field.condition && /* @__PURE__ */ jsx(Text, { size: "1", children: /* @__PURE__ */ jsxs(Em, { children: [
1814
2342
  "Display only if ",
1815
- /* @__PURE__ */ r(ut, { children: $ }),
2343
+ /* @__PURE__ */ jsx(Strong, { children: conditionLabel }),
1816
2344
  " ",
1817
- R,
2345
+ conditionComparison,
1818
2346
  " ",
1819
- /* @__PURE__ */ r(ut, { children: U })
2347
+ /* @__PURE__ */ jsx(Strong, { children: conditionValue })
1820
2348
  ] }) }),
1821
- /* @__PURE__ */ r(it, { droppableId: e.identifier, type: "SECTION", isDropDisabled: c, children: (E) => /* @__PURE__ */ b(
1822
- y,
2349
+ /* @__PURE__ */ jsx(Droppable, { droppableId: field.identifier, type: "SECTION", isDropDisabled, children: (droppableProvided) => /* @__PURE__ */ jsxs(
2350
+ Flex,
1823
2351
  {
1824
- ref: E.innerRef,
1825
- ...E.droppableProps,
2352
+ ref: droppableProvided.innerRef,
2353
+ ...droppableProvided.droppableProps,
1826
2354
  direction: "column",
1827
2355
  gap: "0",
1828
2356
  children: [
1829
- e.fields.map((D, P) => /* @__PURE__ */ r(
1830
- bn,
2357
+ field.fields.map((child, i) => /* @__PURE__ */ jsx(
2358
+ FieldWithActions,
1831
2359
  {
1832
- field: D,
1833
- index: P,
1834
- sectionIndex: t,
1835
- remove: () => g(P),
1836
- takenLabels: f,
1837
- mode: s[P] ?? "display",
1838
- onModeChange: (_) => I(P, _)
2360
+ field: child,
2361
+ index: i,
2362
+ sectionIndex,
2363
+ remove: () => removeField(i),
2364
+ takenLabels: takenFieldLabels
1839
2365
  },
1840
- D.identifier
2366
+ child.identifier
1841
2367
  )),
1842
- E.placeholder,
1843
- /* @__PURE__ */ r(he, { ...A, children: /* @__PURE__ */ b(H, { type: "button", variant: "outline", children: [
1844
- /* @__PURE__ */ r(_e, {}),
2368
+ droppableProvided.placeholder,
2369
+ /* @__PURE__ */ jsx(FieldBuilder, { ...insertFieldAtEndOfSection, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", children: [
2370
+ /* @__PURE__ */ jsx(PlusIcon, {}),
1845
2371
  " Add a field"
1846
2372
  ] }) })
1847
2373
  ]
1848
2374
  }
1849
2375
  ) })
1850
2376
  ] }),
1851
- /* @__PURE__ */ r(
1852
- qt,
2377
+ /* @__PURE__ */ jsx(
2378
+ FieldActions,
1853
2379
  {
1854
- remove: v,
1855
- insertAfterProps: k,
1856
- dragHandleProps: F.dragHandleProps,
1857
- editProps: w,
1858
- duplicateProps: C
2380
+ remove: removeSection,
2381
+ insertAfterProps: insertSectionProps,
2382
+ dragHandleProps: draggableProvided.dragHandleProps,
2383
+ editProps: editSectionProps,
2384
+ duplicateProps: duplicateSectionProps
1859
2385
  }
1860
2386
  )
1861
2387
  ] })
1862
2388
  }
1863
2389
  ) });
1864
- }), vn = (o, i) => {
1865
- var t;
1866
- const e = { ...o };
1867
- switch (i.type) {
2390
+ });
2391
+ const reducer = (state, action) => {
2392
+ var _a;
2393
+ const next = { ...state };
2394
+ switch (action.type) {
1868
2395
  case "release":
1869
- for (const n in e)
1870
- e[n].disabled = !1;
1871
- return e;
2396
+ for (const sectionId in next) {
2397
+ next[sectionId].disabled = false;
2398
+ }
2399
+ return next;
1872
2400
  case "hold":
1873
- for (const n in e)
1874
- (t = e[n]) != null && t.conditionFields.has(i.fieldId) && (e[n].disabled = !0);
1875
- return e;
1876
- case "update":
1877
- return i.state;
1878
- }
1879
- }, wn = (o, i) => {
1880
- if (i)
1881
- for (let e = 0; e < o.length; e++) {
1882
- const t = o[e];
1883
- if (t) {
1884
- for (const n of t.fields)
1885
- if (n.identifier === i)
1886
- return e;
2401
+ for (const sectionId in next) {
2402
+ if ((_a = next[sectionId]) == null ? void 0 : _a.conditionFields.has(action.fieldId)) {
2403
+ next[sectionId].disabled = true;
2404
+ }
1887
2405
  }
2406
+ return next;
2407
+ case "update":
2408
+ return action.state;
2409
+ }
2410
+ };
2411
+ const getConditionIndex = (fields, identifier) => {
2412
+ if (!identifier)
2413
+ return void 0;
2414
+ for (let i = 0; i < fields.length; i++) {
2415
+ const section = fields[i];
2416
+ if (!section)
2417
+ continue;
2418
+ for (const field of section.fields) {
2419
+ if (field.identifier === identifier)
2420
+ return i;
1888
2421
  }
1889
- }, bt = (o) => {
1890
- var e, t, n;
1891
- const i = {};
1892
- for (let s = 0; s < o.length; s++) {
1893
- const a = o[s];
1894
- if (!a)
2422
+ }
2423
+ };
2424
+ const initializer = (fields) => {
2425
+ var _a, _b, _c;
2426
+ const acc = {};
2427
+ for (let index = 0; index < fields.length; index++) {
2428
+ const field = fields[index];
2429
+ if (!field)
1895
2430
  throw new Error("Field is undefined.");
1896
- const c = s > 0 ? (e = i[o[s - 1].identifier]) == null ? void 0 : e.conditionFields : void 0, l = new Set(c);
1897
- (t = a.condition) != null && t.identifier && l.add(a.condition.identifier), i[a.identifier] = {
1898
- disabled: !1,
1899
- conditionFields: l,
1900
- conditionIndex: wn(o, (n = a.condition) == null ? void 0 : n.identifier),
1901
- index: s,
1902
- label: a.label
2431
+ const previousConditionFields = index > 0 ? (_a = acc[fields[index - 1].identifier]) == null ? void 0 : _a.conditionFields : void 0;
2432
+ const disabledFields = new Set(previousConditionFields);
2433
+ if ((_b = field.condition) == null ? void 0 : _b.identifier) {
2434
+ disabledFields.add(field.condition.identifier);
2435
+ }
2436
+ acc[field.identifier] = {
2437
+ disabled: false,
2438
+ conditionFields: disabledFields,
2439
+ conditionIndex: getConditionIndex(fields, (_c = field.condition) == null ? void 0 : _c.identifier),
2440
+ index,
2441
+ label: field.label
1903
2442
  };
1904
2443
  }
1905
- return i;
1906
- }, yt = (o, i) => {
1907
- for (const [e, t] of Object.entries(o))
1908
- if (t.identifier === i)
1909
- return [t, e];
1910
- }, xn = S(function() {
1911
- const { values: i, setFieldValue: e } = me(), [t, n] = Ii(vn, i.fields, bt), { showInfo: s } = vi();
1912
- ve(() => {
1913
- n({ type: "update", state: bt(i.fields) });
1914
- }, [n, i.fields]);
1915
- const a = T((d) => {
1916
- d.type === "SECTION" && n({ type: "hold", fieldId: d.draggableId });
1917
- }, []), c = T(
1918
- (d) => {
1919
- const { source: u, destination: f, type: p, reason: h, draggableId: g } = d;
1920
- if (n({ type: "release" }), !f || h === "CANCEL")
2444
+ return acc;
2445
+ };
2446
+ const findSection = (fields, sectionId) => {
2447
+ for (const [i, section] of Object.entries(fields)) {
2448
+ if (section.identifier === sectionId)
2449
+ return [section, i];
2450
+ }
2451
+ };
2452
+ const FieldsEditor = memo(function FieldsEditor2() {
2453
+ const { values, setFieldValue } = useFormikContext();
2454
+ const [dropState, dispatch] = useReducer(reducer, values.fields, initializer);
2455
+ const { showInfo } = useToast();
2456
+ useEffect(() => {
2457
+ dispatch({ type: "update", state: initializer(values.fields) });
2458
+ }, [dispatch, values.fields]);
2459
+ const handleDragStart = useCallback((start) => {
2460
+ if (start.type === "SECTION") {
2461
+ dispatch({ type: "hold", fieldId: start.draggableId });
2462
+ }
2463
+ }, []);
2464
+ const handleDragEnd = useCallback(
2465
+ (result) => {
2466
+ const { source, destination, type, reason, draggableId } = result;
2467
+ dispatch({ type: "release" });
2468
+ if (!destination || reason === "CANCEL")
1921
2469
  return;
1922
- if (p === "ROOT") {
1923
- const k = t[g];
1924
- if (!k)
2470
+ if (type === "ROOT") {
2471
+ const state = dropState[draggableId];
2472
+ if (!state)
1925
2473
  throw new Error("Could not find section context.");
1926
- let A = typeof k.conditionIndex < "u" ? (
2474
+ let dest = typeof state.conditionIndex !== "undefined" ? (
1927
2475
  // cannot move a section with a condition before the condition's field
1928
- Math.max(k.conditionIndex + 1, f.index)
1929
- ) : f.index;
1930
- for (const C of Object.values(t))
1931
- C.conditionIndex === u.index && (A = Math.min(A, C.index - 1));
1932
- return A != f.index && s({
1933
- title: "Reordered sections",
1934
- description: "Sections with conditions must be below the fields they reference."
1935
- }), e("fields", Ge(i.fields, u.index, A));
2476
+ Math.max(state.conditionIndex + 1, destination.index)
2477
+ ) : destination.index;
2478
+ for (const section of Object.values(dropState)) {
2479
+ if (section.conditionIndex === source.index) {
2480
+ dest = Math.min(dest, section.index - 1);
2481
+ }
2482
+ }
2483
+ if (dest != destination.index) {
2484
+ showInfo({
2485
+ title: "Reordered sections",
2486
+ description: "Sections with conditions must be below the fields they reference."
2487
+ });
2488
+ }
2489
+ return setFieldValue("fields", reorder(values.fields, source.index, dest));
1936
2490
  }
1937
- if (p !== "SECTION")
2491
+ if (type !== "SECTION")
1938
2492
  throw new Error("Unexpected droppable type.");
1939
- const [v, z] = yt(i.fields, u.droppableId) ?? [], [I, w] = yt(i.fields, f.droppableId) ?? [];
1940
- if (!(v != null && v.fields) || !I)
2493
+ const [sourceSection, srcIndex] = findSection(values.fields, source.droppableId) ?? [];
2494
+ const [destinationSection, destIndex] = findSection(values.fields, destination.droppableId) ?? [];
2495
+ if (!(sourceSection == null ? void 0 : sourceSection.fields) || !destinationSection)
1941
2496
  throw new Error("Could not find section with fields.");
1942
- if (v.identifier === I.identifier)
1943
- e(
1944
- `fields.${z}.fields`,
1945
- Ge(v.fields, u.index, f.index)
2497
+ if (sourceSection.identifier === destinationSection.identifier) {
2498
+ setFieldValue(
2499
+ `fields.${srcIndex}.fields`,
2500
+ reorder(sourceSection.fields, source.index, destination.index)
1946
2501
  ).then();
1947
- else {
1948
- const k = v.fields[u.index];
1949
- if (!k)
2502
+ } else {
2503
+ const removed = sourceSection.fields[source.index];
2504
+ if (!removed)
1950
2505
  throw new Error("Could not find field to reorder.");
1951
- e(`fields.${z}.fields`, Le(v.fields, u.index)).then(), e(
1952
- `fields.${w}.fields`,
1953
- Lt(I.fields, f.index, k)
2506
+ setFieldValue(`fields.${srcIndex}.fields`, remove(sourceSection.fields, source.index)).then();
2507
+ setFieldValue(
2508
+ `fields.${destIndex}.fields`,
2509
+ insert(destinationSection.fields, destination.index, removed)
1954
2510
  ).then();
1955
2511
  }
1956
2512
  },
1957
- [i.fields, e, t, s]
1958
- ), l = x(
2513
+ [values.fields, setFieldValue, dropState, showInfo]
2514
+ );
2515
+ const makeFieldSectionProps = useMemo(
1959
2516
  () => ({
1960
- index: i.fields.length,
2517
+ index: values.fields.length,
1961
2518
  parentPath: "fields",
1962
- initial: Ee(),
1963
- conditionalSourceFields: Se(i.fields, i.fields.length),
1964
- onComplete: () => console.log("makefieldsectionprops")
2519
+ initial: emptySection(),
2520
+ conditionalSourceFields: makeConditionalSourceFields(values.fields, values.fields.length)
1965
2521
  }),
1966
- [i.fields]
2522
+ [values.fields]
1967
2523
  );
1968
- return /* @__PURE__ */ r(It, { onDragStart: a, onDragEnd: c, children: /* @__PURE__ */ r(it, { droppableId: "droppable", type: "ROOT", children: (d) => /* @__PURE__ */ b(
1969
- y,
2524
+ return /* @__PURE__ */ jsx(DragDropContext, { onDragStart: handleDragStart, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx(Droppable, { droppableId: "droppable", type: "ROOT", children: (droppableProvided) => /* @__PURE__ */ jsxs(
2525
+ Flex,
1970
2526
  {
1971
- ref: d.innerRef,
1972
- ...d.droppableProps,
2527
+ ref: droppableProvided.innerRef,
2528
+ ...droppableProvided.droppableProps,
1973
2529
  direction: "column",
1974
2530
  gap: "0",
1975
2531
  children: [
1976
- i.fields.map((u, f) => /* @__PURE__ */ r(
1977
- yn,
2532
+ values.fields.map((field, index) => /* @__PURE__ */ jsx(
2533
+ FieldSectionWithActions,
1978
2534
  {
1979
- field: u,
1980
- index: f,
1981
- dropState: t
2535
+ field,
2536
+ index,
2537
+ dropState
1982
2538
  },
1983
- u.label
2539
+ field.label
1984
2540
  )),
1985
- d.placeholder,
1986
- /* @__PURE__ */ r(he, { ...l, children: /* @__PURE__ */ b(H, { type: "button", variant: "outline", children: [
1987
- /* @__PURE__ */ r(_e, {}),
2541
+ droppableProvided.placeholder,
2542
+ /* @__PURE__ */ jsx(FieldBuilder, { ...makeFieldSectionProps, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", children: [
2543
+ /* @__PURE__ */ jsx(PlusIcon, {}),
1988
2544
  " Add a section"
1989
2545
  ] }) })
1990
2546
  ]
1991
2547
  }
1992
2548
  ) }) });
1993
- }), In = {
2549
+ });
2550
+ const initialValues = {
1994
2551
  title: "",
1995
2552
  description: "",
1996
2553
  fields: []
1997
- }, Cn = new be({
2554
+ };
2555
+ const title = new StringField({
1998
2556
  label: "Title",
1999
2557
  minLength: 0,
2000
2558
  maxLength: 100,
2001
- required: !0,
2559
+ required: true,
2002
2560
  identifier: "title"
2003
- }), Fn = { formId: Be, placeholder: "Give your form a title." }, Tn = new ye({
2561
+ });
2562
+ const titleProps = { formId, placeholder: "Give your form a title." };
2563
+ const description = new TextField({
2004
2564
  label: "Description",
2005
2565
  minLength: 0,
2006
2566
  maxLength: 1e3,
2007
- required: !1,
2567
+ required: false,
2008
2568
  identifier: "description"
2009
- }), Sn = { formId: Be, placeholder: "Explain the purpose of this form." }, zn = () => {
2569
+ });
2570
+ const descriptionProps = { formId, placeholder: "Explain the purpose of this form." };
2571
+ const previewSubmit = () => {
2010
2572
  alert("This is a form preview, your data will not be saved.");
2011
- }, qn = S(
2012
- pe((o, i) => {
2013
- const { onCancel: e, onSave: t, revision: n } = o, s = n ? "Edit form" : "Create a new form", { heading: a = s } = o, c = T((h) => {
2014
- const g = {};
2015
- if (h.title || (g.title = "Title is required."), (!h.fields || h.fields.length === 0) && (g.fields = "At least one field is required."), De(g))
2016
- return g;
2017
- }, []), l = et({
2018
- initialValues: Bi(n) ?? In,
2019
- validate: c,
2020
- onSubmit: (h) => t(h),
2573
+ };
2574
+ const FormBuilder = memo(
2575
+ forwardRef((props, ref) => {
2576
+ const { onCancel, onSave, revision } = props;
2577
+ const defaultHeading = revision ? "Edit form" : "Create a new form";
2578
+ const { heading = defaultHeading } = props;
2579
+ const validate = useCallback((form) => {
2580
+ const errors = {};
2581
+ if (!form.title) {
2582
+ errors.title = "Title is required.";
2583
+ }
2584
+ if (!form.fields || form.fields.length === 0) {
2585
+ errors.fields = "At least one field is required.";
2586
+ }
2587
+ if (hasKeys(errors)) {
2588
+ return errors;
2589
+ }
2590
+ }, []);
2591
+ const formik = useFormik({
2592
+ initialValues: wrapRootFieldsWithFieldSection(revision) ?? initialValues,
2593
+ validate,
2594
+ onSubmit: (form) => onSave(form),
2021
2595
  // only validate the entire for on submit
2022
- validateOnChange: !1,
2023
- validateOnBlur: !1
2024
- }), d = x(() => Dt(l.values), [l.values]), u = $e(Cn, Fn), f = $e(Tn, Sn), p = x(
2025
- () => typeof a == "object" ? a : /* @__PURE__ */ r(Me, { children: a }),
2026
- [a]
2596
+ validateOnChange: false,
2597
+ validateOnBlur: false
2598
+ });
2599
+ const previewSchema = useMemo(() => formRevisionToSchema(formik.values), [formik.values]);
2600
+ const titleInput = useFieldInput(title, titleProps);
2601
+ const descriptionInput = useFieldInput(description, descriptionProps);
2602
+ const FormBuilderHeading = useMemo(
2603
+ () => typeof heading === "object" ? heading : /* @__PURE__ */ jsx(Heading, { children: heading }),
2604
+ [heading]
2027
2605
  );
2028
- return /* @__PURE__ */ r(Z.Root, { ref: i, defaultValue: "edit", children: /* @__PURE__ */ b(y, { direction: "column", gap: "2", children: [
2029
- /* @__PURE__ */ b(Z.List, { children: [
2030
- /* @__PURE__ */ r(Z.Trigger, { value: "edit", children: "Edit" }),
2031
- /* @__PURE__ */ r(Z.Trigger, { value: "preview", children: "Preview" })
2606
+ return /* @__PURE__ */ jsx(Tabs.Root, { ref, defaultValue: "edit", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
2607
+ /* @__PURE__ */ jsxs(Tabs.List, { children: [
2608
+ /* @__PURE__ */ jsx(Tabs.Trigger, { value: "edit", children: "Edit" }),
2609
+ /* @__PURE__ */ jsx(Tabs.Trigger, { value: "preview", children: "Preview" })
2032
2610
  ] }),
2033
- /* @__PURE__ */ b(Z.Content, { value: "edit", children: [
2034
- p,
2035
- /* @__PURE__ */ b(V, { children: [
2611
+ /* @__PURE__ */ jsxs(Tabs.Content, { value: "edit", children: [
2612
+ FormBuilderHeading,
2613
+ /* @__PURE__ */ jsxs(Text, { children: [
2036
2614
  "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",
2037
2615
  " ",
2038
- /* @__PURE__ */ r("em", { children: "Preview" }),
2616
+ /* @__PURE__ */ jsx("em", { children: "Preview" }),
2039
2617
  " tab, but",
2040
2618
  " ",
2041
- /* @__PURE__ */ r("strong", { children: "field values entered on this page will not be saved." })
2619
+ /* @__PURE__ */ jsx("strong", { children: "field values entered on this page will not be saved." })
2042
2620
  ] }),
2043
- /* @__PURE__ */ r(y, { asChild: !0, direction: "column", gap: "2", mt: "3", children: /* @__PURE__ */ b("form", { id: Be, onSubmit: l.handleSubmit, children: [
2044
- /* @__PURE__ */ b(tt, { value: l, children: [
2045
- u,
2046
- f,
2047
- /* @__PURE__ */ r(xn, {}),
2048
- /* @__PURE__ */ r(V, { severity: "danger", size: "1", children: typeof l.errors.fields == "string" && l.errors.fields })
2621
+ /* @__PURE__ */ jsx(Flex, { asChild: true, direction: "column", gap: "2", mt: "3", children: /* @__PURE__ */ jsxs("form", { id: formId, onSubmit: formik.handleSubmit, children: [
2622
+ /* @__PURE__ */ jsxs(FormikProvider, { value: formik, children: [
2623
+ titleInput,
2624
+ descriptionInput,
2625
+ /* @__PURE__ */ jsx(FieldsEditor, {}),
2626
+ /* @__PURE__ */ jsx(Text, { severity: "danger", size: "1", children: typeof formik.errors.fields === "string" && formik.errors.fields })
2049
2627
  ] }),
2050
- /* @__PURE__ */ b(y, { justify: "end", gap: "2", children: [
2051
- /* @__PURE__ */ r(H, { type: "button", variant: "soft", onClick: e, children: "Cancel" }),
2052
- /* @__PURE__ */ r(H, { type: "submit", disabled: !l.isValid, children: "Save" })
2628
+ /* @__PURE__ */ jsxs(Flex, { justify: "end", gap: "2", children: [
2629
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "soft", onClick: onCancel, children: "Cancel" }),
2630
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: !formik.isValid, children: "Save" })
2053
2631
  ] })
2054
2632
  ] }) })
2055
2633
  ] }),
2056
- /* @__PURE__ */ r(Z.Content, { value: "preview", children: /* @__PURE__ */ r(ct, { schema: d, onSubmit: zn }) })
2634
+ /* @__PURE__ */ jsx(Tabs.Content, { value: "preview", children: /* @__PURE__ */ jsx(FormRenderer, { schema: previewSchema, onSubmit: previewSubmit }) })
2057
2635
  ] }) });
2058
2636
  })
2059
2637
  );
2060
2638
  export {
2061
- de as BooleanField,
2062
- Di as BooleanInput,
2063
- Ue as DateField,
2064
- Mi as DateInput,
2065
- X as FieldSection,
2066
- On as FormBrowser,
2067
- qn as FormBuilder,
2068
- ct as FormRenderer,
2069
- Rn as FormSubmissionBrowser,
2070
- Mn as FormSubmissionViewer,
2071
- ke as MultiSelectField,
2072
- Hi as MultiSelectInput,
2073
- Ae as MultiStringField,
2074
- Wi as MultiStringInput,
2075
- Q as NumberField,
2076
- _i as NumberInput,
2077
- Nn as PatchField,
2078
- Bn as PatchFormProvider,
2079
- Pe as SelectField,
2080
- Ni as SelectInput,
2081
- be as StringField,
2082
- Oi as StringInput,
2083
- ye as TextField,
2084
- Ri as TextInput,
2085
- Ne as deserialize,
2086
- $t as deserializeField,
2087
- Dt as formRevisionToSchema,
2088
- _t as isConditionMet,
2089
- $e as useFieldInput,
2090
- Mt as useFieldInputs,
2091
- Qe as valueIsFile
2639
+ BooleanField,
2640
+ BooleanInput,
2641
+ DateField,
2642
+ DateInput,
2643
+ FieldSection,
2644
+ FormBrowser,
2645
+ FormBuilder,
2646
+ FormRenderer,
2647
+ FormSubmissionBrowser,
2648
+ FormSubmissionViewer,
2649
+ MultiSelectField,
2650
+ MultiSelectInput,
2651
+ MultiStringField,
2652
+ MultiStringInput,
2653
+ NumberField,
2654
+ NumberInput$1 as NumberInput,
2655
+ PatchField,
2656
+ PatchFormProvider,
2657
+ SelectField,
2658
+ SelectInput,
2659
+ StringField,
2660
+ StringInput,
2661
+ TextField,
2662
+ TextInput,
2663
+ deserialize,
2664
+ deserializeField,
2665
+ formRevisionToSchema,
2666
+ isConditionMet,
2667
+ useFieldInput,
2668
+ useFieldInputs,
2669
+ valueIsFile
2092
2670
  };
2671
+ //# sourceMappingURL=forms.js.map