@rachelallyson/hero-hook-form 2.6.0 → 2.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/dist/cypress/index.d.ts +62 -71
- package/dist/cypress/index.js +583 -70
- package/dist/index.d.ts +876 -101
- package/dist/index.js +1684 -719
- package/package.json +15 -12
- package/dist/react/index.d.ts +0 -3428
- package/dist/react/index.js +0 -3989
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
// src/components/Form.tsx
|
|
9
|
-
import
|
|
9
|
+
import React20 from "react";
|
|
10
10
|
import { Button as Button3 } from "@heroui/react";
|
|
11
11
|
|
|
12
12
|
// src/hooks/useFormHelper.ts
|
|
@@ -24,7 +24,9 @@ function useFormHelper({
|
|
|
24
24
|
isSubmitting: false,
|
|
25
25
|
isSuccess: false
|
|
26
26
|
});
|
|
27
|
-
const form = methods ?? useForm({
|
|
27
|
+
const form = methods ?? useForm({
|
|
28
|
+
...defaultValues && { defaultValues }
|
|
29
|
+
});
|
|
28
30
|
const handleSubmit = async () => {
|
|
29
31
|
setSubmissionState((prev) => ({
|
|
30
32
|
...prev,
|
|
@@ -64,6 +66,7 @@ function useFormHelper({
|
|
|
64
66
|
};
|
|
65
67
|
return {
|
|
66
68
|
error: submissionState.error,
|
|
69
|
+
// useForm returns UseFormReturn<T, any, T> which is structurally compatible with UseFormReturn<T>
|
|
67
70
|
form,
|
|
68
71
|
handleSubmit,
|
|
69
72
|
isSubmitted: submissionState.isSubmitted,
|
|
@@ -74,9 +77,15 @@ function useFormHelper({
|
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
// src/types.ts
|
|
81
|
+
function pathToString(path) {
|
|
82
|
+
if (path === void 0) return "";
|
|
83
|
+
return path;
|
|
84
|
+
}
|
|
85
|
+
|
|
77
86
|
// src/components/FormField.tsx
|
|
78
|
-
import
|
|
79
|
-
import { useWatch as useWatch3 } from "react-hook-form";
|
|
87
|
+
import React19 from "react";
|
|
88
|
+
import { get, useWatch as useWatch3 } from "react-hook-form";
|
|
80
89
|
|
|
81
90
|
// src/fields/AutocompleteField.tsx
|
|
82
91
|
import React from "react";
|
|
@@ -129,6 +138,7 @@ function AutocompleteField(props) {
|
|
|
129
138
|
isDisabled,
|
|
130
139
|
isInvalid: Boolean(fieldState.error),
|
|
131
140
|
label,
|
|
141
|
+
name,
|
|
132
142
|
placeholder,
|
|
133
143
|
selectedKey: allowsCustomValue ? void 0 : hasSelectedValue ? String(selectedKey) : void 0,
|
|
134
144
|
inputValue: shouldShowInputValue ? field2.value ?? "" : void 0,
|
|
@@ -171,81 +181,93 @@ function HeroHookFormProvider(props) {
|
|
|
171
181
|
const value = useMemo(() => props.defaults ?? {}, [props.defaults]);
|
|
172
182
|
return /* @__PURE__ */ React2.createElement(DefaultsContext.Provider, { value }, props.children);
|
|
173
183
|
}
|
|
184
|
+
function extractInputCommon(common) {
|
|
185
|
+
const result = {};
|
|
186
|
+
if (common.color !== void 0) {
|
|
187
|
+
const color = common.color;
|
|
188
|
+
result.color = color;
|
|
189
|
+
}
|
|
190
|
+
if (common.size !== void 0) {
|
|
191
|
+
const size = common.size;
|
|
192
|
+
result.size = size;
|
|
193
|
+
}
|
|
194
|
+
if (common.variant !== void 0) {
|
|
195
|
+
const variant = common.variant;
|
|
196
|
+
result.variant = variant;
|
|
197
|
+
}
|
|
198
|
+
if (common.radius !== void 0) {
|
|
199
|
+
const radius = common.radius;
|
|
200
|
+
result.radius = radius;
|
|
201
|
+
}
|
|
202
|
+
if (common.labelPlacement !== void 0) {
|
|
203
|
+
const labelPlacement = common.labelPlacement;
|
|
204
|
+
result.labelPlacement = labelPlacement;
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
function extractTextareaCommon(common) {
|
|
209
|
+
const result = {};
|
|
210
|
+
if (common.color !== void 0) {
|
|
211
|
+
const color = common.color;
|
|
212
|
+
result.color = color;
|
|
213
|
+
}
|
|
214
|
+
if (common.size !== void 0) {
|
|
215
|
+
const size = common.size;
|
|
216
|
+
result.size = size;
|
|
217
|
+
}
|
|
218
|
+
if (common.variant !== void 0) {
|
|
219
|
+
const variant = common.variant;
|
|
220
|
+
result.variant = variant;
|
|
221
|
+
}
|
|
222
|
+
if (common.radius !== void 0) {
|
|
223
|
+
const radius = common.radius;
|
|
224
|
+
result.radius = radius;
|
|
225
|
+
}
|
|
226
|
+
if (common.labelPlacement !== void 0) {
|
|
227
|
+
const labelPlacement = common.labelPlacement;
|
|
228
|
+
result.labelPlacement = labelPlacement;
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
function extractSelectCommon(common) {
|
|
233
|
+
const result = {};
|
|
234
|
+
if (common.color !== void 0) {
|
|
235
|
+
const color = common.color;
|
|
236
|
+
result.color = color;
|
|
237
|
+
}
|
|
238
|
+
if (common.size !== void 0) {
|
|
239
|
+
const size = common.size;
|
|
240
|
+
result.size = size;
|
|
241
|
+
}
|
|
242
|
+
if (common.variant !== void 0) {
|
|
243
|
+
const variant = common.variant;
|
|
244
|
+
result.variant = variant;
|
|
245
|
+
}
|
|
246
|
+
if (common.radius !== void 0) {
|
|
247
|
+
const radius = common.radius;
|
|
248
|
+
result.radius = radius;
|
|
249
|
+
}
|
|
250
|
+
if (common.labelPlacement !== void 0) {
|
|
251
|
+
const labelPlacement = common.labelPlacement;
|
|
252
|
+
result.labelPlacement = labelPlacement;
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
174
256
|
function useHeroHookFormDefaults() {
|
|
175
257
|
const cfg = useContext(DefaultsContext) ?? {};
|
|
176
258
|
const common = cfg.common ?? {};
|
|
177
|
-
const commonInput =
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
181
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
182
|
-
...common.labelPlacement !== void 0 ? {
|
|
183
|
-
labelPlacement: common.labelPlacement
|
|
184
|
-
} : {}
|
|
185
|
-
};
|
|
186
|
-
const commonTextarea = {
|
|
187
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
188
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
189
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
190
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
191
|
-
...common.labelPlacement !== void 0 ? {
|
|
192
|
-
labelPlacement: common.labelPlacement
|
|
193
|
-
} : {}
|
|
194
|
-
};
|
|
195
|
-
const commonSelect = {
|
|
196
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
197
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
198
|
-
...common.variant !== void 0 ? { variant: common.variant } : {},
|
|
199
|
-
...common.radius !== void 0 ? { radius: common.radius } : {},
|
|
200
|
-
...common.labelPlacement !== void 0 ? {
|
|
201
|
-
labelPlacement: common.labelPlacement
|
|
202
|
-
} : {}
|
|
203
|
-
};
|
|
204
|
-
const commonCheckbox = {
|
|
205
|
-
...common.color !== void 0 ? {
|
|
206
|
-
color: common.color
|
|
207
|
-
} : {},
|
|
208
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
209
|
-
};
|
|
210
|
-
const commonRadioGroup = {
|
|
211
|
-
...common.color !== void 0 ? {
|
|
212
|
-
color: common.color
|
|
213
|
-
} : {},
|
|
214
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
215
|
-
};
|
|
216
|
-
const commonDateInput = {
|
|
217
|
-
...common.color !== void 0 ? {
|
|
218
|
-
color: common.color
|
|
219
|
-
} : {},
|
|
220
|
-
...common.size !== void 0 ? { size: common.size } : {},
|
|
221
|
-
...common.variant !== void 0 ? {
|
|
222
|
-
variant: common.variant
|
|
223
|
-
} : {},
|
|
224
|
-
...common.radius !== void 0 ? {
|
|
225
|
-
radius: common.radius
|
|
226
|
-
} : {}
|
|
227
|
-
};
|
|
228
|
-
const commonSlider = {
|
|
229
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
230
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
231
|
-
};
|
|
232
|
-
const commonSwitch = {
|
|
233
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
234
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
235
|
-
};
|
|
236
|
-
const commonButton = {
|
|
237
|
-
...common.color !== void 0 ? { color: common.color } : {},
|
|
238
|
-
...common.size !== void 0 ? { size: common.size } : {}
|
|
239
|
-
};
|
|
259
|
+
const commonInput = extractInputCommon(common);
|
|
260
|
+
const commonTextarea = extractTextareaCommon(common);
|
|
261
|
+
const commonSelect = extractSelectCommon(common);
|
|
240
262
|
return {
|
|
241
|
-
checkbox:
|
|
242
|
-
dateInput:
|
|
263
|
+
checkbox: cfg.checkbox ?? {},
|
|
264
|
+
dateInput: cfg.dateInput ?? {},
|
|
243
265
|
input: { ...commonInput, ...cfg.input ?? {} },
|
|
244
|
-
radioGroup:
|
|
266
|
+
radioGroup: cfg.radioGroup ?? {},
|
|
245
267
|
select: { ...commonSelect, ...cfg.select ?? {} },
|
|
246
|
-
slider:
|
|
247
|
-
submitButton:
|
|
248
|
-
switch:
|
|
268
|
+
slider: cfg.slider ?? {},
|
|
269
|
+
submitButton: cfg.submitButton ?? {},
|
|
270
|
+
switch: cfg.switch ?? {},
|
|
249
271
|
textarea: { ...commonTextarea, ...cfg.textarea ?? {} }
|
|
250
272
|
};
|
|
251
273
|
}
|
|
@@ -263,31 +285,111 @@ function CheckboxField(props) {
|
|
|
263
285
|
rules
|
|
264
286
|
} = props;
|
|
265
287
|
const defaults = useHeroHookFormDefaults();
|
|
288
|
+
const checkboxValue = checkboxProps?.value ?? "on";
|
|
266
289
|
return /* @__PURE__ */ React3.createElement(
|
|
267
290
|
Controller2,
|
|
268
291
|
{
|
|
269
292
|
control,
|
|
270
293
|
name,
|
|
271
|
-
render: ({ field: field2, fieldState }) =>
|
|
272
|
-
|
|
273
|
-
{
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
294
|
+
render: ({ field: field2, fieldState }) => {
|
|
295
|
+
const containerRef = React3.useRef(null);
|
|
296
|
+
React3.useLayoutEffect(() => {
|
|
297
|
+
const setValue = () => {
|
|
298
|
+
if (containerRef.current) {
|
|
299
|
+
const input = containerRef.current.querySelector(
|
|
300
|
+
`input[type="checkbox"][name="${name}"]`
|
|
301
|
+
);
|
|
302
|
+
if (input instanceof HTMLInputElement) {
|
|
303
|
+
input.setAttribute("value", checkboxValue);
|
|
304
|
+
input.value = checkboxValue;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
setValue();
|
|
309
|
+
const timeoutId = setTimeout(setValue, 0);
|
|
310
|
+
return () => clearTimeout(timeoutId);
|
|
311
|
+
}, [name, checkboxValue, field2.value]);
|
|
312
|
+
return /* @__PURE__ */ React3.createElement("div", { ref: containerRef, className }, /* @__PURE__ */ React3.createElement(
|
|
313
|
+
Checkbox,
|
|
314
|
+
{
|
|
315
|
+
...defaults.checkbox,
|
|
316
|
+
...checkboxProps,
|
|
317
|
+
isDisabled,
|
|
318
|
+
isInvalid: Boolean(fieldState.error),
|
|
319
|
+
isSelected: Boolean(field2.value),
|
|
320
|
+
name,
|
|
321
|
+
value: checkboxValue,
|
|
322
|
+
onBlur: field2.onBlur,
|
|
323
|
+
onValueChange: (val) => field2.onChange(val)
|
|
324
|
+
},
|
|
325
|
+
label
|
|
326
|
+
), description ? /* @__PURE__ */ React3.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React3.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null);
|
|
327
|
+
},
|
|
284
328
|
rules
|
|
285
329
|
}
|
|
286
330
|
);
|
|
287
331
|
}
|
|
288
332
|
|
|
289
|
-
// src/fields/
|
|
333
|
+
// src/fields/CheckboxGroupField.tsx
|
|
290
334
|
import React4 from "react";
|
|
335
|
+
import { Controller as Controller3 } from "react-hook-form";
|
|
336
|
+
function CheckboxGroupField(props) {
|
|
337
|
+
const {
|
|
338
|
+
checkboxProps,
|
|
339
|
+
className,
|
|
340
|
+
control,
|
|
341
|
+
description,
|
|
342
|
+
isDisabled,
|
|
343
|
+
label,
|
|
344
|
+
name,
|
|
345
|
+
options,
|
|
346
|
+
orientation = "vertical",
|
|
347
|
+
rules
|
|
348
|
+
} = props;
|
|
349
|
+
const defaults = useHeroHookFormDefaults();
|
|
350
|
+
return /* @__PURE__ */ React4.createElement(
|
|
351
|
+
Controller3,
|
|
352
|
+
{
|
|
353
|
+
control,
|
|
354
|
+
name,
|
|
355
|
+
render: ({ field: field2, fieldState }) => {
|
|
356
|
+
const currentValues = field2.value || [];
|
|
357
|
+
const handleCheckboxChange = (optionValue, checked) => {
|
|
358
|
+
if (checked) {
|
|
359
|
+
if (!currentValues.includes(optionValue)) {
|
|
360
|
+
field2.onChange([...currentValues, optionValue]);
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
field2.onChange(currentValues.filter((val) => val !== optionValue));
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const containerClass = orientation === "horizontal" ? "flex flex-row gap-4 flex-wrap" : "flex flex-col gap-2";
|
|
367
|
+
return /* @__PURE__ */ React4.createElement("div", { className }, label && /* @__PURE__ */ React4.createElement("label", { className: "text-sm font-medium text-foreground block mb-2" }, label), description && /* @__PURE__ */ React4.createElement("p", { className: "text-sm text-default-500 mb-2" }, description), /* @__PURE__ */ React4.createElement("div", { className: containerClass }, options.map((option) => {
|
|
368
|
+
const isSelected = currentValues.includes(option.value);
|
|
369
|
+
return /* @__PURE__ */ React4.createElement(
|
|
370
|
+
Checkbox,
|
|
371
|
+
{
|
|
372
|
+
key: String(option.value),
|
|
373
|
+
...defaults.checkbox,
|
|
374
|
+
...checkboxProps,
|
|
375
|
+
isDisabled: isDisabled || option.disabled,
|
|
376
|
+
isInvalid: Boolean(fieldState.error),
|
|
377
|
+
isSelected,
|
|
378
|
+
name,
|
|
379
|
+
onBlur: field2.onBlur,
|
|
380
|
+
onValueChange: (checked) => handleCheckboxChange(option.value, checked)
|
|
381
|
+
},
|
|
382
|
+
option.label
|
|
383
|
+
);
|
|
384
|
+
})), fieldState.error?.message ? /* @__PURE__ */ React4.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null);
|
|
385
|
+
},
|
|
386
|
+
rules
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/fields/ConditionalField.tsx
|
|
392
|
+
import React5 from "react";
|
|
291
393
|
import { useWatch, useFormContext } from "react-hook-form";
|
|
292
394
|
function ConditionalField({
|
|
293
395
|
className,
|
|
@@ -301,7 +403,7 @@ function ConditionalField({
|
|
|
301
403
|
if (!shouldShow) {
|
|
302
404
|
return null;
|
|
303
405
|
}
|
|
304
|
-
return /* @__PURE__ */
|
|
406
|
+
return /* @__PURE__ */ React5.createElement("div", { className }, /* @__PURE__ */ React5.createElement(
|
|
305
407
|
FormField,
|
|
306
408
|
{
|
|
307
409
|
config: field2,
|
|
@@ -317,29 +419,29 @@ function ConditionalField({
|
|
|
317
419
|
}
|
|
318
420
|
|
|
319
421
|
// src/fields/ContentField.tsx
|
|
320
|
-
import
|
|
422
|
+
import React6 from "react";
|
|
321
423
|
function ContentField({
|
|
322
424
|
config,
|
|
323
425
|
form,
|
|
324
426
|
submissionState
|
|
325
427
|
}) {
|
|
326
428
|
if (config.render) {
|
|
327
|
-
return /* @__PURE__ */
|
|
429
|
+
return /* @__PURE__ */ React6.createElement("div", { className: config.className }, config.render({
|
|
328
430
|
errors: form.formState.errors,
|
|
329
431
|
form,
|
|
330
432
|
isSubmitting: submissionState.isSubmitting
|
|
331
433
|
}));
|
|
332
434
|
}
|
|
333
|
-
return /* @__PURE__ */
|
|
435
|
+
return /* @__PURE__ */ React6.createElement("div", { className: config.className }, config.title && /* @__PURE__ */ React6.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, config.title), config.description && /* @__PURE__ */ React6.createElement("p", { className: "text-sm text-muted-foreground" }, config.description));
|
|
334
436
|
}
|
|
335
437
|
|
|
336
438
|
// src/fields/DateField.tsx
|
|
337
|
-
import
|
|
338
|
-
import { Controller as
|
|
439
|
+
import React7 from "react";
|
|
440
|
+
import { Controller as Controller4 } from "react-hook-form";
|
|
339
441
|
function CoercedDateInput(props) {
|
|
340
442
|
const { dateProps, description, disabled, errorMessage, field: field2, label } = props;
|
|
341
443
|
const defaults = useHeroHookFormDefaults();
|
|
342
|
-
return /* @__PURE__ */
|
|
444
|
+
return /* @__PURE__ */ React7.createElement(
|
|
343
445
|
DateInput,
|
|
344
446
|
{
|
|
345
447
|
...defaults.dateInput,
|
|
@@ -349,6 +451,7 @@ function CoercedDateInput(props) {
|
|
|
349
451
|
isDisabled: disabled,
|
|
350
452
|
isInvalid: Boolean(errorMessage),
|
|
351
453
|
label,
|
|
454
|
+
name: field2.name,
|
|
352
455
|
value: field2.value ?? null,
|
|
353
456
|
onBlur: field2.onBlur,
|
|
354
457
|
onChange: field2.onChange
|
|
@@ -367,12 +470,12 @@ function DateField(props) {
|
|
|
367
470
|
rules,
|
|
368
471
|
transform
|
|
369
472
|
} = props;
|
|
370
|
-
return /* @__PURE__ */
|
|
371
|
-
|
|
473
|
+
return /* @__PURE__ */ React7.createElement(
|
|
474
|
+
Controller4,
|
|
372
475
|
{
|
|
373
476
|
control,
|
|
374
477
|
name,
|
|
375
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
478
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
|
|
376
479
|
CoercedDateInput,
|
|
377
480
|
{
|
|
378
481
|
dateProps,
|
|
@@ -392,7 +495,7 @@ function DateField(props) {
|
|
|
392
495
|
}
|
|
393
496
|
|
|
394
497
|
// src/fields/DynamicSectionField.tsx
|
|
395
|
-
import
|
|
498
|
+
import React8 from "react";
|
|
396
499
|
import { useWatch as useWatch2, useFormContext as useFormContext2 } from "react-hook-form";
|
|
397
500
|
function DynamicSectionField({
|
|
398
501
|
className,
|
|
@@ -406,7 +509,7 @@ function DynamicSectionField({
|
|
|
406
509
|
if (!shouldShow) {
|
|
407
510
|
return null;
|
|
408
511
|
}
|
|
409
|
-
return /* @__PURE__ */
|
|
512
|
+
return /* @__PURE__ */ React8.createElement("div", { className }, (title || description) && /* @__PURE__ */ React8.createElement("div", { className: "mb-6" }, title && /* @__PURE__ */ React8.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-2" }, title), description && /* @__PURE__ */ React8.createElement("p", { className: "text-sm text-gray-600" }, description)), /* @__PURE__ */ React8.createElement("div", { className: "space-y-4" }, fields.map((fieldConfig, index) => /* @__PURE__ */ React8.createElement(
|
|
410
513
|
FormField,
|
|
411
514
|
{
|
|
412
515
|
key: `${fieldConfig.name}-${index}`,
|
|
@@ -423,7 +526,7 @@ function DynamicSectionField({
|
|
|
423
526
|
}
|
|
424
527
|
|
|
425
528
|
// src/fields/FieldArrayField.tsx
|
|
426
|
-
import
|
|
529
|
+
import React9 from "react";
|
|
427
530
|
import { useFieldArray, useFormContext as useFormContext3 } from "react-hook-form";
|
|
428
531
|
import { Button as Button2 } from "@heroui/react";
|
|
429
532
|
function FieldArrayField({
|
|
@@ -432,71 +535,61 @@ function FieldArrayField({
|
|
|
432
535
|
}) {
|
|
433
536
|
const {
|
|
434
537
|
addButtonText = "Add Item",
|
|
538
|
+
defaultItem,
|
|
539
|
+
enableReordering = false,
|
|
435
540
|
fields: fieldConfigs,
|
|
436
541
|
max = 10,
|
|
437
542
|
min = 0,
|
|
438
543
|
name,
|
|
439
|
-
removeButtonText = "Remove"
|
|
544
|
+
removeButtonText = "Remove",
|
|
545
|
+
renderAddButton,
|
|
546
|
+
renderItem,
|
|
547
|
+
reorderButtonText = { down: "\u2193", up: "\u2191" }
|
|
440
548
|
} = config;
|
|
441
549
|
const form = useFormContext3();
|
|
442
550
|
if (!form || !form.control) {
|
|
443
551
|
return null;
|
|
444
552
|
}
|
|
445
553
|
const { control } = form;
|
|
446
|
-
const { append, fields, remove } = useFieldArray({
|
|
554
|
+
const { append, fields, move, remove } = useFieldArray({
|
|
447
555
|
control,
|
|
448
556
|
name
|
|
449
|
-
// FieldArray name
|
|
450
557
|
});
|
|
451
558
|
const canAdd = fields.length < max;
|
|
452
559
|
const canRemove = fields.length > min;
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
const defaultValues = fieldConfigs.reduce((acc, fieldConfig) => {
|
|
456
|
-
const fieldName = fieldConfig.name;
|
|
457
|
-
if (fieldConfig.type === "checkbox" || fieldConfig.type === "switch") {
|
|
458
|
-
acc[fieldName] = false;
|
|
459
|
-
} else if (fieldConfig.type === "slider") {
|
|
460
|
-
acc[fieldName] = 0;
|
|
461
|
-
} else {
|
|
462
|
-
acc[fieldName] = "";
|
|
463
|
-
}
|
|
464
|
-
return acc;
|
|
465
|
-
}, {});
|
|
466
|
-
append(defaultValues);
|
|
467
|
-
}
|
|
560
|
+
const getFieldPath = (fieldName, itemIndex) => {
|
|
561
|
+
return `${String(name)}.${itemIndex}.${fieldName}`;
|
|
468
562
|
};
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
563
|
+
const processFieldConfig = (fieldConfig, itemIndex) => {
|
|
564
|
+
const fieldName = String(fieldConfig.name);
|
|
565
|
+
const fullPath = getFieldPath(fieldName, itemIndex);
|
|
566
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn && typeof fieldConfig.dependsOn === "string") {
|
|
567
|
+
const dependsOnPath = fieldConfig.dependsOn;
|
|
568
|
+
const arrayNamePrefix = `${String(name)}.`;
|
|
569
|
+
if (!dependsOnPath.startsWith(arrayNamePrefix)) {
|
|
570
|
+
const nestedDependsOn = getFieldPath(dependsOnPath, itemIndex);
|
|
571
|
+
return {
|
|
572
|
+
...fieldConfig,
|
|
573
|
+
dependsOn: nestedDependsOn,
|
|
574
|
+
name: fullPath,
|
|
575
|
+
..."dependsOnValue" in fieldConfig && {
|
|
576
|
+
dependsOnValue: fieldConfig.dependsOnValue
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
}
|
|
472
580
|
}
|
|
581
|
+
return {
|
|
582
|
+
...fieldConfig,
|
|
583
|
+
name: fullPath
|
|
584
|
+
};
|
|
473
585
|
};
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
key: field2.id,
|
|
478
|
-
className: "border border-gray-200 rounded-lg p-4 space-y-4"
|
|
479
|
-
},
|
|
480
|
-
/* @__PURE__ */ React8.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React8.createElement("h4", { className: "text-sm font-medium text-gray-700" }, config.label, " #", index + 1), canRemove && /* @__PURE__ */ React8.createElement(
|
|
481
|
-
Button2,
|
|
482
|
-
{
|
|
483
|
-
size: "sm",
|
|
484
|
-
variant: "light",
|
|
485
|
-
color: "danger",
|
|
486
|
-
startContent: "\u{1F5D1}\uFE0F",
|
|
487
|
-
onPress: () => handleRemove(index),
|
|
488
|
-
"aria-label": `${removeButtonText} ${config.label} ${index + 1}`
|
|
489
|
-
},
|
|
490
|
-
removeButtonText
|
|
491
|
-
)),
|
|
492
|
-
/* @__PURE__ */ React8.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldConfigs.map((fieldConfig) => /* @__PURE__ */ React8.createElement(
|
|
586
|
+
const renderField = (fieldConfig, itemIndex) => {
|
|
587
|
+
const processedConfig = processFieldConfig(fieldConfig, itemIndex);
|
|
588
|
+
return /* @__PURE__ */ React9.createElement(
|
|
493
589
|
FormField,
|
|
494
590
|
{
|
|
495
|
-
key: `${fieldConfig.name}-${
|
|
496
|
-
config:
|
|
497
|
-
...fieldConfig,
|
|
498
|
-
name: `${name}.${index}.${fieldConfig.name}`
|
|
499
|
-
},
|
|
591
|
+
key: `${fieldConfig.name}-${itemIndex}`,
|
|
592
|
+
config: processedConfig,
|
|
500
593
|
form,
|
|
501
594
|
submissionState: {
|
|
502
595
|
error: void 0,
|
|
@@ -505,31 +598,125 @@ function FieldArrayField({
|
|
|
505
598
|
isSuccess: false
|
|
506
599
|
}
|
|
507
600
|
}
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
{
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
601
|
+
);
|
|
602
|
+
};
|
|
603
|
+
const handleAdd = () => {
|
|
604
|
+
if (canAdd) {
|
|
605
|
+
if (defaultItem) {
|
|
606
|
+
append(defaultItem());
|
|
607
|
+
} else {
|
|
608
|
+
console.warn(
|
|
609
|
+
`FieldArrayField: defaultItem is required for field array "${String(name)}". Please provide a defaultItem function that returns the default item structure.`
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
const handleRemove = (index) => {
|
|
615
|
+
if (canRemove) {
|
|
616
|
+
remove(index);
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
const handleMoveUp = (index) => {
|
|
620
|
+
if (index > 0) {
|
|
621
|
+
move(index, index - 1);
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
const handleMoveDown = (index) => {
|
|
625
|
+
if (index < fields.length - 1) {
|
|
626
|
+
move(index, index + 1);
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const renderFieldArrayItems = () => {
|
|
630
|
+
return fields.map((field2, index) => {
|
|
631
|
+
const canMoveUp = enableReordering && index > 0;
|
|
632
|
+
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
633
|
+
const itemCanRemove = canRemove;
|
|
634
|
+
const fieldElements = fieldConfigs.map(
|
|
635
|
+
(fieldConfig) => renderField(fieldConfig, index)
|
|
636
|
+
);
|
|
637
|
+
if (renderItem) {
|
|
638
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, { key: field2.id }, renderItem({
|
|
639
|
+
canMoveDown,
|
|
640
|
+
canMoveUp,
|
|
641
|
+
canRemove: itemCanRemove,
|
|
642
|
+
children: /* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements),
|
|
643
|
+
field: field2,
|
|
644
|
+
fields,
|
|
645
|
+
index,
|
|
646
|
+
onMoveDown: () => handleMoveDown(index),
|
|
647
|
+
onMoveUp: () => handleMoveUp(index),
|
|
648
|
+
onRemove: () => handleRemove(index)
|
|
649
|
+
}));
|
|
650
|
+
}
|
|
651
|
+
return /* @__PURE__ */ React9.createElement(
|
|
652
|
+
"div",
|
|
653
|
+
{
|
|
654
|
+
key: field2.id,
|
|
655
|
+
className: "border border-gray-200 rounded-lg p-4 space-y-4"
|
|
656
|
+
},
|
|
657
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React9.createElement("h4", { className: "text-sm font-medium text-gray-700" }, config.label, " #", index + 1), /* @__PURE__ */ React9.createElement("div", { className: "flex gap-2" }, enableReordering && /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
|
|
658
|
+
Button2,
|
|
659
|
+
{
|
|
660
|
+
size: "sm",
|
|
661
|
+
variant: "light",
|
|
662
|
+
isDisabled: !canMoveUp,
|
|
663
|
+
onPress: () => handleMoveUp(index),
|
|
664
|
+
"aria-label": `Move ${config.label} ${index + 1} up`
|
|
665
|
+
},
|
|
666
|
+
reorderButtonText.up
|
|
667
|
+
), /* @__PURE__ */ React9.createElement(
|
|
668
|
+
Button2,
|
|
669
|
+
{
|
|
670
|
+
size: "sm",
|
|
671
|
+
variant: "light",
|
|
672
|
+
isDisabled: !canMoveDown,
|
|
673
|
+
onPress: () => handleMoveDown(index),
|
|
674
|
+
"aria-label": `Move ${config.label} ${index + 1} down`
|
|
675
|
+
},
|
|
676
|
+
reorderButtonText.down
|
|
677
|
+
)), itemCanRemove && /* @__PURE__ */ React9.createElement(
|
|
678
|
+
Button2,
|
|
679
|
+
{
|
|
680
|
+
size: "sm",
|
|
681
|
+
variant: "light",
|
|
682
|
+
color: "danger",
|
|
683
|
+
startContent: "\u{1F5D1}\uFE0F",
|
|
684
|
+
onPress: () => handleRemove(index),
|
|
685
|
+
"aria-label": `${removeButtonText} ${config.label} ${index + 1}`
|
|
686
|
+
},
|
|
687
|
+
removeButtonText
|
|
688
|
+
))),
|
|
689
|
+
/* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements)
|
|
690
|
+
);
|
|
691
|
+
});
|
|
692
|
+
};
|
|
693
|
+
const renderAddButtonElement = () => {
|
|
694
|
+
if (renderAddButton) {
|
|
695
|
+
return renderAddButton({
|
|
696
|
+
canAdd,
|
|
697
|
+
onAdd: handleAdd
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
if (!canAdd) {
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
return /* @__PURE__ */ React9.createElement(
|
|
704
|
+
Button2,
|
|
705
|
+
{
|
|
706
|
+
variant: "bordered",
|
|
707
|
+
startContent: "\u2795",
|
|
708
|
+
onPress: handleAdd,
|
|
709
|
+
className: "w-full"
|
|
710
|
+
},
|
|
711
|
+
addButtonText
|
|
712
|
+
);
|
|
713
|
+
};
|
|
714
|
+
return /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement("div", { className: "space-y-4" }, fields.length > 0 ? renderFieldArrayItems() : /* @__PURE__ */ React9.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React9.createElement("p", null, "No ", config.label?.toLowerCase(), " added yet."), renderAddButtonElement()), fields.length > 0 && renderAddButtonElement()));
|
|
528
715
|
}
|
|
529
716
|
|
|
530
717
|
// src/fields/FileField.tsx
|
|
531
|
-
import
|
|
532
|
-
import { Controller as
|
|
718
|
+
import React10 from "react";
|
|
719
|
+
import { Controller as Controller5 } from "react-hook-form";
|
|
533
720
|
function CoercedFileInput(props) {
|
|
534
721
|
const {
|
|
535
722
|
accept,
|
|
@@ -542,7 +729,7 @@ function CoercedFileInput(props) {
|
|
|
542
729
|
multiple
|
|
543
730
|
} = props;
|
|
544
731
|
const defaults = useHeroHookFormDefaults();
|
|
545
|
-
return /* @__PURE__ */
|
|
732
|
+
return /* @__PURE__ */ React10.createElement(
|
|
546
733
|
Input,
|
|
547
734
|
{
|
|
548
735
|
...defaults.input,
|
|
@@ -554,10 +741,14 @@ function CoercedFileInput(props) {
|
|
|
554
741
|
isInvalid: Boolean(errorMessage),
|
|
555
742
|
label,
|
|
556
743
|
multiple,
|
|
744
|
+
name: field2.name,
|
|
557
745
|
type: "file",
|
|
558
746
|
value: field2.value ? "" : "",
|
|
559
747
|
onBlur: field2.onBlur,
|
|
560
748
|
onChange: (e) => {
|
|
749
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
561
752
|
const target = e.target;
|
|
562
753
|
field2.onChange(target.files);
|
|
563
754
|
}
|
|
@@ -578,12 +769,12 @@ function FileField(props) {
|
|
|
578
769
|
rules,
|
|
579
770
|
transform
|
|
580
771
|
} = props;
|
|
581
|
-
return /* @__PURE__ */
|
|
582
|
-
|
|
772
|
+
return /* @__PURE__ */ React10.createElement(
|
|
773
|
+
Controller5,
|
|
583
774
|
{
|
|
584
775
|
control,
|
|
585
776
|
name,
|
|
586
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
777
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
|
|
587
778
|
CoercedFileInput,
|
|
588
779
|
{
|
|
589
780
|
accept,
|
|
@@ -605,8 +796,8 @@ function FileField(props) {
|
|
|
605
796
|
}
|
|
606
797
|
|
|
607
798
|
// src/fields/FontPickerField.tsx
|
|
608
|
-
import
|
|
609
|
-
import { Controller as
|
|
799
|
+
import React11 from "react";
|
|
800
|
+
import { Controller as Controller6 } from "react-hook-form";
|
|
610
801
|
var FontPickerComponent = null;
|
|
611
802
|
var fontPickerLoaded = false;
|
|
612
803
|
var fontPickerLoading = false;
|
|
@@ -622,12 +813,12 @@ function FontPickerField(props) {
|
|
|
622
813
|
name,
|
|
623
814
|
rules
|
|
624
815
|
} = props;
|
|
625
|
-
const [fontPickerState, setFontPickerState] =
|
|
816
|
+
const [fontPickerState, setFontPickerState] = React11.useState({
|
|
626
817
|
component: FontPickerComponent,
|
|
627
818
|
error: null,
|
|
628
819
|
loading: false
|
|
629
820
|
});
|
|
630
|
-
|
|
821
|
+
React11.useEffect(() => {
|
|
631
822
|
if (fontPickerLoaded && FontPickerComponent) {
|
|
632
823
|
setFontPickerState({
|
|
633
824
|
component: FontPickerComponent,
|
|
@@ -685,17 +876,17 @@ function FontPickerField(props) {
|
|
|
685
876
|
void loadFontPicker();
|
|
686
877
|
}, []);
|
|
687
878
|
if (fontPickerState.loading) {
|
|
688
|
-
return /* @__PURE__ */
|
|
879
|
+
return /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React11.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React11.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React11.createElement("div", { className: "p-4 border border-default-200 bg-default-50 rounded-medium" }, /* @__PURE__ */ React11.createElement("p", { className: "text-default-600 text-sm" }, "Loading font picker..."))));
|
|
689
880
|
}
|
|
690
881
|
if (!fontPickerState.component) {
|
|
691
|
-
return /* @__PURE__ */
|
|
882
|
+
return /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React11.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React11.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React11.createElement("div", { className: "p-4 border border-warning-200 bg-warning-50 rounded-medium" }, /* @__PURE__ */ React11.createElement("p", { className: "text-warning-800 text-sm" }, "Font picker requires the @rachelallyson/heroui-font-picker package. Please install it as a peer dependency for advanced font selection features."))));
|
|
692
883
|
}
|
|
693
|
-
return /* @__PURE__ */
|
|
694
|
-
|
|
884
|
+
return /* @__PURE__ */ React11.createElement(
|
|
885
|
+
Controller6,
|
|
695
886
|
{
|
|
696
887
|
control,
|
|
697
888
|
name,
|
|
698
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
889
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React11.createElement(
|
|
699
890
|
fontPickerState.component,
|
|
700
891
|
{
|
|
701
892
|
label,
|
|
@@ -714,12 +905,12 @@ function FontPickerField(props) {
|
|
|
714
905
|
}
|
|
715
906
|
|
|
716
907
|
// src/fields/InputField.tsx
|
|
717
|
-
import
|
|
718
|
-
import { Controller as
|
|
908
|
+
import React12 from "react";
|
|
909
|
+
import { Controller as Controller7 } from "react-hook-form";
|
|
719
910
|
function CoercedInput(props) {
|
|
720
911
|
const { description, disabled, errorMessage, field: field2, inputProps, label } = props;
|
|
721
912
|
const defaults = useHeroHookFormDefaults();
|
|
722
|
-
return /* @__PURE__ */
|
|
913
|
+
return /* @__PURE__ */ React12.createElement(
|
|
723
914
|
Input,
|
|
724
915
|
{
|
|
725
916
|
...defaults.input,
|
|
@@ -729,13 +920,14 @@ function CoercedInput(props) {
|
|
|
729
920
|
isDisabled: disabled,
|
|
730
921
|
isInvalid: Boolean(errorMessage),
|
|
731
922
|
label,
|
|
923
|
+
name: field2.name,
|
|
732
924
|
value: field2.value ?? "",
|
|
733
925
|
onBlur: field2.onBlur,
|
|
734
926
|
onValueChange: field2.onChange
|
|
735
927
|
}
|
|
736
928
|
);
|
|
737
929
|
}
|
|
738
|
-
var InputField =
|
|
930
|
+
var InputField = React12.memo(
|
|
739
931
|
(props) => {
|
|
740
932
|
const {
|
|
741
933
|
className,
|
|
@@ -748,12 +940,12 @@ var InputField = React11.memo(
|
|
|
748
940
|
rules,
|
|
749
941
|
transform
|
|
750
942
|
} = props;
|
|
751
|
-
return /* @__PURE__ */
|
|
752
|
-
|
|
943
|
+
return /* @__PURE__ */ React12.createElement(
|
|
944
|
+
Controller7,
|
|
753
945
|
{
|
|
754
946
|
control,
|
|
755
947
|
name,
|
|
756
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
948
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
|
|
757
949
|
CoercedInput,
|
|
758
950
|
{
|
|
759
951
|
description,
|
|
@@ -783,8 +975,8 @@ var InputField = React11.memo(
|
|
|
783
975
|
);
|
|
784
976
|
|
|
785
977
|
// src/fields/RadioGroupField.tsx
|
|
786
|
-
import
|
|
787
|
-
import { Controller as
|
|
978
|
+
import React13 from "react";
|
|
979
|
+
import { Controller as Controller8 } from "react-hook-form";
|
|
788
980
|
function RadioGroupField(props) {
|
|
789
981
|
const {
|
|
790
982
|
className,
|
|
@@ -798,12 +990,12 @@ function RadioGroupField(props) {
|
|
|
798
990
|
rules
|
|
799
991
|
} = props;
|
|
800
992
|
const defaults = useHeroHookFormDefaults();
|
|
801
|
-
return /* @__PURE__ */
|
|
802
|
-
|
|
993
|
+
return /* @__PURE__ */ React13.createElement(
|
|
994
|
+
Controller8,
|
|
803
995
|
{
|
|
804
996
|
control,
|
|
805
997
|
name,
|
|
806
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
998
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
|
|
807
999
|
RadioGroup,
|
|
808
1000
|
{
|
|
809
1001
|
...defaults.radioGroup,
|
|
@@ -812,11 +1004,12 @@ function RadioGroupField(props) {
|
|
|
812
1004
|
isDisabled,
|
|
813
1005
|
isInvalid: Boolean(fieldState.error),
|
|
814
1006
|
label,
|
|
1007
|
+
name,
|
|
815
1008
|
value: String(field2.value ?? ""),
|
|
816
1009
|
onBlur: field2.onBlur,
|
|
817
1010
|
onValueChange: (val) => field2.onChange(val)
|
|
818
1011
|
},
|
|
819
|
-
options.map((opt) => /* @__PURE__ */
|
|
1012
|
+
options.map((opt) => /* @__PURE__ */ React13.createElement(
|
|
820
1013
|
Radio,
|
|
821
1014
|
{
|
|
822
1015
|
key: String(opt.value),
|
|
@@ -825,15 +1018,15 @@ function RadioGroupField(props) {
|
|
|
825
1018
|
},
|
|
826
1019
|
opt.label
|
|
827
1020
|
))
|
|
828
|
-
), fieldState.error?.message ? /* @__PURE__ */
|
|
1021
|
+
), fieldState.error?.message ? /* @__PURE__ */ React13.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
829
1022
|
rules
|
|
830
1023
|
}
|
|
831
1024
|
);
|
|
832
1025
|
}
|
|
833
1026
|
|
|
834
1027
|
// src/fields/SelectField.tsx
|
|
835
|
-
import
|
|
836
|
-
import { Controller as
|
|
1028
|
+
import React14 from "react";
|
|
1029
|
+
import { Controller as Controller9 } from "react-hook-form";
|
|
837
1030
|
function SelectField(props) {
|
|
838
1031
|
const {
|
|
839
1032
|
className,
|
|
@@ -848,14 +1041,14 @@ function SelectField(props) {
|
|
|
848
1041
|
selectProps
|
|
849
1042
|
} = props;
|
|
850
1043
|
const defaults = useHeroHookFormDefaults();
|
|
851
|
-
return /* @__PURE__ */
|
|
852
|
-
|
|
1044
|
+
return /* @__PURE__ */ React14.createElement(
|
|
1045
|
+
Controller9,
|
|
853
1046
|
{
|
|
854
1047
|
control,
|
|
855
1048
|
name,
|
|
856
1049
|
render: ({ field: field2, fieldState }) => {
|
|
857
1050
|
const selectedKey = field2.value;
|
|
858
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
|
|
859
1052
|
Select,
|
|
860
1053
|
{
|
|
861
1054
|
...defaults.select,
|
|
@@ -865,6 +1058,7 @@ function SelectField(props) {
|
|
|
865
1058
|
isDisabled,
|
|
866
1059
|
isInvalid: Boolean(fieldState.error),
|
|
867
1060
|
label,
|
|
1061
|
+
name,
|
|
868
1062
|
placeholder,
|
|
869
1063
|
selectedKeys: selectedKey != null ? /* @__PURE__ */ new Set([String(selectedKey)]) : /* @__PURE__ */ new Set(),
|
|
870
1064
|
onSelectionChange: (keys) => {
|
|
@@ -873,7 +1067,7 @@ function SelectField(props) {
|
|
|
873
1067
|
field2.onChange(next);
|
|
874
1068
|
}
|
|
875
1069
|
},
|
|
876
|
-
options.map((opt) => /* @__PURE__ */
|
|
1070
|
+
options.map((opt) => /* @__PURE__ */ React14.createElement(
|
|
877
1071
|
SelectItem,
|
|
878
1072
|
{
|
|
879
1073
|
key: String(opt.value),
|
|
@@ -890,12 +1084,12 @@ function SelectField(props) {
|
|
|
890
1084
|
}
|
|
891
1085
|
|
|
892
1086
|
// src/fields/SliderField.tsx
|
|
893
|
-
import
|
|
894
|
-
import { Controller as
|
|
1087
|
+
import React15 from "react";
|
|
1088
|
+
import { Controller as Controller10 } from "react-hook-form";
|
|
895
1089
|
function CoercedSlider(props) {
|
|
896
1090
|
const { description, disabled, errorMessage, field: field2, label, sliderProps } = props;
|
|
897
1091
|
const defaults = useHeroHookFormDefaults();
|
|
898
|
-
return /* @__PURE__ */
|
|
1092
|
+
return /* @__PURE__ */ React15.createElement(
|
|
899
1093
|
Slider,
|
|
900
1094
|
{
|
|
901
1095
|
...defaults.slider,
|
|
@@ -905,6 +1099,7 @@ function CoercedSlider(props) {
|
|
|
905
1099
|
isDisabled: disabled,
|
|
906
1100
|
isInvalid: Boolean(errorMessage),
|
|
907
1101
|
label,
|
|
1102
|
+
name: field2.name,
|
|
908
1103
|
value: field2.value ?? 0,
|
|
909
1104
|
onBlur: field2.onBlur,
|
|
910
1105
|
onValueChange: field2.onChange
|
|
@@ -923,12 +1118,12 @@ function SliderField(props) {
|
|
|
923
1118
|
sliderProps,
|
|
924
1119
|
transform
|
|
925
1120
|
} = props;
|
|
926
|
-
return /* @__PURE__ */
|
|
927
|
-
|
|
1121
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1122
|
+
Controller10,
|
|
928
1123
|
{
|
|
929
1124
|
control,
|
|
930
1125
|
name,
|
|
931
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1126
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React15.createElement("div", { className }, /* @__PURE__ */ React15.createElement(
|
|
932
1127
|
CoercedSlider,
|
|
933
1128
|
{
|
|
934
1129
|
description,
|
|
@@ -947,46 +1142,161 @@ function SliderField(props) {
|
|
|
947
1142
|
);
|
|
948
1143
|
}
|
|
949
1144
|
|
|
950
|
-
// src/fields/
|
|
951
|
-
import
|
|
952
|
-
import { Controller as
|
|
953
|
-
function
|
|
1145
|
+
// src/fields/StringArrayField.tsx
|
|
1146
|
+
import React16, { useState as useState2 } from "react";
|
|
1147
|
+
import { Controller as Controller11 } from "react-hook-form";
|
|
1148
|
+
function StringArrayInput(props) {
|
|
954
1149
|
const {
|
|
955
|
-
className,
|
|
956
|
-
control,
|
|
957
1150
|
description,
|
|
958
|
-
|
|
1151
|
+
disabled,
|
|
1152
|
+
errorMessage,
|
|
1153
|
+
field: field2,
|
|
959
1154
|
label,
|
|
960
|
-
|
|
961
|
-
rules,
|
|
962
|
-
switchProps
|
|
1155
|
+
stringArrayProps
|
|
963
1156
|
} = props;
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1157
|
+
const [inputValue, setInputValue] = useState2("");
|
|
1158
|
+
const items = field2.value || [];
|
|
1159
|
+
const {
|
|
1160
|
+
addButtonText = "Add",
|
|
1161
|
+
allowDuplicates = false,
|
|
1162
|
+
maxItems,
|
|
1163
|
+
minItems,
|
|
1164
|
+
placeholder = "Add item...",
|
|
1165
|
+
showAddButton = true,
|
|
1166
|
+
transformItem = (item) => item.trim(),
|
|
1167
|
+
validateItem = () => true
|
|
1168
|
+
} = stringArrayProps || {};
|
|
1169
|
+
const canAddMore = !maxItems || items.length < maxItems;
|
|
1170
|
+
const handleAddItem = () => {
|
|
1171
|
+
const trimmedValue = inputValue.trim();
|
|
1172
|
+
if (!trimmedValue) return;
|
|
1173
|
+
const transformedValue = transformItem(trimmedValue);
|
|
1174
|
+
const validation = validateItem(transformedValue);
|
|
1175
|
+
if (validation !== true) return;
|
|
1176
|
+
if (!allowDuplicates && items.includes(transformedValue)) return;
|
|
1177
|
+
const newItems = [...items, transformedValue];
|
|
1178
|
+
field2.onChange(newItems);
|
|
1179
|
+
setInputValue("");
|
|
1180
|
+
};
|
|
1181
|
+
const handleRemoveItem = (indexToRemove) => {
|
|
1182
|
+
const newItems = items.filter((_, index) => index !== indexToRemove);
|
|
1183
|
+
field2.onChange(newItems);
|
|
1184
|
+
};
|
|
1185
|
+
const handleKeyPress = (e) => {
|
|
1186
|
+
if (e.key === "Enter") {
|
|
1187
|
+
e.preventDefault();
|
|
1188
|
+
if (!showAddButton) {
|
|
1189
|
+
handleAddItem();
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
return /* @__PURE__ */ React16.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React16.createElement("label", { className: "block text-sm font-medium text-foreground" }, label, minItems !== void 0 && /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-muted-foreground ml-1" }, "(min ", minItems, ")"), maxItems !== void 0 && /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-muted-foreground ml-1" }, "(max ", maxItems, ")")), description && /* @__PURE__ */ React16.createElement("p", { className: "text-sm text-muted-foreground" }, description), canAddMore && /* @__PURE__ */ React16.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React16.createElement(
|
|
1194
|
+
Input,
|
|
1195
|
+
{
|
|
1196
|
+
className: "flex-1",
|
|
1197
|
+
disabled,
|
|
1198
|
+
placeholder,
|
|
1199
|
+
value: inputValue,
|
|
1200
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
1201
|
+
onKeyPress: handleKeyPress,
|
|
1202
|
+
isInvalid: !!errorMessage,
|
|
1203
|
+
errorMessage
|
|
1204
|
+
}
|
|
1205
|
+
), showAddButton && /* @__PURE__ */ React16.createElement(
|
|
1206
|
+
Button,
|
|
1207
|
+
{
|
|
1208
|
+
type: "button",
|
|
1209
|
+
variant: "flat",
|
|
1210
|
+
onClick: handleAddItem,
|
|
1211
|
+
disabled: disabled || !inputValue.trim(),
|
|
1212
|
+
size: "sm"
|
|
1213
|
+
},
|
|
1214
|
+
addButtonText
|
|
1215
|
+
)), items.length > 0 && /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" }, items.map((item, index) => /* @__PURE__ */ React16.createElement(
|
|
1216
|
+
"div",
|
|
1217
|
+
{
|
|
1218
|
+
key: index,
|
|
1219
|
+
className: "flex items-center gap-2 p-2 bg-content2 rounded-md"
|
|
1220
|
+
},
|
|
1221
|
+
/* @__PURE__ */ React16.createElement("span", { className: "flex-1 text-sm" }, item),
|
|
1222
|
+
/* @__PURE__ */ React16.createElement(
|
|
1223
|
+
Button,
|
|
1224
|
+
{
|
|
1225
|
+
type: "button",
|
|
1226
|
+
variant: "light",
|
|
1227
|
+
size: "sm",
|
|
1228
|
+
onClick: () => handleRemoveItem(index),
|
|
1229
|
+
disabled,
|
|
1230
|
+
className: "min-w-[60px]"
|
|
1231
|
+
},
|
|
1232
|
+
"Remove"
|
|
1233
|
+
)
|
|
1234
|
+
))), minItems !== void 0 && items.length < minItems && /* @__PURE__ */ React16.createElement("p", { className: "text-xs text-danger" }, "At least ", minItems, " item", minItems === 1 ? "" : "s", " required"), maxItems !== void 0 && items.length >= maxItems && /* @__PURE__ */ React16.createElement("p", { className: "text-xs text-muted-foreground" }, "Maximum ", maxItems, " item", maxItems === 1 ? "" : "s", " allowed"));
|
|
1235
|
+
}
|
|
1236
|
+
function StringArrayField(props) {
|
|
1237
|
+
const { control, label, name, rules, ...fieldProps } = props;
|
|
1238
|
+
return /* @__PURE__ */ React16.createElement(
|
|
1239
|
+
Controller11,
|
|
1240
|
+
{
|
|
1241
|
+
control,
|
|
1242
|
+
name,
|
|
1243
|
+
rules,
|
|
1244
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React16.createElement(
|
|
1245
|
+
StringArrayInput,
|
|
1246
|
+
{
|
|
1247
|
+
field: field2,
|
|
1248
|
+
label,
|
|
1249
|
+
description: fieldProps.description,
|
|
1250
|
+
disabled: fieldProps.isDisabled,
|
|
1251
|
+
errorMessage: fieldState.error?.message,
|
|
1252
|
+
stringArrayProps: fieldProps.stringArrayProps
|
|
1253
|
+
}
|
|
1254
|
+
)
|
|
1255
|
+
}
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// src/fields/SwitchField.tsx
|
|
1260
|
+
import React17 from "react";
|
|
1261
|
+
import { Controller as Controller12 } from "react-hook-form";
|
|
1262
|
+
function SwitchField(props) {
|
|
1263
|
+
const {
|
|
1264
|
+
className,
|
|
1265
|
+
control,
|
|
1266
|
+
description,
|
|
1267
|
+
isDisabled,
|
|
1268
|
+
label,
|
|
1269
|
+
name,
|
|
1270
|
+
rules,
|
|
1271
|
+
switchProps
|
|
1272
|
+
} = props;
|
|
1273
|
+
const defaults = useHeroHookFormDefaults();
|
|
1274
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1275
|
+
Controller12,
|
|
1276
|
+
{
|
|
1277
|
+
control,
|
|
1278
|
+
name,
|
|
1279
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React17.createElement("div", { className }, /* @__PURE__ */ React17.createElement(
|
|
1280
|
+
Switch,
|
|
1281
|
+
{
|
|
1282
|
+
...defaults.switch,
|
|
1283
|
+
...switchProps,
|
|
1284
|
+
isDisabled,
|
|
1285
|
+
isSelected: Boolean(field2.value),
|
|
1286
|
+
name,
|
|
1287
|
+
onBlur: field2.onBlur,
|
|
1288
|
+
onValueChange: (val) => field2.onChange(val)
|
|
1289
|
+
},
|
|
1290
|
+
label
|
|
1291
|
+
), description ? /* @__PURE__ */ React17.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React17.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
1292
|
+
rules
|
|
983
1293
|
}
|
|
984
1294
|
);
|
|
985
1295
|
}
|
|
986
1296
|
|
|
987
1297
|
// src/fields/TextareaField.tsx
|
|
988
|
-
import
|
|
989
|
-
import { Controller as
|
|
1298
|
+
import React18 from "react";
|
|
1299
|
+
import { Controller as Controller13 } from "react-hook-form";
|
|
990
1300
|
function TextareaField(props) {
|
|
991
1301
|
const {
|
|
992
1302
|
className,
|
|
@@ -999,12 +1309,12 @@ function TextareaField(props) {
|
|
|
999
1309
|
textareaProps
|
|
1000
1310
|
} = props;
|
|
1001
1311
|
const defaults = useHeroHookFormDefaults();
|
|
1002
|
-
return /* @__PURE__ */
|
|
1003
|
-
|
|
1312
|
+
return /* @__PURE__ */ React18.createElement(
|
|
1313
|
+
Controller13,
|
|
1004
1314
|
{
|
|
1005
1315
|
control,
|
|
1006
1316
|
name,
|
|
1007
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1317
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React18.createElement("div", { className }, /* @__PURE__ */ React18.createElement(
|
|
1008
1318
|
Textarea,
|
|
1009
1319
|
{
|
|
1010
1320
|
...defaults.textarea,
|
|
@@ -1014,6 +1324,7 @@ function TextareaField(props) {
|
|
|
1014
1324
|
isDisabled,
|
|
1015
1325
|
isInvalid: Boolean(fieldState.error),
|
|
1016
1326
|
label,
|
|
1327
|
+
name: field2.name,
|
|
1017
1328
|
value: field2.value ?? "",
|
|
1018
1329
|
onBlur: field2.onBlur,
|
|
1019
1330
|
onValueChange: field2.onChange
|
|
@@ -1025,213 +1336,319 @@ function TextareaField(props) {
|
|
|
1025
1336
|
}
|
|
1026
1337
|
|
|
1027
1338
|
// src/components/FormField.tsx
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1339
|
+
function FormFieldComponent({
|
|
1340
|
+
config,
|
|
1341
|
+
form,
|
|
1342
|
+
submissionState
|
|
1343
|
+
}) {
|
|
1344
|
+
if (!form || !form.control) {
|
|
1345
|
+
return null;
|
|
1346
|
+
}
|
|
1347
|
+
const { control } = form;
|
|
1348
|
+
const watchedValues = useWatch3({ control });
|
|
1349
|
+
const fieldConfig = config;
|
|
1350
|
+
if ("type" in fieldConfig && fieldConfig.type === "content") {
|
|
1351
|
+
if ("render" in fieldConfig || "content" in fieldConfig) {
|
|
1352
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1041
1353
|
ContentField,
|
|
1042
1354
|
{
|
|
1043
|
-
config,
|
|
1355
|
+
config: fieldConfig,
|
|
1044
1356
|
form,
|
|
1045
1357
|
submissionState
|
|
1046
1358
|
}
|
|
1047
1359
|
);
|
|
1048
1360
|
}
|
|
1049
|
-
|
|
1361
|
+
}
|
|
1362
|
+
if ("condition" in fieldConfig && fieldConfig.condition && !fieldConfig.condition(watchedValues)) {
|
|
1363
|
+
return null;
|
|
1364
|
+
}
|
|
1365
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn) {
|
|
1366
|
+
const dependentValue = get(watchedValues, fieldConfig.dependsOn);
|
|
1367
|
+
if ("dependsOnValue" in fieldConfig && fieldConfig.dependsOnValue !== void 0 && dependentValue !== fieldConfig.dependsOnValue) {
|
|
1050
1368
|
return null;
|
|
1051
1369
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1370
|
+
}
|
|
1371
|
+
const baseProps = {
|
|
1372
|
+
ariaDescribedBy: "ariaDescribedBy" in fieldConfig ? fieldConfig.ariaDescribedBy : void 0,
|
|
1373
|
+
ariaLabel: "ariaLabel" in fieldConfig ? fieldConfig.ariaLabel : void 0,
|
|
1374
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1375
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1376
|
+
isDisabled: ("isDisabled" in fieldConfig ? fieldConfig.isDisabled : void 0) ?? submissionState.isSubmitting,
|
|
1377
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1378
|
+
// name is Path<TFieldValues> | string, but FieldBaseProps expects Path<TFieldValues>
|
|
1379
|
+
// We pass it directly to each component instead of through baseProps
|
|
1380
|
+
rules: "rules" in fieldConfig ? fieldConfig.rules : void 0
|
|
1381
|
+
};
|
|
1382
|
+
switch (fieldConfig.type) {
|
|
1383
|
+
case "input": {
|
|
1384
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1385
|
+
InputField,
|
|
1386
|
+
{
|
|
1387
|
+
...baseProps,
|
|
1388
|
+
name: fieldConfig.name,
|
|
1389
|
+
control,
|
|
1390
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1391
|
+
inputProps: "inputProps" in fieldConfig ? fieldConfig.inputProps : void 0
|
|
1392
|
+
}
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
case "textarea": {
|
|
1396
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1397
|
+
TextareaField,
|
|
1398
|
+
{
|
|
1399
|
+
...baseProps,
|
|
1400
|
+
name: fieldConfig.name,
|
|
1401
|
+
control,
|
|
1402
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1403
|
+
textareaProps: "textareaProps" in fieldConfig ? fieldConfig.textareaProps : void 0
|
|
1404
|
+
}
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
case "select": {
|
|
1408
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1409
|
+
SelectField,
|
|
1410
|
+
{
|
|
1411
|
+
...baseProps,
|
|
1412
|
+
name: fieldConfig.name,
|
|
1413
|
+
control,
|
|
1414
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1415
|
+
options: "options" in fieldConfig && fieldConfig.options ? fieldConfig.options.map((opt) => ({
|
|
1416
|
+
label: opt.label,
|
|
1417
|
+
value: String(opt.value)
|
|
1418
|
+
})) : [],
|
|
1419
|
+
selectProps: "selectProps" in fieldConfig ? fieldConfig.selectProps : void 0
|
|
1420
|
+
}
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
case "autocomplete": {
|
|
1424
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1425
|
+
AutocompleteField,
|
|
1426
|
+
{
|
|
1427
|
+
...baseProps,
|
|
1428
|
+
name: fieldConfig.name,
|
|
1429
|
+
control,
|
|
1430
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1431
|
+
items: ("options" in fieldConfig && fieldConfig.options ? fieldConfig.options : []).map((opt) => ({
|
|
1432
|
+
label: opt.label,
|
|
1433
|
+
value: String(opt.value)
|
|
1434
|
+
})),
|
|
1435
|
+
autocompleteProps: "autocompleteProps" in fieldConfig ? fieldConfig.autocompleteProps : void 0
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
case "checkbox": {
|
|
1440
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1441
|
+
CheckboxField,
|
|
1442
|
+
{
|
|
1443
|
+
...baseProps,
|
|
1444
|
+
name: fieldConfig.name,
|
|
1445
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1446
|
+
control,
|
|
1447
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1448
|
+
}
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
case "checkboxGroup": {
|
|
1452
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1453
|
+
CheckboxGroupField,
|
|
1454
|
+
{
|
|
1455
|
+
...baseProps,
|
|
1456
|
+
name: fieldConfig.name,
|
|
1457
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1458
|
+
control,
|
|
1459
|
+
defaultValue: "defaultValue" in fieldConfig && fieldConfig.defaultValue && Array.isArray(fieldConfig.defaultValue) ? fieldConfig.defaultValue.map((v) => String(v)) : void 0,
|
|
1460
|
+
options: ("checkboxGroupOptions" in fieldConfig && fieldConfig.checkboxGroupOptions ? fieldConfig.checkboxGroupOptions : []).map((opt) => ({
|
|
1461
|
+
label: opt.label,
|
|
1462
|
+
value: String(opt.value)
|
|
1463
|
+
})),
|
|
1464
|
+
orientation: "orientation" in fieldConfig ? fieldConfig.orientation : void 0
|
|
1465
|
+
}
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
case "radio": {
|
|
1469
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1470
|
+
RadioGroupField,
|
|
1471
|
+
{
|
|
1472
|
+
...baseProps,
|
|
1473
|
+
name: fieldConfig.name,
|
|
1474
|
+
control,
|
|
1475
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1476
|
+
options: ("radioOptions" in fieldConfig && fieldConfig.radioOptions ? fieldConfig.radioOptions : []).map((opt) => ({
|
|
1477
|
+
label: opt.label,
|
|
1478
|
+
value: String(opt.value)
|
|
1479
|
+
})),
|
|
1480
|
+
radioGroupProps: "radioProps" in fieldConfig ? fieldConfig.radioProps : void 0
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
case "switch": {
|
|
1485
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1486
|
+
SwitchField,
|
|
1487
|
+
{
|
|
1488
|
+
...baseProps,
|
|
1489
|
+
name: fieldConfig.name,
|
|
1490
|
+
control,
|
|
1491
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1492
|
+
switchProps: "switchProps" in fieldConfig ? fieldConfig.switchProps : void 0
|
|
1493
|
+
}
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
case "slider": {
|
|
1497
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1498
|
+
SliderField,
|
|
1499
|
+
{
|
|
1500
|
+
...baseProps,
|
|
1501
|
+
name: fieldConfig.name,
|
|
1502
|
+
control,
|
|
1503
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1504
|
+
sliderProps: "sliderProps" in fieldConfig ? fieldConfig.sliderProps : void 0
|
|
1505
|
+
}
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
case "stringArray": {
|
|
1509
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1510
|
+
StringArrayField,
|
|
1511
|
+
{
|
|
1512
|
+
...baseProps,
|
|
1513
|
+
name: fieldConfig.name,
|
|
1514
|
+
control,
|
|
1515
|
+
stringArrayProps: "stringArrayProps" in fieldConfig ? fieldConfig.stringArrayProps : void 0,
|
|
1516
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
case "date": {
|
|
1521
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1522
|
+
DateField,
|
|
1523
|
+
{
|
|
1524
|
+
...baseProps,
|
|
1525
|
+
name: fieldConfig.name,
|
|
1526
|
+
control,
|
|
1527
|
+
dateProps: "dateProps" in fieldConfig ? fieldConfig.dateProps : void 0,
|
|
1528
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1529
|
+
}
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
case "file": {
|
|
1533
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1534
|
+
FileField,
|
|
1535
|
+
{
|
|
1536
|
+
...baseProps,
|
|
1537
|
+
name: fieldConfig.name,
|
|
1538
|
+
accept: "accept" in fieldConfig ? fieldConfig.accept : void 0,
|
|
1539
|
+
control,
|
|
1540
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1541
|
+
fileProps: "fileProps" in fieldConfig ? fieldConfig.fileProps : void 0,
|
|
1542
|
+
multiple: "multiple" in fieldConfig ? fieldConfig.multiple : void 0
|
|
1543
|
+
}
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
case "fontPicker": {
|
|
1547
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1548
|
+
FontPickerField,
|
|
1549
|
+
{
|
|
1550
|
+
...baseProps,
|
|
1551
|
+
name: fieldConfig.name,
|
|
1552
|
+
control,
|
|
1553
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1554
|
+
fontPickerProps: "fontPickerProps" in fieldConfig ? fieldConfig.fontPickerProps : void 0
|
|
1555
|
+
}
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
case "custom": {
|
|
1559
|
+
if (!("render" in fieldConfig)) {
|
|
1055
1560
|
return null;
|
|
1056
1561
|
}
|
|
1562
|
+
return fieldConfig.render({
|
|
1563
|
+
control,
|
|
1564
|
+
errors: form.formState.errors,
|
|
1565
|
+
form,
|
|
1566
|
+
isSubmitting: submissionState.isSubmitting,
|
|
1567
|
+
name: fieldConfig.name
|
|
1568
|
+
});
|
|
1057
1569
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
defaultValue: config.defaultValue,
|
|
1076
|
-
inputProps: config.inputProps
|
|
1077
|
-
}
|
|
1078
|
-
);
|
|
1079
|
-
case "textarea":
|
|
1080
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1081
|
-
TextareaField,
|
|
1082
|
-
{
|
|
1083
|
-
...baseProps,
|
|
1084
|
-
control,
|
|
1085
|
-
defaultValue: config.defaultValue,
|
|
1086
|
-
textareaProps: config.textareaProps
|
|
1087
|
-
}
|
|
1088
|
-
);
|
|
1089
|
-
case "select":
|
|
1090
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1091
|
-
SelectField,
|
|
1092
|
-
{
|
|
1093
|
-
...baseProps,
|
|
1094
|
-
control,
|
|
1095
|
-
defaultValue: config.defaultValue,
|
|
1096
|
-
options: (config.options ?? []).map((opt) => ({
|
|
1097
|
-
label: opt.label,
|
|
1098
|
-
value: String(opt.value)
|
|
1099
|
-
})),
|
|
1100
|
-
selectProps: config.selectProps
|
|
1101
|
-
}
|
|
1102
|
-
);
|
|
1103
|
-
case "autocomplete":
|
|
1104
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1105
|
-
AutocompleteField,
|
|
1106
|
-
{
|
|
1107
|
-
...baseProps,
|
|
1108
|
-
control,
|
|
1109
|
-
defaultValue: config.defaultValue,
|
|
1110
|
-
items: (config.options ?? []).map((opt) => ({
|
|
1111
|
-
label: opt.label,
|
|
1112
|
-
value: String(opt.value)
|
|
1113
|
-
})),
|
|
1114
|
-
autocompleteProps: config.autocompleteProps
|
|
1115
|
-
}
|
|
1116
|
-
);
|
|
1117
|
-
case "checkbox":
|
|
1118
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1119
|
-
CheckboxField,
|
|
1120
|
-
{
|
|
1121
|
-
...baseProps,
|
|
1122
|
-
checkboxProps: config.checkboxProps,
|
|
1123
|
-
control,
|
|
1124
|
-
defaultValue: config.defaultValue
|
|
1125
|
-
}
|
|
1126
|
-
);
|
|
1127
|
-
case "radio":
|
|
1128
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1129
|
-
RadioGroupField,
|
|
1130
|
-
{
|
|
1131
|
-
...baseProps,
|
|
1132
|
-
control,
|
|
1133
|
-
defaultValue: config.defaultValue,
|
|
1134
|
-
options: (config.radioOptions ?? []).map((opt) => ({
|
|
1135
|
-
label: opt.label,
|
|
1136
|
-
value: String(opt.value)
|
|
1137
|
-
})),
|
|
1138
|
-
radioGroupProps: config.radioProps
|
|
1139
|
-
}
|
|
1140
|
-
);
|
|
1141
|
-
case "switch":
|
|
1142
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1143
|
-
SwitchField,
|
|
1144
|
-
{
|
|
1145
|
-
...baseProps,
|
|
1146
|
-
control,
|
|
1147
|
-
defaultValue: config.defaultValue,
|
|
1148
|
-
switchProps: config.switchProps
|
|
1149
|
-
}
|
|
1150
|
-
);
|
|
1151
|
-
case "slider":
|
|
1152
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1153
|
-
SliderField,
|
|
1154
|
-
{
|
|
1155
|
-
...baseProps,
|
|
1156
|
-
control,
|
|
1157
|
-
defaultValue: config.defaultValue,
|
|
1158
|
-
sliderProps: config.sliderProps
|
|
1159
|
-
}
|
|
1160
|
-
);
|
|
1161
|
-
case "date":
|
|
1162
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1163
|
-
DateField,
|
|
1164
|
-
{
|
|
1165
|
-
...baseProps,
|
|
1166
|
-
control,
|
|
1167
|
-
dateProps: config.dateProps,
|
|
1168
|
-
defaultValue: config.defaultValue
|
|
1169
|
-
}
|
|
1170
|
-
);
|
|
1171
|
-
case "file":
|
|
1172
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1173
|
-
FileField,
|
|
1174
|
-
{
|
|
1175
|
-
...baseProps,
|
|
1176
|
-
accept: config.accept,
|
|
1177
|
-
control,
|
|
1178
|
-
defaultValue: config.defaultValue,
|
|
1179
|
-
fileProps: config.fileProps,
|
|
1180
|
-
multiple: config.multiple
|
|
1181
|
-
}
|
|
1182
|
-
);
|
|
1183
|
-
case "fontPicker":
|
|
1184
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1185
|
-
FontPickerField,
|
|
1186
|
-
{
|
|
1187
|
-
...baseProps,
|
|
1188
|
-
control,
|
|
1189
|
-
defaultValue: config.defaultValue,
|
|
1190
|
-
fontPickerProps: config.fontPickerProps
|
|
1191
|
-
}
|
|
1192
|
-
);
|
|
1193
|
-
case "custom":
|
|
1194
|
-
return config.render({
|
|
1570
|
+
case "conditional": {
|
|
1571
|
+
if (!("condition" in fieldConfig) || !("field" in fieldConfig)) {
|
|
1572
|
+
return null;
|
|
1573
|
+
}
|
|
1574
|
+
const conditionalConfig = {
|
|
1575
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1576
|
+
condition: fieldConfig.condition,
|
|
1577
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1578
|
+
field: fieldConfig.field,
|
|
1579
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1580
|
+
name: fieldConfig.name,
|
|
1581
|
+
type: "conditional"
|
|
1582
|
+
};
|
|
1583
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1584
|
+
ConditionalField,
|
|
1585
|
+
{
|
|
1586
|
+
config: conditionalConfig,
|
|
1195
1587
|
control,
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
return
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1588
|
+
className: conditionalConfig.className
|
|
1589
|
+
}
|
|
1590
|
+
);
|
|
1591
|
+
}
|
|
1592
|
+
case "fieldArray": {
|
|
1593
|
+
if (!("fields" in fieldConfig) || !fieldConfig.fields) {
|
|
1594
|
+
return null;
|
|
1595
|
+
}
|
|
1596
|
+
const fieldArrayConfig = {
|
|
1597
|
+
addButtonText: "addButtonText" in fieldConfig ? fieldConfig.addButtonText : void 0,
|
|
1598
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1599
|
+
defaultItem: "defaultItem" in fieldConfig ? fieldConfig.defaultItem : void 0,
|
|
1600
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1601
|
+
enableReordering: "enableReordering" in fieldConfig ? fieldConfig.enableReordering : void 0,
|
|
1602
|
+
fields: fieldConfig.fields,
|
|
1603
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1604
|
+
max: "max" in fieldConfig ? fieldConfig.max : void 0,
|
|
1605
|
+
min: "min" in fieldConfig ? fieldConfig.min : void 0,
|
|
1606
|
+
name: fieldConfig.name,
|
|
1607
|
+
removeButtonText: "removeButtonText" in fieldConfig ? fieldConfig.removeButtonText : void 0,
|
|
1608
|
+
renderAddButton: "renderAddButton" in fieldConfig ? fieldConfig.renderAddButton : void 0,
|
|
1609
|
+
renderItem: "renderItem" in fieldConfig ? fieldConfig.renderItem : void 0,
|
|
1610
|
+
reorderButtonText: "reorderButtonText" in fieldConfig ? fieldConfig.reorderButtonText : void 0,
|
|
1611
|
+
type: "fieldArray"
|
|
1612
|
+
};
|
|
1613
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1614
|
+
FieldArrayField,
|
|
1615
|
+
{
|
|
1616
|
+
config: fieldArrayConfig,
|
|
1617
|
+
className: fieldArrayConfig.className
|
|
1618
|
+
}
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
case "dynamicSection": {
|
|
1622
|
+
if (!("sections" in fieldConfig) || !("condition" in fieldConfig) || !("fields" in fieldConfig)) {
|
|
1230
1623
|
return null;
|
|
1231
1624
|
}
|
|
1625
|
+
const dynamicSectionConfig = {
|
|
1626
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1627
|
+
condition: fieldConfig.condition,
|
|
1628
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1629
|
+
fields: fieldConfig.fields,
|
|
1630
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1631
|
+
name: fieldConfig.name,
|
|
1632
|
+
title: "title" in fieldConfig ? fieldConfig.title : void 0,
|
|
1633
|
+
type: "dynamicSection"
|
|
1634
|
+
};
|
|
1635
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1636
|
+
DynamicSectionField,
|
|
1637
|
+
{
|
|
1638
|
+
config: dynamicSectionConfig,
|
|
1639
|
+
control,
|
|
1640
|
+
className: dynamicSectionConfig.className
|
|
1641
|
+
}
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
default: {
|
|
1645
|
+
const fieldType = "type" in config ? config.type : "unknown";
|
|
1646
|
+
console.warn(`Unknown field type: ${fieldType}`);
|
|
1647
|
+
return null;
|
|
1232
1648
|
}
|
|
1233
1649
|
}
|
|
1234
|
-
|
|
1650
|
+
}
|
|
1651
|
+
var FormField = FormFieldComponent;
|
|
1235
1652
|
|
|
1236
1653
|
// src/components/Form.tsx
|
|
1237
1654
|
function ConfigurableForm({
|
|
@@ -1268,12 +1685,12 @@ function ConfigurableForm({
|
|
|
1268
1685
|
});
|
|
1269
1686
|
const renderFields = () => {
|
|
1270
1687
|
if (layout === "grid") {
|
|
1271
|
-
return /* @__PURE__ */
|
|
1688
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1272
1689
|
"div",
|
|
1273
1690
|
{
|
|
1274
1691
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
1275
1692
|
},
|
|
1276
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1693
|
+
fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1277
1694
|
FormField,
|
|
1278
1695
|
{
|
|
1279
1696
|
key: field2.name,
|
|
@@ -1285,7 +1702,7 @@ function ConfigurableForm({
|
|
|
1285
1702
|
);
|
|
1286
1703
|
}
|
|
1287
1704
|
if (layout === "horizontal") {
|
|
1288
|
-
return /* @__PURE__ */
|
|
1705
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1289
1706
|
FormField,
|
|
1290
1707
|
{
|
|
1291
1708
|
key: field2.name,
|
|
@@ -1295,10 +1712,10 @@ function ConfigurableForm({
|
|
|
1295
1712
|
}
|
|
1296
1713
|
)));
|
|
1297
1714
|
}
|
|
1298
|
-
return /* @__PURE__ */
|
|
1715
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1299
1716
|
FormField,
|
|
1300
1717
|
{
|
|
1301
|
-
key: field2.name
|
|
1718
|
+
key: field2.name ? pathToString(field2.name) : `field-${Math.random()}`,
|
|
1302
1719
|
config: field2,
|
|
1303
1720
|
form,
|
|
1304
1721
|
submissionState
|
|
@@ -1309,23 +1726,23 @@ function ConfigurableForm({
|
|
|
1309
1726
|
e.preventDefault();
|
|
1310
1727
|
void handleSubmit();
|
|
1311
1728
|
};
|
|
1312
|
-
return /* @__PURE__ */
|
|
1729
|
+
return /* @__PURE__ */ React20.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React20.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React20.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React20.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React20.createElement(
|
|
1313
1730
|
"div",
|
|
1314
1731
|
{
|
|
1315
1732
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1316
1733
|
"data-testid": "success-message"
|
|
1317
1734
|
},
|
|
1318
|
-
/* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
), error && /* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1736
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
|
|
1737
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
1321
1738
|
"div",
|
|
1322
1739
|
{
|
|
1323
1740
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1324
1741
|
"data-testid": "error-message"
|
|
1325
1742
|
},
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
), renderFields(), /* @__PURE__ */
|
|
1743
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1744
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
|
|
1745
|
+
), renderFields(), /* @__PURE__ */ React20.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React20.createElement(
|
|
1329
1746
|
Button3,
|
|
1330
1747
|
{
|
|
1331
1748
|
color: "primary",
|
|
@@ -1335,7 +1752,7 @@ function ConfigurableForm({
|
|
|
1335
1752
|
...submitButtonProps
|
|
1336
1753
|
},
|
|
1337
1754
|
submitButtonText
|
|
1338
|
-
), showResetButton && /* @__PURE__ */
|
|
1755
|
+
), showResetButton && /* @__PURE__ */ React20.createElement(
|
|
1339
1756
|
Button3,
|
|
1340
1757
|
{
|
|
1341
1758
|
isDisabled: isSubmitting,
|
|
@@ -1348,7 +1765,7 @@ function ConfigurableForm({
|
|
|
1348
1765
|
}
|
|
1349
1766
|
|
|
1350
1767
|
// src/components/ServerActionForm.tsx
|
|
1351
|
-
import
|
|
1768
|
+
import React21 from "react";
|
|
1352
1769
|
import { useActionState } from "react";
|
|
1353
1770
|
function ServerActionForm({
|
|
1354
1771
|
action,
|
|
@@ -1373,10 +1790,10 @@ function ServerActionForm({
|
|
|
1373
1790
|
action,
|
|
1374
1791
|
initialState ?? { errors: void 0, message: void 0, success: false }
|
|
1375
1792
|
);
|
|
1376
|
-
const formRef =
|
|
1377
|
-
const [clientErrors, setClientErrors] =
|
|
1378
|
-
const lastSubmittedFormData =
|
|
1379
|
-
|
|
1793
|
+
const formRef = React21.useRef(null);
|
|
1794
|
+
const [clientErrors, setClientErrors] = React21.useState({});
|
|
1795
|
+
const lastSubmittedFormData = React21.useRef(null);
|
|
1796
|
+
React21.useEffect(() => {
|
|
1380
1797
|
if (state && (state.errors || state.message && !state.success)) {
|
|
1381
1798
|
onError?.({
|
|
1382
1799
|
errors: state.errors,
|
|
@@ -1384,7 +1801,7 @@ function ServerActionForm({
|
|
|
1384
1801
|
});
|
|
1385
1802
|
}
|
|
1386
1803
|
}, [state, onError]);
|
|
1387
|
-
|
|
1804
|
+
React21.useEffect(() => {
|
|
1388
1805
|
if (state?.success && lastSubmittedFormData.current) {
|
|
1389
1806
|
onSuccess?.(lastSubmittedFormData.current);
|
|
1390
1807
|
}
|
|
@@ -1397,14 +1814,14 @@ function ServerActionForm({
|
|
|
1397
1814
|
e.preventDefault();
|
|
1398
1815
|
if (clientValidationSchema) {
|
|
1399
1816
|
const formData2 = new FormData(e.currentTarget);
|
|
1817
|
+
const form = e.currentTarget;
|
|
1400
1818
|
const values = {};
|
|
1401
1819
|
formData2.forEach((val, key) => {
|
|
1402
|
-
|
|
1820
|
+
const formElement = form.querySelector(
|
|
1821
|
+
`input[type="checkbox"][name="${key}"], input[role="switch"][name="${key}"]`
|
|
1822
|
+
);
|
|
1823
|
+
if (formElement instanceof HTMLInputElement && (formElement.type === "checkbox" || formElement.getAttribute("role") === "switch")) {
|
|
1403
1824
|
values[key] = true;
|
|
1404
|
-
} else if (val === "") {
|
|
1405
|
-
if (!values[key]) {
|
|
1406
|
-
values[key] = false;
|
|
1407
|
-
}
|
|
1408
1825
|
} else {
|
|
1409
1826
|
values[key] = val;
|
|
1410
1827
|
}
|
|
@@ -1427,12 +1844,12 @@ function ServerActionForm({
|
|
|
1427
1844
|
};
|
|
1428
1845
|
const renderFields = () => {
|
|
1429
1846
|
if (layout === "grid") {
|
|
1430
|
-
return /* @__PURE__ */
|
|
1847
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1431
1848
|
"div",
|
|
1432
1849
|
{
|
|
1433
1850
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
1434
1851
|
},
|
|
1435
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1852
|
+
fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1436
1853
|
ServerActionField,
|
|
1437
1854
|
{
|
|
1438
1855
|
key: field2.name,
|
|
@@ -1445,7 +1862,7 @@ function ServerActionForm({
|
|
|
1445
1862
|
);
|
|
1446
1863
|
}
|
|
1447
1864
|
if (layout === "horizontal") {
|
|
1448
|
-
return /* @__PURE__ */
|
|
1865
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1449
1866
|
ServerActionField,
|
|
1450
1867
|
{
|
|
1451
1868
|
key: field2.name,
|
|
@@ -1456,10 +1873,10 @@ function ServerActionForm({
|
|
|
1456
1873
|
}
|
|
1457
1874
|
)));
|
|
1458
1875
|
}
|
|
1459
|
-
return /* @__PURE__ */
|
|
1876
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1460
1877
|
ServerActionField,
|
|
1461
1878
|
{
|
|
1462
|
-
key: field2.name,
|
|
1879
|
+
key: pathToString(field2.name),
|
|
1463
1880
|
clientErrors,
|
|
1464
1881
|
defaultValues,
|
|
1465
1882
|
errors: state?.errors,
|
|
@@ -1467,7 +1884,7 @@ function ServerActionForm({
|
|
|
1467
1884
|
}
|
|
1468
1885
|
)));
|
|
1469
1886
|
};
|
|
1470
|
-
return /* @__PURE__ */
|
|
1887
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1471
1888
|
"form",
|
|
1472
1889
|
{
|
|
1473
1890
|
ref: formRef,
|
|
@@ -1475,27 +1892,27 @@ function ServerActionForm({
|
|
|
1475
1892
|
role: "form",
|
|
1476
1893
|
onSubmit: handleSubmit
|
|
1477
1894
|
},
|
|
1478
|
-
title && /* @__PURE__ */
|
|
1479
|
-
state?.success && !pending && /* @__PURE__ */
|
|
1895
|
+
title && /* @__PURE__ */ React21.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React21.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)),
|
|
1896
|
+
state?.success && !pending && /* @__PURE__ */ React21.createElement(
|
|
1480
1897
|
"div",
|
|
1481
1898
|
{
|
|
1482
1899
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1483
1900
|
"data-testid": "success-message"
|
|
1484
1901
|
},
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
state.message && /* @__PURE__ */
|
|
1902
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1903
|
+
state.message && /* @__PURE__ */ React21.createElement("p", { className: "text-success-700 text-sm mt-1" }, state.message)
|
|
1487
1904
|
),
|
|
1488
|
-
state?.message && !state.success && /* @__PURE__ */
|
|
1905
|
+
state?.message && !state.success && /* @__PURE__ */ React21.createElement(
|
|
1489
1906
|
"div",
|
|
1490
1907
|
{
|
|
1491
1908
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1492
1909
|
"data-testid": "error-message"
|
|
1493
1910
|
},
|
|
1494
|
-
/* @__PURE__ */
|
|
1495
|
-
/* @__PURE__ */
|
|
1911
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1912
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-700 text-sm mt-1" }, state.message)
|
|
1496
1913
|
),
|
|
1497
1914
|
renderFields(),
|
|
1498
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ React21.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React21.createElement(
|
|
1499
1916
|
Button,
|
|
1500
1917
|
{
|
|
1501
1918
|
color: "primary",
|
|
@@ -1505,7 +1922,7 @@ function ServerActionForm({
|
|
|
1505
1922
|
...submitButtonProps
|
|
1506
1923
|
},
|
|
1507
1924
|
submitButtonText
|
|
1508
|
-
), showResetButton && /* @__PURE__ */
|
|
1925
|
+
), showResetButton && /* @__PURE__ */ React21.createElement(
|
|
1509
1926
|
Button,
|
|
1510
1927
|
{
|
|
1511
1928
|
isDisabled: pending,
|
|
@@ -1523,24 +1940,44 @@ function ServerActionField({
|
|
|
1523
1940
|
errors,
|
|
1524
1941
|
field: field2
|
|
1525
1942
|
}) {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1943
|
+
const fieldConfig = field2;
|
|
1944
|
+
const getBaseProps = () => {
|
|
1945
|
+
const baseProps2 = {};
|
|
1946
|
+
if ("label" in fieldConfig) {
|
|
1947
|
+
baseProps2.label = fieldConfig.label;
|
|
1948
|
+
}
|
|
1949
|
+
if ("description" in fieldConfig) {
|
|
1950
|
+
baseProps2.description = fieldConfig.description;
|
|
1951
|
+
}
|
|
1952
|
+
if ("isDisabled" in fieldConfig) {
|
|
1953
|
+
baseProps2.isDisabled = fieldConfig.isDisabled;
|
|
1954
|
+
}
|
|
1955
|
+
return baseProps2;
|
|
1956
|
+
};
|
|
1957
|
+
const baseProps = getBaseProps();
|
|
1958
|
+
if (fieldConfig.type === "content") {
|
|
1959
|
+
const contentField = fieldConfig;
|
|
1960
|
+
if (contentField.render) {
|
|
1961
|
+
const mockForm = {
|
|
1962
|
+
formState: { errors: {} },
|
|
1963
|
+
watch: () => ({})
|
|
1964
|
+
};
|
|
1965
|
+
const renderFn = contentField.render;
|
|
1966
|
+
return /* @__PURE__ */ React21.createElement("div", { className: contentField.className }, renderFn({
|
|
1530
1967
|
errors: {},
|
|
1531
|
-
form:
|
|
1968
|
+
form: mockForm,
|
|
1532
1969
|
isSubmitting: false
|
|
1533
1970
|
}));
|
|
1534
1971
|
}
|
|
1535
|
-
return /* @__PURE__ */
|
|
1972
|
+
return /* @__PURE__ */ React21.createElement("div", { className: contentField.className }, contentField.title && /* @__PURE__ */ React21.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, contentField.title), contentField.description && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-muted-foreground" }, contentField.description));
|
|
1536
1973
|
}
|
|
1537
|
-
const fieldName =
|
|
1974
|
+
const fieldName = pathToString(fieldConfig.name);
|
|
1538
1975
|
const fieldErrors = errors?.[fieldName];
|
|
1539
1976
|
const clientError = clientErrors?.[fieldName];
|
|
1540
1977
|
const errorMessage = clientError || (fieldErrors && fieldErrors.length > 0 ? fieldErrors[0] : void 0);
|
|
1541
1978
|
const getDefaultValue = () => {
|
|
1542
1979
|
const fromProps = defaultValues?.[fieldName];
|
|
1543
|
-
const fromField =
|
|
1980
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1544
1981
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1545
1982
|
return typeof fromProps === "string" ? fromProps : String(fromProps);
|
|
1546
1983
|
}
|
|
@@ -1551,7 +1988,7 @@ function ServerActionField({
|
|
|
1551
1988
|
};
|
|
1552
1989
|
const getDefaultChecked = () => {
|
|
1553
1990
|
const fromProps = defaultValues?.[fieldName];
|
|
1554
|
-
const fromField =
|
|
1991
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1555
1992
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1556
1993
|
return typeof fromProps === "boolean" ? fromProps : false;
|
|
1557
1994
|
}
|
|
@@ -1560,121 +1997,326 @@ function ServerActionField({
|
|
|
1560
1997
|
}
|
|
1561
1998
|
return false;
|
|
1562
1999
|
};
|
|
1563
|
-
const [value, setValue] =
|
|
1564
|
-
const [checked, setChecked] =
|
|
1565
|
-
|
|
2000
|
+
const [value, setValue] = React21.useState(getDefaultValue);
|
|
2001
|
+
const [checked, setChecked] = React21.useState(getDefaultChecked);
|
|
2002
|
+
React21.useEffect(() => {
|
|
1566
2003
|
const newDefaultValue = defaultValues?.[fieldName];
|
|
1567
2004
|
if (newDefaultValue !== void 0 && newDefaultValue !== null) {
|
|
1568
|
-
if (
|
|
2005
|
+
if (fieldConfig.type === "checkbox") {
|
|
1569
2006
|
setChecked(
|
|
1570
2007
|
typeof newDefaultValue === "boolean" ? newDefaultValue : false
|
|
1571
2008
|
);
|
|
2009
|
+
} else if (fieldConfig.type === "checkboxGroup") {
|
|
2010
|
+
const arrayValue = Array.isArray(newDefaultValue) ? newDefaultValue.map(String).join(",") : "";
|
|
2011
|
+
setValue(arrayValue);
|
|
1572
2012
|
} else {
|
|
1573
2013
|
setValue(
|
|
1574
2014
|
typeof newDefaultValue === "string" ? newDefaultValue : String(newDefaultValue)
|
|
1575
2015
|
);
|
|
1576
2016
|
}
|
|
1577
2017
|
}
|
|
1578
|
-
}, [defaultValues, fieldName,
|
|
1579
|
-
|
|
2018
|
+
}, [defaultValues, fieldName, fieldConfig.type]);
|
|
2019
|
+
React21.useEffect(() => {
|
|
2020
|
+
if (fieldConfig.type !== "date") {
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
1580
2023
|
const hiddenInput = document.querySelector(
|
|
1581
2024
|
`input[type="hidden"][name="${fieldName}"]`
|
|
1582
2025
|
);
|
|
2026
|
+
if (!(hiddenInput instanceof HTMLInputElement)) {
|
|
2027
|
+
throw new Error(`Expected HTMLInputElement for field ${fieldName}`);
|
|
2028
|
+
}
|
|
1583
2029
|
if (hiddenInput) {
|
|
1584
|
-
|
|
1585
|
-
hiddenInput.value = checked ? "on" : "";
|
|
1586
|
-
} else {
|
|
1587
|
-
hiddenInput.value = value;
|
|
1588
|
-
}
|
|
2030
|
+
hiddenInput.value = value || "";
|
|
1589
2031
|
}
|
|
1590
|
-
}, [value,
|
|
1591
|
-
switch (
|
|
2032
|
+
}, [value, fieldName, fieldConfig.type]);
|
|
2033
|
+
switch (fieldConfig.type) {
|
|
1592
2034
|
case "input": {
|
|
1593
|
-
const
|
|
1594
|
-
|
|
2035
|
+
const stringConfig = fieldConfig;
|
|
2036
|
+
const inputType = stringConfig.inputProps?.type || "text";
|
|
2037
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1595
2038
|
Input,
|
|
1596
2039
|
{
|
|
1597
|
-
...
|
|
2040
|
+
...stringConfig.inputProps,
|
|
2041
|
+
name: fieldName,
|
|
2042
|
+
"data-field-name": fieldName,
|
|
2043
|
+
type: inputType,
|
|
2044
|
+
label: baseProps.label,
|
|
2045
|
+
description: baseProps.description,
|
|
2046
|
+
isDisabled: baseProps.isDisabled,
|
|
2047
|
+
isInvalid: Boolean(errorMessage),
|
|
2048
|
+
errorMessage,
|
|
2049
|
+
value,
|
|
2050
|
+
onValueChange: setValue
|
|
2051
|
+
}
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
case "textarea": {
|
|
2055
|
+
const stringConfig = fieldConfig;
|
|
2056
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2057
|
+
Textarea,
|
|
2058
|
+
{
|
|
2059
|
+
...stringConfig.textareaProps,
|
|
2060
|
+
name: fieldName,
|
|
2061
|
+
"data-field-name": fieldName,
|
|
2062
|
+
label: baseProps.label,
|
|
2063
|
+
description: baseProps.description,
|
|
2064
|
+
isDisabled: baseProps.isDisabled,
|
|
2065
|
+
isInvalid: Boolean(errorMessage),
|
|
2066
|
+
errorMessage,
|
|
2067
|
+
value,
|
|
2068
|
+
onValueChange: setValue
|
|
2069
|
+
}
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2072
|
+
case "checkbox": {
|
|
2073
|
+
const booleanConfig = fieldConfig;
|
|
2074
|
+
const checkboxValue = booleanConfig.checkboxProps?.value ?? "on";
|
|
2075
|
+
const containerRef = React21.useRef(null);
|
|
2076
|
+
React21.useLayoutEffect(() => {
|
|
2077
|
+
const setValue2 = () => {
|
|
2078
|
+
if (containerRef.current) {
|
|
2079
|
+
const input = containerRef.current.querySelector(
|
|
2080
|
+
`input[type="checkbox"][name="${fieldName}"]`
|
|
2081
|
+
);
|
|
2082
|
+
if (input instanceof HTMLInputElement) {
|
|
2083
|
+
input.setAttribute("value", checkboxValue);
|
|
2084
|
+
input.value = checkboxValue;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
};
|
|
2088
|
+
setValue2();
|
|
2089
|
+
const timeoutId = setTimeout(setValue2, 0);
|
|
2090
|
+
return () => clearTimeout(timeoutId);
|
|
2091
|
+
}, [fieldName, checkboxValue, checked]);
|
|
2092
|
+
return /* @__PURE__ */ React21.createElement("div", { ref: containerRef }, /* @__PURE__ */ React21.createElement(
|
|
2093
|
+
Checkbox,
|
|
2094
|
+
{
|
|
2095
|
+
...booleanConfig.checkboxProps,
|
|
2096
|
+
name: fieldName,
|
|
2097
|
+
"data-field-name": fieldName,
|
|
2098
|
+
value: checkboxValue,
|
|
2099
|
+
isDisabled: baseProps.isDisabled,
|
|
2100
|
+
isSelected: checked,
|
|
2101
|
+
onValueChange: setChecked,
|
|
2102
|
+
isInvalid: Boolean(errorMessage),
|
|
2103
|
+
errorMessage
|
|
2104
|
+
},
|
|
2105
|
+
baseProps.label
|
|
2106
|
+
));
|
|
2107
|
+
}
|
|
2108
|
+
case "checkboxGroup": {
|
|
2109
|
+
const checkboxGroupConfig = fieldConfig;
|
|
2110
|
+
const options = checkboxGroupConfig.checkboxGroupOptions || [];
|
|
2111
|
+
const currentValues = value ? String(value).split(",").filter(Boolean) : [];
|
|
2112
|
+
return /* @__PURE__ */ React21.createElement("div", null, baseProps.label && /* @__PURE__ */ React21.createElement("label", { className: "text-sm font-medium text-foreground block mb-2" }, baseProps.label), baseProps.description && /* @__PURE__ */ React21.createElement("p", { className: "text-sm text-default-500 mb-2" }, baseProps.description), /* @__PURE__ */ React21.createElement(
|
|
2113
|
+
"div",
|
|
2114
|
+
{
|
|
2115
|
+
className: checkboxGroupConfig.orientation === "horizontal" ? "flex flex-row gap-4 flex-wrap" : "flex flex-col gap-2"
|
|
2116
|
+
},
|
|
2117
|
+
options.map(
|
|
2118
|
+
(option) => {
|
|
2119
|
+
const optionValue = String(option.value);
|
|
2120
|
+
const isSelected = currentValues.includes(optionValue);
|
|
2121
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2122
|
+
Checkbox,
|
|
2123
|
+
{
|
|
2124
|
+
key: optionValue,
|
|
2125
|
+
...checkboxGroupConfig.checkboxProps,
|
|
2126
|
+
name: fieldName,
|
|
2127
|
+
"data-field-name": fieldName,
|
|
2128
|
+
"data-checkbox-value": optionValue,
|
|
2129
|
+
isDisabled: baseProps.isDisabled,
|
|
2130
|
+
isSelected,
|
|
2131
|
+
onValueChange: (checked2) => {
|
|
2132
|
+
const newValues = checked2 ? [
|
|
2133
|
+
...currentValues.filter((v) => v !== optionValue),
|
|
2134
|
+
optionValue
|
|
2135
|
+
] : currentValues.filter((v) => v !== optionValue);
|
|
2136
|
+
setValue(newValues.join(","));
|
|
2137
|
+
},
|
|
2138
|
+
isInvalid: Boolean(errorMessage),
|
|
2139
|
+
errorMessage
|
|
2140
|
+
},
|
|
2141
|
+
option.label
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
2144
|
+
)
|
|
2145
|
+
), errorMessage && /* @__PURE__ */ React21.createElement("p", { className: "text-tiny text-danger mt-1" }, errorMessage));
|
|
2146
|
+
}
|
|
2147
|
+
case "switch": {
|
|
2148
|
+
const booleanConfig = fieldConfig;
|
|
2149
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2150
|
+
Switch,
|
|
2151
|
+
{
|
|
2152
|
+
...booleanConfig.switchProps,
|
|
2153
|
+
name: fieldName,
|
|
2154
|
+
"data-field-name": fieldName,
|
|
2155
|
+
isDisabled: baseProps.isDisabled,
|
|
2156
|
+
isSelected: checked,
|
|
2157
|
+
onValueChange: setChecked,
|
|
2158
|
+
isInvalid: Boolean(errorMessage),
|
|
2159
|
+
errorMessage
|
|
2160
|
+
},
|
|
2161
|
+
baseProps.label
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
case "select": {
|
|
2165
|
+
const stringConfig = fieldConfig;
|
|
2166
|
+
const options = stringConfig.options || [];
|
|
2167
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2168
|
+
Select,
|
|
2169
|
+
{
|
|
2170
|
+
...stringConfig.selectProps,
|
|
2171
|
+
name: fieldName,
|
|
2172
|
+
"data-field-name": fieldName,
|
|
2173
|
+
label: baseProps.label,
|
|
2174
|
+
description: baseProps.description,
|
|
2175
|
+
isDisabled: baseProps.isDisabled,
|
|
2176
|
+
isInvalid: Boolean(errorMessage),
|
|
2177
|
+
errorMessage,
|
|
2178
|
+
selectedKeys: value ? [value] : [],
|
|
2179
|
+
onSelectionChange: (keys) => {
|
|
2180
|
+
const selectedValue = Array.from(keys)[0];
|
|
2181
|
+
setValue(selectedValue || "");
|
|
2182
|
+
}
|
|
2183
|
+
},
|
|
2184
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(SelectItem, { key: String(option.value) }, option.label))
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
case "radio": {
|
|
2188
|
+
const radioConfig = fieldConfig;
|
|
2189
|
+
const options = radioConfig.radioOptions || [];
|
|
2190
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2191
|
+
RadioGroup,
|
|
2192
|
+
{
|
|
2193
|
+
...radioConfig.radioProps,
|
|
2194
|
+
name: fieldName,
|
|
1598
2195
|
"data-field-name": fieldName,
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
isDisabled: field2.isDisabled,
|
|
2196
|
+
label: baseProps.label,
|
|
2197
|
+
description: baseProps.description,
|
|
2198
|
+
isDisabled: baseProps.isDisabled,
|
|
1603
2199
|
isInvalid: Boolean(errorMessage),
|
|
1604
2200
|
errorMessage,
|
|
1605
|
-
value,
|
|
2201
|
+
value: value || "",
|
|
1606
2202
|
onValueChange: setValue
|
|
1607
|
-
}
|
|
1608
|
-
|
|
2203
|
+
},
|
|
2204
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(Radio, { key: String(option.value), value: String(option.value) }, option.label))
|
|
2205
|
+
);
|
|
1609
2206
|
}
|
|
1610
|
-
case "
|
|
1611
|
-
|
|
1612
|
-
|
|
2207
|
+
case "autocomplete": {
|
|
2208
|
+
const stringConfig = fieldConfig;
|
|
2209
|
+
const items = stringConfig.options?.map((opt) => ({
|
|
2210
|
+
label: opt.label,
|
|
2211
|
+
value: String(opt.value)
|
|
2212
|
+
})) || [];
|
|
2213
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2214
|
+
Autocomplete,
|
|
1613
2215
|
{
|
|
1614
|
-
...
|
|
2216
|
+
...stringConfig.autocompleteProps,
|
|
2217
|
+
name: fieldName,
|
|
1615
2218
|
"data-field-name": fieldName,
|
|
1616
|
-
label:
|
|
1617
|
-
description:
|
|
1618
|
-
isDisabled:
|
|
2219
|
+
label: baseProps.label,
|
|
2220
|
+
description: baseProps.description,
|
|
2221
|
+
isDisabled: baseProps.isDisabled,
|
|
1619
2222
|
isInvalid: Boolean(errorMessage),
|
|
1620
2223
|
errorMessage,
|
|
1621
|
-
value,
|
|
1622
|
-
|
|
2224
|
+
selectedKey: value || null,
|
|
2225
|
+
inputValue: value || "",
|
|
2226
|
+
onSelectionChange: (key) => {
|
|
2227
|
+
setValue(key ? String(key) : "");
|
|
2228
|
+
},
|
|
2229
|
+
onInputChange: setValue,
|
|
2230
|
+
items
|
|
2231
|
+
},
|
|
2232
|
+
items.map((item) => /* @__PURE__ */ React21.createElement(AutocompleteItem, { key: String(item.value) }, item.label))
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
case "slider": {
|
|
2236
|
+
const sliderConfig = fieldConfig;
|
|
2237
|
+
const numValue = value ? Number(value) : 0;
|
|
2238
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2239
|
+
Slider,
|
|
2240
|
+
{
|
|
2241
|
+
...sliderConfig.sliderProps,
|
|
2242
|
+
name: fieldName,
|
|
2243
|
+
"data-field-name": fieldName,
|
|
2244
|
+
label: baseProps.label,
|
|
2245
|
+
description: baseProps.description,
|
|
2246
|
+
isDisabled: baseProps.isDisabled,
|
|
2247
|
+
value: numValue,
|
|
2248
|
+
onChange: (val) => {
|
|
2249
|
+
const newValue = Array.isArray(val) ? val[0] : val;
|
|
2250
|
+
setValue(String(newValue));
|
|
2251
|
+
}
|
|
1623
2252
|
}
|
|
1624
|
-
)
|
|
2253
|
+
);
|
|
1625
2254
|
}
|
|
1626
|
-
case "
|
|
1627
|
-
|
|
1628
|
-
|
|
2255
|
+
case "date": {
|
|
2256
|
+
const dateConfig = fieldConfig;
|
|
2257
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("input", { type: "hidden", name: fieldName, value: value || "" }), /* @__PURE__ */ React21.createElement(
|
|
2258
|
+
DateInput,
|
|
1629
2259
|
{
|
|
1630
|
-
...
|
|
2260
|
+
...dateConfig.dateProps,
|
|
1631
2261
|
"data-field-name": fieldName,
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
2262
|
+
label: baseProps.label,
|
|
2263
|
+
description: baseProps.description,
|
|
2264
|
+
isDisabled: baseProps.isDisabled,
|
|
1635
2265
|
isInvalid: Boolean(errorMessage),
|
|
1636
|
-
errorMessage
|
|
1637
|
-
|
|
1638
|
-
|
|
2266
|
+
errorMessage,
|
|
2267
|
+
value: value ? value : null,
|
|
2268
|
+
onChange: (date) => {
|
|
2269
|
+
const dateString = date ? `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}` : "";
|
|
2270
|
+
setValue(dateString);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
1639
2273
|
));
|
|
1640
2274
|
}
|
|
1641
|
-
case "
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
2275
|
+
case "file": {
|
|
2276
|
+
const fileConfig = fieldConfig;
|
|
2277
|
+
const multiple = fileConfig.multiple || false;
|
|
2278
|
+
const accept = fileConfig.accept;
|
|
2279
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
|
|
2280
|
+
Input,
|
|
1645
2281
|
{
|
|
1646
|
-
...
|
|
2282
|
+
...fileConfig.fileProps,
|
|
2283
|
+
name: fieldName,
|
|
1647
2284
|
"data-field-name": fieldName,
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
2285
|
+
type: "file",
|
|
2286
|
+
label: baseProps.label,
|
|
2287
|
+
description: baseProps.description,
|
|
2288
|
+
isDisabled: baseProps.isDisabled,
|
|
1651
2289
|
isInvalid: Boolean(errorMessage),
|
|
1652
2290
|
errorMessage,
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
2291
|
+
multiple,
|
|
2292
|
+
accept,
|
|
2293
|
+
onChange: (e) => {
|
|
2294
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
const target = e.target;
|
|
2298
|
+
if (target.files) {
|
|
2299
|
+
setValue(String(target.files.length));
|
|
2300
|
+
}
|
|
1657
2301
|
}
|
|
1658
|
-
}
|
|
1659
|
-
options.map(
|
|
1660
|
-
(option) => /* @__PURE__ */ React19.createElement(SelectItem, { key: String(option.value) }, option.label)
|
|
1661
|
-
)
|
|
2302
|
+
}
|
|
1662
2303
|
));
|
|
1663
2304
|
}
|
|
1664
2305
|
default:
|
|
1665
|
-
return /* @__PURE__ */
|
|
2306
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1666
2307
|
Input,
|
|
1667
2308
|
{
|
|
2309
|
+
name: fieldName,
|
|
1668
2310
|
"data-field-name": fieldName,
|
|
1669
|
-
label:
|
|
1670
|
-
description:
|
|
1671
|
-
isDisabled:
|
|
2311
|
+
label: baseProps.label,
|
|
2312
|
+
description: baseProps.description,
|
|
2313
|
+
isDisabled: baseProps.isDisabled,
|
|
1672
2314
|
isInvalid: Boolean(errorMessage),
|
|
1673
2315
|
errorMessage,
|
|
1674
2316
|
value,
|
|
1675
2317
|
onValueChange: setValue
|
|
1676
2318
|
}
|
|
1677
|
-
)
|
|
2319
|
+
);
|
|
1678
2320
|
}
|
|
1679
2321
|
}
|
|
1680
2322
|
|
|
@@ -1692,10 +2334,10 @@ function useHeroForm() {
|
|
|
1692
2334
|
}
|
|
1693
2335
|
|
|
1694
2336
|
// src/providers/FormProvider.tsx
|
|
1695
|
-
import
|
|
2337
|
+
import React22 from "react";
|
|
1696
2338
|
import { FormProvider as RHFProvider } from "react-hook-form";
|
|
1697
2339
|
function FormProvider(props) {
|
|
1698
|
-
return /* @__PURE__ */
|
|
2340
|
+
return /* @__PURE__ */ React22.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React22.createElement(
|
|
1699
2341
|
"form",
|
|
1700
2342
|
{
|
|
1701
2343
|
className: props.className,
|
|
@@ -1708,7 +2350,7 @@ function FormProvider(props) {
|
|
|
1708
2350
|
}
|
|
1709
2351
|
|
|
1710
2352
|
// src/submit/SubmitButton.tsx
|
|
1711
|
-
import
|
|
2353
|
+
import React23 from "react";
|
|
1712
2354
|
function SubmitButton(props) {
|
|
1713
2355
|
const ctx = useFormContext5();
|
|
1714
2356
|
const loading = props.isLoading ?? ctx.formState.isSubmitting;
|
|
@@ -1718,10 +2360,10 @@ function SubmitButton(props) {
|
|
|
1718
2360
|
const defaults = useHeroHookFormDefaults();
|
|
1719
2361
|
const getButtonContent = () => {
|
|
1720
2362
|
if (enhancedState?.isSuccess) {
|
|
1721
|
-
return /* @__PURE__ */
|
|
2363
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u2705", props.successText || "Success!");
|
|
1722
2364
|
}
|
|
1723
2365
|
if (loading) {
|
|
1724
|
-
return /* @__PURE__ */
|
|
2366
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u23F3", props.loadingText || "Submitting...");
|
|
1725
2367
|
}
|
|
1726
2368
|
return props.children;
|
|
1727
2369
|
};
|
|
@@ -1734,7 +2376,7 @@ function SubmitButton(props) {
|
|
|
1734
2376
|
}
|
|
1735
2377
|
return props.buttonProps?.color || defaults.submitButton.color;
|
|
1736
2378
|
};
|
|
1737
|
-
return /* @__PURE__ */
|
|
2379
|
+
return /* @__PURE__ */ React23.createElement(
|
|
1738
2380
|
Button,
|
|
1739
2381
|
{
|
|
1740
2382
|
type: "submit",
|
|
@@ -1975,7 +2617,7 @@ var commonValidations = {
|
|
|
1975
2617
|
import { useFormContext as useFormContext5 } from "react-hook-form";
|
|
1976
2618
|
|
|
1977
2619
|
// src/components/ZodForm.tsx
|
|
1978
|
-
import
|
|
2620
|
+
import React25 from "react";
|
|
1979
2621
|
import { Button as Button5 } from "@heroui/react";
|
|
1980
2622
|
import {
|
|
1981
2623
|
FormProvider as FormProvider2
|
|
@@ -1999,8 +2641,15 @@ function createZodResolver(schema) {
|
|
|
1999
2641
|
const path = err.path.join(".");
|
|
2000
2642
|
errors[path] = { message: err.message };
|
|
2001
2643
|
});
|
|
2644
|
+
const fieldErrors = {};
|
|
2645
|
+
Object.entries(errors).forEach(([path, error2]) => {
|
|
2646
|
+
fieldErrors[path] = error2;
|
|
2647
|
+
});
|
|
2002
2648
|
return {
|
|
2003
|
-
|
|
2649
|
+
// TypeScript can't prove all paths are valid field paths, but at runtime they will be
|
|
2650
|
+
// because Zod validates against the schema which matches T
|
|
2651
|
+
// This is a necessary type assertion due to TypeScript's limitations with dynamic paths
|
|
2652
|
+
errors: fieldErrors,
|
|
2004
2653
|
values: {}
|
|
2005
2654
|
};
|
|
2006
2655
|
}
|
|
@@ -2018,14 +2667,12 @@ function createZodFormConfig(schema, fields, defaultValues) {
|
|
|
2018
2667
|
return {
|
|
2019
2668
|
fields,
|
|
2020
2669
|
schema,
|
|
2021
|
-
...defaultValues && {
|
|
2022
|
-
defaultValues
|
|
2023
|
-
}
|
|
2670
|
+
...defaultValues && { defaultValues }
|
|
2024
2671
|
};
|
|
2025
2672
|
}
|
|
2026
2673
|
|
|
2027
2674
|
// src/hooks/useEnhancedFormState.ts
|
|
2028
|
-
import { useCallback, useEffect, useState as
|
|
2675
|
+
import { useCallback, useEffect, useState as useState3 } from "react";
|
|
2029
2676
|
function useEnhancedFormState(form, options = {}) {
|
|
2030
2677
|
const {
|
|
2031
2678
|
autoReset = true,
|
|
@@ -2037,9 +2684,9 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2037
2684
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2038
2685
|
successMessage: _successMessage = "Form submitted successfully!"
|
|
2039
2686
|
} = options;
|
|
2040
|
-
const [status, setStatus] =
|
|
2041
|
-
const [error, setError] =
|
|
2042
|
-
const [submittedData, setSubmittedData] =
|
|
2687
|
+
const [status, setStatus] = useState3("idle");
|
|
2688
|
+
const [error, setError] = useState3(void 0);
|
|
2689
|
+
const [submittedData, setSubmittedData] = useState3(void 0);
|
|
2043
2690
|
const { formState, getValues: _getValues } = form;
|
|
2044
2691
|
const { dirtyFields, errors, isSubmitting, touchedFields } = formState;
|
|
2045
2692
|
useEffect(() => {
|
|
@@ -2098,7 +2745,7 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2098
2745
|
}
|
|
2099
2746
|
|
|
2100
2747
|
// src/components/FormStatus.tsx
|
|
2101
|
-
import
|
|
2748
|
+
import React24 from "react";
|
|
2102
2749
|
import { Button as Button4 } from "@heroui/react";
|
|
2103
2750
|
function FormStatus({
|
|
2104
2751
|
className = "",
|
|
@@ -2111,25 +2758,25 @@ function FormStatus({
|
|
|
2111
2758
|
return null;
|
|
2112
2759
|
}
|
|
2113
2760
|
if (isSubmitting) {
|
|
2114
|
-
return /* @__PURE__ */
|
|
2761
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2115
2762
|
"div",
|
|
2116
2763
|
{
|
|
2117
2764
|
className: `flex items-center gap-3 p-4 bg-blue-50 border border-blue-200 rounded-lg ${className}`
|
|
2118
2765
|
},
|
|
2119
|
-
/* @__PURE__ */
|
|
2120
|
-
/* @__PURE__ */
|
|
2766
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-blue-600" }, "\u23F3"),
|
|
2767
|
+
/* @__PURE__ */ React24.createElement("div", null, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-blue-900" }, "Submitting form..."), showDetails && /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-blue-700" }, "Please wait while we process your request."))
|
|
2121
2768
|
);
|
|
2122
2769
|
}
|
|
2123
2770
|
if (isSuccess) {
|
|
2124
|
-
return /* @__PURE__ */
|
|
2771
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2125
2772
|
"div",
|
|
2126
2773
|
{
|
|
2127
2774
|
className: `flex items-center gap-3 p-4 bg-green-50 border border-green-200 rounded-lg ${className}`,
|
|
2128
2775
|
"data-testid": "success-message"
|
|
2129
2776
|
},
|
|
2130
|
-
/* @__PURE__ */
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
onDismiss && /* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-green-600" }, "\u2705"),
|
|
2778
|
+
/* @__PURE__ */ React24.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-green-900" }, "Form submitted successfully!"), showDetails && submittedData && /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-green-700" }, "Your data has been saved. Thank you for your submission.")),
|
|
2779
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2133
2780
|
Button4,
|
|
2134
2781
|
{
|
|
2135
2782
|
size: "sm",
|
|
@@ -2143,15 +2790,15 @@ function FormStatus({
|
|
|
2143
2790
|
);
|
|
2144
2791
|
}
|
|
2145
2792
|
if (isError && error) {
|
|
2146
|
-
return /* @__PURE__ */
|
|
2793
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2147
2794
|
"div",
|
|
2148
2795
|
{
|
|
2149
2796
|
className: `flex items-center gap-3 p-4 bg-red-50 border border-red-200 rounded-lg ${className}`,
|
|
2150
2797
|
"data-testid": "error-message"
|
|
2151
2798
|
},
|
|
2152
|
-
/* @__PURE__ */
|
|
2153
|
-
/* @__PURE__ */
|
|
2154
|
-
onDismiss && /* @__PURE__ */
|
|
2799
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-red-600" }, "\u26A0\uFE0F"),
|
|
2800
|
+
/* @__PURE__ */ React24.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React24.createElement("p", { className: "text-sm font-medium text-red-900" }, "Error submitting form"), /* @__PURE__ */ React24.createElement("p", { className: "text-xs text-red-700" }, error)),
|
|
2801
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2155
2802
|
Button4,
|
|
2156
2803
|
{
|
|
2157
2804
|
size: "sm",
|
|
@@ -2172,8 +2819,8 @@ function FormToast({
|
|
|
2172
2819
|
position = "top-right",
|
|
2173
2820
|
state
|
|
2174
2821
|
}) {
|
|
2175
|
-
const [isVisible, setIsVisible] =
|
|
2176
|
-
|
|
2822
|
+
const [isVisible, setIsVisible] = React24.useState(false);
|
|
2823
|
+
React24.useEffect(() => {
|
|
2177
2824
|
if (state.isSuccess || state.isError) {
|
|
2178
2825
|
setIsVisible(true);
|
|
2179
2826
|
if (duration > 0) {
|
|
@@ -2194,7 +2841,7 @@ function FormToast({
|
|
|
2194
2841
|
"top-left": "top-4 left-4",
|
|
2195
2842
|
"top-right": "top-4 right-4"
|
|
2196
2843
|
};
|
|
2197
|
-
return /* @__PURE__ */
|
|
2844
|
+
return /* @__PURE__ */ React24.createElement("div", { className: `fixed z-50 ${positionClasses[position]}` }, /* @__PURE__ */ React24.createElement(FormStatus, { state, onDismiss }));
|
|
2198
2845
|
}
|
|
2199
2846
|
|
|
2200
2847
|
// src/components/ZodForm.tsx
|
|
@@ -2214,7 +2861,10 @@ function ZodForm({
|
|
|
2214
2861
|
subtitle,
|
|
2215
2862
|
title
|
|
2216
2863
|
}) {
|
|
2217
|
-
const
|
|
2864
|
+
const formConfig = {
|
|
2865
|
+
...config
|
|
2866
|
+
};
|
|
2867
|
+
const form = useZodForm(formConfig);
|
|
2218
2868
|
const enhancedState = useEnhancedFormState(form, {
|
|
2219
2869
|
autoReset: true,
|
|
2220
2870
|
onError: (error) => onError?.({ field: "form", message: error }),
|
|
@@ -2244,12 +2894,12 @@ function ZodForm({
|
|
|
2244
2894
|
};
|
|
2245
2895
|
const renderFields = () => {
|
|
2246
2896
|
if (layout === "grid") {
|
|
2247
|
-
return /* @__PURE__ */
|
|
2897
|
+
return /* @__PURE__ */ React25.createElement(
|
|
2248
2898
|
"div",
|
|
2249
2899
|
{
|
|
2250
2900
|
className: `grid gap-${spacing} ${columns === 1 ? "grid-cols-1" : columns === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"}`
|
|
2251
2901
|
},
|
|
2252
|
-
config.fields.map((field2) => /* @__PURE__ */
|
|
2902
|
+
config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2253
2903
|
FormField,
|
|
2254
2904
|
{
|
|
2255
2905
|
key: field2.name,
|
|
@@ -2266,7 +2916,7 @@ function ZodForm({
|
|
|
2266
2916
|
);
|
|
2267
2917
|
}
|
|
2268
2918
|
if (layout === "horizontal") {
|
|
2269
|
-
return /* @__PURE__ */
|
|
2919
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2270
2920
|
FormField,
|
|
2271
2921
|
{
|
|
2272
2922
|
key: field2.name,
|
|
@@ -2281,10 +2931,10 @@ function ZodForm({
|
|
|
2281
2931
|
}
|
|
2282
2932
|
)));
|
|
2283
2933
|
}
|
|
2284
|
-
return /* @__PURE__ */
|
|
2934
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2285
2935
|
FormField,
|
|
2286
2936
|
{
|
|
2287
|
-
key: field2.name,
|
|
2937
|
+
key: pathToString(field2.name),
|
|
2288
2938
|
config: field2,
|
|
2289
2939
|
form,
|
|
2290
2940
|
submissionState: {
|
|
@@ -2300,19 +2950,19 @@ function ZodForm({
|
|
|
2300
2950
|
e.preventDefault();
|
|
2301
2951
|
void handleSubmit();
|
|
2302
2952
|
};
|
|
2303
|
-
|
|
2953
|
+
React25.useEffect(() => {
|
|
2304
2954
|
if (config.onError && Object.keys(form.formState.errors).length > 0) {
|
|
2305
2955
|
config.onError(form.formState.errors);
|
|
2306
2956
|
}
|
|
2307
2957
|
}, [form.formState.errors, config.onError]);
|
|
2308
|
-
return /* @__PURE__ */
|
|
2958
|
+
return /* @__PURE__ */ React25.createElement(FormProvider2, { ...form }, /* @__PURE__ */ React25.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React25.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React25.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React25.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), /* @__PURE__ */ React25.createElement(
|
|
2309
2959
|
FormStatus,
|
|
2310
2960
|
{
|
|
2311
2961
|
state: enhancedState,
|
|
2312
2962
|
onDismiss: () => enhancedState.reset(),
|
|
2313
2963
|
showDetails: true
|
|
2314
2964
|
}
|
|
2315
|
-
), renderFields(), /* @__PURE__ */
|
|
2965
|
+
), renderFields(), /* @__PURE__ */ React25.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React25.createElement(
|
|
2316
2966
|
Button5,
|
|
2317
2967
|
{
|
|
2318
2968
|
color: "primary",
|
|
@@ -2322,7 +2972,7 @@ function ZodForm({
|
|
|
2322
2972
|
...submitButtonProps
|
|
2323
2973
|
},
|
|
2324
2974
|
enhancedState.isSuccess ? "Success!" : submitButtonText
|
|
2325
|
-
), showResetButton && /* @__PURE__ */
|
|
2975
|
+
), showResetButton && /* @__PURE__ */ React25.createElement(
|
|
2326
2976
|
Button5,
|
|
2327
2977
|
{
|
|
2328
2978
|
isDisabled: enhancedState.isSubmitting,
|
|
@@ -2334,6 +2984,44 @@ function ZodForm({
|
|
|
2334
2984
|
))));
|
|
2335
2985
|
}
|
|
2336
2986
|
|
|
2987
|
+
// src/components/SimpleForm.tsx
|
|
2988
|
+
import React26 from "react";
|
|
2989
|
+
function SimpleForm({
|
|
2990
|
+
className,
|
|
2991
|
+
defaultValues,
|
|
2992
|
+
field: field2,
|
|
2993
|
+
hideSubmitButton = false,
|
|
2994
|
+
onError,
|
|
2995
|
+
onSubmit,
|
|
2996
|
+
onSuccess,
|
|
2997
|
+
schema,
|
|
2998
|
+
submitButton,
|
|
2999
|
+
subtitle,
|
|
3000
|
+
title
|
|
3001
|
+
}) {
|
|
3002
|
+
return /* @__PURE__ */ React26.createElement(
|
|
3003
|
+
ZodForm,
|
|
3004
|
+
{
|
|
3005
|
+
className,
|
|
3006
|
+
config: {
|
|
3007
|
+
defaultValues,
|
|
3008
|
+
fields: [field2],
|
|
3009
|
+
schema
|
|
3010
|
+
},
|
|
3011
|
+
onError,
|
|
3012
|
+
onSubmit,
|
|
3013
|
+
onSuccess,
|
|
3014
|
+
showResetButton: false,
|
|
3015
|
+
submitButtonText: hideSubmitButton ? "" : "Submit",
|
|
3016
|
+
subtitle,
|
|
3017
|
+
title,
|
|
3018
|
+
submitButtonProps: hideSubmitButton && submitButton ? {
|
|
3019
|
+
style: { display: "none" }
|
|
3020
|
+
} : {}
|
|
3021
|
+
}
|
|
3022
|
+
);
|
|
3023
|
+
}
|
|
3024
|
+
|
|
2337
3025
|
// src/builders/BasicFormBuilder.ts
|
|
2338
3026
|
var BasicFormBuilder = class {
|
|
2339
3027
|
constructor() {
|
|
@@ -2435,6 +3123,29 @@ var BasicFormBuilder = class {
|
|
|
2435
3123
|
function createBasicFormBuilder() {
|
|
2436
3124
|
return new BasicFormBuilder();
|
|
2437
3125
|
}
|
|
3126
|
+
function inputHelper(name, label, typeOrProps, inputProps) {
|
|
3127
|
+
if (typeOrProps && typeof typeOrProps === "object" && !("type" in typeOrProps && typeof typeOrProps.type === "string" && ["text", "email", "tel", "password"].includes(typeOrProps.type))) {
|
|
3128
|
+
return {
|
|
3129
|
+
inputProps: {
|
|
3130
|
+
type: "text",
|
|
3131
|
+
...typeOrProps
|
|
3132
|
+
},
|
|
3133
|
+
label,
|
|
3134
|
+
name,
|
|
3135
|
+
type: "input"
|
|
3136
|
+
};
|
|
3137
|
+
}
|
|
3138
|
+
const type = typeof typeOrProps === "string" ? typeOrProps : void 0;
|
|
3139
|
+
return {
|
|
3140
|
+
inputProps: {
|
|
3141
|
+
type: type || "text",
|
|
3142
|
+
...inputProps
|
|
3143
|
+
},
|
|
3144
|
+
label,
|
|
3145
|
+
name,
|
|
3146
|
+
type: "input"
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
2438
3149
|
var FormFieldHelpers = {
|
|
2439
3150
|
/**
|
|
2440
3151
|
* Create an autocomplete field
|
|
@@ -2485,6 +3196,34 @@ var FormFieldHelpers = {
|
|
|
2485
3196
|
name,
|
|
2486
3197
|
type: "checkbox"
|
|
2487
3198
|
}),
|
|
3199
|
+
/**
|
|
3200
|
+
* Create a checkbox group field (multiple checkboxes saving to an array)
|
|
3201
|
+
*
|
|
3202
|
+
* @example
|
|
3203
|
+
* ```tsx
|
|
3204
|
+
* // Simple checkbox group
|
|
3205
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", [
|
|
3206
|
+
* { label: "Reading", value: "reading" },
|
|
3207
|
+
* { label: "Sports", value: "sports" },
|
|
3208
|
+
* { label: "Music", value: "music" },
|
|
3209
|
+
* ])
|
|
3210
|
+
*
|
|
3211
|
+
* // With horizontal layout and custom styling
|
|
3212
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", options, {
|
|
3213
|
+
* orientation: "horizontal",
|
|
3214
|
+
* checkboxProps: { color: "primary", size: "lg" }
|
|
3215
|
+
* })
|
|
3216
|
+
* ```
|
|
3217
|
+
*/
|
|
3218
|
+
checkboxGroup: (name, label, options, config) => ({
|
|
3219
|
+
checkboxGroupOptions: options,
|
|
3220
|
+
checkboxProps: config?.checkboxProps,
|
|
3221
|
+
description: config?.description,
|
|
3222
|
+
label,
|
|
3223
|
+
name,
|
|
3224
|
+
orientation: config?.orientation || "vertical",
|
|
3225
|
+
type: "checkboxGroup"
|
|
3226
|
+
}),
|
|
2488
3227
|
/**
|
|
2489
3228
|
* Create a conditional field that shows/hides based on form data
|
|
2490
3229
|
*
|
|
@@ -2509,12 +3248,13 @@ var FormFieldHelpers = {
|
|
|
2509
3248
|
* ```
|
|
2510
3249
|
*/
|
|
2511
3250
|
conditional: (name, condition, field2) => {
|
|
2512
|
-
|
|
3251
|
+
const config = {
|
|
2513
3252
|
condition,
|
|
2514
3253
|
field: field2,
|
|
2515
3254
|
name,
|
|
2516
3255
|
type: "conditional"
|
|
2517
3256
|
};
|
|
3257
|
+
return config;
|
|
2518
3258
|
},
|
|
2519
3259
|
/**
|
|
2520
3260
|
* Create a content field for headers, questions, or custom content between fields
|
|
@@ -2531,7 +3271,7 @@ var FormFieldHelpers = {
|
|
|
2531
3271
|
* ```
|
|
2532
3272
|
*/
|
|
2533
3273
|
content: (title, description, options) => {
|
|
2534
|
-
|
|
3274
|
+
const config = {
|
|
2535
3275
|
className: options?.className,
|
|
2536
3276
|
description: description || void 0,
|
|
2537
3277
|
name: options?.name,
|
|
@@ -2539,7 +3279,31 @@ var FormFieldHelpers = {
|
|
|
2539
3279
|
title: title || void 0,
|
|
2540
3280
|
type: "content"
|
|
2541
3281
|
};
|
|
3282
|
+
return config;
|
|
2542
3283
|
},
|
|
3284
|
+
/**
|
|
3285
|
+
* Create a custom field with full control over rendering
|
|
3286
|
+
*
|
|
3287
|
+
* @example
|
|
3288
|
+
* ```tsx
|
|
3289
|
+
* // Custom field with render function
|
|
3290
|
+
* FormFieldHelpers.custom<FormData>(
|
|
3291
|
+
* "skills",
|
|
3292
|
+
* "Skills",
|
|
3293
|
+
* ({ form, control }) => {
|
|
3294
|
+
* // Custom rendering logic
|
|
3295
|
+
* return <div>...</div>;
|
|
3296
|
+
* }
|
|
3297
|
+
* )
|
|
3298
|
+
* ```
|
|
3299
|
+
*/
|
|
3300
|
+
custom: (name, label, render, options) => ({
|
|
3301
|
+
label,
|
|
3302
|
+
name,
|
|
3303
|
+
render,
|
|
3304
|
+
type: "custom",
|
|
3305
|
+
...options
|
|
3306
|
+
}),
|
|
2543
3307
|
/**
|
|
2544
3308
|
* Create a date field
|
|
2545
3309
|
*
|
|
@@ -2625,7 +3389,10 @@ var FormFieldHelpers = {
|
|
|
2625
3389
|
* // With type
|
|
2626
3390
|
* FormFieldHelpers.input("email", "Email", "email")
|
|
2627
3391
|
*
|
|
2628
|
-
* // With
|
|
3392
|
+
* // With props only (no type)
|
|
3393
|
+
* FormFieldHelpers.input("name", "Name", { placeholder: "Enter name" })
|
|
3394
|
+
*
|
|
3395
|
+
* // With type and props
|
|
2629
3396
|
* FormFieldHelpers.input("email", "Email", "email", {
|
|
2630
3397
|
* placeholder: "Enter your email",
|
|
2631
3398
|
* classNames: { input: "custom-input" },
|
|
@@ -2634,15 +3401,25 @@ var FormFieldHelpers = {
|
|
|
2634
3401
|
* })
|
|
2635
3402
|
* ```
|
|
2636
3403
|
*/
|
|
2637
|
-
input:
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
3404
|
+
input: inputHelper,
|
|
3405
|
+
/**
|
|
3406
|
+
* Create a radio group field
|
|
3407
|
+
*
|
|
3408
|
+
* @example
|
|
3409
|
+
* ```tsx
|
|
3410
|
+
* // Simple radio group
|
|
3411
|
+
* FormFieldHelpers.radio("gender", "Gender", [
|
|
3412
|
+
* { label: "Male", value: "male" },
|
|
3413
|
+
* { label: "Female", value: "female" }
|
|
3414
|
+
* ])
|
|
3415
|
+
*
|
|
3416
|
+
* // With full customization
|
|
3417
|
+
* FormFieldHelpers.radio("gender", "Gender", options, {
|
|
3418
|
+
* orientation: "horizontal",
|
|
3419
|
+
* classNames: { base: "custom-radio" }
|
|
3420
|
+
* })
|
|
3421
|
+
* ```
|
|
3422
|
+
*/
|
|
2646
3423
|
/**
|
|
2647
3424
|
* Create a radio group field
|
|
2648
3425
|
*
|
|
@@ -2775,6 +3552,8 @@ var CommonFields = {
|
|
|
2775
3552
|
* Address fields
|
|
2776
3553
|
*/
|
|
2777
3554
|
address: () => [
|
|
3555
|
+
// Type assertions are necessary: TypeScript can't prove these strings are valid Path<T>
|
|
3556
|
+
// for an arbitrary T, but they will be valid when used with a matching schema
|
|
2778
3557
|
FormFieldHelpers.input("street", "Street Address"),
|
|
2779
3558
|
FormFieldHelpers.input("city", "City"),
|
|
2780
3559
|
FormFieldHelpers.input("state", "State/Province"),
|
|
@@ -2793,6 +3572,7 @@ var CommonFields = {
|
|
|
2793
3572
|
* Personal information fields
|
|
2794
3573
|
*/
|
|
2795
3574
|
personal: () => [
|
|
3575
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2796
3576
|
FormFieldHelpers.input("firstName", "First Name"),
|
|
2797
3577
|
FormFieldHelpers.input("lastName", "Last Name"),
|
|
2798
3578
|
FormFieldHelpers.input("email", "Email", "email"),
|
|
@@ -2802,6 +3582,7 @@ var CommonFields = {
|
|
|
2802
3582
|
* Terms and conditions fields
|
|
2803
3583
|
*/
|
|
2804
3584
|
terms: () => [
|
|
3585
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2805
3586
|
FormFieldHelpers.checkbox(
|
|
2806
3587
|
"terms",
|
|
2807
3588
|
"I agree to the terms and conditions"
|
|
@@ -2818,7 +3599,7 @@ var CommonFields = {
|
|
|
2818
3599
|
};
|
|
2819
3600
|
|
|
2820
3601
|
// src/builders/AdvancedFormBuilder.ts
|
|
2821
|
-
function
|
|
3602
|
+
function createInputField(name, label, props) {
|
|
2822
3603
|
return {
|
|
2823
3604
|
label,
|
|
2824
3605
|
name,
|
|
@@ -2834,7 +3615,7 @@ function inputField(name, label, props) {
|
|
|
2834
3615
|
}
|
|
2835
3616
|
};
|
|
2836
3617
|
}
|
|
2837
|
-
function
|
|
3618
|
+
function createTextareaField(name, label, props) {
|
|
2838
3619
|
return {
|
|
2839
3620
|
label,
|
|
2840
3621
|
name,
|
|
@@ -2850,7 +3631,7 @@ function textareaField(name, label, props) {
|
|
|
2850
3631
|
}
|
|
2851
3632
|
};
|
|
2852
3633
|
}
|
|
2853
|
-
function
|
|
3634
|
+
function createSelectField(name, label, options) {
|
|
2854
3635
|
return {
|
|
2855
3636
|
label,
|
|
2856
3637
|
name,
|
|
@@ -2858,7 +3639,7 @@ function selectField(name, label, options) {
|
|
|
2858
3639
|
type: "select"
|
|
2859
3640
|
};
|
|
2860
3641
|
}
|
|
2861
|
-
function
|
|
3642
|
+
function createCheckboxField(name, label, props) {
|
|
2862
3643
|
return {
|
|
2863
3644
|
label,
|
|
2864
3645
|
name,
|
|
@@ -2871,7 +3652,7 @@ function checkboxField(name, label, props) {
|
|
|
2871
3652
|
}
|
|
2872
3653
|
};
|
|
2873
3654
|
}
|
|
2874
|
-
function
|
|
3655
|
+
function createSwitchField(name, label, props) {
|
|
2875
3656
|
return {
|
|
2876
3657
|
description: props?.description,
|
|
2877
3658
|
isDisabled: props?.isDisabled,
|
|
@@ -2885,7 +3666,7 @@ function switchField(name, label, props) {
|
|
|
2885
3666
|
}
|
|
2886
3667
|
};
|
|
2887
3668
|
}
|
|
2888
|
-
function
|
|
3669
|
+
function createRadioField(name, label, options, props) {
|
|
2889
3670
|
return {
|
|
2890
3671
|
label,
|
|
2891
3672
|
name,
|
|
@@ -2900,7 +3681,7 @@ function radioField(name, label, options, props) {
|
|
|
2900
3681
|
}
|
|
2901
3682
|
};
|
|
2902
3683
|
}
|
|
2903
|
-
function
|
|
3684
|
+
function createSliderField(name, label, props) {
|
|
2904
3685
|
return {
|
|
2905
3686
|
label,
|
|
2906
3687
|
name,
|
|
@@ -2915,20 +3696,19 @@ function sliderField(name, label, props) {
|
|
|
2915
3696
|
}
|
|
2916
3697
|
};
|
|
2917
3698
|
}
|
|
2918
|
-
function
|
|
3699
|
+
function createDateField(name, label, props) {
|
|
3700
|
+
const dateProps = {};
|
|
3701
|
+
if (props?.className !== void 0) {
|
|
3702
|
+
dateProps.className = props.className;
|
|
3703
|
+
}
|
|
2919
3704
|
return {
|
|
2920
3705
|
label,
|
|
2921
3706
|
name,
|
|
2922
3707
|
type: "date",
|
|
2923
|
-
...
|
|
2924
|
-
dateProps: {
|
|
2925
|
-
className: props.className,
|
|
2926
|
-
placeholder: props.placeholder
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
3708
|
+
...Object.keys(dateProps).length > 0 && { dateProps }
|
|
2929
3709
|
};
|
|
2930
3710
|
}
|
|
2931
|
-
function
|
|
3711
|
+
function createFileField(name, label, props) {
|
|
2932
3712
|
return {
|
|
2933
3713
|
label,
|
|
2934
3714
|
name,
|
|
@@ -2943,7 +3723,7 @@ function fileField(name, label, props) {
|
|
|
2943
3723
|
}
|
|
2944
3724
|
};
|
|
2945
3725
|
}
|
|
2946
|
-
function
|
|
3726
|
+
function createFontPickerField(name, label, props) {
|
|
2947
3727
|
return {
|
|
2948
3728
|
className: props?.className,
|
|
2949
3729
|
description: props?.description,
|
|
@@ -2953,83 +3733,119 @@ function fontPickerField(name, label, props) {
|
|
|
2953
3733
|
type: "fontPicker"
|
|
2954
3734
|
};
|
|
2955
3735
|
}
|
|
2956
|
-
function
|
|
3736
|
+
function createStringArrayField(name, label, props) {
|
|
3737
|
+
return {
|
|
3738
|
+
className: props?.className,
|
|
3739
|
+
description: props?.description,
|
|
3740
|
+
isDisabled: props?.isDisabled,
|
|
3741
|
+
label,
|
|
3742
|
+
name,
|
|
3743
|
+
stringArrayProps: {
|
|
3744
|
+
addButtonText: props?.addButtonText,
|
|
3745
|
+
allowDuplicates: props?.allowDuplicates,
|
|
3746
|
+
maxItems: props?.maxItems,
|
|
3747
|
+
minItems: props?.minItems,
|
|
3748
|
+
placeholder: props?.placeholder,
|
|
3749
|
+
showAddButton: props?.showAddButton,
|
|
3750
|
+
transformItem: props?.transformItem,
|
|
3751
|
+
validateItem: props?.validateItem
|
|
3752
|
+
},
|
|
3753
|
+
type: "stringArray"
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
function createContentField(config) {
|
|
2957
3757
|
return {
|
|
2958
|
-
className:
|
|
2959
|
-
description: description || void 0,
|
|
2960
|
-
name:
|
|
2961
|
-
render:
|
|
2962
|
-
title: title || void 0,
|
|
3758
|
+
className: config.className,
|
|
3759
|
+
description: config.description || void 0,
|
|
3760
|
+
name: config.name,
|
|
3761
|
+
render: config.render,
|
|
3762
|
+
title: config.title || void 0,
|
|
2963
3763
|
type: "content"
|
|
2964
3764
|
};
|
|
2965
3765
|
}
|
|
2966
|
-
function
|
|
2967
|
-
switch (type) {
|
|
3766
|
+
function createFieldFromParams(params) {
|
|
3767
|
+
switch (params.type) {
|
|
2968
3768
|
case "input":
|
|
2969
|
-
return
|
|
3769
|
+
return createInputField(params.name, params.label, params.props);
|
|
2970
3770
|
case "textarea":
|
|
2971
|
-
return
|
|
3771
|
+
return createTextareaField(params.name, params.label, params.props);
|
|
2972
3772
|
case "select":
|
|
2973
|
-
return
|
|
3773
|
+
return createSelectField(params.name, params.label, params.options);
|
|
2974
3774
|
case "checkbox":
|
|
2975
|
-
return
|
|
3775
|
+
return createCheckboxField(params.name, params.label, params.props);
|
|
2976
3776
|
case "switch":
|
|
2977
|
-
return
|
|
3777
|
+
return createSwitchField(params.name, params.label, params.props);
|
|
2978
3778
|
case "radio":
|
|
2979
|
-
return
|
|
3779
|
+
return createRadioField(
|
|
3780
|
+
params.name,
|
|
3781
|
+
params.label,
|
|
3782
|
+
params.options,
|
|
3783
|
+
params.props
|
|
3784
|
+
);
|
|
2980
3785
|
case "slider":
|
|
2981
|
-
return
|
|
3786
|
+
return createSliderField(params.name, params.label, params.props);
|
|
2982
3787
|
case "date":
|
|
2983
|
-
return
|
|
3788
|
+
return createDateField(params.name, params.label, params.props);
|
|
2984
3789
|
case "file":
|
|
2985
|
-
return
|
|
3790
|
+
return createFileField(params.name, params.label, params.props);
|
|
2986
3791
|
case "fontPicker":
|
|
2987
|
-
return
|
|
3792
|
+
return createFontPickerField(params.name, params.label, params.props);
|
|
3793
|
+
case "stringArray":
|
|
3794
|
+
return createStringArrayField(params.name, params.label, params.props);
|
|
3795
|
+
case "autocomplete":
|
|
3796
|
+
return {
|
|
3797
|
+
autocompleteProps: params.props,
|
|
3798
|
+
label: params.label,
|
|
3799
|
+
name: params.name,
|
|
3800
|
+
options: params.options,
|
|
3801
|
+
type: "autocomplete"
|
|
3802
|
+
};
|
|
2988
3803
|
case "content":
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
}
|
|
2999
|
-
|
|
3000
|
-
name,
|
|
3001
|
-
label,
|
|
3002
|
-
optionsOrProps
|
|
3003
|
-
);
|
|
3004
|
-
default:
|
|
3005
|
-
throw new Error(`Unknown field type: ${type}`);
|
|
3804
|
+
return createContentField({
|
|
3805
|
+
className: params.className,
|
|
3806
|
+
description: params.description,
|
|
3807
|
+
name: params.name,
|
|
3808
|
+
render: params.render,
|
|
3809
|
+
title: params.title
|
|
3810
|
+
});
|
|
3811
|
+
default: {
|
|
3812
|
+
const _exhaustive = params;
|
|
3813
|
+
throw new Error(`Unknown field type: ${_exhaustive.type}`);
|
|
3814
|
+
}
|
|
3006
3815
|
}
|
|
3007
3816
|
}
|
|
3817
|
+
function createField(params) {
|
|
3818
|
+
return createFieldFromParams(params);
|
|
3819
|
+
}
|
|
3008
3820
|
var AdvancedFieldBuilder = class {
|
|
3009
3821
|
constructor() {
|
|
3010
3822
|
this.fields = [];
|
|
3011
3823
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3824
|
+
/**
|
|
3825
|
+
* Add any field type using the unified API
|
|
3826
|
+
*/
|
|
3827
|
+
field(params) {
|
|
3828
|
+
this.fields.push(createField(params));
|
|
3014
3829
|
return this;
|
|
3015
3830
|
}
|
|
3016
3831
|
/**
|
|
3017
3832
|
* Add a conditional field that shows/hides based on form data
|
|
3018
3833
|
*/
|
|
3019
3834
|
conditionalField(name, condition, field2) {
|
|
3020
|
-
|
|
3835
|
+
const config = {
|
|
3021
3836
|
condition,
|
|
3022
3837
|
field: field2,
|
|
3023
3838
|
name,
|
|
3024
3839
|
type: "conditional"
|
|
3025
|
-
}
|
|
3840
|
+
};
|
|
3841
|
+
this.fields.push(config);
|
|
3026
3842
|
return this;
|
|
3027
3843
|
}
|
|
3028
3844
|
/**
|
|
3029
3845
|
* Add a field array for dynamic repeating field groups
|
|
3030
3846
|
*/
|
|
3031
3847
|
fieldArray(name, label, fields, options) {
|
|
3032
|
-
|
|
3848
|
+
const config = {
|
|
3033
3849
|
addButtonText: options?.addButtonText,
|
|
3034
3850
|
fields,
|
|
3035
3851
|
label,
|
|
@@ -3038,21 +3854,23 @@ var AdvancedFieldBuilder = class {
|
|
|
3038
3854
|
name,
|
|
3039
3855
|
removeButtonText: options?.removeButtonText,
|
|
3040
3856
|
type: "fieldArray"
|
|
3041
|
-
}
|
|
3857
|
+
};
|
|
3858
|
+
this.fields.push(config);
|
|
3042
3859
|
return this;
|
|
3043
3860
|
}
|
|
3044
3861
|
/**
|
|
3045
3862
|
* Add a dynamic section that shows/hides based on form data
|
|
3046
3863
|
*/
|
|
3047
3864
|
dynamicSection(name, condition, fields, options) {
|
|
3048
|
-
|
|
3865
|
+
const config = {
|
|
3049
3866
|
condition,
|
|
3050
3867
|
description: options?.description,
|
|
3051
3868
|
fields,
|
|
3052
3869
|
name,
|
|
3053
3870
|
title: options?.title,
|
|
3054
3871
|
type: "dynamicSection"
|
|
3055
|
-
}
|
|
3872
|
+
};
|
|
3873
|
+
this.fields.push(config);
|
|
3056
3874
|
return this;
|
|
3057
3875
|
}
|
|
3058
3876
|
/**
|
|
@@ -3066,8 +3884,11 @@ var FieldArrayItemBuilder = class {
|
|
|
3066
3884
|
constructor() {
|
|
3067
3885
|
this.fields = [];
|
|
3068
3886
|
}
|
|
3069
|
-
|
|
3070
|
-
|
|
3887
|
+
/**
|
|
3888
|
+
* Add any field type using the unified API for array items
|
|
3889
|
+
*/
|
|
3890
|
+
field(params) {
|
|
3891
|
+
this.fields.push(createField(params));
|
|
3071
3892
|
return this;
|
|
3072
3893
|
}
|
|
3073
3894
|
/**
|
|
@@ -3085,15 +3906,12 @@ var FieldArrayBuilder = class {
|
|
|
3085
3906
|
this.arrayName = arrayName;
|
|
3086
3907
|
this.fields = [];
|
|
3087
3908
|
}
|
|
3088
|
-
field(
|
|
3089
|
-
const fullPath = `${this.arrayName}.${name}`;
|
|
3090
|
-
const fieldConfig = createField(
|
|
3091
|
-
|
|
3092
|
-
fullPath
|
|
3093
|
-
|
|
3094
|
-
optionsOrProps,
|
|
3095
|
-
props
|
|
3096
|
-
);
|
|
3909
|
+
field(params) {
|
|
3910
|
+
const fullPath = `${this.arrayName}.${params.name}`;
|
|
3911
|
+
const fieldConfig = createField({
|
|
3912
|
+
...params,
|
|
3913
|
+
name: fullPath
|
|
3914
|
+
});
|
|
3097
3915
|
this.fields.push(fieldConfig);
|
|
3098
3916
|
return this;
|
|
3099
3917
|
}
|
|
@@ -3136,7 +3954,7 @@ var TypeInferredBuilder = class {
|
|
|
3136
3954
|
new RegExp(pattern),
|
|
3137
3955
|
`${label} format is invalid`
|
|
3138
3956
|
);
|
|
3139
|
-
this.schemaFields[name] = zodType;
|
|
3957
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3140
3958
|
this.formFields.push({
|
|
3141
3959
|
inputProps: { type: "text", ...fieldOptions },
|
|
3142
3960
|
label,
|
|
@@ -3149,7 +3967,7 @@ var TypeInferredBuilder = class {
|
|
|
3149
3967
|
* Add an email field
|
|
3150
3968
|
*/
|
|
3151
3969
|
email(name, label, options) {
|
|
3152
|
-
this.schemaFields[name] = z3.string().email(`Please enter a valid email address`);
|
|
3970
|
+
this.schemaFields[pathToString(name)] = z3.string().email(`Please enter a valid email address`);
|
|
3153
3971
|
this.formFields.push({
|
|
3154
3972
|
inputProps: { type: "email", ...options },
|
|
3155
3973
|
label,
|
|
@@ -3168,7 +3986,7 @@ var TypeInferredBuilder = class {
|
|
|
3168
3986
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3169
3987
|
if (max !== void 0)
|
|
3170
3988
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3171
|
-
this.schemaFields[name] = zodType;
|
|
3989
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3172
3990
|
this.formFields.push({
|
|
3173
3991
|
inputProps: { max, min, step, type: "number", ...fieldOptions },
|
|
3174
3992
|
label,
|
|
@@ -3188,7 +4006,7 @@ var TypeInferredBuilder = class {
|
|
|
3188
4006
|
minLength,
|
|
3189
4007
|
`${label} must be at least ${minLength} characters`
|
|
3190
4008
|
);
|
|
3191
|
-
this.schemaFields[name] = zodType;
|
|
4009
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3192
4010
|
this.formFields.push({
|
|
3193
4011
|
label,
|
|
3194
4012
|
name,
|
|
@@ -3201,7 +4019,7 @@ var TypeInferredBuilder = class {
|
|
|
3201
4019
|
* Add a select field
|
|
3202
4020
|
*/
|
|
3203
4021
|
select(name, label, options) {
|
|
3204
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4022
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3205
4023
|
this.formFields.push({
|
|
3206
4024
|
label,
|
|
3207
4025
|
name,
|
|
@@ -3222,7 +4040,7 @@ var TypeInferredBuilder = class {
|
|
|
3222
4040
|
`You must agree to ${label.toLowerCase()}`
|
|
3223
4041
|
);
|
|
3224
4042
|
}
|
|
3225
|
-
this.schemaFields[name] = zodType;
|
|
4043
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3226
4044
|
this.formFields.push({
|
|
3227
4045
|
checkboxProps: fieldOptions,
|
|
3228
4046
|
label,
|
|
@@ -3235,7 +4053,7 @@ var TypeInferredBuilder = class {
|
|
|
3235
4053
|
* Add a switch field
|
|
3236
4054
|
*/
|
|
3237
4055
|
switch(name, label, options) {
|
|
3238
|
-
this.schemaFields[name] = z3.boolean().optional();
|
|
4056
|
+
this.schemaFields[pathToString(name)] = z3.boolean().optional();
|
|
3239
4057
|
this.formFields.push({
|
|
3240
4058
|
label,
|
|
3241
4059
|
name,
|
|
@@ -3248,7 +4066,7 @@ var TypeInferredBuilder = class {
|
|
|
3248
4066
|
* Add a radio field
|
|
3249
4067
|
*/
|
|
3250
4068
|
radio(name, label, options, fieldOptions) {
|
|
3251
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4069
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3252
4070
|
this.formFields.push({
|
|
3253
4071
|
label,
|
|
3254
4072
|
name,
|
|
@@ -3268,15 +4086,19 @@ var TypeInferredBuilder = class {
|
|
|
3268
4086
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3269
4087
|
if (max !== void 0)
|
|
3270
4088
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3271
|
-
this.schemaFields[name] = zodType;
|
|
4089
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
4090
|
+
const { className, description, isDisabled, ...validSliderProps } = fieldOptions || {};
|
|
3272
4091
|
this.formFields.push({
|
|
4092
|
+
className,
|
|
4093
|
+
description,
|
|
4094
|
+
isDisabled,
|
|
3273
4095
|
label,
|
|
3274
4096
|
name,
|
|
3275
4097
|
sliderProps: {
|
|
3276
4098
|
maxValue: max,
|
|
3277
4099
|
minValue: min,
|
|
3278
4100
|
step,
|
|
3279
|
-
...
|
|
4101
|
+
...validSliderProps
|
|
3280
4102
|
},
|
|
3281
4103
|
type: "slider"
|
|
3282
4104
|
});
|
|
@@ -3286,7 +4108,7 @@ var TypeInferredBuilder = class {
|
|
|
3286
4108
|
* Add a date field
|
|
3287
4109
|
*/
|
|
3288
4110
|
date(name, label, options) {
|
|
3289
|
-
this.schemaFields[name] = z3.string().min(1, `${label} is required`);
|
|
4111
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `${label} is required`);
|
|
3290
4112
|
this.formFields.push({
|
|
3291
4113
|
dateProps: options,
|
|
3292
4114
|
label,
|
|
@@ -3299,7 +4121,7 @@ var TypeInferredBuilder = class {
|
|
|
3299
4121
|
* Add a file field
|
|
3300
4122
|
*/
|
|
3301
4123
|
file(name, label, options) {
|
|
3302
|
-
this.schemaFields[name] = z3.any().optional();
|
|
4124
|
+
this.schemaFields[pathToString(name)] = z3.any().optional();
|
|
3303
4125
|
this.formFields.push({
|
|
3304
4126
|
fileProps: options,
|
|
3305
4127
|
label,
|
|
@@ -3376,11 +4198,18 @@ var field = {
|
|
|
3376
4198
|
// src/builders/NestedPathBuilder.ts
|
|
3377
4199
|
var NestedPathBuilder = class {
|
|
3378
4200
|
constructor() {
|
|
4201
|
+
// fields is accessed by nested builder classes, so it needs to be accessible
|
|
4202
|
+
// Making it public allows nested builders to add fields while maintaining encapsulation
|
|
3379
4203
|
this.fields = [];
|
|
3380
4204
|
}
|
|
3381
4205
|
/**
|
|
3382
4206
|
* Create a nested object path builder
|
|
3383
4207
|
* Usage: builder.nest("address").field("street", "Street Address")
|
|
4208
|
+
*
|
|
4209
|
+
* @param path - A path in the form data structure. When called from root level,
|
|
4210
|
+
* accepts Path<T>. When called after .end() from a nested context,
|
|
4211
|
+
* accepts any string for nested paths under sections.
|
|
4212
|
+
* @returns A builder for nested paths under the specified path
|
|
3384
4213
|
*/
|
|
3385
4214
|
nest(path) {
|
|
3386
4215
|
return new NestedObjectBuilder(this, path);
|
|
@@ -3394,29 +4223,18 @@ var NestedPathBuilder = class {
|
|
|
3394
4223
|
}
|
|
3395
4224
|
/**
|
|
3396
4225
|
* Add a field with single path
|
|
3397
|
-
* Usage: builder.field("firstName", "First Name")
|
|
4226
|
+
* Usage: builder.field({ type: "input", name: "firstName", label: "First Name" })
|
|
3398
4227
|
*/
|
|
3399
|
-
field(
|
|
3400
|
-
this.fields.push(
|
|
3401
|
-
label,
|
|
3402
|
-
name,
|
|
3403
|
-
type,
|
|
3404
|
-
...props
|
|
3405
|
-
});
|
|
4228
|
+
field(params) {
|
|
4229
|
+
this.fields.push(createField(params));
|
|
3406
4230
|
return this;
|
|
3407
4231
|
}
|
|
3408
4232
|
/**
|
|
3409
4233
|
* Add a field with path segments
|
|
3410
|
-
* Usage: builder.fieldPath(
|
|
4234
|
+
* Usage: builder.fieldPath({ type: "input", name: path.join("."), label: "Full Name" })
|
|
3411
4235
|
*/
|
|
3412
|
-
fieldPath(
|
|
3413
|
-
|
|
3414
|
-
this.fields.push({
|
|
3415
|
-
label,
|
|
3416
|
-
name,
|
|
3417
|
-
type,
|
|
3418
|
-
...props
|
|
3419
|
-
});
|
|
4236
|
+
fieldPath(params) {
|
|
4237
|
+
this.fields.push(createField(params));
|
|
3420
4238
|
return this;
|
|
3421
4239
|
}
|
|
3422
4240
|
/**
|
|
@@ -3445,23 +4263,28 @@ var NestedObjectBuilder = class _NestedObjectBuilder {
|
|
|
3445
4263
|
/**
|
|
3446
4264
|
* Add a field to the current nested path
|
|
3447
4265
|
*/
|
|
3448
|
-
field(
|
|
3449
|
-
const fullPath = `${this.path}.${
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
name: fullPath
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
});
|
|
4266
|
+
field(params) {
|
|
4267
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4268
|
+
const fieldParams = {
|
|
4269
|
+
...params,
|
|
4270
|
+
name: fullPath
|
|
4271
|
+
};
|
|
4272
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3456
4273
|
return this;
|
|
3457
4274
|
}
|
|
3458
4275
|
/**
|
|
3459
4276
|
* Nest deeper into the object
|
|
4277
|
+
*
|
|
4278
|
+
* @param subPath - A string representing a nested path under the current path.
|
|
4279
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4280
|
+
* path (basePath.subPath) in the return type.
|
|
4281
|
+
* @returns A builder for the nested path
|
|
3460
4282
|
*/
|
|
3461
4283
|
nest(subPath) {
|
|
4284
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3462
4285
|
return new _NestedObjectBuilder(
|
|
3463
4286
|
this.parent,
|
|
3464
|
-
|
|
4287
|
+
fullPath
|
|
3465
4288
|
);
|
|
3466
4289
|
}
|
|
3467
4290
|
/**
|
|
@@ -3479,14 +4302,13 @@ var SectionBuilder = class {
|
|
|
3479
4302
|
/**
|
|
3480
4303
|
* Add a field to the current section
|
|
3481
4304
|
*/
|
|
3482
|
-
field(
|
|
3483
|
-
const fullPath = `${this.path}.${
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
name: fullPath
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
});
|
|
4305
|
+
field(params) {
|
|
4306
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4307
|
+
const fieldParams = {
|
|
4308
|
+
...params,
|
|
4309
|
+
name: fullPath
|
|
4310
|
+
};
|
|
4311
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3490
4312
|
return this;
|
|
3491
4313
|
}
|
|
3492
4314
|
/**
|
|
@@ -3494,17 +4316,29 @@ var SectionBuilder = class {
|
|
|
3494
4316
|
*/
|
|
3495
4317
|
fields(fieldDefinitions) {
|
|
3496
4318
|
fieldDefinitions.forEach((field2) => {
|
|
3497
|
-
this.
|
|
4319
|
+
const fullPath = `${this.path}.${field2.name}`;
|
|
4320
|
+
this.parent.fields.push({
|
|
4321
|
+
label: field2.label,
|
|
4322
|
+
name: fullPath,
|
|
4323
|
+
type: field2.type || "input",
|
|
4324
|
+
...field2.props
|
|
4325
|
+
});
|
|
3498
4326
|
});
|
|
3499
4327
|
return this;
|
|
3500
4328
|
}
|
|
3501
4329
|
/**
|
|
3502
4330
|
* Nest deeper into the section
|
|
4331
|
+
*
|
|
4332
|
+
* @param subPath - A string representing a nested path under the current section path.
|
|
4333
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4334
|
+
* path (basePath.subPath) in the return type.
|
|
4335
|
+
* @returns A builder for the nested path
|
|
3503
4336
|
*/
|
|
3504
4337
|
nest(subPath) {
|
|
4338
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3505
4339
|
return new NestedObjectBuilder(
|
|
3506
4340
|
this.parent,
|
|
3507
|
-
|
|
4341
|
+
fullPath
|
|
3508
4342
|
);
|
|
3509
4343
|
}
|
|
3510
4344
|
/**
|
|
@@ -3522,13 +4356,12 @@ var FieldTemplateBuilder = class {
|
|
|
3522
4356
|
/**
|
|
3523
4357
|
* Complete the field definition
|
|
3524
4358
|
*/
|
|
3525
|
-
complete(
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
name: this.path
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
});
|
|
4359
|
+
complete(params) {
|
|
4360
|
+
const fieldParams = {
|
|
4361
|
+
...params,
|
|
4362
|
+
name: params.name ? `${this.path}.${params.name}` : this.path
|
|
4363
|
+
};
|
|
4364
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3532
4365
|
return this.parent;
|
|
3533
4366
|
}
|
|
3534
4367
|
};
|
|
@@ -3742,6 +4575,133 @@ function useMemoizedFieldProps(props, deps) {
|
|
|
3742
4575
|
return useMemo2(() => props, deps);
|
|
3743
4576
|
}
|
|
3744
4577
|
|
|
4578
|
+
// src/utils/arraySync.ts
|
|
4579
|
+
function syncArrays(options) {
|
|
4580
|
+
const { current, existing, getId } = options;
|
|
4581
|
+
const existingMap = /* @__PURE__ */ new Map();
|
|
4582
|
+
const currentMap = /* @__PURE__ */ new Map();
|
|
4583
|
+
existing.forEach((item) => {
|
|
4584
|
+
const id = getId(item);
|
|
4585
|
+
if (id !== void 0) {
|
|
4586
|
+
existingMap.set(id, item);
|
|
4587
|
+
}
|
|
4588
|
+
});
|
|
4589
|
+
current.forEach((item) => {
|
|
4590
|
+
const id = getId(item);
|
|
4591
|
+
if (id !== void 0) {
|
|
4592
|
+
currentMap.set(id, item);
|
|
4593
|
+
}
|
|
4594
|
+
});
|
|
4595
|
+
const toDelete = [];
|
|
4596
|
+
existingMap.forEach((item, id) => {
|
|
4597
|
+
if (!currentMap.has(id)) {
|
|
4598
|
+
toDelete.push(item);
|
|
4599
|
+
}
|
|
4600
|
+
});
|
|
4601
|
+
const toUpdate = [];
|
|
4602
|
+
existingMap.forEach((existingItem, id) => {
|
|
4603
|
+
const currentItem = currentMap.get(id);
|
|
4604
|
+
if (currentItem) {
|
|
4605
|
+
toUpdate.push({ current: currentItem, existing: existingItem });
|
|
4606
|
+
}
|
|
4607
|
+
});
|
|
4608
|
+
const toCreate = [];
|
|
4609
|
+
currentMap.forEach((item, id) => {
|
|
4610
|
+
if (!existingMap.has(id)) {
|
|
4611
|
+
toCreate.push(item);
|
|
4612
|
+
}
|
|
4613
|
+
});
|
|
4614
|
+
return {
|
|
4615
|
+
toCreate,
|
|
4616
|
+
toDelete,
|
|
4617
|
+
toUpdate
|
|
4618
|
+
};
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4621
|
+
// src/utils/createFieldArrayCustomConfig.tsx
|
|
4622
|
+
import React27 from "react";
|
|
4623
|
+
import { useFieldArray as useFieldArray2 } from "react-hook-form";
|
|
4624
|
+
import { Button as Button6 } from "@heroui/react";
|
|
4625
|
+
function createFieldArrayCustomConfig(options) {
|
|
4626
|
+
const {
|
|
4627
|
+
className,
|
|
4628
|
+
defaultItem,
|
|
4629
|
+
enableReordering = false,
|
|
4630
|
+
label,
|
|
4631
|
+
max = 10,
|
|
4632
|
+
min = 0,
|
|
4633
|
+
name,
|
|
4634
|
+
renderAddButton,
|
|
4635
|
+
renderItem
|
|
4636
|
+
} = options;
|
|
4637
|
+
return {
|
|
4638
|
+
className,
|
|
4639
|
+
label,
|
|
4640
|
+
name,
|
|
4641
|
+
// ArrayPath is now accepted by CustomFieldConfig
|
|
4642
|
+
render: ({ control, errors, form }) => {
|
|
4643
|
+
const { append, fields, move, remove } = useFieldArray2({
|
|
4644
|
+
control,
|
|
4645
|
+
name
|
|
4646
|
+
// ArrayPath is the correct type for useFieldArray
|
|
4647
|
+
});
|
|
4648
|
+
const canAdd = fields.length < max;
|
|
4649
|
+
const canRemove = fields.length > min;
|
|
4650
|
+
const handleAdd = () => {
|
|
4651
|
+
if (canAdd) {
|
|
4652
|
+
if (defaultItem) {
|
|
4653
|
+
append(defaultItem());
|
|
4654
|
+
} else {
|
|
4655
|
+
append({});
|
|
4656
|
+
}
|
|
4657
|
+
}
|
|
4658
|
+
};
|
|
4659
|
+
const handleRemove = (index) => {
|
|
4660
|
+
if (canRemove) {
|
|
4661
|
+
remove(index);
|
|
4662
|
+
}
|
|
4663
|
+
};
|
|
4664
|
+
const handleMoveUp = (index) => {
|
|
4665
|
+
if (enableReordering && index > 0) {
|
|
4666
|
+
move(index, index - 1);
|
|
4667
|
+
}
|
|
4668
|
+
};
|
|
4669
|
+
const handleMoveDown = (index) => {
|
|
4670
|
+
if (enableReordering && index < fields.length - 1) {
|
|
4671
|
+
move(index, index + 1);
|
|
4672
|
+
}
|
|
4673
|
+
};
|
|
4674
|
+
return /* @__PURE__ */ React27.createElement("div", { className }, /* @__PURE__ */ React27.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => {
|
|
4675
|
+
const canMoveUp = enableReordering && index > 0;
|
|
4676
|
+
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
4677
|
+
return /* @__PURE__ */ React27.createElement(React27.Fragment, { key: field2.id }, renderItem({
|
|
4678
|
+
canMoveDown,
|
|
4679
|
+
canMoveUp,
|
|
4680
|
+
control,
|
|
4681
|
+
errors,
|
|
4682
|
+
// fields from useFieldArray are already typed correctly
|
|
4683
|
+
field: field2,
|
|
4684
|
+
fields,
|
|
4685
|
+
form,
|
|
4686
|
+
index,
|
|
4687
|
+
onMoveDown: () => handleMoveDown(index),
|
|
4688
|
+
onMoveUp: () => handleMoveUp(index),
|
|
4689
|
+
onRemove: () => handleRemove(index)
|
|
4690
|
+
}));
|
|
4691
|
+
}), fields.length === 0 && renderAddButton ? /* @__PURE__ */ React27.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React27.createElement("p", null, "No ", label?.toLowerCase() || "items", " added yet."), renderAddButton({ canAdd, onAdd: handleAdd })) : null, fields.length > 0 && renderAddButton ? renderAddButton({ canAdd, onAdd: handleAdd }) : canAdd && /* @__PURE__ */ React27.createElement(
|
|
4692
|
+
Button6,
|
|
4693
|
+
{
|
|
4694
|
+
variant: "bordered",
|
|
4695
|
+
onPress: handleAdd,
|
|
4696
|
+
className: "w-full"
|
|
4697
|
+
},
|
|
4698
|
+
"Add Item"
|
|
4699
|
+
)));
|
|
4700
|
+
},
|
|
4701
|
+
type: "custom"
|
|
4702
|
+
};
|
|
4703
|
+
}
|
|
4704
|
+
|
|
3745
4705
|
// src/builders/validation-helpers.ts
|
|
3746
4706
|
import { z as z4 } from "zod";
|
|
3747
4707
|
var validationPatterns = {
|
|
@@ -3894,6 +4854,7 @@ export {
|
|
|
3894
4854
|
AutocompleteField,
|
|
3895
4855
|
BasicFormBuilder,
|
|
3896
4856
|
CheckboxField,
|
|
4857
|
+
CheckboxGroupField,
|
|
3897
4858
|
CommonFields,
|
|
3898
4859
|
ConditionalField,
|
|
3899
4860
|
ConfigurableForm,
|
|
@@ -3915,6 +4876,7 @@ export {
|
|
|
3915
4876
|
RadioGroupField,
|
|
3916
4877
|
SelectField,
|
|
3917
4878
|
ServerActionForm,
|
|
4879
|
+
SimpleForm,
|
|
3918
4880
|
SliderField,
|
|
3919
4881
|
SubmitButton,
|
|
3920
4882
|
SwitchField,
|
|
@@ -3930,6 +4892,7 @@ export {
|
|
|
3930
4892
|
createEmailSchema,
|
|
3931
4893
|
createField,
|
|
3932
4894
|
createFieldArrayBuilder,
|
|
4895
|
+
createFieldArrayCustomConfig,
|
|
3933
4896
|
createFieldArrayItemBuilder,
|
|
3934
4897
|
createFileSchema,
|
|
3935
4898
|
createFormTestUtils,
|
|
@@ -3959,10 +4922,12 @@ export {
|
|
|
3959
4922
|
getFormErrors,
|
|
3960
4923
|
hasFieldError,
|
|
3961
4924
|
hasFormErrors,
|
|
4925
|
+
pathToString,
|
|
3962
4926
|
serverValidation,
|
|
3963
4927
|
shallowEqual,
|
|
3964
4928
|
simulateFieldInput,
|
|
3965
4929
|
simulateFormSubmission,
|
|
4930
|
+
syncArrays,
|
|
3966
4931
|
throttle,
|
|
3967
4932
|
useDebouncedFieldValidation,
|
|
3968
4933
|
useDebouncedValidation,
|